mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
Merge pull request #1418 from qwerasd205/macos-titlebar-tabs
macOS: Added titlebar tabs
This commit is contained in:
@ -65,6 +65,7 @@
|
||||
A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E112942AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift */; };
|
||||
A5E112972AF7401B00C6E0C2 /* ClipboardConfirmationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E112962AF7401B00C6E0C2 /* ClipboardConfirmationView.swift */; };
|
||||
A5FEB3002ABB69450068369E /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5FEB2FF2ABB69450068369E /* main.swift */; };
|
||||
AEF9CE242B6AD07A0017E195 /* TerminalToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */; };
|
||||
C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
|
||||
C159E89D2B69A2EF00FDFE9C /* OSColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -125,6 +126,7 @@
|
||||
A5E112942AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardConfirmationController.swift; sourceTree = "<group>"; };
|
||||
A5E112962AF7401B00C6E0C2 /* ClipboardConfirmationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClipboardConfirmationView.swift; sourceTree = "<group>"; };
|
||||
A5FEB2FF2ABB69450068369E /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminalToolbar.swift; sourceTree = "<group>"; };
|
||||
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OSColor+Extension.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -281,6 +283,7 @@
|
||||
A5D0AF3A2B36A1DE00D21823 /* TerminalRestorable.swift */,
|
||||
A596309D2AEE1D6C00D64628 /* TerminalView.swift */,
|
||||
A51B78462AF4B58B00F3EDB9 /* TerminalWindow.swift */,
|
||||
AEF9CE232B6AD07A0017E195 /* TerminalToolbar.swift */,
|
||||
A535B9D9299C569B0017E2E4 /* ErrorView.swift */,
|
||||
);
|
||||
path = Terminal;
|
||||
@ -493,6 +496,7 @@
|
||||
A5E112952AF73E8A00C6E0C2 /* ClipboardConfirmationController.swift in Sources */,
|
||||
8503D7C72A549C66006CFF3D /* FullScreenHandler.swift in Sources */,
|
||||
A596309E2AEE1D6C00D64628 /* TerminalView.swift in Sources */,
|
||||
AEF9CE242B6AD07A0017E195 /* TerminalToolbar.swift in Sources */,
|
||||
C159E81D2B66A06B00FDFE9C /* OSColor+Extension.swift in Sources */,
|
||||
A5CEAFDE29B8058B00646FDA /* SplitView.Divider.swift in Sources */,
|
||||
A5E112972AF7401B00C6E0C2 /* ClipboardConfirmationView.swift in Sources */,
|
||||
|
@ -159,7 +159,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
}
|
||||
|
||||
override func windowDidLoad() {
|
||||
guard let window = window else { return }
|
||||
guard let window = window as? TerminalWindow else { return }
|
||||
|
||||
// Setting all three of these is required for restoration to work.
|
||||
window.isRestorable = restorable
|
||||
@ -205,6 +205,18 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
// when cascading.
|
||||
window.center()
|
||||
|
||||
// Set the background color of the window
|
||||
window.backgroundColor = NSColor(ghostty.config.backgroundColor)
|
||||
|
||||
// Handle titlebar tabs config option
|
||||
window.titlebarTabs = ghostty.config.macosTitlebarTabs
|
||||
window.setTitlebarBackground(
|
||||
window
|
||||
.backgroundColor
|
||||
.withAlphaComponent(ghostty.config.backgroundOpacity)
|
||||
.cgColor
|
||||
)
|
||||
|
||||
// Initialize our content view to the SwiftUI root
|
||||
window.contentView = NSHostingView(rootView: TerminalView(
|
||||
ghostty: self.ghostty,
|
||||
@ -470,7 +482,15 @@ class TerminalController: NSWindowController, NSWindowDelegate,
|
||||
}
|
||||
|
||||
func titleDidChange(to: String) {
|
||||
self.window?.title = to
|
||||
guard let window = window as? TerminalWindow else { return }
|
||||
|
||||
// Set the main window title
|
||||
window.title = to
|
||||
|
||||
// Custom toolbar-based title used when titlebar tabs are enabled.
|
||||
if let toolbar = window.toolbar as? TerminalToolbar {
|
||||
toolbar.titleText = to
|
||||
}
|
||||
}
|
||||
|
||||
func cellSizeDidChange(to: NSSize) {
|
||||
|
49
macos/Sources/Features/Terminal/TerminalToolbar.swift
Normal file
49
macos/Sources/Features/Terminal/TerminalToolbar.swift
Normal file
@ -0,0 +1,49 @@
|
||||
import Cocoa
|
||||
|
||||
// Custom NSToolbar subclass that displays a centered window title,
|
||||
// in order to accommodate the titlebar tabs feature.
|
||||
class TerminalToolbar: NSToolbar, NSToolbarDelegate {
|
||||
static private let identifier = NSToolbarItem.Identifier("TitleText")
|
||||
private let titleTextField = NSTextField(labelWithString: "👻 Ghostty")
|
||||
|
||||
var titleText: String {
|
||||
get {
|
||||
titleTextField.stringValue
|
||||
}
|
||||
|
||||
set {
|
||||
titleTextField.stringValue = newValue
|
||||
}
|
||||
}
|
||||
|
||||
override init(identifier: NSToolbar.Identifier) {
|
||||
super.init(identifier: identifier)
|
||||
|
||||
delegate = self
|
||||
|
||||
if #available(macOS 13.0, *) {
|
||||
centeredItemIdentifiers.insert(Self.identifier)
|
||||
} else {
|
||||
centeredItemIdentifier = Self.identifier
|
||||
}
|
||||
}
|
||||
|
||||
func toolbar(_ toolbar: NSToolbar,
|
||||
itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier,
|
||||
willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
|
||||
guard itemIdentifier == Self.identifier else { return nil }
|
||||
|
||||
let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
|
||||
toolbarItem.isEnabled = true
|
||||
toolbarItem.view = self.titleTextField
|
||||
return toolbarItem
|
||||
}
|
||||
|
||||
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
||||
return [Self.identifier]
|
||||
}
|
||||
|
||||
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
|
||||
return [Self.identifier]
|
||||
}
|
||||
}
|
@ -5,4 +5,243 @@ class TerminalWindow: NSWindow {
|
||||
// still become key/main and receive events.
|
||||
override var canBecomeKey: Bool { return true }
|
||||
override var canBecomeMain: Bool { return true }
|
||||
|
||||
// MARK: - NSWindow
|
||||
|
||||
override func becomeKey() {
|
||||
// This is required because the removeTitlebarAccessoryViewControlle hook does not
|
||||
// catch the creation of a new window by "tearing off" a tab from a tabbed window.
|
||||
if let tabGroup = self.tabGroup, tabGroup.windows.count < 2 {
|
||||
hideCustomTabBarViews()
|
||||
}
|
||||
|
||||
super.becomeKey()
|
||||
}
|
||||
|
||||
// MARK: - Titlebar Tabs
|
||||
|
||||
// Used by the window controller to enable/disable titlebar tabs.
|
||||
var titlebarTabs = false {
|
||||
didSet {
|
||||
changedTitlebarTabs(to: titlebarTabs)
|
||||
}
|
||||
}
|
||||
|
||||
private var windowButtonsBackdrop: NSView? = nil
|
||||
private var windowDragHandle: WindowDragView? = nil
|
||||
|
||||
// The tab bar controller ID from macOS
|
||||
static private let TabBarController = NSUserInterfaceItemIdentifier("_tabBarController")
|
||||
|
||||
/// This is called by titlebarTabs changing so that we can setup the rest of our window
|
||||
private func changedTitlebarTabs(to newValue: Bool) {
|
||||
self.titlebarAppearsTransparent = newValue
|
||||
|
||||
if (newValue) {
|
||||
// We use the toolbar to anchor our tab bar positions in the titlebar,
|
||||
// so we make sure it's the right size/position, and exists.
|
||||
self.toolbarStyle = .unifiedCompact
|
||||
if (self.toolbar == nil) {
|
||||
self.toolbar = TerminalToolbar(identifier: "Toolbar")
|
||||
}
|
||||
|
||||
// We directly hide the view containing the title text because if we use the
|
||||
// `titleVisibility` property for this it prevents the window from hiding the
|
||||
// tab bar when we get down to a single tab.
|
||||
if let toolbarTitleView = contentView?.superview?.subviews.first(where: {
|
||||
$0.className == "NSTitlebarContainerView"
|
||||
})?.subviews.first(where: {
|
||||
$0.className == "NSTitlebarView"
|
||||
})?.subviews.first(where: {
|
||||
$0.className == "NSToolbarView"
|
||||
})?.subviews.first(where: {
|
||||
$0.className == "NSToolbarTitleView"
|
||||
}) {
|
||||
toolbarTitleView.isHidden = true
|
||||
}
|
||||
} else {
|
||||
// "expanded" places the toolbar below the titlebar, so setting this style and
|
||||
// removing the toolbar ensures that the titlebar will be the default height.
|
||||
self.toolbarStyle = .expanded
|
||||
self.toolbar = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Assign a background color to the titlebar area.
|
||||
func setTitlebarBackground(_ color: CGColor) {
|
||||
guard let titlebarContainer = contentView?.superview?.subviews.first(where: {
|
||||
$0.className == "NSTitlebarContainerView"
|
||||
}) else { return }
|
||||
|
||||
titlebarContainer.wantsLayer = true
|
||||
titlebarContainer.layer?.backgroundColor = color
|
||||
}
|
||||
|
||||
// This is called by macOS for native tabbing in order to add the tab bar. We hook into
|
||||
// this, detect the tab bar being added, and override its behavior.
|
||||
override func addTitlebarAccessoryViewController(_ childViewController: NSTitlebarAccessoryViewController) {
|
||||
let isTabBar = self.titlebarTabs && (
|
||||
childViewController.layoutAttribute == .bottom ||
|
||||
childViewController.identifier == Self.TabBarController
|
||||
)
|
||||
|
||||
if (isTabBar) {
|
||||
// Ensure it has the right layoutAttribute to force it next to our titlebar
|
||||
childViewController.layoutAttribute = .right
|
||||
|
||||
// If we don't set titleVisibility to hidden here, the toolbar will display a
|
||||
// "collapsed items" indicator which interferes with the tab bar.
|
||||
titleVisibility = .hidden
|
||||
|
||||
// Mark the controller for future reference so we can easily find it. Otherwise
|
||||
// the tab bar has no ID by default.
|
||||
childViewController.identifier = Self.TabBarController
|
||||
}
|
||||
|
||||
super.addTitlebarAccessoryViewController(childViewController)
|
||||
|
||||
if (isTabBar) {
|
||||
pushTabsToTitlebar(childViewController)
|
||||
}
|
||||
}
|
||||
|
||||
override func removeTitlebarAccessoryViewController(at index: Int) {
|
||||
let isTabBar = titlebarAccessoryViewControllers[index].identifier == Self.TabBarController
|
||||
super.removeTitlebarAccessoryViewController(at: index)
|
||||
if (isTabBar) {
|
||||
hideCustomTabBarViews()
|
||||
}
|
||||
}
|
||||
|
||||
// To be called immediately after the tab bar is disabled.
|
||||
private func hideCustomTabBarViews() {
|
||||
// Hide the window buttons backdrop.
|
||||
windowButtonsBackdrop?.isHidden = true
|
||||
|
||||
// Hide the window drag handle.
|
||||
windowDragHandle?.isHidden = true
|
||||
}
|
||||
|
||||
private func pushTabsToTitlebar(_ tabBarController: NSTitlebarAccessoryViewController) {
|
||||
let accessoryView = tabBarController.view
|
||||
guard let accessoryClipView = accessoryView.superview else { return }
|
||||
guard let titlebarView = accessoryClipView.superview else { return }
|
||||
guard titlebarView.className == "NSTitlebarView" else { return }
|
||||
guard let toolbarView = titlebarView.subviews.first(where: {
|
||||
$0.className == "NSToolbarView"
|
||||
}) else { return }
|
||||
|
||||
addWindowButtonsBackdrop(titlebarView: titlebarView, toolbarView: toolbarView)
|
||||
guard let windowButtonsBackdrop = windowButtonsBackdrop else { return }
|
||||
windowButtonsBackdrop.isHidden = false
|
||||
|
||||
addWindowDragHandle(titlebarView: titlebarView, toolbarView: toolbarView)
|
||||
windowDragHandle?.isHidden = false
|
||||
|
||||
accessoryClipView.translatesAutoresizingMaskIntoConstraints = false
|
||||
accessoryClipView.leftAnchor.constraint(equalTo: windowButtonsBackdrop.rightAnchor).isActive = true
|
||||
accessoryClipView.rightAnchor.constraint(equalTo: toolbarView.rightAnchor).isActive = true
|
||||
accessoryClipView.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true
|
||||
accessoryClipView.heightAnchor.constraint(equalTo: toolbarView.heightAnchor).isActive = true
|
||||
accessoryClipView.needsLayout = true
|
||||
|
||||
accessoryView.translatesAutoresizingMaskIntoConstraints = false
|
||||
accessoryView.leftAnchor.constraint(equalTo: accessoryClipView.leftAnchor).isActive = true
|
||||
accessoryView.rightAnchor.constraint(equalTo: accessoryClipView.rightAnchor).isActive = true
|
||||
accessoryView.topAnchor.constraint(equalTo: accessoryClipView.topAnchor).isActive = true
|
||||
accessoryView.heightAnchor.constraint(equalTo: accessoryClipView.heightAnchor).isActive = true
|
||||
accessoryView.needsLayout = true
|
||||
|
||||
// This is a horrible hack. During the transition while things are resizing to make room for
|
||||
// new tabs or expand existing tabs to fill the empty space after one is closed, the centering
|
||||
// of the tab titles can't be properly calculated, so we wait for 0.2 seconds and then mark
|
||||
// the entire view hierarchy for the tab bar as dirty to fix the positioning...
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
|
||||
self.markHierarchyForLayout(accessoryView)
|
||||
}
|
||||
}
|
||||
|
||||
private func addWindowButtonsBackdrop(titlebarView: NSView, toolbarView: NSView) {
|
||||
guard windowButtonsBackdrop == nil else { return }
|
||||
|
||||
let view = NSView()
|
||||
view.identifier = NSUserInterfaceItemIdentifier("_windowButtonsBackdrop")
|
||||
titlebarView.addSubview(view)
|
||||
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.leftAnchor.constraint(equalTo: toolbarView.leftAnchor).isActive = true
|
||||
view.rightAnchor.constraint(equalTo: toolbarView.leftAnchor, constant: 80).isActive = true
|
||||
view.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true
|
||||
view.heightAnchor.constraint(equalTo: toolbarView.heightAnchor).isActive = true
|
||||
view.wantsLayer = true
|
||||
view.layer?.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.45)
|
||||
|
||||
let topBorder = NSView()
|
||||
view.addSubview(topBorder)
|
||||
topBorder.translatesAutoresizingMaskIntoConstraints = false
|
||||
topBorder.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
|
||||
topBorder.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
|
||||
topBorder.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
|
||||
topBorder.bottomAnchor.constraint(equalTo: view.topAnchor, constant: 1).isActive = true
|
||||
topBorder.wantsLayer = true
|
||||
topBorder.layer?.backgroundColor = CGColor(genericGrayGamma2_2Gray: 0.0, alpha: 0.85)
|
||||
|
||||
windowButtonsBackdrop = view
|
||||
}
|
||||
|
||||
private func addWindowDragHandle(titlebarView: NSView, toolbarView: NSView) {
|
||||
guard windowDragHandle == nil else { return }
|
||||
|
||||
let view = WindowDragView()
|
||||
view.identifier = NSUserInterfaceItemIdentifier("_windowDragHandle")
|
||||
titlebarView.superview?.addSubview(view)
|
||||
view.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.leftAnchor.constraint(equalTo: toolbarView.leftAnchor).isActive = true
|
||||
view.rightAnchor.constraint(equalTo: toolbarView.rightAnchor).isActive = true
|
||||
view.topAnchor.constraint(equalTo: toolbarView.topAnchor).isActive = true
|
||||
view.bottomAnchor.constraint(equalTo: toolbarView.topAnchor, constant: 12).isActive = true
|
||||
|
||||
windowDragHandle = view
|
||||
}
|
||||
|
||||
// This forces this view and all subviews to update layout and redraw. This is
|
||||
// a hack (see the caller).
|
||||
private func markHierarchyForLayout(_ view: NSView) {
|
||||
view.needsUpdateConstraints = true
|
||||
view.needsLayout = true
|
||||
view.needsDisplay = true
|
||||
view.setNeedsDisplay(view.bounds)
|
||||
for subview in view.subviews {
|
||||
markHierarchyForLayout(subview)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Passes mouseDown events from this view to window.performDrag so that you can drag the window by it.
|
||||
fileprivate class WindowDragView: NSView {
|
||||
override public func mouseDown(with event: NSEvent) {
|
||||
// Drag the window for single left clicks, double clicks should bypass the drag handle.
|
||||
if (event.type == .leftMouseDown && event.clickCount == 1) {
|
||||
window?.performDrag(with: event)
|
||||
NSCursor.closedHand.set()
|
||||
} else {
|
||||
super.mouseDown(with: event)
|
||||
}
|
||||
}
|
||||
|
||||
override public func mouseEntered(with event: NSEvent) {
|
||||
super.mouseEntered(with: event)
|
||||
window?.disableCursorRects()
|
||||
NSCursor.openHand.set()
|
||||
}
|
||||
|
||||
override func mouseExited(with event: NSEvent) {
|
||||
super.mouseExited(with: event)
|
||||
window?.enableCursorRects()
|
||||
NSCursor.arrow.set()
|
||||
}
|
||||
|
||||
override func resetCursorRects() {
|
||||
addCursorRect(bounds, cursor: .openHand)
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ extension Ghostty {
|
||||
/// Return the errors found while loading the configuration.
|
||||
var errors: [String] {
|
||||
guard let cfg = self.config else { return [] }
|
||||
|
||||
|
||||
var errors: [String] = [];
|
||||
let errCount = ghostty_config_errors_count(cfg)
|
||||
for i in 0..<errCount {
|
||||
@ -29,7 +29,7 @@ extension Ghostty {
|
||||
let message = String(cString: err.message)
|
||||
errors.append(message)
|
||||
}
|
||||
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ extension Ghostty {
|
||||
guard let ptr = v else { return "" }
|
||||
return String(cString: ptr)
|
||||
}
|
||||
|
||||
|
||||
var windowNewTabPosition: String {
|
||||
guard let config = self.config else { return "" }
|
||||
var v: UnsafePointer<Int8>? = nil
|
||||
@ -164,7 +164,7 @@ extension Ghostty {
|
||||
guard let ptr = v else { return "" }
|
||||
return String(cString: ptr)
|
||||
}
|
||||
|
||||
|
||||
var windowDecorations: Bool {
|
||||
guard let config = self.config else { return true }
|
||||
var v = false;
|
||||
@ -198,30 +198,38 @@ extension Ghostty {
|
||||
return v
|
||||
}
|
||||
|
||||
var macosTitlebarTabs: Bool {
|
||||
guard let config = self.config else { return false }
|
||||
var v = false;
|
||||
let key = "macos-titlebar-tabs"
|
||||
_ = ghostty_config_get(config, &v, key, UInt(key.count))
|
||||
return v
|
||||
}
|
||||
|
||||
var backgroundColor: Color {
|
||||
var rgb: UInt32 = 0
|
||||
let bg_key = "background"
|
||||
if (!ghostty_config_get(config, &rgb, bg_key, UInt(bg_key.count))) {
|
||||
#if os(macOS)
|
||||
#if os(macOS)
|
||||
return Color(NSColor.windowBackgroundColor)
|
||||
#elseif os(iOS)
|
||||
#elseif os(iOS)
|
||||
return Color(UIColor.systemBackground)
|
||||
#else
|
||||
#error("unsupported")
|
||||
#endif
|
||||
#else
|
||||
#error("unsupported")
|
||||
#endif
|
||||
}
|
||||
|
||||
let red = Double(rgb & 0xff)
|
||||
let green = Double((rgb >> 8) & 0xff)
|
||||
let blue = Double((rgb >> 16) & 0xff)
|
||||
|
||||
|
||||
return Color(
|
||||
red: red / 255,
|
||||
green: green / 255,
|
||||
blue: blue / 255
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
var backgroundOpacity: Double {
|
||||
guard let config = self.config else { return 1 }
|
||||
var v: Double = 1
|
||||
@ -247,11 +255,11 @@ extension Ghostty {
|
||||
let bg_key = "background"
|
||||
_ = ghostty_config_get(config, &rgb, bg_key, UInt(bg_key.count));
|
||||
}
|
||||
|
||||
|
||||
let red = Double(rgb & 0xff)
|
||||
let green = Double((rgb >> 8) & 0xff)
|
||||
let blue = Double((rgb >> 16) & 0xff)
|
||||
|
||||
|
||||
return Color(
|
||||
red: red / 255,
|
||||
green: green / 255,
|
||||
|
@ -882,15 +882,32 @@ keybind: Keybinds = .{},
|
||||
/// using a new space. It's faster than the native fullscreen mode since it
|
||||
/// doesn't use animations.
|
||||
///
|
||||
/// Warning: tabs do not work with a non-native fullscreen window. This
|
||||
/// can be fixed but is looking for contributors to help. See issue #392.
|
||||
///
|
||||
/// Allowable values are:
|
||||
///
|
||||
/// * `visible-menu` - Use non-native macOS fullscreen, keep the menu bar visible
|
||||
///
|
||||
/// * `true` - Use non-native macOS fullscreen, hide the menu bar
|
||||
///
|
||||
/// * `false` - Use native macOS fullscreeen
|
||||
///
|
||||
@"macos-non-native-fullscreen": NonNativeFullscreen = .false,
|
||||
|
||||
/// If `true`, places the tab bar in the titlebar for tabbed windows.
|
||||
///
|
||||
/// When this is true, the titlebar will also always appear even when
|
||||
/// fullscreen (native fullscreen) with only one tab. This is not considered
|
||||
/// a bug but if you'd like to improve this behavior then I'm open to it and
|
||||
/// please contribute to the project.
|
||||
///
|
||||
/// This option intercepts the native tab bar view from macOS and forces it to use
|
||||
/// different positioning. Because of this, it might be buggy or break entirely if
|
||||
/// macOS changes the way its native tab bar view is constructed or managed.
|
||||
/// This has been tested on macOS 14.
|
||||
///
|
||||
/// This option only applies to new windows when changed.
|
||||
@"macos-titlebar-tabs": bool = false,
|
||||
|
||||
/// If `true`, the *Option* key will be treated as *Alt*. This makes terminal
|
||||
/// sequences expecting *Alt* to work properly, but will break Unicode input
|
||||
/// sequences on macOS if you use them via the *Alt* key. You may set this to
|
||||
|
Reference in New Issue
Block a user