diff --git a/Sources/ContentView.swift b/Sources/ContentView.swift index 8145ea58..248dc2f3 100644 --- a/Sources/ContentView.swift +++ b/Sources/ContentView.swift @@ -2500,14 +2500,13 @@ struct ContentView: View { .contentShape(Rectangle()) .background(TitlebarDoubleClickMonitorView()) .background({ - // The terminal area has two stacked semi-transparent layers: the Bonsplit - // container chrome background plus Ghostty's own Metal-rendered background. - // Compute the effective composited opacity so the titlebar matches visually. + // The terminal background is provided by a single CALayer + // (backgroundView in GhosttySurfaceScrollView), so the titlebar + // opacity matches the configured value directly. let alpha = CGFloat(GhosttyApp.shared.defaultBackgroundOpacity) - let effective = alpha >= 0.999 ? alpha : 1.0 - pow(1.0 - alpha, 2) return TitlebarLayerBackground( backgroundColor: GhosttyApp.shared.defaultBackgroundColor, - opacity: effective + opacity: alpha ) }()) .overlay(alignment: .bottom) { @@ -14022,14 +14021,13 @@ private struct SidebarBackdrop: View { let cornerRadius = CGFloat(max(0, sidebarCornerRadius)) if matchTerminalBackground { - // The terminal area has two stacked semi-transparent layers (Bonsplit chrome + - // Ghostty Metal background). Compute the effective composited opacity to match. + // The terminal background is provided by a single CALayer, so + // the sidebar uses the configured opacity directly. let alpha = CGFloat(GhosttyApp.shared.defaultBackgroundOpacity) - let effective = alpha >= 0.999 ? alpha : 1.0 - pow(1.0 - alpha, 2) return AnyView( SidebarTerminalBackgroundView( backgroundColor: GhosttyApp.shared.defaultBackgroundColor, - opacity: effective + opacity: alpha ) .clipShape(RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)) .onReceive(NotificationCenter.default.publisher(for: .ghosttyDefaultBackgroundDidChange)) { _ in diff --git a/Sources/GhosttyTerminalView.swift b/Sources/GhosttyTerminalView.swift index e7027e80..d7d920aa 100644 --- a/Sources/GhosttyTerminalView.swift +++ b/Sources/GhosttyTerminalView.swift @@ -1303,6 +1303,12 @@ class GhosttyApp { return } + loadInlineGhosttyConfig( + "macos-background-from-layer = true", + into: fallbackConfig, + prefix: "cmux-layer-bg", + logLabel: "layer background (fallback)" + ) ghostty_config_finalize(fallbackConfig) updateDefaultBackground(from: fallbackConfig, source: "initialize.fallbackConfig") @@ -1391,6 +1397,15 @@ class GhosttyApp { userConfigDefinesShiftEnterBinding = Self.userConfigDefinesShiftEnterBinding() loadCopyOnSelectOverride(config) loadCJKFontFallbackIfNeeded(config) + // cmux provides the terminal background via backgroundView (CALayer) + // instead of the GPU full-screen bg pass, so the layer can provide + // instant coverage during sidebar toggle and other layout transitions. + loadInlineGhosttyConfig( + "macos-background-from-layer = true", + into: config, + prefix: "cmux-layer-bg", + logLabel: "layer background" + ) ghostty_config_finalize(config) } @@ -7485,11 +7500,6 @@ final class GhosttySurfaceScrollView: NSView { } private(set) var searchFocusTarget: SearchFocusTarget = .searchField - private static func panelBackgroundFillColor(for terminalBackgroundColor: NSColor) -> NSColor { - // The Ghostty renderer already draws translucent terminal backgrounds. If we paint an - // additional translucent layer here, alpha stacks and appears effectively opaque. - terminalBackgroundColor.alphaComponent < 0.999 ? .clear : terminalBackgroundColor - } #if DEBUG private var lastDropZoneOverlayLogSignature: String? @@ -7677,9 +7687,8 @@ final class GhosttySurfaceScrollView: NSView { backgroundView.wantsLayer = true let initialTerminalBackground = GhosttyApp.shared.defaultBackgroundColor .withAlphaComponent(GhosttyApp.shared.defaultBackgroundOpacity) - let initialPanelFill = Self.panelBackgroundFillColor(for: initialTerminalBackground) - backgroundView.layer?.backgroundColor = initialPanelFill.cgColor - backgroundView.layer?.isOpaque = initialPanelFill.alphaComponent >= 1.0 + backgroundView.layer?.backgroundColor = initialTerminalBackground.cgColor + backgroundView.layer?.isOpaque = initialTerminalBackground.alphaComponent >= 1.0 addSubview(backgroundView) addSubview(scrollView) inactiveOverlayView.wantsLayer = true @@ -8245,11 +8254,10 @@ final class GhosttySurfaceScrollView: NSView { func setBackgroundColor(_ color: NSColor) { guard let layer = backgroundView.layer else { return } - let fillColor = Self.panelBackgroundFillColor(for: color) CATransaction.begin() CATransaction.setDisableActions(true) - layer.backgroundColor = fillColor.cgColor - layer.isOpaque = fillColor.alphaComponent >= 1.0 + layer.backgroundColor = color.cgColor + layer.isOpaque = color.alphaComponent >= 1.0 CATransaction.commit() } diff --git a/docs/ghostty-fork.md b/docs/ghostty-fork.md index 49de9988..55cc1207 100644 --- a/docs/ghostty-fork.md +++ b/docs/ghostty-fork.md @@ -102,6 +102,17 @@ The fork branch HEAD is now the section 6 zsh redraw follow-up commit. The fork branch HEAD is now the section 7 cmux theme picker helper commit. +### 8) macos-background-from-layer config flag + +- Branch: `feat-layer-bg` +- Files: + - `src/config/Config.zig` + - `src/renderer/generic.zig` +- Summary: + - Adds a `macos-background-from-layer` bool config (default false). + - When true, sets `bg_color[3] = 0` in the per-frame uniform update so the Metal renderer skips the full-screen background fill. + - Allows the host app to provide the terminal background via `CALayer.backgroundColor` for instant coverage during view resizes, avoiding alpha double-stacking. + ## Upstreamed fork changes ### cursor-click-to-move respects OSC 133 click-to-move @@ -130,4 +141,9 @@ These files change frequently upstream; be careful when rebasing the fork: If upstream reorganizes the preview loop or key handling, re-check the cmux mode path and keep the stock Ghostty behavior unchanged when the cmux env vars are absent. +- `src/renderer/generic.zig` + - The `macos-background-from-layer` check sits next to the glass-style check in `updateFrame`. + If upstream refactors the bg_color uniform update or the glass conditional, re-check that both + paths still zero out `bg_color[3]` correctly. + If you resolve a conflict, update this doc with what changed. diff --git a/ghostty b/ghostty index bc9be90a..f9030b5c 160000 --- a/ghostty +++ b/ghostty @@ -1 +1 @@ -Subproject commit bc9be90a21997a4e5f06bf15ae2ec0f937c2dc42 +Subproject commit f9030b5c5232db69ba8625bb53d51ce735b80d51 diff --git a/scripts/ghosttykit-checksums.txt b/scripts/ghosttykit-checksums.txt index 1e45a32a..0d5946e9 100644 --- a/scripts/ghosttykit-checksums.txt +++ b/scripts/ghosttykit-checksums.txt @@ -8,3 +8,5 @@ c47010b80cd9ae6d1ab744c120f011a465521ea3 d6904870a3c920b2787b1c4b950cfdef232606b 312c7b23a7c8dc0704431940d76ba5dc32a46afb ae73cb18a9d6efec42126a1d99e0e9d12022403d7dc301dfa21ed9f7c89c9e30 404a3f175ba6baafabc46cac807194883e040980 bcbd2954f4746fe5bcb4bfca6efeddd3ea355fda2836371f4c7150271c58acbd bc9be90a21997a4e5f06bf15ae2ec0f937c2dc42 6b83b66768e8bba871a3753ae8ffbaabd03370b306c429cd86c9cdcc8db82589 +41e796064e89eacabdf3a6729475e250a5518e7a 135302bbdf3e83b200f0165ff2a32cdf13017219e6c8ffca17b672edfbfae395 +f9030b5c5232db69ba8625bb53d51ce735b80d51 6c439d731d97bd35a3289f54478af3ac01e30ba74ec2672490e0c98f95262b55