Skip to content

Commit 4b34b23

Browse files
committed
config: add scrollbar config to control when scrollbars appear
1 parent 7207ff0 commit 4b34b23

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

macos/Sources/Ghostty/Ghostty.Config.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,17 @@ extension Ghostty {
603603
let str = String(cString: ptr)
604604
return MacShortcuts(rawValue: str) ?? defaultValue
605605
}
606+
607+
var scrollbar: Scrollbar {
608+
let defaultValue = Scrollbar.system
609+
guard let config = self.config else { return defaultValue }
610+
var v: UnsafePointer<Int8>? = nil
611+
let key = "scrollbar"
612+
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
613+
guard let ptr = v else { return defaultValue }
614+
let str = String(cString: ptr)
615+
return Scrollbar(rawValue: str) ?? defaultValue
616+
}
606617
}
607618
}
608619

@@ -641,6 +652,11 @@ extension Ghostty.Config {
641652
case ask
642653
}
643654

655+
enum Scrollbar: String {
656+
case system
657+
case never
658+
}
659+
644660
enum ResizeOverlay : String {
645661
case always
646662
case never

macos/Sources/Ghostty/SurfaceScrollView.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import SwiftUI
2+
import Combine
23

34
/// Wraps a Ghostty surface view in an NSScrollView to provide native macOS scrollbar support.
45
///
@@ -16,6 +17,7 @@ class SurfaceScrollView: NSView {
1617
private let documentView: NSView
1718
private let surfaceView: Ghostty.SurfaceView
1819
private var observers: [NSObjectProtocol] = []
20+
private var cancellables: Set<AnyCancellable> = []
1921
private var isLiveScrolling = false
2022

2123
/// The last row position sent via scroll_to_row action. Used to avoid
@@ -28,7 +30,7 @@ class SurfaceScrollView: NSView {
2830
// The scroll view is our outermost view that controls all our scrollbar
2931
// rendering and behavior.
3032
scrollView = NSScrollView()
31-
scrollView.hasVerticalScroller = true
33+
scrollView.hasVerticalScroller = false
3234
scrollView.hasHorizontalScroller = false
3335
scrollView.autohidesScrollers = true
3436
scrollView.usesPredominantAxisScrolling = true
@@ -49,6 +51,9 @@ class SurfaceScrollView: NSView {
4951
// Our scroll view is our only view
5052
addSubview(scrollView)
5153

54+
// Apply initial scrollbar settings
55+
synchronizeAppearance()
56+
5257
// We listen for scroll events through bounds notifications on our NSClipView.
5358
// This is based on: https://christiantietze.de/posts/2018/07/synchronize-nsscrollview/
5459
scrollView.contentView.postsBoundsChangedNotifications = true
@@ -93,6 +98,15 @@ class SurfaceScrollView: NSView {
9398
) { [weak self] _ in
9499
self?.handleLiveScroll()
95100
})
101+
102+
// Listen for derived config changes to update scrollbar settings live
103+
surfaceView.$derivedConfig
104+
.sink { [weak self] _ in
105+
DispatchQueue.main.async { [weak self] in
106+
self?.synchronizeAppearance()
107+
}
108+
}
109+
.store(in: &cancellables)
96110
}
97111

98112
required init?(coder: NSCoder) {

macos/Sources/Ghostty/SurfaceView_AppKit.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,13 +1532,15 @@ extension Ghostty {
15321532
let macosWindowShadow: Bool
15331533
let windowTitleFontFamily: String?
15341534
let windowAppearance: NSAppearance?
1535+
let scrollbar: Ghostty.Config.Scrollbar
15351536

15361537
init() {
15371538
self.backgroundColor = Color(NSColor.windowBackgroundColor)
15381539
self.backgroundOpacity = 1
15391540
self.macosWindowShadow = true
15401541
self.windowTitleFontFamily = nil
15411542
self.windowAppearance = nil
1543+
self.scrollbar = .system
15421544
}
15431545

15441546
init(_ config: Ghostty.Config) {
@@ -1547,6 +1549,7 @@ extension Ghostty {
15471549
self.macosWindowShadow = config.macosWindowShadow
15481550
self.windowTitleFontFamily = config.windowTitleFontFamily
15491551
self.windowAppearance = .init(ghosttyConfig: config)
1552+
self.scrollbar = config.scrollbar
15501553
}
15511554
}
15521555

src/config/Config.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,24 @@ input: RepeatableReadableIO = .{},
11971197
/// This can be changed at runtime but will only affect new terminal surfaces.
11981198
@"scrollback-limit": usize = 10_000_000, // 10MB
11991199

1200+
/// Control when the scrollbar is shown to scroll the scrollback buffer.
1201+
///
1202+
/// The default value is `system`.
1203+
///
1204+
/// Valid values:
1205+
///
1206+
/// * `system` - Respect the system settings for when to show scrollbars.
1207+
/// For example, on macOS, this will respect the "Scrollbar behavior"
1208+
/// system setting which by default usually only shows scrollbars while
1209+
/// actively scrolling or hovering the gutter.
1210+
///
1211+
/// * `never` - Never show a scrollbar. You can still scroll using the mouse,
1212+
/// keybind actions, etc. but you will not have a visual UI widget showing
1213+
/// a scrollbar.
1214+
///
1215+
/// This only applies to macOS currently. GTK doesn't yet support scrollbars.
1216+
scrollbar: Scrollbar = .system,
1217+
12001218
/// Match a regular expression against the terminal text and associate clicking
12011219
/// it with an action. This can be used to match URLs, file paths, etc. Actions
12021220
/// can be opening using the system opener (e.g. `open` or `xdg-open`) or
@@ -8379,6 +8397,12 @@ pub const WindowPadding = struct {
83798397
}
83808398
};
83818399

8400+
/// See scrollbar
8401+
pub const Scrollbar = enum {
8402+
system,
8403+
never,
8404+
};
8405+
83828406
/// See scroll-to-bottom
83838407
pub const ScrollToBottom = packed struct {
83848408
keystroke: bool = true,

0 commit comments

Comments
 (0)