From 7a4f911c64b552081d957e826f32d90b2b11c858 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 04 Jun 2026 19:38:13 +0800
Subject: [PATCH] Make quick switch clicks activate targets

---
 C1.source/Sources/Aligner/QuickSwitchRootView.swift |  140 +++++++++++++++++++++++++++++++++++++---------
 1 files changed, 112 insertions(+), 28 deletions(-)

diff --git a/C1.source/Sources/Aligner/QuickSwitchRootView.swift b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
index 4e3051e..046f96a 100644
--- a/C1.source/Sources/Aligner/QuickSwitchRootView.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
@@ -9,7 +9,10 @@
 
 @MainActor
 final class QuickSwitchRootView: NSView {
+    private let backdropBlurView = NSVisualEffectView()
+    private let layerHostView = NSView()
     private let backgroundLayer = CAGradientLayer()
+    private let safeAreaFillLayer = CALayer()
     private let glassLayer = CALayer()
     private let laneLayer = CALayer()
     private let spaceLaneContentLayer = CALayer()
@@ -118,6 +121,14 @@
         static let maxRows = 2
     }
 
+    private enum RootLayoutMetrics {
+        static let horizontalMargin: CGFloat = 24
+        static let topContentMargin: CGFloat = 24
+        static let shelfGap: CGFloat = 16
+        static let waterfallTopGap: CGFloat = 14
+        static let bottomMargin: CGFloat = 34
+    }
+
     private enum WaterfallMetrics {
         static let gap: CGFloat = 16
         static let columnWidth: CGFloat = 252
@@ -143,12 +154,16 @@
 
     override init(frame frameRect: NSRect) {
         super.init(frame: frameRect)
+        setupBackdropBlurView()
+        setupLayerHostView()
         wantsLayer = true
         setupLayers()
     }
 
     required init?(coder: NSCoder) {
         super.init(coder: coder)
+        setupBackdropBlurView()
+        setupLayerHostView()
         wantsLayer = true
         setupLayers()
     }
@@ -176,6 +191,8 @@
 
     override func layout() {
         super.layout()
+        backdropBlurView.frame = bounds
+        layerHostView.frame = bounds
         layoutLayers()
     }
 
@@ -342,6 +359,9 @@
             if isHoverCommand(command) {
                 hoverResponseLatencyMilliseconds.append(elapsed)
             }
+            if lastCommitSource == .mouse {
+                break
+            }
         }
     }
 
@@ -443,7 +463,12 @@
             "viewClass": String(describing: Self.self),
             "isLayerBacked": wantsLayer,
             "bounds": dictionary(from: bounds),
+            "safeAreaTopInset": Double(topSafeAreaInset),
+            "safeAreaFillFrame": dictionary(from: safeAreaFillLayer.frame),
             "glassFrame": dictionary(from: glassLayer.frame),
+            "glassCornerRadius": Double(glassLayer.cornerRadius),
+            "glassBorderWidth": Double(glassLayer.borderWidth),
+            "glassShadowOpacity": Double(glassLayer.shadowOpacity),
             "spaceLaneFrame": dictionary(from: laneLayer.frame),
             "spaceLaneContentWidth": Double(spaceLaneContentWidth),
             "spaceLaneVisibleWidth": Double(laneLayer.bounds.width),
@@ -701,7 +726,17 @@
             "spaceID": segment.space.id,
             "label": segment.space.label
         ])
-        focusSpace(segment.space.id, persistent: true)
+        lastSpaceLaneClickSpaceID = segment.space.id
+
+        guard let firstCard = firstWaterfallCard(inSpaceID: segment.space.id) else {
+            DevelopmentDiagnostics.log("quickSwitch.view.clickSpaceLane.emptySpaceUnsupported", [
+                "spaceID": segment.space.id,
+                "label": segment.space.label
+            ])
+            return
+        }
+
+        commitWindowCard(firstCard, trigger: "spaceLane")
     }
 
     private func focusSpace(_ spaceID: UInt64, persistent: Bool) {
@@ -752,12 +787,14 @@
             columnSelectionHistory[nextSelection.appGroupIndex] = nextSelection.windowIndex
             lastAppShelfClickChangedSelection = previousSelection != nextSelection
             ensureWaterfallSelectionVisible(nextSelection, horizontalIntent: .alignWithAppShelf(animated: true))
+            updateHoverState(appGroupIndex: appGroupIndex, windowID: nil, spaceID: nil)
+            commitWindowCard(firstCard, trigger: "appShelf")
         } else {
             lastAppShelfClickChangedSelection = false
             ensureWaterfallColumnVisible(column)
+            updateHoverState(appGroupIndex: appGroupIndex, windowID: nil, spaceID: nil)
+            needsLayout = true
         }
