config: add `scrollbar` config to control when scrollbars appear
parent
7207ff08d5
commit
4b34b2389a
|
|
@ -603,6 +603,17 @@ extension Ghostty {
|
||||||
let str = String(cString: ptr)
|
let str = String(cString: ptr)
|
||||||
return MacShortcuts(rawValue: str) ?? defaultValue
|
return MacShortcuts(rawValue: str) ?? defaultValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var scrollbar: Scrollbar {
|
||||||
|
let defaultValue = Scrollbar.system
|
||||||
|
guard let config = self.config else { return defaultValue }
|
||||||
|
var v: UnsafePointer<Int8>? = nil
|
||||||
|
let key = "scrollbar"
|
||||||
|
guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue }
|
||||||
|
guard let ptr = v else { return defaultValue }
|
||||||
|
let str = String(cString: ptr)
|
||||||
|
return Scrollbar(rawValue: str) ?? defaultValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -641,6 +652,11 @@ extension Ghostty.Config {
|
||||||
case ask
|
case ask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Scrollbar: String {
|
||||||
|
case system
|
||||||
|
case never
|
||||||
|
}
|
||||||
|
|
||||||
enum ResizeOverlay : String {
|
enum ResizeOverlay : String {
|
||||||
case always
|
case always
|
||||||
case never
|
case never
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
|
||||||
/// Wraps a Ghostty surface view in an NSScrollView to provide native macOS scrollbar support.
|
/// Wraps a Ghostty surface view in an NSScrollView to provide native macOS scrollbar support.
|
||||||
///
|
///
|
||||||
|
|
@ -16,6 +17,7 @@ class SurfaceScrollView: NSView {
|
||||||
private let documentView: NSView
|
private let documentView: NSView
|
||||||
private let surfaceView: Ghostty.SurfaceView
|
private let surfaceView: Ghostty.SurfaceView
|
||||||
private var observers: [NSObjectProtocol] = []
|
private var observers: [NSObjectProtocol] = []
|
||||||
|
private var cancellables: Set<AnyCancellable> = []
|
||||||
private var isLiveScrolling = false
|
private var isLiveScrolling = false
|
||||||
|
|
||||||
/// The last row position sent via scroll_to_row action. Used to avoid
|
/// The last row position sent via scroll_to_row action. Used to avoid
|
||||||
|
|
@ -28,7 +30,7 @@ class SurfaceScrollView: NSView {
|
||||||
// The scroll view is our outermost view that controls all our scrollbar
|
// The scroll view is our outermost view that controls all our scrollbar
|
||||||
// rendering and behavior.
|
// rendering and behavior.
|
||||||
scrollView = NSScrollView()
|
scrollView = NSScrollView()
|
||||||
scrollView.hasVerticalScroller = true
|
scrollView.hasVerticalScroller = false
|
||||||
scrollView.hasHorizontalScroller = false
|
scrollView.hasHorizontalScroller = false
|
||||||
scrollView.autohidesScrollers = true
|
scrollView.autohidesScrollers = true
|
||||||
scrollView.usesPredominantAxisScrolling = true
|
scrollView.usesPredominantAxisScrolling = true
|
||||||
|
|
@ -49,6 +51,9 @@ class SurfaceScrollView: NSView {
|
||||||
// Our scroll view is our only view
|
// Our scroll view is our only view
|
||||||
addSubview(scrollView)
|
addSubview(scrollView)
|
||||||
|
|
||||||
|
// Apply initial scrollbar settings
|
||||||
|
synchronizeAppearance()
|
||||||
|
|
||||||
// We listen for scroll events through bounds notifications on our NSClipView.
|
// We listen for scroll events through bounds notifications on our NSClipView.
|
||||||
// This is based on: https://christiantietze.de/posts/2018/07/synchronize-nsscrollview/
|
// This is based on: https://christiantietze.de/posts/2018/07/synchronize-nsscrollview/
|
||||||
scrollView.contentView.postsBoundsChangedNotifications = true
|
scrollView.contentView.postsBoundsChangedNotifications = true
|
||||||
|
|
@ -93,6 +98,15 @@ class SurfaceScrollView: NSView {
|
||||||
) { [weak self] _ in
|
) { [weak self] _ in
|
||||||
self?.handleLiveScroll()
|
self?.handleLiveScroll()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Listen for derived config changes to update scrollbar settings live
|
||||||
|
surfaceView.$derivedConfig
|
||||||
|
.sink { [weak self] _ in
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.synchronizeAppearance()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
|
|
|
||||||
|
|
@ -1532,6 +1532,7 @@ extension Ghostty {
|
||||||
let macosWindowShadow: Bool
|
let macosWindowShadow: Bool
|
||||||
let windowTitleFontFamily: String?
|
let windowTitleFontFamily: String?
|
||||||
let windowAppearance: NSAppearance?
|
let windowAppearance: NSAppearance?
|
||||||
|
let scrollbar: Ghostty.Config.Scrollbar
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
self.backgroundColor = Color(NSColor.windowBackgroundColor)
|
self.backgroundColor = Color(NSColor.windowBackgroundColor)
|
||||||
|
|
@ -1539,6 +1540,7 @@ extension Ghostty {
|
||||||
self.macosWindowShadow = true
|
self.macosWindowShadow = true
|
||||||
self.windowTitleFontFamily = nil
|
self.windowTitleFontFamily = nil
|
||||||
self.windowAppearance = nil
|
self.windowAppearance = nil
|
||||||
|
self.scrollbar = .system
|
||||||
}
|
}
|
||||||
|
|
||||||
init(_ config: Ghostty.Config) {
|
init(_ config: Ghostty.Config) {
|
||||||
|
|
@ -1547,6 +1549,7 @@ extension Ghostty {
|
||||||
self.macosWindowShadow = config.macosWindowShadow
|
self.macosWindowShadow = config.macosWindowShadow
|
||||||
self.windowTitleFontFamily = config.windowTitleFontFamily
|
self.windowTitleFontFamily = config.windowTitleFontFamily
|
||||||
self.windowAppearance = .init(ghosttyConfig: config)
|
self.windowAppearance = .init(ghosttyConfig: config)
|
||||||
|
self.scrollbar = config.scrollbar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1197,6 +1197,24 @@ input: RepeatableReadableIO = .{},
|
||||||
/// This can be changed at runtime but will only affect new terminal surfaces.
|
/// This can be changed at runtime but will only affect new terminal surfaces.
|
||||||
@"scrollback-limit": usize = 10_000_000, // 10MB
|
@"scrollback-limit": usize = 10_000_000, // 10MB
|
||||||
|
|
||||||
|
/// Control when the scrollbar is shown to scroll the scrollback buffer.
|
||||||
|
///
|
||||||
|
/// The default value is `system`.
|
||||||
|
///
|
||||||
|
/// Valid values:
|
||||||
|
///
|
||||||
|
/// * `system` - Respect the system settings for when to show scrollbars.
|
||||||
|
/// For example, on macOS, this will respect the "Scrollbar behavior"
|
||||||
|
/// system setting which by default usually only shows scrollbars while
|
||||||
|
/// actively scrolling or hovering the gutter.
|
||||||
|
///
|
||||||
|
/// * `never` - Never show a scrollbar. You can still scroll using the mouse,
|
||||||
|
/// keybind actions, etc. but you will not have a visual UI widget showing
|
||||||
|
/// a scrollbar.
|
||||||
|
///
|
||||||
|
/// This only applies to macOS currently. GTK doesn't yet support scrollbars.
|
||||||
|
scrollbar: Scrollbar = .system,
|
||||||
|
|
||||||
/// Match a regular expression against the terminal text and associate clicking
|
/// Match a regular expression against the terminal text and associate clicking
|
||||||
/// it with an action. This can be used to match URLs, file paths, etc. Actions
|
/// it with an action. This can be used to match URLs, file paths, etc. Actions
|
||||||
/// can be opening using the system opener (e.g. `open` or `xdg-open`) or
|
/// can be opening using the system opener (e.g. `open` or `xdg-open`) or
|
||||||
|
|
@ -8379,6 +8397,12 @@ pub const WindowPadding = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// See scrollbar
|
||||||
|
pub const Scrollbar = enum {
|
||||||
|
system,
|
||||||
|
never,
|
||||||
|
};
|
||||||
|
|
||||||
/// See scroll-to-bottom
|
/// See scroll-to-bottom
|
||||||
pub const ScrollToBottom = packed struct {
|
pub const ScrollToBottom = packed struct {
|
||||||
keystroke: bool = true,
|
keystroke: bool = true,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue