From 6f2856fa70722dad7f7c69a3addaa05ea9fd6e94 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Fri, 19 Jun 2026 22:36:43 +0800
Subject: [PATCH] Add two-key window shortcut codes

---
 C1.source/Sources/Aligner/QuickSwitchRootView.swift |  236 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 232 insertions(+), 4 deletions(-)

diff --git a/C1.source/Sources/Aligner/QuickSwitchRootView.swift b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
index 552dca0..5fff479 100644
--- a/C1.source/Sources/Aligner/QuickSwitchRootView.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
@@ -11,6 +11,16 @@
 @MainActor
 final class QuickSwitchRootView: NSView {
     private static let appShelfIndexSymbols = Array("1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ").map(String.init)
+    private static let windowIndexKeyPendingInterval: CFTimeInterval = 0.8
+    private static let appShelfIndexKeyCodes: [String: UInt16] = [
+        "1": 18, "2": 19, "3": 20, "4": 21, "5": 23,
+        "6": 22, "7": 26, "8": 28, "9": 25, "0": 29,
+        "A": 0, "B": 11, "C": 8, "D": 2, "E": 14, "F": 3,
+        "G": 5, "H": 4, "I": 34, "J": 38, "K": 40, "L": 37,
+        "M": 46, "N": 45, "O": 31, "P": 35, "Q": 12, "R": 15,
+        "S": 1, "T": 17, "U": 32, "V": 9, "W": 13, "X": 7,
+        "Y": 16, "Z": 6
+    ]
 
     private let backdropBlurView = NSVisualEffectView()
     private let layerHostView = NSView()
@@ -74,6 +84,12 @@
     private var keyboardCommandsApplied: [String] = []
     private var lastKeyboardCommand: String?
     private var lastKeyboardAppIndexCommand: String?
+    private var appShelfIndexKeyDownCount = 0
+    private var lastAppShelfIndexKeySymbol: String?
+    private var windowIndexKeyPending: WindowIndexKeyPending?
+    private var windowIndexKeyPendingClearTask: Task<Void, Never>?
+    private var lastWindowIndexKeyCommand: String?
+    private var lastWindowIndexKeyCommitCode: String?
     private var lastBoundaryBounceAxis: String?
     private var lastBoundaryBounceDirection: String?
     private var boundaryBounceCount = 0
@@ -313,6 +329,12 @@
         let closeButton: CloseButtonLayers
     }
 
