From 9ba7cd3b47fb91eaaa8d0c3df8b7286a89be1756 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 28 Jun 2026 21:19:30 +0800
Subject: [PATCH] Freeze 0.1.12 local QA baseline

---
 C1.source/Sources/Aligner/QuickSwitchSessionController.swift |  126 +++++++++++++++++++++++++++++++++++++----
 1 files changed, 112 insertions(+), 14 deletions(-)

diff --git a/C1.source/Sources/Aligner/QuickSwitchSessionController.swift b/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
index 947b96e..8122f9a 100644
--- a/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchSessionController.swift
@@ -20,6 +20,7 @@
     private let systemCriticalWindowDetector: any SystemCriticalWindowDetecting
     private let disableScreenshotRefresh: Bool
     private var waterfallViewMode: QuickSwitchWaterfallViewMode
+    private var theme: ThemePreference
     private var closeConfirmationRequired: Bool
     private let onCloseConfirmationDisabled: (() -> Void)?
     private let debugOverlayWidth: CGFloat?
@@ -56,6 +57,7 @@
     private var lastActivationWindowID: UInt32?
     private var lastActivationResult: WindowActivationResult?
     private var lastActivationError: String?
+    private var lastActivationDurationMilliseconds: Double?
     private var lastSpaceActivationSpaceID: UInt64?
     private var lastSpaceActivationDidRequestFocus: Bool?
     private var lastSpaceActivationDisplayIdentifier: String?
@@ -69,6 +71,7 @@
     private var lastCloseError: String?
     private var pendingCloseVerification: PendingCloseVerification?
     private var suppressedCloseTargets: [SuppressedCloseTarget] = []
+    private var suppressedActivationWindowIDs = Set<UInt32>()
     private var lastDismissReason: DismissReason?
     private var lastSystemCriticalAction: String?
     private var lastSystemCriticalMonitorSource: String?
@@ -86,7 +89,8 @@
     private var lifecycleResidualOverlayWindows = 0
     private var lifecycleResidualVisibleOverlayWindows = 0
     var onSnapshotUpdated: (() -> Void)?
