From 4d335a220f8ef52291ca1f61c82fc5df82b5863e Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Sun, 4 Feb 2024 16:55:07 -0500 Subject: [PATCH 1/4] fix(macOS): Adjust custom toolbar title to fix clipping problems. --- .../Features/Terminal/TerminalToolbar.swift | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalToolbar.swift b/macos/Sources/Features/Terminal/TerminalToolbar.swift index 5b4760642..ba73f3adc 100644 --- a/macos/Sources/Features/Terminal/TerminalToolbar.swift +++ b/macos/Sources/Features/Terminal/TerminalToolbar.swift @@ -4,7 +4,7 @@ import Cocoa // 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") + private let titleTextField = CenteredDynamicLabel(labelWithString: "👻 Ghostty") var titleText: String { get { @@ -34,8 +34,22 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { guard itemIdentifier == Self.identifier else { return nil } let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier) - toolbarItem.isEnabled = true toolbarItem.view = self.titleTextField + toolbarItem.visibilityPriority = .user + + // NSToolbarItem.minSize and NSToolbarItem.maxSize are deprecated, and make big ugly + // warnings in Xcode when you use them, but I cannot for the life of me figure out + // how to get this to work with constraints. The behavior isn't the same, instead of + // shrinking the item and clipping the subview, it hides the item as soon as the + // intrinsic size of the subview gets too big for the toolbar width, regardless of + // whether I have constraints set on its width, height, or both :/ + // + // If someone can fix this so we don't have to use deprecated properties: Please do. + toolbarItem.minSize = NSSize(width: 65, height: 1) + toolbarItem.maxSize = NSSize(width: 1024, height: self.titleTextField.intrinsicContentSize.height) + + toolbarItem.isEnabled = true + return toolbarItem } @@ -47,3 +61,15 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { return [Self.identifier] } } + +class CenteredDynamicLabel: NSTextField { + override func viewDidMoveToSuperview() { + guard let superview = superview else { return } + widthAnchor.constraint(equalTo: superview.widthAnchor).isActive = true + centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true + + alignment = .center + + needsLayout = true + } +} From fdab397c61c53ce08ac290ab0a864aa6941a7bc9 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Sun, 4 Feb 2024 16:55:18 -0500 Subject: [PATCH 2/4] macOS: Simplify native title hiding logic for titlebar tabs. --- .../Features/Terminal/TerminalWindow.swift | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalWindow.swift b/macos/Sources/Features/Terminal/TerminalWindow.swift index 7db4db42e..d9951ea56 100644 --- a/macos/Sources/Features/Terminal/TerminalWindow.swift +++ b/macos/Sources/Features/Terminal/TerminalWindow.swift @@ -45,19 +45,10 @@ class TerminalWindow: NSWindow { 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 + // We have to wait before setting the titleVisibility or else it prevents + // the window from hiding the tab bar when we get down to a single tab. + DispatchQueue.main.async { + self.titleVisibility = .hidden } } else { // "expanded" places the toolbar below the titlebar, so setting this style and From a121549f321424905a477c977981da2ac6fd0e84 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Sun, 4 Feb 2024 17:56:08 -0500 Subject: [PATCH 3/4] macOS: Improve custom title label centering and overflow appearance. --- .../Features/Terminal/TerminalToolbar.swift | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalToolbar.swift b/macos/Sources/Features/Terminal/TerminalToolbar.swift index ba73f3adc..5f100c624 100644 --- a/macos/Sources/Features/Terminal/TerminalToolbar.swift +++ b/macos/Sources/Features/Terminal/TerminalToolbar.swift @@ -31,7 +31,9 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { - guard itemIdentifier == Self.identifier else { return nil } + guard itemIdentifier == Self.identifier else { + return NSToolbarItem(itemIdentifier: itemIdentifier) + } let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier) toolbarItem.view = self.titleTextField @@ -45,7 +47,7 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { // whether I have constraints set on its width, height, or both :/ // // If someone can fix this so we don't have to use deprecated properties: Please do. - toolbarItem.minSize = NSSize(width: 65, height: 1) + toolbarItem.minSize = NSSize(width: 32, height: 1) toolbarItem.maxSize = NSSize(width: 1024, height: self.titleTextField.intrinsicContentSize.height) toolbarItem.isEnabled = true @@ -54,22 +56,30 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { } func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - return [Self.identifier] + return [Self.identifier, .space] } func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { - return [Self.identifier] + // These space items are here to ensure that the title remains centered when it starts + // getting smaller than the max size so starts clipping. Lucky for us, three of the + // built-in spacers seems to exactly match the space on the left that's reserved for + // the window buttons. + return [Self.identifier, .space, .space, .space] } } +/// A label that expands to fit whatever text you put in it and horizontally centers itself in the current window. class CenteredDynamicLabel: NSTextField { override func viewDidMoveToSuperview() { - guard let superview = superview else { return } - widthAnchor.constraint(equalTo: superview.widthAnchor).isActive = true - centerXAnchor.constraint(equalTo: superview.centerXAnchor).isActive = true + // Truncate the title when it gets too long- cutting it off with an ellipsis. + cell?.truncatesLastVisibleLine = true + cell?.lineBreakMode = .byCharWrapping - alignment = .center + // Make the text field as small as possible while fitting its text. + setContentHuggingPriority(.required, for: .horizontal) + cell?.alignment = .center + // We've changed some alignment settings, make sure the layout is updated immediately. needsLayout = true } } From bd38689539cb20836fe13862fd2e9de0cf087ff5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 4 Feb 2024 15:41:15 -0800 Subject: [PATCH 4/4] macos: make label fileprivate --- macos/Sources/Features/Terminal/TerminalToolbar.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalToolbar.swift b/macos/Sources/Features/Terminal/TerminalToolbar.swift index 5f100c624..b0857cb24 100644 --- a/macos/Sources/Features/Terminal/TerminalToolbar.swift +++ b/macos/Sources/Features/Terminal/TerminalToolbar.swift @@ -69,9 +69,9 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate { } /// A label that expands to fit whatever text you put in it and horizontally centers itself in the current window. -class CenteredDynamicLabel: NSTextField { +fileprivate class CenteredDynamicLabel: NSTextField { override func viewDidMoveToSuperview() { - // Truncate the title when it gets too long- cutting it off with an ellipsis. + // Truncate the title when it gets too long, cutting it off with an ellipsis. cell?.truncatesLastVisibleLine = true cell?.lineBreakMode = .byCharWrapping