-        updateHoverState(appGroupIndex: appGroupIndex, windowID: nil, spaceID: nil)
-        needsLayout = true
     }
 
     private func scrollAppShelf(to targetOffset: CGFloat) {
@@ -799,12 +836,17 @@
 
     private func clickWindowCard(_ card: WaterfallCardLayers) {
         hoverWindowCard(card)
+        commitWindowCard(card, trigger: "windowCard")
+    }
+
+    private func commitWindowCard(_ card: WaterfallCardLayers, trigger: String) {
         let selection = QuickSwitchSelection(
             appGroupIndex: card.item.appGroupIndex,
             windowIndex: card.item.windowIndex,
             windowID: card.item.window.id
         )
-        DevelopmentDiagnostics.log("quickSwitch.view.clickWindowCard", [
+        DevelopmentDiagnostics.log("quickSwitch.view.commitMouseWindow", [
+            "trigger": trigger,
             "appGroupIndex": selection.appGroupIndex,
             "windowIndex": selection.windowIndex,
             "windowID": selection.windowID,
@@ -1162,35 +1204,54 @@
         value ?? NSNull()
     }
 
+    private func setupBackdropBlurView() {
+        backdropBlurView.material = .fullScreenUI
+        backdropBlurView.blendingMode = .behindWindow
+        backdropBlurView.state = .active
+        backdropBlurView.isEmphasized = false
+        backdropBlurView.frame = bounds
+        backdropBlurView.autoresizingMask = [.width, .height]
+        addSubview(backdropBlurView, positioned: .below, relativeTo: nil)
+    }
+
+    private func setupLayerHostView() {
+        layerHostView.wantsLayer = true
+        layerHostView.frame = bounds
+        layerHostView.autoresizingMask = [.width, .height]
+        layerHostView.layer?.masksToBounds = true
+        layerHostView.layer?.backgroundColor = NSColor.clear.cgColor
+        addSubview(layerHostView, positioned: .above, relativeTo: backdropBlurView)
+    }
+
     private func setupLayers() {
-        guard let rootLayer = layer else { return }
+        guard let rootLayer = layerHostView.layer else { return }
 
         rootLayer.masksToBounds = true
         backgroundLayer.colors = [
-            NSColor.windowBackgroundColor.withAlphaComponent(0.72).cgColor,
-            NSColor.controlBackgroundColor.withAlphaComponent(0.62).cgColor
+            NSColor.windowBackgroundColor.withAlphaComponent(0.58).cgColor,
+            NSColor.controlBackgroundColor.withAlphaComponent(0.48).cgColor
         ]
         backgroundLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
         backgroundLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
         rootLayer.addSublayer(backgroundLayer)
 
-        glassLayer.cornerRadius = 24
-        glassLayer.backgroundColor = NSColor.windowBackgroundColor.withAlphaComponent(0.72).cgColor
-        glassLayer.borderColor = NSColor.separatorColor.withAlphaComponent(0.35).cgColor
-        glassLayer.borderWidth = 1
-        glassLayer.shadowColor = NSColor.black.cgColor
-        glassLayer.shadowOpacity = 0.16
-        glassLayer.shadowRadius = 24
-        glassLayer.shadowOffset = CGSize(width: 0, height: -8)
+        safeAreaFillLayer.backgroundColor = NSColor.black.cgColor
+        rootLayer.addSublayer(safeAreaFillLayer)
+
+        glassLayer.cornerRadius = 0
+        glassLayer.backgroundColor = NSColor.clear.cgColor
+        glassLayer.borderColor = NSColor.clear.cgColor
+        glassLayer.borderWidth = 0
+        glassLayer.shadowOpacity = 0
         rootLayer.addSublayer(glassLayer)
 
-        laneLayer.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.50).cgColor
+        laneLayer.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.68).cgColor
         laneLayer.cornerRadius = 16
         laneLayer.masksToBounds = true
         glassLayer.addSublayer(laneLayer)
         laneLayer.addSublayer(spaceLaneContentLayer)
 
-        shelfLayer.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.42).cgColor
+        shelfLayer.backgroundColor = NSColor.clear.cgColor
         shelfLayer.cornerRadius = 16
         shelfLayer.masksToBounds = true
         glassLayer.addSublayer(shelfLayer)
@@ -1282,12 +1343,12 @@
             container.name = column.app.name
             container.cornerRadius = 14
             container.masksToBounds = true
-            container.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.34).cgColor
-            container.borderColor = NSColor.separatorColor.withAlphaComponent(0.28).cgColor
+            container.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.56).cgColor
+            container.borderColor = NSColor.separatorColor.withAlphaComponent(0.34).cgColor
             container.borderWidth = 1
 
             let header = CALayer()
-            header.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.58).cgColor
+            header.backgroundColor = NSColor.controlBackgroundColor.withAlphaComponent(0.68).cgColor
 
             let appName = makeTextLayer(
                 string: column.app.name,
@@ -1459,33 +1520,40 @@
 
         backgroundLayer.frame = bounds
 
-        let horizontalInset = max(36, bounds.width * 0.045)
-        let topInset = max(36, bounds.height * 0.055)
-        glassLayer.frame = bounds.insetBy(dx: horizontalInset, dy: topInset)
+        let safeAreaTopInset = topSafeAreaInset
+        safeAreaFillLayer.frame = CGRect(
+            x: 0,
+            y: max(0, bounds.height - safeAreaTopInset),
+            width: bounds.width,
+            height: safeAreaTopInset
+        )
+        safeAreaFillLayer.isHidden = safeAreaTopInset <= 0.5
+        glassLayer.frame = bounds
 
         let contentBounds = glassLayer.bounds
-        let horizontalMargin: CGFloat = 22
+        let horizontalMargin = RootLayoutMetrics.horizontalMargin
+        let topMargin = safeAreaTopInset + RootLayoutMetrics.topContentMargin
         let laneHeight = min(104, max(82, contentBounds.height * 0.12))
         let availableContentWidth = contentBounds.width - horizontalMargin * 2
         appShelfLayout = appShelfLayout(for: availableContentWidth)
         let shelfHeight = appShelfHeight(forRows: appShelfLayout.rows)
         laneLayer.frame = CGRect(
             x: horizontalMargin,
-            y: contentBounds.height - horizontalMargin - laneHeight,
+            y: contentBounds.height - topMargin - laneHeight,
             width: availableContentWidth,
             height: laneHeight
         )
         shelfLayer.frame = CGRect(
             x: horizontalMargin,
-            y: laneLayer.frame.minY - 16 - shelfHeight,
+            y: laneLayer.frame.minY - RootLayoutMetrics.shelfGap - shelfHeight,
             width: laneLayer.frame.width,
             height: shelfHeight
         )
         waterfallLayer.frame = CGRect(
             x: shelfLayer.frame.minX,
-            y: 34,
+            y: RootLayoutMetrics.bottomMargin,
             width: shelfLayer.frame.width,
-            height: shelfLayer.frame.minY - 48
+            height: max(1, shelfLayer.frame.minY - RootLayoutMetrics.bottomMargin - RootLayoutMetrics.waterfallTopGap)
         )
 
         layoutSpaceLaneSegments()
@@ -1493,6 +1561,10 @@
         layoutWaterfallColumns()
 
         CATransaction.commit()
+    }
+
+    private var topSafeAreaInset: CGFloat {
+        max(0, window?.screen?.safeAreaInsets.top ?? safeAreaInsets.top)
     }
 
     private func appShelfLayout(for availableWidth: CGFloat) -> AppShelfLayout {
@@ -1882,6 +1954,18 @@
             .sorted()
     }
 
+    private func firstWaterfallCard(inSpaceID spaceID: UInt64) -> WaterfallCardLayers? {
+        for column in waterfallColumns.sorted(by: { $0.column.appGroupIndex < $1.column.appGroupIndex }) {
+            if let card = column.cards
+                .sorted(by: { $0.item.windowIndex < $1.item.windowIndex })
+                .first(where: { $0.item.primarySpaceID == spaceID }) {
+                return card
+            }
+        }
+
+        return nil
+    }
+
     private func spaceFocusWindowCount(for appGroupIndex: Int) -> Int {
         guard let activeSpaceFocusID else { return 0 }
 

--
Gitblit v1.9.3