-    var onOpenSettings: (() -> Void)?
+    var onToggleWaterfallViewMode: (() -> Void)?
+    var onToggleTheme: (() -> Void)?
 
     private struct PendingCloseVerification {
         let request: QuickSwitchCloseRequest
@@ -123,6 +127,7 @@
         systemCriticalWindowDetector: any SystemCriticalWindowDetecting = CGWindowSystemCriticalWindowDetector(),
         disableScreenshotRefresh: Bool = false,
         waterfallViewMode: QuickSwitchWaterfallViewMode = .verticalColumns,
+        theme: ThemePreference = .light,
         closeConfirmationRequired: Bool = true,
         onCloseConfirmationDisabled: (() -> Void)? = nil,
         debugHoveredAppGroupIndex: Int? = nil,
@@ -139,6 +144,7 @@
         self.systemCriticalWindowDetector = systemCriticalWindowDetector
         self.disableScreenshotRefresh = disableScreenshotRefresh
         self.waterfallViewMode = waterfallViewMode
+        self.theme = theme
         self.closeConfirmationRequired = closeConfirmationRequired
         self.onCloseConfirmationDisabled = onCloseConfirmationDisabled
         self.debugOverlayWidth = debugOverlayWidth
@@ -169,6 +175,7 @@
         lastActivationWindowID = nil
         lastActivationResult = nil
         lastActivationError = nil
+        lastActivationDurationMilliseconds = nil
         lastSpaceActivationSpaceID = nil
         lastSpaceActivationDidRequestFocus = nil
         lastSpaceActivationDisplayIdentifier = nil
@@ -182,6 +189,7 @@
         lastCloseError = nil
         pendingCloseVerification = nil
         suppressedCloseTargets = []
+        suppressedActivationWindowIDs = []
         cancelPendingLockedSpaceUnlock()
         lockedSpaceFilterID = nil
         selectionBeforeSpaceFilter = nil
@@ -213,8 +221,11 @@
         view.onBackgroundClick = { [weak self] in
             self?.handleBackgroundClick() ?? false
         }
-        view.onOpenSettings = { [weak self] in
-            self?.onOpenSettings?()
+        view.onToggleWaterfallViewMode = { [weak self] in
+            self?.onToggleWaterfallViewMode?()
+        }
+        view.onToggleTheme = { [weak self] in
+            self?.onToggleTheme?()
         }
         view.setSuppressEventInput(!debugMouseSequence.isEmpty || !debugKeySequence.isEmpty)
         view.onRequestClose = { [weak self] request in
@@ -227,6 +238,7 @@
         }
         view.setCloseConfirmationRequired(closeConfirmationRequired)
         view.setWaterfallViewMode(waterfallViewMode)
+        view.setTheme(theme)
         view.apply(viewModel: nil)
         view.beginPerformanceFirstFrameMeasurement()
         coordinator.openQuickSwitch()
@@ -280,7 +292,27 @@
 
     func retriggerFromShortcut() {
         DevelopmentDiagnostics.log("quickSwitch.session.retriggerFromShortcut")
-        show()
+        guard isVisible else {
+            show()
+            return
+        }
+
+        guard currentViewModel != nil else {
+            DevelopmentDiagnostics.log("quickSwitch.session.retriggerFromShortcut.noSnapshot", [
+                "action": "fallbackShow"
+            ])
+            show()
+            return
+        }
+
+        let didCycle = view.hoverNextAppGroupIndex()
+        DevelopmentDiagnostics.log("quickSwitch.session.retriggerFromShortcut.hoverApp", [
+            "didCycle": didCycle
+        ])
+
+        if !didCycle {
+            show()
+        }
     }
 
     func setWaterfallViewMode(_ mode: QuickSwitchWaterfallViewMode) {
@@ -297,6 +329,20 @@
         if isVisible, let currentViewModel {
             view.applyProjected(viewModel: currentViewModel)
         }
+        onSnapshotUpdated?()
+    }
+
+    func setTheme(_ theme: ThemePreference) {
+        guard self.theme != theme else { return }
+
+        self.theme = theme
+        DevelopmentDiagnostics.log("quickSwitch.session.themeChanged", [
+            "theme": theme.rawValue,
+            "visible": isVisible,
+            "hasViewModel": currentViewModel != nil
+        ])
+
+        view.setTheme(theme)
         onSnapshotUpdated?()
     }
 
@@ -334,6 +380,7 @@
             "lastActivationWindowID": lastActivationWindowID ?? NSNull(),
             "lastActivationResult": lastActivationResult.map(Self.activationResultString) ?? NSNull(),
             "lastActivationError": lastActivationError ?? NSNull(),
+            "lastActivationDurationMilliseconds": lastActivationDurationMilliseconds ?? NSNull(),
             "lastSpaceActivationSpaceID": lastSpaceActivationSpaceID ?? NSNull(),
             "lastSpaceActivationDidRequestFocus": lastSpaceActivationDidRequestFocus ?? NSNull(),
             "lastSpaceActivationDisplayIdentifier": lastSpaceActivationDisplayIdentifier ?? NSNull(),
@@ -346,6 +393,8 @@
             "lastCloseResult": lastCloseResult.map(Self.closeResultString) ?? NSNull(),
             "lastCloseError": lastCloseError ?? NSNull(),
             "suppressedCloseTargetCount": suppressedCloseTargets.count,
+            "suppressedActivationWindowCount": suppressedActivationWindowIDs.count,
+            "suppressedActivationWindowIDs": Array(suppressedActivationWindowIDs).sorted(),
             "lastDismissReason": lastDismissReason.map(Self.dismissReasonString) ?? NSNull(),
             "overlayLevel": Int(coordinator.currentLevel),
             "overlayMainMenuLevel": Int(CGWindowLevelForKey(.mainMenuWindow)),
@@ -526,9 +575,11 @@
         lastCommitSource = source
         lastActivationWindowID = selection.windowID
         lastActivationError = nil
+        lastActivationDurationMilliseconds = nil
 
         guard let window = window(for: selection, in: viewModel ?? currentViewModel) else {
             lastActivationResult = .windowNotFound
+            suppressActivationWindowID(selection.windowID, reason: "selectionMissing")
             DevelopmentDiagnostics.log("quickSwitch.activation.commit.windowNotFound", [
                 "source": source.rawValue,
                 "appGroupIndex": selection.appGroupIndex,
@@ -545,8 +596,10 @@
         ])
         hide(reason: .userClosed)
 
+        let activationStartedAt = CACurrentMediaTime()
         do {
             lastActivationResult = try windowActivationService.activate(window: window)
+            lastActivationDurationMilliseconds = (CACurrentMediaTime() - activationStartedAt) * 1_000
             DevelopmentDiagnostics.log("quickSwitch.activation.commit.result", [
                 "source": source.rawValue,
                 "windowID": window.id,
@@ -555,9 +608,11 @@
                 "titleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
                 "titleLength": window.title.count,
                 "titleIsEmpty": window.title.isEmpty,
-                "result": lastActivationResult.map(Self.activationResultString)
+                "result": lastActivationResult.map(Self.activationResultString),
+                "durationMilliseconds": lastActivationDurationMilliseconds
             ])
         } catch {
+            lastActivationDurationMilliseconds = (CACurrentMediaTime() - activationStartedAt) * 1_000
             let errorSummary = DevelopmentDiagnostics.errorSummaryString(error)
             lastActivationResult = .failed(errorSummary)
             lastActivationError = errorSummary
@@ -567,10 +622,15 @@
                 "appName": window.app.name,
                 "titleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
                 "titleLength": window.title.count,
-                "titleIsEmpty": window.title.isEmpty
+                "titleIsEmpty": window.title.isEmpty,
+                "durationMilliseconds": lastActivationDurationMilliseconds
             ]
             DevelopmentDiagnostics.errorSummaryFields(error).forEach { fields[$0.key] = $0.value }
             DevelopmentDiagnostics.log("quickSwitch.activation.commit.error", fields)
+        }
+
+        if shouldSuppressAfterActivationResult(lastActivationResult) {
+            suppressActivationWindowID(window.id, reason: lastActivationResult.map(Self.activationResultString) ?? "unknown")
         }
 
         if shouldCloseAfterActivation(lastActivationResult) {
@@ -587,7 +647,7 @@
 
     private func handleSpaceLaneClick(_ spaceID: UInt64, clickCount: Int) {
         if clickCount >= 2 {
-            if pendingLockedSpaceUnlockSpaceID == spaceID {
+            if pendingLockedSpaceUnlockSpaceID == spaceID || lockedSpaceFilterID == spaceID {
                 cancelPendingLockedSpaceUnlock()
                 activateLockedSpace(spaceID)
             } else {
@@ -919,18 +979,37 @@
         ])
     }
 
+    private func suppressActivationWindowID(_ windowID: UInt32, reason: String) {
+        guard windowID != 0 else { return }
+        suppressedActivationWindowIDs.insert(windowID)
+
+        guard let sourceViewModel else { return }
+        let visibleViewModel = projectedViewModel(from: sourceViewModel, preferredSelection: view.effectiveSelectionForProjection())
+        self.currentViewModel = visibleViewModel
+        view.applyProjected(viewModel: visibleViewModel)
+        DevelopmentDiagnostics.log("quickSwitch.activation.suppressWindow", [
+            "windowID": windowID,
+            "reason": reason,
+            "remainingWindowCount": visibleViewModel.windowCount,
+            "suppressedActivationWindowCount": suppressedActivationWindowIDs.count
+        ])
+    }
+
     private func viewModel(
         _ viewModel: QuickSwitchViewModel,
-        excluding suppressedTargets: [SuppressedCloseTarget]
+        excluding suppressedTargets: [SuppressedCloseTarget],
+        suppressedActivationWindowIDs: Set<UInt32> = []
     ) -> QuickSwitchViewModel {
-        guard !suppressedTargets.isEmpty else { return viewModel }
+        guard !suppressedTargets.isEmpty || !suppressedActivationWindowIDs.isEmpty else { return viewModel }
 
         var nextGlobalIndex = 0
         let columns = viewModel.waterfallColumns.compactMap { column -> QuickSwitchWaterfallColumnViewModel? in
             let windows = column.windows.filter { card in
-                !suppressedTargets.contains { target in
+                let isActivationSuppressed = suppressedActivationWindowIDs.contains(card.window.id)
+                let isCloseSuppressed = suppressedTargets.contains { target in
                     suppressedTarget(target, matches: card)
                 }
+                return !isActivationSuppressed && !isCloseSuppressed
             }
             guard !windows.isEmpty else { return nil }
 
@@ -979,7 +1058,11 @@
         from sourceViewModel: QuickSwitchViewModel,
         preferredSelection: QuickSwitchSelection? = nil
     ) -> QuickSwitchViewModel {
-        let closeProjectedViewModel = viewModel(sourceViewModel, excluding: suppressedCloseTargets)
+        let closeProjectedViewModel = viewModel(
+            sourceViewModel,
+            excluding: suppressedCloseTargets,
+            suppressedActivationWindowIDs: suppressedActivationWindowIDs
+        )
         return QuickSwitchSpaceFilterPolicy.projectedViewModel(
             from: closeProjectedViewModel,
             lockedSpaceID: lockedSpaceFilterID,
@@ -1036,9 +1119,18 @@
 
     private func shouldCloseAfterActivation(_ result: WindowActivationResult?) -> Bool {
         switch result {
-        case .activated, .restored, .appActivatedOnly:
+        case .activated, .restored:
             return true
-        case .windowNotFound, .unsupported, .activationFailed, .failed, nil:
+        case .appActivatedOnly, .windowNotFound, .unsupported, .activationFailed, .failed, nil:
+            return false
+        }
+    }
+
+    private func shouldSuppressAfterActivationResult(_ result: WindowActivationResult?) -> Bool {
+        switch result {
+        case .windowNotFound, .unsupported, .activationFailed, .failed:
+            return true
+        case .activated, .restored, .appActivatedOnly, nil:
             return false
         }
     }
@@ -1478,6 +1570,8 @@
     let fixtureCandidateFiltering: Bool
     let fixtureActivation: Bool
     let fixtureSpaceFilter: Bool
+    let fixtureSplitView: Bool
+    let fixtureMultiPageIdentity: Bool
     let debugHoveredAppGroupIndex: Int?
     let debugOverlayWidth: CGFloat?
     let debugKeySequence: [String]
@@ -1490,6 +1584,7 @@
     let lifecycleCycles: Int?
     let lifecycleInterval: TimeInterval
     let lifecycleVisibleDuration: TimeInterval
+    let simulateDockReopenAfter: TimeInterval?
 
     static func parse(arguments: [String]) -> Round1QuickSwitchLaunchOptions {
         Round1QuickSwitchLaunchOptions(
@@ -1506,6 +1601,8 @@
             fixtureCandidateFiltering: arguments.contains("--round01-fixture-candidate-filtering"),
             fixtureActivation: arguments.contains("--round01-fixture-window-activation"),
             fixtureSpaceFilter: arguments.contains("--round01-fixture-space-filter"),
+            fixtureSplitView: arguments.contains("--round01-fixture-split-view"),
+            fixtureMultiPageIdentity: arguments.contains("--round01-fixture-multi-page-identity"),
             debugHoveredAppGroupIndex: intValue(for: "--round01-debug-hover-app-index", in: arguments),
             debugOverlayWidth: cgFloatValue(for: "--round01-debug-overlay-width", in: arguments),
             debugKeySequence: stringListValue(for: "--round01-debug-key-sequence", in: arguments),
@@ -1517,7 +1614,8 @@
             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
+            lifecycleVisibleDuration: timeInterval(for: "--round01-quick-switch-lifecycle-visible-duration", in: arguments) ?? 0.16,
+            simulateDockReopenAfter: timeInterval(for: "--round01-simulate-dock-reopen-after", in: arguments)
         )
     }
 

--
Gitblit v1.9.3