| | |
| | | private let windowCloseService: any WindowCloseServiceProtocol |
| | | private let systemCriticalWindowDetector: any SystemCriticalWindowDetecting |
| | | private let disableScreenshotRefresh: Bool |
| | | private var waterfallViewMode: QuickSwitchWaterfallViewMode |
| | | private var closeConfirmationRequired: Bool |
| | | private let onCloseConfirmationDisabled: (() -> Void)? |
| | | private let debugOverlayWidth: CGFloat? |
| | |
| | | private var lifecycleResidualOverlayWindows = 0 |
| | | private var lifecycleResidualVisibleOverlayWindows = 0 |
| | | var onSnapshotUpdated: (() -> Void)? |
| | | var onOpenSettings: (() -> Void)? |
| | | |
| | | private struct PendingCloseVerification { |
| | | let request: QuickSwitchCloseRequest |
| | |
| | | ), |
| | | systemCriticalWindowDetector: any SystemCriticalWindowDetecting = CGWindowSystemCriticalWindowDetector(), |
| | | disableScreenshotRefresh: Bool = false, |
| | | waterfallViewMode: QuickSwitchWaterfallViewMode = .verticalColumns, |
| | | closeConfirmationRequired: Bool = true, |
| | | onCloseConfirmationDisabled: (() -> Void)? = nil, |
| | | debugHoveredAppGroupIndex: Int? = nil, |
| | |
| | | self.windowCloseService = windowCloseService |
| | | self.systemCriticalWindowDetector = systemCriticalWindowDetector |
| | | self.disableScreenshotRefresh = disableScreenshotRefresh |
| | | self.waterfallViewMode = waterfallViewMode |
| | | self.closeConfirmationRequired = closeConfirmationRequired |
| | | self.onCloseConfirmationDisabled = onCloseConfirmationDisabled |
| | | self.debugOverlayWidth = debugOverlayWidth |
| | |
| | | view.onBackgroundClick = { [weak self] in |
| | | self?.handleBackgroundClick() ?? false |
| | | } |
| | | view.onOpenSettings = { [weak self] in |
| | | self?.onOpenSettings?() |
| | | } |
| | | view.setSuppressEventInput(!debugMouseSequence.isEmpty || !debugKeySequence.isEmpty) |
| | | view.onRequestClose = { [weak self] request in |
| | | self?.requestClose(request) |
| | |
| | | self.onCloseConfirmationDisabled?() |
| | | } |
| | | view.setCloseConfirmationRequired(closeConfirmationRequired) |
| | | view.setWaterfallViewMode(waterfallViewMode) |
| | | view.apply(viewModel: nil) |
| | | view.beginPerformanceFirstFrameMeasurement() |
| | | coordinator.openQuickSwitch() |
| | |
| | | func retriggerFromShortcut() { |
| | | DevelopmentDiagnostics.log("quickSwitch.session.retriggerFromShortcut") |
| | | show() |
| | | } |
| | | |
| | | func setWaterfallViewMode(_ mode: QuickSwitchWaterfallViewMode) { |
| | | guard waterfallViewMode != mode else { return } |
| | | |
| | | waterfallViewMode = mode |
| | | DevelopmentDiagnostics.log("quickSwitch.session.waterfallViewModeChanged", [ |
| | | "mode": mode.rawValue, |
| | | "visible": isVisible, |
| | | "hasViewModel": currentViewModel != nil |
| | | ]) |
| | | |
| | | view.setWaterfallViewMode(mode) |
| | | if isVisible, let currentViewModel { |
| | | view.applyProjected(viewModel: currentViewModel) |
| | | } |
| | | onSnapshotUpdated?() |
| | | } |
| | | |
| | | func reportDictionary() -> [String: Any] { |
| | |
| | | let debugWindowActivation: Bool |
| | | let debugWindowClose: Bool |
| | | let disableScreenshotRefresh: Bool |
| | | let waterfallViewMode: QuickSwitchWaterfallViewMode? |
| | | let lifecycleCycles: Int? |
| | | let lifecycleInterval: TimeInterval |
| | | let lifecycleVisibleDuration: TimeInterval |
| | |
| | | debugWindowActivation: arguments.contains("--round01-debug-window-activation"), |
| | | debugWindowClose: arguments.contains("--round01-debug-window-close"), |
| | | disableScreenshotRefresh: arguments.contains("--round01-disable-screenshot-refresh"), |
| | | waterfallViewMode: waterfallViewModeValue(for: "--round01-waterfall-view-mode", in: arguments), |
| | | lifecycleCycles: intValue(for: "--round01-quick-switch-lifecycle-cycles", in: arguments), |
| | | lifecycleInterval: timeInterval(for: "--round01-quick-switch-lifecycle-interval", in: arguments) ?? 0.02, |
| | | lifecycleVisibleDuration: timeInterval(for: "--round01-quick-switch-lifecycle-visible-duration", in: arguments) ?? 0.16 |
| | |
| | | return String(argument.dropFirst(prefix.count)) |
| | | } |
| | | |
| | | private static func waterfallViewModeValue( |
| | | for key: String, |
| | | in arguments: [String] |
| | | ) -> QuickSwitchWaterfallViewMode? { |
| | | guard let value = stringValue(for: key, in: arguments) else { return nil } |
| | | |
| | | switch value { |
| | | case "vertical", "vertical-columns", "verticalColumns": |
| | | return .verticalColumns |
| | | case "horizontal", "horizontal-masonry", "horizontalMasonry": |
| | | return .horizontalMasonry |
| | | default: |
| | | return nil |
| | | } |
| | | } |
| | | |
| | | private static func intValue(for key: String, in arguments: [String]) -> Int? { |
| | | stringValue(for: key, in: arguments).flatMap(Int.init) |
| | | } |