From ecba8206e4c8cac76dd3e6f8844204abfda03dfd Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Thu, 04 Jun 2026 17:24:20 +0800
Subject: [PATCH] make quick switch overlay full bleed

---
 C3.tools/round1-session-snapshot-qa.sh              |   18 +++++++++
 C1.source/Sources/Aligner/QuickSwitchRootView.swift |   57 ++++++++++++++++++++--------
 C1.source/Resources/Aligner-Info.plist              |    4 +-
 3 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/C1.source/Resources/Aligner-Info.plist b/C1.source/Resources/Aligner-Info.plist
index 5fe5dd4..be79823 100644
--- a/C1.source/Resources/Aligner-Info.plist
+++ b/C1.source/Resources/Aligner-Info.plist
@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-	<string>0.0.22</string>
+	<string>0.0.23</string>
 	<key>CFBundleVersion</key>
-	<string>20260604.1515</string>
+	<string>20260604.1723</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>26.0</string>
 	<key>NSHighResolutionCapable</key>
diff --git a/C1.source/Sources/Aligner/QuickSwitchRootView.swift b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
index 4e3051e..41973d4 100644
--- a/C1.source/Sources/Aligner/QuickSwitchRootView.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
@@ -10,6 +10,7 @@
 @MainActor
 final class QuickSwitchRootView: NSView {
     private let backgroundLayer = CAGradientLayer()
+    private let safeAreaFillLayer = CALayer()
     private let glassLayer = CALayer()
     private let laneLayer = CALayer()
     private let spaceLaneContentLayer = CALayer()
@@ -116,6 +117,14 @@
         static let normalGap: CGFloat = 16
         static let minGap: CGFloat = 8
         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 {
@@ -443,7 +452,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),
@@ -1174,14 +1188,14 @@
         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
@@ -1459,33 +1473,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()
@@ -1495,6 +1516,10 @@
         CATransaction.commit()
     }
 
+    private var topSafeAreaInset: CGFloat {
+        max(0, window?.screen?.safeAreaInsets.top ?? safeAreaInsets.top)
+    }
+
     private func appShelfLayout(for availableWidth: CGFloat) -> AppShelfLayout {
         let itemCount = appShelfItems.count
         guard itemCount > 0 else {
diff --git a/C3.tools/round1-session-snapshot-qa.sh b/C3.tools/round1-session-snapshot-qa.sh
index d45033c..23be5db 100755
--- a/C3.tools/round1-session-snapshot-qa.sh
+++ b/C3.tools/round1-session-snapshot-qa.sh
@@ -55,6 +55,9 @@
         print(json.dumps(report, indent=2, ensure_ascii=False), file=sys.stderr)
         sys.exit(1)
 
+def near(lhs, rhs, tolerance=0.01):
+    return abs((lhs or 0) - (rhs or 0)) <= tolerance
+
 require(report.get("snapshotLoaded") is True, "snapshotLoaded must be true")
 require(report.get("displayCount", 0) >= 1, "displayCount must be >= 1")
 require(report.get("spaceCount", 0) >= 1, "spaceCount must be >= 1")
@@ -70,9 +73,24 @@
 space_labels = report.get("spaceLabels", [])
 lane_labels = root_view.get("spaceLaneLabels", [])
 lane_segments = root_view.get("spaceLaneSegments", [])
+root_bounds = root_view.get("bounds", {})
+glass_frame = root_view.get("glassFrame", {})
+safe_area_top_inset = root_view.get("safeAreaTopInset", 0)
+safe_area_fill_frame = root_view.get("safeAreaFillFrame", {})
 lane_frame = root_view.get("spaceLaneFrame", {})
 shelf_frame = root_view.get("appShelfFrame", {})
 waterfall_frame = root_view.get("waterfallFrame", {})
+require(near(glass_frame.get("x"), root_bounds.get("x")), "Quick Switch glass layer x must match root bounds")
+require(near(glass_frame.get("y"), root_bounds.get("y")), "Quick Switch glass layer y must match root bounds")
+require(near(glass_frame.get("width"), root_bounds.get("width")), "Quick Switch glass layer width must match root bounds")
+require(near(glass_frame.get("height"), root_bounds.get("height")), "Quick Switch glass layer height must match root bounds")
+require(root_view.get("glassCornerRadius") == 0, "Quick Switch glass layer must not draw an outer rounded frame")
+require(root_view.get("glassBorderWidth") == 0, "Quick Switch glass layer must not draw an outer border")
+require(root_view.get("glassShadowOpacity") == 0, "Quick Switch glass layer must not draw an outer shadow")
+require(safe_area_top_inset >= 0, "safeAreaTopInset must be non-negative")
+if safe_area_top_inset > 0.5:
+    require(near(safe_area_fill_frame.get("height"), safe_area_top_inset), "safe-area fill height must match safeAreaTopInset")
+    require(near(safe_area_fill_frame.get("y") + safe_area_fill_frame.get("height"), root_bounds.get("height")), "safe-area fill must sit at the top edge")
 require(root_view.get("spaceLaneSegmentCount") == report.get("spaceCount"), "Space Lane segment count must match spaceCount")
 require(lane_labels == space_labels, "Space Lane labels must match report spaceLabels exactly")
 require(len(set(lane_labels)) == len(lane_labels), "Space Lane labels must be unique")

--
Gitblit v1.9.3