diff --git a/macos/Sources/Ghostty/SurfaceScrollView.swift b/macos/Sources/Ghostty/SurfaceScrollView.swift index 714227cd1..b1e1b9baf 100644 --- a/macos/Sources/Ghostty/SurfaceScrollView.swift +++ b/macos/Sources/Ghostty/SurfaceScrollView.swift @@ -142,18 +142,35 @@ class SurfaceScrollView: NSView { // Only update sizes if we have a valid (non-zero) content size. The content size // can be zero when this is added early to a view, or to an invisible hierarchy. // Practically, this happened in the quick terminal. - let contentSize = scrollView.contentSize - if contentSize.width > 0 && contentSize.height > 0 { - // Keep document width synchronized with content width - documentView.setFrameSize(CGSize( - width: contentSize.width, - height: documentView.frame.height - )) - - // Inform the actual pty of our size change - surfaceView.sizeDidChange(contentSize) + var contentSize = scrollView.contentSize + guard contentSize.width > 0 && contentSize.height > 0 else { + synchronizeSurfaceView() + return } + // If we have a legacy scrollbar and its not visible, then we account for that + // in advance, because legacy scrollbars change our contentSize and force reflow + // of our terminal which is not desirable. + // See: https://github.com/ghostty-org/ghostty/discussions/9254 + let style = scrollView.verticalScroller?.scrollerStyle ?? NSScroller.preferredScrollerStyle + if style == .legacy { + if (scrollView.verticalScroller?.isHidden ?? true) { + let scrollerWidth = NSScroller.scrollerWidth(for: .regular, scrollerStyle: .legacy) + contentSize.width -= scrollerWidth + } + } + + // Keep document width synchronized with content width + documentView.setFrameSize(CGSize( + width: contentSize.width, + height: documentView.frame.height + )) + + // Inform the actual pty of our size change. This doesn't change the actual view + // frame because we do want to render the whole thing, but it will prevent our + // rows/cols from going into the non-content area. + surfaceView.sizeDidChange(contentSize) + // When our scrollview changes make sure our surface view is synchronized synchronizeSurfaceView() }