From 1fea9bfc8a7639bb3573a7cf2a449ab55065ab9e Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sat, 20 Jun 2026 13:40:07 +0800
Subject: [PATCH] Bump version to 0.1.3
---
C1.source/Sources/Aligner/QuickSwitchRootView.swift | 244 +++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 229 insertions(+), 15 deletions(-)
diff --git a/C1.source/Sources/Aligner/QuickSwitchRootView.swift b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
index 81e6310..3b0a67e 100644
--- a/C1.source/Sources/Aligner/QuickSwitchRootView.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
@@ -99,6 +99,8 @@
private var windowIndexKeyPendingClearTask: Task<Void, Never>?
private var lastWindowIndexKeyCommand: String?
private var lastWindowIndexKeyCommitCode: String?
+ private var windowShortcutFilterPhase: WindowShortcutFilterPhase = .none
+ private var lastWindowShortcutPreCommitFilterSnapshot: WindowShortcutPreCommitFilterSnapshot?
private var lastBoundaryBounceAxis: String?
private var lastBoundaryBounceDirection: String?
private var boundaryBounceCount = 0
@@ -343,6 +345,47 @@
let appSymbol: String
let appGroupIndex: Int
let startedAt: CFTimeInterval
+ }
+
+ private enum WindowShortcutFilterPhase: String {
+ case none
+ case appPending
+ case targetPreCommit
+ case invalid
+ case expired
+ }
+
+ private enum WindowShortcutFilterState: String {
+ case none
+ case matched
+ case dimmed
+ case target
+ }
+
+ private struct WindowShortcutPreCommitFilterSnapshot {
+ let targetCode: String
+ let targetWindowID: UInt32
+ let matchedWindowIDs: [UInt32]
+ let dimmedWindowIDs: [UInt32]
+
+ var reportDictionary: [String: Any] {
+ [
+ "phase": WindowShortcutFilterPhase.targetPreCommit.rawValue,
+ "targetCode": targetCode,
+ "targetWindowID": Int(targetWindowID),
+ "matchedWindowIDs": matchedWindowIDs.map(Int.init),
+ "dimmedWindowIDs": dimmedWindowIDs.map(Int.init)
+ ]
+ }
+ }
+
+ private struct WindowShortcutFilterReport {
+ let active: Bool
+ let phase: WindowShortcutFilterPhase
+ let pendingAppGroupIndex: Int?
+ let prefix: String?
+ let matchedWindowIDs: [UInt32]
+ let dimmedWindowIDs: [UInt32]
}
private struct ProjectionLayerSnapshot {
@@ -1087,6 +1130,8 @@
clearWindowIndexKeyPending()
lastWindowIndexKeyCommand = nil
lastWindowIndexKeyCommitCode = nil
+ windowShortcutFilterPhase = .none
+ lastWindowShortcutPreCommitFilterSnapshot = nil
lastBoundaryBounceAxis = nil
lastBoundaryBounceDirection = nil
boundaryBounceCount = 0
@@ -1405,6 +1450,7 @@
let firstFrameGatePassed = firstFrameP95.map { $0 < 150 } ?? false
let keyboardGatePassed = keyboardP95.map { $0 < 50 } ?? false
let hoverGatePassed = hoverP95.map { $0 <= 32 } ?? false
+ let shortcutFilterReport = makeWindowShortcutFilterReport()
return [
"viewClass": String(describing: Self.self),
@@ -1535,6 +1581,15 @@
"windowIndexKeyPendingAppSymbol": windowIndexKeyPending?.appSymbol ?? NSNull(),
"lastWindowIndexKeyCommand": lastWindowIndexKeyCommand ?? NSNull(),
"lastWindowIndexKeyCommitCode": lastWindowIndexKeyCommitCode ?? NSNull(),
+ "windowShortcutFilterActive": shortcutFilterReport.active,
+ "windowShortcutFilterPhase": shortcutFilterReport.phase.rawValue,
+ "windowShortcutFilterPendingAppGroupIndex": shortcutFilterReport.pendingAppGroupIndex ?? NSNull(),
+ "windowShortcutFilterPrefix": shortcutFilterReport.prefix ?? NSNull(),
+ "windowShortcutFilterMatchedCount": shortcutFilterReport.matchedWindowIDs.count,
+ "windowShortcutFilterDimmedCount": shortcutFilterReport.dimmedWindowIDs.count,
+ "windowShortcutFilterMatchedWindowIDs": shortcutFilterReport.matchedWindowIDs.map(Int.init),
+ "windowShortcutFilterDimmedWindowIDs": shortcutFilterReport.dimmedWindowIDs.map(Int.init),
+ "lastWindowShortcutPreCommitFilterSnapshot": lastWindowShortcutPreCommitFilterSnapshot?.reportDictionary ?? NSNull(),
"lastBoundaryBounceAxis": lastBoundaryBounceAxis ?? NSNull(),
"lastBoundaryBounceDirection": lastBoundaryBounceDirection ?? NSNull(),
"boundaryBounceCount": boundaryBounceCount,
@@ -1708,7 +1763,12 @@
recordKeyboardCommand("window:\(code)")
lastWindowIndexKeyCommand = "window:\(code)"
lastWindowIndexKeyCommitCode = code
- clearWindowIndexKeyPending()
+ lastWindowShortcutPreCommitFilterSnapshot = makeWindowShortcutPreCommitFilterSnapshot(
+ target: card,
+ code: code
+ )
+ windowShortcutFilterPhase = .targetPreCommit
+ clearWindowIndexKeyPending(resetShortcutFilter: false)
commitKeyboardWindowCard(card, trigger: "windowIndexKey")
return true
}
@@ -1716,8 +1776,10 @@
recordKeyboardCommand("windowInvalid:\(code)")
lastWindowIndexKeyCommand = "windowInvalid:\(code)"
lastWindowIndexKeyCommitCode = nil
+ windowShortcutFilterPhase = .invalid
+ lastWindowShortcutPreCommitFilterSnapshot = nil
selectionChangedByLastCommand = false
- clearWindowIndexKeyPending()
+ clearWindowIndexKeyPending(resetShortcutFilter: false)
return true
}
@@ -1728,11 +1790,21 @@
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
- )
+ let appGroupIndex = appShelfItems[ordinal].item.appGroupIndex
+ if let card = singleVisibleWaterfallCard(appGroupIndex: appGroupIndex) {
+ recordKeyboardCommand("windowSingle:\(symbol)")
+ lastWindowIndexKeyCommand = "windowSingle:\(symbol)"
+ lastWindowIndexKeyCommitCode = symbol
+ lastWindowShortcutPreCommitFilterSnapshot = nil
+ clearWindowIndexKeyPending()
+ commitKeyboardWindowCard(card, trigger: "windowIndexSingleApp")
+ } else {
+ setWindowIndexKeyPending(
+ appSymbol: symbol,
+ appGroupIndex: appGroupIndex,
+ startedAt: now
+ )
+ }
} else {
selectionChangedByLastCommand = false
clearWindowIndexKeyPending()
@@ -1783,6 +1855,9 @@
appGroupIndex: appGroupIndex,
startedAt: startedAt
)
+ windowShortcutFilterPhase = .appPending
+ lastWindowShortcutPreCommitFilterSnapshot = nil
+ needsLayout = true
windowIndexKeyPendingClearTask = Task { @MainActor [weak self] in
do {
try await Task.sleep(nanoseconds: UInt64(Self.windowIndexKeyPendingInterval * 1_000_000_000))
@@ -1799,13 +1874,26 @@
}
self.windowIndexKeyPending = nil
self.windowIndexKeyPendingClearTask = nil
+ self.windowShortcutFilterPhase = .expired
+ self.lastWindowShortcutPreCommitFilterSnapshot = nil
+ self.needsLayout = true
}
}
- private func clearWindowIndexKeyPending() {
+ private func clearWindowIndexKeyPending(resetShortcutFilter: Bool = true) {
+ let hadFilterState = windowIndexKeyPending != nil
+ || windowShortcutFilterPhase != .none
+ || lastWindowShortcutPreCommitFilterSnapshot != nil
windowIndexKeyPendingClearTask?.cancel()
windowIndexKeyPendingClearTask = nil
windowIndexKeyPending = nil
+ if resetShortcutFilter {
+ windowShortcutFilterPhase = .none
+ lastWindowShortcutPreCommitFilterSnapshot = nil
+ }
+ if hadFilterState {
+ needsLayout = true
+ }
}
@discardableResult
@@ -5451,13 +5539,15 @@
let isKeyboardFocused = card.item.window.id == keyboardFocusedWindowID
let isHorizontalAppDefaultFocused = isHorizontalAppDefaultCard(card)
let isAppLinked = isWaterfallCardAppLinked(card)
+ let shortcutFilterState = windowShortcutFilterState(for: card)
applyWaterfallCardVisualState(
card,
selected: shouldShowSelectedVisual(isSelected: isSelected, isHovered: isHovered)
|| isKeyboardFocused
|| isHorizontalAppDefaultFocused,
hovered: isHovered,
- appLinked: isAppLinked
+ appLinked: isAppLinked,
+ shortcutFilterState: shortcutFilterState
)
let outerInset: CGFloat = 0
@@ -5512,7 +5602,7 @@
windowIndex: card.item.windowIndex,
windowID: card.item.window.id
),
- visible: isHovered,
+ visible: isHovered && shortcutFilterState != .dimmed,
anchorTopRight: CGPoint(x: bounds.maxX - 12, y: bounds.maxY - 12)
)
card.shineLayer.frame = CGRect(
@@ -5532,9 +5622,11 @@
_ card: WaterfallCardLayers,
selected: Bool,
hovered: Bool,
- appLinked: Bool
+ appLinked: Bool,
+ shortcutFilterState: WindowShortcutFilterState
) {
let isSpaceFocused = isWaterfallCardSpaceFocused(card)
+ let isShortcutDimmed = shortcutFilterState == .dimmed
card.containerLayer.backgroundColor = (selected
? themePalette.cardSelectedBackground
: hovered
@@ -5545,6 +5637,7 @@
? accentTintedWindowBackground(fraction: 0.10, alpha: 0.94)
: themePalette.cardBackground
).cgColor
+ card.containerLayer.opacity = isShortcutDimmed ? windowShortcutFilterDimOpacity : 1
card.containerLayer.borderColor = (selected
? NSColor.controlAccentColor.withAlphaComponent(0.52)
: hovered
@@ -5558,7 +5651,7 @@
card.containerLayer.borderWidth = (selected || hovered || appLinked || isSpaceFocused) ? 1.5 : 1
card.containerLayer.shadowColor = NSColor.black.cgColor
let darkShadowBoost: Float = resolvedTheme == .dark ? 0.08 : 0
- card.containerLayer.shadowOpacity = selected
+ let baseShadowOpacity: Float = selected
? 0.24 + darkShadowBoost
: hovered
? 0.14 + darkShadowBoost
@@ -5567,6 +5660,7 @@
: isSpaceFocused
? 0.20 + darkShadowBoost
: 0
+ card.containerLayer.shadowOpacity = isShortcutDimmed ? min(baseShadowOpacity, 0.03) : baseShadowOpacity
card.containerLayer.shadowRadius = selected ? 22 : hovered ? 17 : appLinked ? 18 : isSpaceFocused ? 24 : 0
card.containerLayer.shadowOffset = selected
? CGSize(width: 0, height: -6)
@@ -5579,10 +5673,10 @@
: .zero
card.containerLayer.zPosition = selected ? 20 : hovered ? 12 : appLinked ? 10 : isSpaceFocused ? 8 : 0
let focusedScale: CGFloat = selected ? WaterfallMetrics.selectedCardScale : isSpaceFocused ? 1.012 : 1.008
- card.containerLayer.transform = (selected || hovered || isSpaceFocused)
+ card.containerLayer.transform = (!isShortcutDimmed && (selected || hovered || isSpaceFocused))
? CATransform3DMakeScale(focusedScale, focusedScale, 1)
: CATransform3DIdentity
- card.containerLayer.shadowPath = (selected || hovered || appLinked || isSpaceFocused)
+ card.containerLayer.shadowPath = (!isShortcutDimmed && (selected || hovered || appLinked || isSpaceFocused))
? CGPath(
roundedRect: card.containerLayer.bounds,
cornerWidth: card.containerLayer.cornerRadius,
@@ -5598,7 +5692,7 @@
).cgColor
card.titleBarLayer.borderColor = NSColor.clear.cgColor
card.titleBarLayer.borderWidth = 0
- card.shineLayer.opacity = selected ? 1 : 0
+ card.shineLayer.opacity = (!isShortcutDimmed && selected) ? 1 : 0
}
private func layoutCloseButton(
@@ -6338,6 +6432,110 @@
return Self.appShelfIndexSymbols[ordinal]
}
+ private var visibleWaterfallCards: [WaterfallCardLayers] {
+ waterfallColumns.flatMap(\.cards)
+ }
+
+ private func singleVisibleWaterfallCard(appGroupIndex: Int) -> WaterfallCardLayers? {
+ let cards = visibleWaterfallCards.filter { $0.item.appGroupIndex == appGroupIndex }
+ return cards.count == 1 ? cards[0] : nil
+ }
+
+ private var windowShortcutFilterDimOpacity: Float {
+ resolvedTheme == .dark ? 0.44 : 0.38
+ }
+
+ private func windowShortcutFilterState(for card: WaterfallCardLayers) -> WindowShortcutFilterState {
+ switch windowShortcutFilterPhase {
+ case .appPending:
+ guard let pending = windowIndexKeyPending else { return .none }
+ return card.item.appGroupIndex == pending.appGroupIndex ? .matched : .dimmed
+ case .targetPreCommit:
+ guard let snapshot = lastWindowShortcutPreCommitFilterSnapshot else { return .none }
+ if card.item.window.id == snapshot.targetWindowID {
+ return .target
+ }
+ if snapshot.dimmedWindowIDs.contains(card.item.window.id) {
+ return .dimmed
+ }
+ if snapshot.matchedWindowIDs.contains(card.item.window.id) {
+ return .matched
+ }
+ return .none
+ case .none, .invalid, .expired:
+ return .none
+ }
+ }
+
+ private func makeWindowShortcutPreCommitFilterSnapshot(
+ target card: WaterfallCardLayers,
+ code: String
+ ) -> WindowShortcutPreCommitFilterSnapshot {
+ let targetWindowID = card.item.window.id
+ let allWindowIDs = visibleWaterfallCards.map { $0.item.window.id }
+ return WindowShortcutPreCommitFilterSnapshot(
+ targetCode: code,
+ targetWindowID: targetWindowID,
+ matchedWindowIDs: [targetWindowID],
+ dimmedWindowIDs: allWindowIDs.filter { $0 != targetWindowID }.sorted()
+ )
+ }
+
+ private func makeWindowShortcutFilterReport() -> WindowShortcutFilterReport {
+ switch windowShortcutFilterPhase {
+ case .appPending:
+ guard let pending = windowIndexKeyPending else {
+ return emptyWindowShortcutFilterReport(phase: .none)
+ }
+ let cards = visibleWaterfallCards
+ let matched = cards
+ .filter { $0.item.appGroupIndex == pending.appGroupIndex }
+ .map { $0.item.window.id }
+ .sorted()
+ let dimmed = cards
+ .filter { $0.item.appGroupIndex != pending.appGroupIndex }
+ .map { $0.item.window.id }
+ .sorted()
+ return WindowShortcutFilterReport(
+ active: true,
+ phase: .appPending,
+ pendingAppGroupIndex: pending.appGroupIndex,
+ prefix: pending.appSymbol,
+ matchedWindowIDs: matched,
+ dimmedWindowIDs: dimmed
+ )
+ case .targetPreCommit:
+ guard let snapshot = lastWindowShortcutPreCommitFilterSnapshot else {
+ return emptyWindowShortcutFilterReport(phase: .none)
+ }
+ return WindowShortcutFilterReport(
+ active: true,
+ phase: .targetPreCommit,
+ pendingAppGroupIndex: nil,
+ prefix: snapshot.targetCode,
+ matchedWindowIDs: snapshot.matchedWindowIDs,
+ dimmedWindowIDs: snapshot.dimmedWindowIDs
+ )
+ case .invalid, .expired:
+ return emptyWindowShortcutFilterReport(phase: windowShortcutFilterPhase)
+ case .none:
+ return emptyWindowShortcutFilterReport(phase: .none)
+ }
+ }
+
+ private func emptyWindowShortcutFilterReport(
+ phase: WindowShortcutFilterPhase
+ ) -> WindowShortcutFilterReport {
+ WindowShortcutFilterReport(
+ active: false,
+ phase: phase,
+ pendingAppGroupIndex: nil,
+ prefix: nil,
+ matchedWindowIDs: [],
+ dimmedWindowIDs: []
+ )
+ }
+
private func waterfallStateText(for card: QuickSwitchWindowCardViewModel) -> String {
var states: [String] = []
if card.window.isMinimized {
@@ -6844,6 +7042,10 @@
dy: column.containerLayer.frame.minY + column.cardsClipLayer.frame.minY
)
let screenshotSource = screenshotSourcesByWindowID[card.item.window.id]
+ let shortcutFilterState = windowShortcutFilterState(for: card)
+ let shortcutFilterOpacity = shortcutFilterState == .dimmed
+ ? windowShortcutFilterDimOpacity
+ : Float(1)
var report = [
"appGroupIndex": card.item.appGroupIndex,
@@ -6862,6 +7064,8 @@
"isSelected": card.item.window.id == effectiveSelection?.windowID,
"isKeyboardFocused": card.item.window.id == keyboardFocusedWindowID,
"isHorizontalAppDefault": isHorizontalAppDefaultCard(card),
+ "windowShortcutFilterState": shortcutFilterState.rawValue,
+ "windowShortcutFilterOpacity": Double(shortcutFilterOpacity),
"visualStates": waterfallCardVisualStates(for: card),
"thumbnailStrategy": thumbnailStrategyString(for: card.item.window),
"screenshotSource": screenshotSourceString(screenshotSource, for: card.item.window),
@@ -7006,6 +7210,16 @@
if isWaterfallCardSpaceFocused(card) {
states.append("spaceFocused")
}
+ switch windowShortcutFilterState(for: card) {
+ case .matched:
+ states.append("shortcutMatched")
+ case .dimmed:
+ states.append("shortcutDimmed")
+ case .target:
+ states.append("shortcutTarget")
+ case .none:
+ break
+ }
if card.item.window.isMinimized {
states.append("minimized")
}
--
Gitblit v1.9.3