+    private struct WindowIndexKeyPending {
+        let appSymbol: String
+        let appGroupIndex: Int
+        let startedAt: CFTimeInterval
+    }
+
     private struct ProjectionLayerSnapshot {
         let layer: CALayer
         let frame: CGRect
@@ -494,6 +516,7 @@
     }
 
     override func scrollWheel(with event: NSEvent) {
+        clearWindowIndexKeyPending()
         refreshHoverTarget(at: event.locationInWindow)
 
         let dominantDelta = abs(event.scrollingDeltaX) >= abs(event.scrollingDeltaY)
@@ -549,6 +572,7 @@
 
     override func mouseMoved(with event: NSEvent) {
         guard debugHoveredAppGroupIndex == nil else { return }
+        clearWindowIndexKeyPending()
 
         let toggleHovered = viewModeToggleButtonContains(windowLocation: event.locationInWindow)
         if !toggleHovered {
@@ -575,6 +599,7 @@
 
     override func mouseExited(with event: NSEvent) {
         guard debugHoveredAppGroupIndex == nil else { return }
+        clearWindowIndexKeyPending()
         isViewModeToggleButtonHovered = false
         suppressViewModeToggleHoverPreview = false
         hoveredCloseTarget = nil
@@ -590,6 +615,7 @@
             ])
             return
         }
+        clearWindowIndexKeyPending()
 
         if handleCloseConfirmationMouseDown(at: event.locationInWindow) {
             return
@@ -644,11 +670,49 @@
         layoutSubtreeIfNeeded()
         for command in commands {
             let measurementStart = CACurrentMediaTime()
-            performKeyboardCommand(command)
+            if !performDebugPhysicalIndexKeyCommand(command) {
+                performKeyboardCommand(command)
+            }
             layoutSubtreeIfNeeded()
             CATransaction.flush()
             keyboardResponseLatencyMilliseconds.append(milliseconds(since: measurementStart))
         }
+    }
+
+    private func performDebugPhysicalIndexKeyCommand(_ rawCommand: String) -> Bool {
+        let command = rawCommand.trimmingCharacters(in: .whitespacesAndNewlines)
+        let uppercased = command.uppercased()
+        let prefixes = ["PHYSICAL-INDEX:", "PHYSICAL-INDEX-", "KEYDOWN:", "KEYDOWN-"]
+        guard let prefix = prefixes.first(where: { uppercased.hasPrefix($0) }) else {
+            return false
+        }
+
+        let symbolStart = command.index(command.startIndex, offsetBy: prefix.count)
+        guard let symbol = appShelfIndexSymbol(fromKeyboardCommand: String(command[symbolStart...])),
+              let keyCode = Self.appShelfIndexKeyCodes[symbol],
+              let event = NSEvent.keyEvent(
+                with: .keyDown,
+                location: .zero,
+                modifierFlags: [.option],
+                timestamp: ProcessInfo.processInfo.systemUptime,
+                windowNumber: window?.windowNumber ?? 0,
+                context: nil,
+                characters: symbol.lowercased(),
+                charactersIgnoringModifiers: symbol.lowercased(),
+                isARepeat: false,
+                keyCode: keyCode
+              )
+        else {
+            recordKeyboardCommand("invalidPhysicalIndex:\(command)")
+            selectionChangedByLastCommand = false
+            return true
+        }
+
+        let previousSuppressEventInput = suppressEventInput
+        suppressEventInput = false
+        keyDown(with: event)
+        suppressEventInput = previousSuppressEventInput
+        return true
     }
 
     func performDebugMouseCommands(_ commands: [String]) {
@@ -871,6 +935,11 @@
             keyboardCommandsApplied = []
             lastKeyboardCommand = nil
             lastKeyboardAppIndexCommand = nil
+            appShelfIndexKeyDownCount = 0
+            lastAppShelfIndexKeySymbol = nil
+            clearWindowIndexKeyPending()
+            lastWindowIndexKeyCommand = nil
+            lastWindowIndexKeyCommitCode = nil
             lastBoundaryBounceAxis = nil
             lastBoundaryBounceDirection = nil
             boundaryBounceCount = 0
@@ -1299,6 +1368,12 @@
             "keyboardCommandsApplied": keyboardCommandsApplied,
             "lastKeyboardCommand": lastKeyboardCommand ?? NSNull(),
             "lastKeyboardAppIndexCommand": lastKeyboardAppIndexCommand ?? NSNull(),
+            "appShelfIndexKeyDownCount": appShelfIndexKeyDownCount,
+            "lastAppShelfIndexKeySymbol": lastAppShelfIndexKeySymbol ?? NSNull(),
+            "windowIndexKeyPendingAppGroupIndex": windowIndexKeyPending?.appGroupIndex ?? NSNull(),
+            "windowIndexKeyPendingAppSymbol": windowIndexKeyPending?.appSymbol ?? NSNull(),
+            "lastWindowIndexKeyCommand": lastWindowIndexKeyCommand ?? NSNull(),
+            "lastWindowIndexKeyCommitCode": lastWindowIndexKeyCommitCode ?? NSNull(),
             "lastBoundaryBounceAxis": lastBoundaryBounceAxis ?? NSNull(),
             "lastBoundaryBounceDirection": lastBoundaryBounceDirection ?? NSNull(),
             "boundaryBounceCount": boundaryBounceCount,
@@ -1378,6 +1453,7 @@
         if let indexSymbol = appShelfIndexSymbol(fromKeyboardCommand: command) {
             let recordedCommand = "app:\(indexSymbol)"
             recordKeyboardCommand(recordedCommand)
+            clearWindowIndexKeyPending()
             if !focusAppShelfItemForKeyboard(indexSymbol: indexSymbol, commandLabel: recordedCommand) {
                 selectionChangedByLastCommand = false
             }
@@ -1386,6 +1462,7 @@
 
         switch command {
         case "left":
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("left")
             if isHorizontalMasonryMode {
                 moveSelection(.left)
@@ -1393,6 +1470,7 @@
                 selectionChangedByLastCommand = false
             }
         case "right":
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("right")
             if isHorizontalMasonryMode {
                 moveSelection(.right)
@@ -1400,6 +1478,7 @@
                 selectionChangedByLastCommand = false
             }
         case "up":
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("up")
             if isHorizontalMasonryMode {
                 moveSelection(.up)
@@ -1407,6 +1486,7 @@
                 moveVerticalSelectionWithinFocusedColumn(.up)
             }
         case "down":
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("down")
             if isHorizontalMasonryMode {
                 moveSelection(.down)
@@ -1414,10 +1494,12 @@
                 moveVerticalSelectionWithinFocusedColumn(.down)
             }
         case "enter", "return", "commit":
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("enter")
             selectionChangedByLastCommand = false
             commitCurrentSelection()
         case "tab":
+            clearWindowIndexKeyPending()
             if isHorizontalMasonryMode {
                 recordKeyboardCommand("tab")
                 moveHorizontalMasonryTabSelection()
@@ -1427,6 +1509,7 @@
                 selectionChangedByLastCommand = false
             }
         default:
+            clearWindowIndexKeyPending()
             recordKeyboardCommand("unknown:\(command)")
             selectionChangedByLastCommand = false
         }
@@ -1438,7 +1521,6 @@
     }
 
     private func handleAppShelfIndexKey(_ event: NSEvent) -> Bool {
-        guard !isHorizontalMasonryMode else { return false }
         let flags = event.modifierFlags.intersection(.deviceIndependentFlagsMask)
         guard flags.isDisjoint(with: [.command, .control]) else { return false }
         guard let characters = event.charactersIgnoringModifiers,
@@ -1447,7 +1529,53 @@
             return false
         }
 
+        appShelfIndexKeyDownCount += 1
+        lastAppShelfIndexKeySymbol = symbol
+        if flags.contains(.option), handleWindowIndexKey(symbol: symbol) {
+            return true
+        }
+        clearWindowIndexKeyPending()
         performKeyboardCommand(symbol)
+        return true
+    }
+
+    private func handleWindowIndexKey(symbol: String) -> Bool {
+        let now = CACurrentMediaTime()
+        if let pending = validWindowIndexKeyPending(now: now) {
+            let code = "\(pending.appSymbol)\(symbol)"
+            if let card = waterfallCard(appGroupIndex: pending.appGroupIndex, windowIndexSymbol: symbol) {
+                recordKeyboardCommand("window:\(code)")
+                lastWindowIndexKeyCommand = "window:\(code)"
+                lastWindowIndexKeyCommitCode = code
+                clearWindowIndexKeyPending()
+                commitKeyboardWindowCard(card, trigger: "windowIndexKey")
+                return true
+            }
+
+            recordKeyboardCommand("windowInvalid:\(code)")
+            lastWindowIndexKeyCommand = "windowInvalid:\(code)"
+            lastWindowIndexKeyCommitCode = nil
+            selectionChangedByLastCommand = false
+            clearWindowIndexKeyPending()
+            return true
+        }
+
+        let recordedCommand = "app:\(symbol)"
+        recordKeyboardCommand(recordedCommand)
+        lastWindowIndexKeyCommand = nil
+        lastWindowIndexKeyCommitCode = nil
+        if focusAppShelfItemForKeyboard(indexSymbol: symbol, commandLabel: recordedCommand),
+           let ordinal = Self.appShelfIndexSymbols.firstIndex(of: symbol),
+           ordinal < appShelfItems.count {
+            setWindowIndexKeyPending(
+                appSymbol: symbol,
+                appGroupIndex: appShelfItems[ordinal].item.appGroupIndex,
+                startedAt: now
+            )
+        } else {
+            selectionChangedByLastCommand = false
+            clearWindowIndexKeyPending()
+        }
         return true
     }
 
@@ -1476,6 +1604,47 @@
             appGroupIndex: appShelfItems[ordinal].item.appGroupIndex,
             appIndexCommand: commandLabel
         )
