diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index f2868adb0..78245d5a6 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -377,6 +377,14 @@ class TerminalController: BaseTerminalController { shouldCascadeWindows = false } + fileprivate func hideWindowButtons() { + guard let window else { return } + + window.standardWindowButton(.closeButton)?.isHidden = true + window.standardWindowButton(.miniaturizeButton)?.isHidden = true + window.standardWindowButton(.zoomButton)?.isHidden = true + } + fileprivate func applyHiddenTitlebarStyle() { guard let window else { return } @@ -398,9 +406,7 @@ class TerminalController: BaseTerminalController { window.titlebarAppearsTransparent = true // Hide the traffic lights (window control buttons) - window.standardWindowButton(.closeButton)?.isHidden = true - window.standardWindowButton(.miniaturizeButton)?.isHidden = true - window.standardWindowButton(.zoomButton)?.isHidden = true + hideWindowButtons() // Disallow tabbing if the titlebar is hidden, since that will (should) also hide the tab bar. window.tabbingMode = .disallowed @@ -456,6 +462,10 @@ class TerminalController: BaseTerminalController { y: config.windowPositionY, windowDecorations: config.windowDecorations) + if config.macosWindowButtons == .hidden { + hideWindowButtons() + } + // Make sure our theme is set on the window so styling is correct. if let windowTheme = config.windowTheme { window.windowTheme = .init(rawValue: windowTheme) @@ -872,17 +882,20 @@ class TerminalController: BaseTerminalController { struct DerivedConfig { let backgroundColor: Color + let macosWindowButtons: Ghostty.MacOSWindowButtons let macosTitlebarStyle: String let maximize: Bool init() { self.backgroundColor = Color(NSColor.windowBackgroundColor) + self.macosWindowButtons = .visible self.macosTitlebarStyle = "system" self.maximize = false } init(_ config: Ghostty.Config) { self.backgroundColor = config.backgroundColor + self.macosWindowButtons = config.macosWindowButtons self.macosTitlebarStyle = config.macosTitlebarStyle self.maximize = config.maximize } diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index 9a2bdc60f..5e90d0696 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -45,6 +45,18 @@ class TerminalWindow: NSWindow { }, ] + private var hasWindowButtons: Bool { + get { + if let close = standardWindowButton(.closeButton), + let miniaturize = standardWindowButton(.miniaturizeButton), + let zoom = standardWindowButton(.zoomButton) { + return !(close.isHidden && miniaturize.isHidden && zoom.isHidden) + } else { + return false + } + } + } + // Both of these must be true for windows without decorations to be able to // still become key/main and receive events. override var canBecomeKey: Bool { return true } @@ -613,7 +625,7 @@ class TerminalWindow: NSWindow { view.translatesAutoresizingMaskIntoConstraints = false view.leftAnchor.constraint(equalTo: toolbarView.leftAnchor).isActive = true - view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 78).isActive = true + view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: hasWindowButtons ? 78 : 0).isActive = true view.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true view.heightAnchor.constraint(equalTo: toolbarView.heightAnchor).isActive = true diff --git a/macos/Sources/Ghostty/Ghostty.Config.swift b/macos/Sources/Ghostty/Ghostty.Config.swift index d7be4eb5b..cce14ca0f 100644 --- a/macos/Sources/Ghostty/Ghostty.Config.swift +++ b/macos/Sources/Ghostty/Ghostty.Config.swift @@ -250,6 +250,17 @@ extension Ghostty { return String(cString: ptr) } + var macosWindowButtons: MacOSWindowButtons { + let defaultValue = MacOSWindowButtons.visible + guard let config = self.config else { return defaultValue } + var v: UnsafePointer? = nil + let key = "macos-window-buttons" + 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 MacOSWindowButtons(rawValue: str) ?? defaultValue + } + var macosTitlebarStyle: String { let defaultValue = "transparent" guard let config = self.config else { return defaultValue } diff --git a/macos/Sources/Ghostty/Package.swift b/macos/Sources/Ghostty/Package.swift index 30d5573df..82721c17e 100644 --- a/macos/Sources/Ghostty/Package.swift +++ b/macos/Sources/Ghostty/Package.swift @@ -239,6 +239,12 @@ extension Ghostty { case chrome } + /// Enum for the macos-window-buttons config option + enum MacOSWindowButtons: String { + case visible + case hidden + } + /// Enum for the macos-titlebar-proxy-icon config option enum MacOSTitlebarProxyIcon: String { case visible diff --git a/src/config/Config.zig b/src/config/Config.zig index bf6d26f4b..03fc53321 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -2053,6 +2053,25 @@ keybind: Keybinds = .{}, /// it will retain the previous setting until fullscreen is exited. @"macos-non-native-fullscreen": NonNativeFullscreen = .false, +/// Whether the window buttons in the macOS titlebar are visible. The window +/// buttons are the colored buttons in the upper left corner of most macOS apps, +/// also known as the traffic lights, that allow you to close, miniaturize, and +/// zoom the window. +/// +/// This setting has no effect when `window-decoration = false` or +/// `macos-titlebar-style = hidden`, as the window buttons are always hidden in +/// these modes. +/// +/// Valid values are: +/// +/// * `visible` - Show the window buttons. +/// * `hidden` - Hide the window buttons. +/// +/// The default value is `visible`. +/// +/// Changing this option at runtime only applies to new windows. +@"macos-window-buttons": MacWindowButtons = .visible, + /// The style of the macOS titlebar. Available values are: "native", /// "transparent", "tabs", and "hidden". /// @@ -5803,6 +5822,12 @@ pub const WindowColorspace = enum { @"display-p3", }; +/// See macos-window-buttons +pub const MacWindowButtons = enum { + visible, + hidden, +}; + /// See macos-titlebar-style pub const MacTitlebarStyle = enum { native,