From 2182f72105033db025bb29e08319586112e53c5f Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Wed, 10 Jun 2026 19:37:25 +0800
Subject: [PATCH] Fix empty Space lane fill
---
C1.source/Sources/Aligner/QuickSwitchRootView.swift | 137 +++++++++++++++++++++++++++++++++++----------
1 files changed, 107 insertions(+), 30 deletions(-)
diff --git a/C1.source/Sources/Aligner/QuickSwitchRootView.swift b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
index 0b41426..0d3590c 100644
--- a/C1.source/Sources/Aligner/QuickSwitchRootView.swift
+++ b/C1.source/Sources/Aligner/QuickSwitchRootView.swift
@@ -722,7 +722,8 @@
"waterfallMaxScrollOffset": Double(waterfallMaxScrollOffset),
"waterfallAlignmentMinScrollOffset": Double(waterfallAlignmentScrollRange.lowerBound),
"waterfallAlignmentMaxScrollOffset": Double(waterfallAlignmentScrollRange.upperBound),
- "waterfallScrollable": waterfallAlignmentScrollable,
+ "waterfallScrollable": waterfallMaxScrollOffset > 0,
+ "waterfallAlignmentScrollable": waterfallAlignmentScrollable,
"waterfallColumnCount": waterfallColumns.count,
"waterfallColumnNames": waterfallColumns.map(\.column.app.name),
"waterfallClipsToBounds": waterfallLayer.masksToBounds,
@@ -1835,12 +1836,14 @@
groupContainer.shadowOffset = .zero
let segments = display.spaces.map { space in
- let container = CALayer()
+ let container = CAGradientLayer()
container.name = space.label
container.cornerRadius = 10
container.borderWidth = 1
container.borderColor = NSColor.separatorColor.withAlphaComponent(0.34).cgColor
- container.backgroundColor = spaceColor(for: space).cgColor
+ container.backgroundColor = NSColor.clear.cgColor
+ container.startPoint = CGPoint(x: 0.5, y: 1.0)
+ container.endPoint = CGPoint(x: 0.5, y: 0.0)
container.shadowColor = NSColor.black.cgColor
let labelLayer = makeTextLayer(
@@ -2148,28 +2151,46 @@
? NSColor.labelColor.withAlphaComponent(0.34)
: NSColor.separatorColor.withAlphaComponent(0.34)
).cgColor
- segment.containerLayer.backgroundColor = (isActive
- ? accentTintedWindowBackground(fraction: 0.10, alpha: 0.94)
- : isAssociated
- ? accentTintedWindowBackground(fraction: 0.07, alpha: 0.90)
- : spaceColor(for: segment.space)
- ).cgColor
- segment.containerLayer.shadowOpacity = isActive ? 0.26 : isAssociated ? 0.18 : isCurrent ? 0.14 : 0
- segment.containerLayer.shadowRadius = isActive ? 24 : isAssociated ? 18 : isCurrent ? 12 : 0
+ if !hasWindows {
+ applySpaceLaneSolidFill(to: segment.containerLayer, color: .clear)
+ } else if isActive {
+ applySpaceLaneSolidFill(
+ to: segment.containerLayer,
+ color: accentTintedWindowBackground(fraction: 0.10, alpha: 0.94)
+ )
+ } else if isAssociated {
+ applySpaceLaneSolidFill(
+ to: segment.containerLayer,
+ color: accentTintedWindowBackground(fraction: 0.07, alpha: 0.90)
+ )
+ } else if hasWindows {
+ applySpaceLaneGradientFill(
+ to: segment.containerLayer,
+ colors: spaceLaneIdleOccupiedGradientColors()
+ )
+ }
+ segment.containerLayer.shadowOpacity = hasWindows
+ ? (isActive ? 0.26 : isAssociated ? 0.18 : isCurrent ? 0.14 : 0)
+ : 0
+ segment.containerLayer.shadowRadius = hasWindows
+ ? (isActive ? 24 : isAssociated ? 18 : isCurrent ? 12 : 0)
+ : 0
segment.containerLayer.shadowOffset = CGSize(
width: 0,
- height: isActive ? -6 : isAssociated ? -4 : isCurrent ? -2.5 : 0
+ height: hasWindows ? (isActive ? -6 : isAssociated ? -4 : isCurrent ? -2.5 : 0) : 0
)
segment.containerLayer.zPosition = isActive ? 30 : isAssociated ? 18 : isCurrent ? 10 : 0
segment.containerLayer.transform = (isActive || isAssociated)
? CATransform3DMakeScale(isActive ? 1.03 : 1.015, isActive ? 1.03 : 1.015, 1)
: CATransform3DIdentity
- segment.containerLayer.shadowPath = CGPath(
- roundedRect: segment.containerLayer.bounds,
- cornerWidth: segment.containerLayer.cornerRadius,
- cornerHeight: segment.containerLayer.cornerRadius,
- transform: nil
- )
+ segment.containerLayer.shadowPath = hasWindows
+ ? CGPath(
+ roundedRect: segment.containerLayer.bounds,
+ cornerWidth: segment.containerLayer.cornerRadius,
+ cornerHeight: segment.containerLayer.cornerRadius,
+ transform: nil
+ )
+ : nil
}
private func shouldScrollSpaceLane(for event: NSEvent) -> Bool {
@@ -3440,20 +3461,43 @@
return states.joined(separator: " / ")
}
- private func spaceColor(for space: QuickSwitchSpaceViewModel) -> NSColor {
- if space.windowCount > 0 {
- return NSColor.controlBackgroundColor.withAlphaComponent(0.36)
- }
-
- return NSColor.clear
- }
-
private var spaceLaneOccupiedColor: NSColor {
if effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua {
return NSColor(calibratedRed: 10 / 255, green: 132 / 255, blue: 1, alpha: 1)
}
return NSColor(calibratedRed: 0, green: 122 / 255, blue: 1, alpha: 1)
+ }
+
+ private func spaceLaneIdleOccupiedGradientColors() -> [NSColor] {
+ if effectiveAppearance.bestMatch(from: [.darkAqua, .aqua]) == .darkAqua {
+ let blue = NSColor(calibratedRed: 36 / 255, green: 54 / 255, blue: 72 / 255, alpha: 1)
+ let surface = NSColor.windowBackgroundColor.withAlphaComponent(1)
+ return [blue, surface]
+ }
+
+ return [
+ NSColor(calibratedRed: 232 / 255, green: 246 / 255, blue: 1, alpha: 1),
+ NSColor.white
+ ]
+ }
+
+ private func applySpaceLaneGradientFill(to layer: CALayer, colors: [NSColor]) {
+ if let gradientLayer = layer as? CAGradientLayer {
+ gradientLayer.colors = colors.map(\.cgColor)
+ gradientLayer.locations = [0, 1]
+ gradientLayer.startPoint = CGPoint(x: 0.5, y: 1.0)
+ gradientLayer.endPoint = CGPoint(x: 0.5, y: 0.0)
+ }
+ layer.backgroundColor = NSColor.clear.cgColor
+ }
+
+ private func applySpaceLaneSolidFill(to layer: CALayer, color: NSColor) {
+ if let gradientLayer = layer as? CAGradientLayer {
+ gradientLayer.colors = nil
+ gradientLayer.locations = nil
+ }
+ layer.backgroundColor = color.cgColor
}
private func makeFullscreenMarkerLayer(for space: QuickSwitchSpaceViewModel) -> CALayer? {
@@ -3675,11 +3719,18 @@
}
private func fullscreenMarkerFrame(in segmentBounds: CGRect) -> CGRect {
- CGRect(
+ let topReserved: CGFloat = 32
+ let bottomReserved: CGFloat = 16
+ let availableHeight = max(20, segmentBounds.height - topReserved - bottomReserved)
+ let markerHeight = min(30, max(20, availableHeight))
+ let markerCenterY = bottomReserved + availableHeight * 0.5
+ let markerY = max(8, min(segmentBounds.height - topReserved - markerHeight, markerCenterY - markerHeight * 0.5))
+
+ return CGRect(
x: 10,
- y: 30,
+ y: markerY,
width: max(1, segmentBounds.width - 20),
- height: max(1, segmentBounds.height - 58)
+ height: markerHeight
)
}
@@ -4049,6 +4100,10 @@
dx: (group?.containerLayer.frame.minX ?? 0) + spaceLaneContentLayer.frame.minX,
dy: group?.containerLayer.frame.minY ?? 0
)
+ let fullscreenMarkerFrame = segment.fullscreenMarkerLayer?.frame
+ let fullscreenMarkerCenterRatio = fullscreenMarkerFrame.map {
+ Double($0.midY / max(1, segment.containerLayer.bounds.height))
+ }
return [
"displayUUID": display.displayUUID,
"displayLabel": display.displayLabel,
@@ -4058,11 +4113,14 @@
"visualStates": visualStates(for: space),
"fullscreenMarkerVisible": segment.fullscreenMarkerLayer != nil,
"fullscreenMarkerKind": segment.fullscreenMarkerLayer == nil ? "none" : "cornerBracket",
- "fullscreenMarkerFrame": segment.fullscreenMarkerLayer.map { dictionary(from: $0.frame) } ?? NSNull(),
+ "fullscreenMarkerFrame": fullscreenMarkerFrame.map { dictionary(from: $0) } ?? NSNull(),
+ "fullscreenMarkerCenterRatio": fullscreenMarkerCenterRatio ?? NSNull(),
"windowBlockCount": segment.windowBlocks.count,
"windowBlockColors": segment.windowBlocks.map { colorDictionary(from: $0.backgroundColor) },
"windowBlockFrames": segment.windowBlocks.map { dictionary(from: $0.frame) },
+ "backgroundKind": spaceLaneFillKind(for: segment.containerLayer),
"backgroundColor": colorDictionary(from: segment.containerLayer.backgroundColor),
+ "gradientColors": gradientColorDictionaries(from: segment.containerLayer),
"borderColor": colorDictionary(from: segment.containerLayer.borderColor),
"borderWidth": Double(segment.containerLayer.borderWidth),
"shadowOpacity": Double(segment.containerLayer.shadowOpacity),
@@ -4153,4 +4211,23 @@
"alpha": Double(nsColor.alphaComponent)
]
}
+
+ private func gradientColorDictionaries(from layer: CALayer) -> [[String: Double]] {
+ guard let gradientLayer = layer as? CAGradientLayer else { return [] }
+ return (gradientLayer.colors ?? []).map { color in
+ let cgColor = color as! CGColor
+ return colorDictionary(from: cgColor)
+ }
+ }
+
+ private func spaceLaneFillKind(for layer: CALayer) -> String {
+ if !gradientColorDictionaries(from: layer).isEmpty {
+ return "gradient"
+ }
+ let background = colorDictionary(from: layer.backgroundColor)
+ if background["alpha", default: 0] <= 0.01 {
+ return "clear"
+ }
+ return "solid"
+ }
}
--
Gitblit v1.9.3