Fix transparent background flash during sidebar toggle (#2378)
* Fix transparent background flash during sidebar toggle Move terminal background rendering from the Metal GPU pass to a CALayer (backgroundView). The GPU bg_color pass is disabled via a new Ghostty config flag (macos-background-from-layer). The CALayer resizes instantly with its parent NSView, eliminating the 3-5 frame gap where the desktop was visible through the transparent window during sidebar toggles and layout transitions. Also simplifies the titlebar and sidebar opacity formulas since there is now a single background layer instead of two stacked semi-transparent layers. * Document macos-background-from-layer fork change * Pin GhosttyKit checksum for macos-background-from-layer * Address review feedback: fix fallback config path, inline identity wrapper - Inject macos-background-from-layer in the fallback config path too, preventing alpha double-stacking when user config is invalid - Inline panelBackgroundFillColor (now an identity function) at its two call sites and remove the wrapper * Address adversarial review: skip fullscreen bg draw call explicitly The bg_color uniform alpha is still zeroed for cell compositing (so transparent cells pass through to the CALayer), but the fullscreen background fill draw step is now explicitly skipped instead of relying on alpha=0 as a no-op. * Pin GhosttyKit checksum for bg draw-call skip --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
parent
2d2d8da1c7
commit
543481ce12
5 changed files with 45 additions and 21 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue