macOS: support drag-handle config (#13709)

Closes https://github.com/ghostty-org/ghostty/discussions/12332

Also a tiny rephrasing for the documentation.
This commit is contained in:
Mitchell Hashimoto
2026-08-09 07:35:55 -07:00
committed by GitHub
4 changed files with 42 additions and 5 deletions

View File

@@ -274,6 +274,16 @@ extension Ghostty {
return v
}
var dragHandle: DragHandle {
let defaultValue = DragHandle.auto
guard let config = self.config else { return defaultValue }
var v: UnsafePointer<Int8>?
let key = "drag-handle"
guard ghostty_config_get(config, &v, key, UInt(key.lengthOfBytes(using: .utf8))) else { return defaultValue }
guard let ptr = v else { return defaultValue }
return DragHandle(rawValue: String(cString: ptr)) ?? defaultValue
}
/// Returns the fullscreen mode if fullscreen is enabled, or nil if disabled.
/// This parses the `fullscreen` enum config which supports both
/// native and non-native fullscreen modes.
@@ -933,4 +943,8 @@ extension Ghostty.Config {
static let `default` = MacOSTitlebarStyle.transparent
case native, transparent, tabs, hidden
}
enum DragHandle: String {
case always, auto, never
}
}

View File

@@ -10,11 +10,20 @@ extension Ghostty {
private static let hoverHeightFactor: CGFloat = 0.2
@ObservedObject var surfaceView: SurfaceView
let dragHandle: Ghostty.Config.DragHandle
@State private var isHovering: Bool = false
@State private var isDragging: Bool = false
private var handleVisible: Bool {
switch dragHandle {
case .always:
return true
case .never:
return false
case .auto:
break
}
// Handle should always be visible in non-fullscreen
guard let window = surfaceView.window else { return true }
guard window.styleMask.contains(.fullScreen) else { return true }
@@ -25,6 +34,14 @@ extension Ghostty {
}
private var ellipsisVisible: Bool {
switch dragHandle {
case .always:
return true
case .never:
return false
case .auto:
break
}
// If the cursor isn't visible, never show the handle
guard surfaceView.cursorVisible else { return false }
// If we're hovering or actively dragging, always visible

View File

@@ -205,7 +205,10 @@ extension Ghostty {
// top Z-index os it isn't faded by the unfocused overlay.
//
// This is disabled except on macOS because it uses AppKit drag/drop APIs.
SurfaceGrabHandle(surfaceView: surfaceView)
SurfaceGrabHandle(
surfaceView: surfaceView,
dragHandle: ghostty.config.dragHandle,
)
#endif
}
}

View File

@@ -2356,8 +2356,13 @@ keybind: Keybinds = .{},
///
/// - `auto` *(default)*
///
/// Automatically show and hide the drag handle. The handle is only
/// shown when there are two or more splits present.
/// Automatically show and hide the drag handle.
///
/// On Linux, the handle is only shown when there are two or
/// more splits present.
///
/// On macOS, the handle is only hidden when there's one split
/// in **fullscreen** mode, otherwise it's shown when hovered.
///
/// - `never`
///
@@ -2365,8 +2370,6 @@ keybind: Keybinds = .{},
/// mouse controls.
///
/// Available since: 1.4.0.
///
/// Currently only supported on Linux (GTK).
@"drag-handle": DragHandle = .auto,
/// This controls when resize overlays are shown. Resize overlays are a