From 53c510ac4055166038da29f4d05dbb7fa958e4e7 Mon Sep 17 00:00:00 2001 From: John Xu Date: Tue, 30 Dec 2025 16:32:12 +0800 Subject: [PATCH] macos: keep glass titlebar inset in sync on layout --- .../Terminal/TerminalViewContainer.swift | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalViewContainer.swift b/macos/Sources/Features/Terminal/TerminalViewContainer.swift index 1765edec3..c65dca1d2 100644 --- a/macos/Sources/Features/Terminal/TerminalViewContainer.swift +++ b/macos/Sources/Features/Terminal/TerminalViewContainer.swift @@ -8,6 +8,7 @@ class TerminalViewContainer: NSView { /// Glass effect view for liquid glass background when transparency is enabled private var glassEffectView: NSView? + private var glassTopConstraint: NSLayoutConstraint? private var derivedConfig: DerivedConfig init(ghostty: Ghostty.App, viewModel: ViewModel, delegate: (any TerminalViewDelegate)? = nil) { @@ -54,6 +55,12 @@ class TerminalViewContainer: NSView { override func viewDidMoveToWindow() { super.viewDidMoveToWindow() updateGlassEffectIfNeeded() + updateGlassEffectTopInsetIfNeeded() + } + + override func layout() { + super.layout() + updateGlassEffectTopInsetIfNeeded() } @objc private func ghosttyConfigDidChange(_ notification: Notification) { @@ -74,6 +81,7 @@ private extension TerminalViewContainer { @available(macOS 26.0, *) func addGlassEffectViewIfNeeded() -> NSGlassEffectView? { if let existed = glassEffectView as? NSGlassEffectView { + updateGlassEffectTopInsetIfNeeded() return existed } guard let themeFrameView = window?.contentView?.superview else { @@ -82,12 +90,18 @@ private extension TerminalViewContainer { let effectView = NSGlassEffectView() addSubview(effectView, positioned: .below, relativeTo: terminalView) effectView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - effectView.topAnchor.constraint(equalTo: topAnchor, constant: -themeFrameView.safeAreaInsets.top), - effectView.leadingAnchor.constraint(equalTo: leadingAnchor), - effectView.bottomAnchor.constraint(equalTo: bottomAnchor), - effectView.trailingAnchor.constraint(equalTo: trailingAnchor), - ]) + glassTopConstraint = effectView.topAnchor.constraint( + equalTo: topAnchor, + constant: -themeFrameView.safeAreaInsets.top + ) + if let glassTopConstraint { + NSLayoutConstraint.activate([ + glassTopConstraint, + effectView.leadingAnchor.constraint(equalTo: leadingAnchor), + effectView.bottomAnchor.constraint(equalTo: bottomAnchor), + effectView.trailingAnchor.constraint(equalTo: trailingAnchor), + ]) + } glassEffectView = effectView return effectView } @@ -98,6 +112,7 @@ private extension TerminalViewContainer { guard #available(macOS 26.0, *), derivedConfig.backgroundBlur.isGlassStyle else { glassEffectView?.removeFromSuperview() glassEffectView = nil + glassTopConstraint = nil return } guard let effectView = addGlassEffectViewIfNeeded() else { @@ -120,6 +135,17 @@ private extension TerminalViewContainer { #endif // compiler(>=6.2) } + func updateGlassEffectTopInsetIfNeeded() { +#if compiler(>=6.2) + guard #available(macOS 26.0, *), derivedConfig.backgroundBlur.isGlassStyle else { + return + } + guard glassEffectView != nil else { return } + guard let themeFrameView = window?.contentView?.superview else { return } + glassTopConstraint?.constant = -themeFrameView.safeAreaInsets.top +#endif // compiler(>=6.2) + } + struct DerivedConfig: Equatable { var backgroundOpacity: Double = 0 var backgroundBlur: Ghostty.Config.BackgroundBlur