+    }
+
+    private func validWindowIndexKeyPending(now: CFTimeInterval) -> WindowIndexKeyPending? {
+        guard let pending = windowIndexKeyPending else { return nil }
+        guard now - pending.startedAt <= Self.windowIndexKeyPendingInterval else {
+            clearWindowIndexKeyPending()
+            return nil
+        }
+        return pending
+    }
+
+    private func setWindowIndexKeyPending(appSymbol: String, appGroupIndex: Int, startedAt: CFTimeInterval) {
+        windowIndexKeyPendingClearTask?.cancel()
+        windowIndexKeyPending = WindowIndexKeyPending(
+            appSymbol: appSymbol,
+            appGroupIndex: appGroupIndex,
+            startedAt: startedAt
+        )
+        windowIndexKeyPendingClearTask = Task { @MainActor [weak self] in
+            do {
+                try await Task.sleep(nanoseconds: UInt64(Self.windowIndexKeyPendingInterval * 1_000_000_000))
+            } catch {
+                return
+            }
+            guard let self,
+                  let pending = self.windowIndexKeyPending,
+                  pending.appSymbol == appSymbol,
+                  pending.appGroupIndex == appGroupIndex,
+                  pending.startedAt == startedAt
+            else {
+                return
+            }
+            self.windowIndexKeyPending = nil
+            self.windowIndexKeyPendingClearTask = nil
+        }
+    }
+
+    private func clearWindowIndexKeyPending() {
+        windowIndexKeyPendingClearTask?.cancel()
+        windowIndexKeyPendingClearTask = nil
+        windowIndexKeyPending = nil
     }
 
     @discardableResult
@@ -1718,6 +1887,7 @@
             .trimmingCharacters(in: .whitespacesAndNewlines)
             .lowercased()
         guard !command.isEmpty else { return }
+        clearWindowIndexKeyPending()
 
         let parts = command.split(separator: ":").map(String.init)
         switch parts.first {
@@ -2026,6 +2196,34 @@
     private func clickWindowCard(_ card: WaterfallCardLayers) {
         hoverWindowCard(card)
         commitWindowCard(card, trigger: "windowCard")
+    }
+
+    private func commitKeyboardWindowCard(_ card: WaterfallCardLayers, trigger: String) {
+        let selection = QuickSwitchSelection(
+            appGroupIndex: card.item.appGroupIndex,
+            windowIndex: card.item.windowIndex,
+            windowID: card.item.window.id
+        )
+        DevelopmentDiagnostics.log("quickSwitch.view.commitKeyboardWindow", [
+            "trigger": trigger,
+            "appGroupIndex": selection.appGroupIndex,
+            "windowIndex": selection.windowIndex,
+            "windowID": selection.windowID,
+            "appName": card.item.window.app.name,
+            "appPID": card.item.window.app.processIdentifier,
+            "titleHash": DevelopmentDiagnostics.stableFingerprint(card.item.window.title),
+            "titleLength": card.item.window.title.count,
+            "titleIsEmpty": card.item.window.title.isEmpty,
+            "isMinimized": card.item.window.isMinimized,
+            "isFullscreen": card.item.window.isFullscreen,
+            "identifierSource": String(describing: card.item.window.identifierSource)
+        ])
+        currentSelection = selection
+        columnSelectionHistory[selection.appGroupIndex] = selection.windowIndex
+        lastCommittedSelection = selection
+        lastCommitSource = .keyboard
+        ensureCurrentSelectionVisible()
+        onCommitSelection?(selection, .keyboard)
     }
 
     private func commitWindowCard(_ card: WaterfallCardLayers, trigger: String) {
@@ -3253,7 +3451,8 @@
                     string: waterfallMetaText(for: window),
                     fontSize: 10,
                     weight: .regular,
-                    color: .secondaryLabelColor
+                    color: .secondaryLabelColor,
+                    alignment: .right
                 )
                 let appIcon = CALayer()
                 appIcon.contentsGravity = .resizeAspect
@@ -4049,6 +4248,15 @@
             .first(where: { $0.column.appGroupIndex == appGroupIndex })?
             .cards
             .first(where: { $0.item.windowIndex == windowIndex })
+    }
+
+    private func waterfallCard(appGroupIndex: Int, windowIndexSymbol: String) -> WaterfallCardLayers? {
+        guard let ordinal = Self.appShelfIndexSymbols.firstIndex(of: windowIndexSymbol),
+              ordinal < Self.appShelfIndexSymbols.count
+        else {
+            return nil
+        }
+        return waterfallCard(appGroupIndex: appGroupIndex, windowIndex: ordinal)
     }
 
     private func waterfallCard(windowID: UInt32) -> WaterfallCardLayers? {
@@ -5606,7 +5814,26 @@
     }
 
     private func waterfallMetaText(for card: QuickSwitchWindowCardViewModel) -> String {
-        card.primarySpaceLabel ?? "No Space"
+        windowShortcutCode(for: card) ?? ""
+    }
+
+    private func windowShortcutCode(for card: QuickSwitchWindowCardViewModel) -> String? {
+        guard let appOrdinal = appShelfItems.firstIndex(where: { $0.item.appGroupIndex == card.appGroupIndex }),
+              let appSymbol = singleIndexSymbol(forOrdinal: appOrdinal),
+              let windowSymbol = singleIndexSymbol(forOrdinal: card.windowIndex)
+        else {
+            return nil
+        }
+        return "\(appSymbol)\(windowSymbol)"
+    }
+
+    private func singleIndexSymbol(forOrdinal ordinal: Int) -> String? {
+        guard ordinal >= 0,
+              ordinal < Self.appShelfIndexSymbols.count
+        else {
+            return nil
+        }
+        return Self.appShelfIndexSymbols[ordinal]
     }
 
     private func waterfallStateText(for card: QuickSwitchWindowCardViewModel) -> String {
@@ -6126,6 +6353,7 @@
                 "titleIsEmpty": card.item.window.title.isEmpty,
                 "primarySpaceID": card.item.primarySpaceID ?? NSNull(),
                 "primarySpaceLabel": card.item.primarySpaceLabel ?? NSNull(),
+                "windowShortcutCode": waterfallMetaText(for: card.item),
                 "isMinimized": card.item.window.isMinimized,
                 "isFullscreen": card.item.window.isFullscreen,
                 "identifierSource": "\(card.item.window.identifierSource)",

--
Gitblit v1.9.3