Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions Sources/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -14008,14 +14007,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
Expand Down
30 changes: 19 additions & 11 deletions Sources/GhosttyTerminalView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,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")

Expand Down Expand Up @@ -1389,6 +1395,15 @@ class GhosttyApp {
loadCmuxAppSupportGhosttyConfigIfNeeded(config)
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"
)
Comment on lines +1398 to +1406

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reset compositor blur when this path goes back to opaque.

Turning on macos-background-from-layer makes the host layer/window path responsible for the visible background, but GhosttyApp.applyBackgroundToKeyWindow() and GhosttyNSView.applyWindowBackgroundIfActive() still only touch the blur setter on the transparent branch. If the user moves from translucent back to opaque, the old blur radius can stay latched and bleed into the supposedly solid background. Please clear blur on every background update and pass 0 when opacity is opaque or blur is disabled.

Based on learnings: In Sources/GhosttyTerminalView.swift, CGS window background blur is stateful. Always call cmuxApplyBackgroundBlur(to: NSWindow, radius: Int) on background updates and pass radius 0 when blur should be disabled (opacity >= 1.0 or configured radius == 0).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/GhosttyTerminalView.swift` around lines 1392 - 1400, The blur radius
isn't cleared when switching back to an opaque background; update the background
update paths (e.g. GhosttyApp.applyBackgroundToKeyWindow() and
GhosttyNSView.applyWindowBackgroundIfActive()) to always call
cmuxApplyBackgroundBlur(to: radius:) on every background change and pass radius
0 whenever the effective opacity is >= 1.0 or the configured blur radius is 0
(i.e. when blur is disabled), ensuring blur is explicitly cleared even on the
opaque branch.

ghostty_config_finalize(config)
}

Expand Down Expand Up @@ -7287,11 +7302,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?
Expand Down Expand Up @@ -7479,9 +7489,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
Expand Down Expand Up @@ -8047,11 +8056,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()
}

Expand Down
16 changes: 16 additions & 0 deletions docs/ghostty-fork.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
2 changes: 1 addition & 1 deletion ghostty
2 changes: 2 additions & 0 deletions scripts/ghosttykit-checksums.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ c47010b80cd9ae6d1ab744c120f011a465521ea3 d6904870a3c920b2787b1c4b950cfdef232606b
312c7b23a7c8dc0704431940d76ba5dc32a46afb ae73cb18a9d6efec42126a1d99e0e9d12022403d7dc301dfa21ed9f7c89c9e30
404a3f175ba6baafabc46cac807194883e040980 bcbd2954f4746fe5bcb4bfca6efeddd3ea355fda2836371f4c7150271c58acbd
bc9be90a21997a4e5f06bf15ae2ec0f937c2dc42 6b83b66768e8bba871a3753ae8ffbaabd03370b306c429cd86c9cdcc8db82589
41e796064e89eacabdf3a6729475e250a5518e7a 135302bbdf3e83b200f0165ff2a32cdf13017219e6c8ffca17b672edfbfae395
f9030b5c5232db69ba8625bb53d51ce735b80d51 6c439d731d97bd35a3289f54478af3ac01e30ba74ec2672490e0c98f95262b55
Loading