Skip to content

Commit 5bf05df

Browse files
authored
macos: make terminal smaller to account for legacy scrollbar (#9255)
#9254 When the preferred scrollbar style is "legacy", the scrollbar takes up space that offsets the actual terminal. To prevent reflow, we detect this before the scrollbar becomes visible and shrink our terminal width to prepare for it. This doesn't account for the style changing at runtime, yet. ## Demo Notice even before scrollbars, the `gh` output doesn't wrap. https://github.com/user-attachments/assets/8716ff4d-0660-48b1-aadb-0d31e0b70fcd
2 parents e4db7f5 + 5b7f145 commit 5bf05df

File tree

1 file changed

+27
-10
lines changed

1 file changed

+27
-10
lines changed

macos/Sources/Ghostty/SurfaceScrollView.swift

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,35 @@ class SurfaceScrollView: NSView {
142142
// Only update sizes if we have a valid (non-zero) content size. The content size
143143
// can be zero when this is added early to a view, or to an invisible hierarchy.
144144
// Practically, this happened in the quick terminal.
145-
let contentSize = scrollView.contentSize
146-
if contentSize.width > 0 && contentSize.height > 0 {
147-
// Keep document width synchronized with content width
148-
documentView.setFrameSize(CGSize(
149-
width: contentSize.width,
150-
height: documentView.frame.height
151-
))
152-
153-
// Inform the actual pty of our size change
154-
surfaceView.sizeDidChange(contentSize)
145+
var contentSize = scrollView.contentSize
146+
guard contentSize.width > 0 && contentSize.height > 0 else {
147+
synchronizeSurfaceView()
148+
return
155149
}
156150

151+
// If we have a legacy scrollbar and its not visible, then we account for that
152+
// in advance, because legacy scrollbars change our contentSize and force reflow
153+
// of our terminal which is not desirable.
154+
// See: https://github.com/ghostty-org/ghostty/discussions/9254
155+
let style = scrollView.verticalScroller?.scrollerStyle ?? NSScroller.preferredScrollerStyle
156+
if style == .legacy {
157+
if (scrollView.verticalScroller?.isHidden ?? true) {
158+
let scrollerWidth = NSScroller.scrollerWidth(for: .regular, scrollerStyle: .legacy)
159+
contentSize.width -= scrollerWidth
160+
}
161+
}
162+
163+
// Keep document width synchronized with content width
164+
documentView.setFrameSize(CGSize(
165+
width: contentSize.width,
166+
height: documentView.frame.height
167+
))
168+
169+
// Inform the actual pty of our size change. This doesn't change the actual view
170+
// frame because we do want to render the whole thing, but it will prevent our
171+
// rows/cols from going into the non-content area.
172+
surfaceView.sizeDidChange(contentSize)
173+
157174
// When our scrollview changes make sure our surface view is synchronized
158175
synchronizeSurfaceView()
159176
}

0 commit comments

Comments
 (0)