From e2fe0cf53ab3fced976c794f823cff8e33282d1f Mon Sep 17 00:00:00 2001 From: Daniel Wennberg Date: Thu, 23 Oct 2025 08:33:39 -0700 Subject: [PATCH] macOS: remove scroll edge styling with hidden titlebar (#9317) With `macos-titlebar-style = hidden`, creating splits or cycling fullscreen sometimes produces a transparent overlay in the titlebar area, clipping the top of the surfaces: Screenshot 2025-10-22 at 21 27 28 This is actually SwiftUI styling for scroll views, and the fact that it pops up even though the titlebar is hidden is possibly a SwiftUI bug; at least it's causing frustration for others too, see https://developer.apple.com/forums/thread/798392 and https://stackoverflow.com/questions/79776037/strange-nsscrollpocket-height-on-my-nstableview-in-fullscreen-mode-on-macos-taho. I tried setting `.scrollEdgeEffectHidden()` on various nodes in the SwiftUI hierarchy, but couldn't get it to work, so I ended up resorting to an old-fashioned game of imperative whack-a-mole. Now: Screenshot 2025-10-22 at 21 28 47 AI disclosure (my first!): I consulted copilot trying to figure out of the whole SwiftUI/AppKit situation and whether there might be a declarative solution on the SwiftUI side. Just chatting in general terms without showing real-world code. No dice. --- macos/Sources/Ghostty/SurfaceScrollView.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/macos/Sources/Ghostty/SurfaceScrollView.swift b/macos/Sources/Ghostty/SurfaceScrollView.swift index b1e1b9baf..08d249c4e 100644 --- a/macos/Sources/Ghostty/SurfaceScrollView.swift +++ b/macos/Sources/Ghostty/SurfaceScrollView.swift @@ -133,6 +133,20 @@ class SurfaceScrollView: NSView { override func layout() { super.layout() + + // The SwiftUI ScrollView host likes to add its own styling overlays to + // the titlebar area, which are incompatible with the hidden titlebar + // style. They won't be present when the app is first opened, but will + // appear when creating splits or cycling fullscreen. There's no public + // way to disable them in AppKit, so we just have to play whack-a-mole. + // See https://developer.apple.com/forums/thread/798392. + if window is HiddenTitlebarTerminalWindow { + for view in scrollView.subviews { + if view.className.contains("NSScrollPocket") { + view.removeFromSuperview() + } + } + } // Fill entire bounds with scroll view scrollView.frame = bounds