Merge pull request #1458 from qwerasd205/macos-fix-title-label

(macOS) Fixed/improved titlebar tabs custom title label handling
This commit is contained in:
Mitchell Hashimoto
2024-02-04 15:41:38 -08:00
committed by GitHub
2 changed files with 45 additions and 18 deletions

View File

@ -4,7 +4,7 @@ import Cocoa
// in order to accommodate the titlebar tabs feature. // in order to accommodate the titlebar tabs feature.
class TerminalToolbar: NSToolbar, NSToolbarDelegate { class TerminalToolbar: NSToolbar, NSToolbarDelegate {
static private let identifier = NSToolbarItem.Identifier("TitleText") static private let identifier = NSToolbarItem.Identifier("TitleText")
private let titleTextField = NSTextField(labelWithString: "👻 Ghostty") private let titleTextField = CenteredDynamicLabel(labelWithString: "👻 Ghostty")
var titleText: String { var titleText: String {
get { get {
@ -31,19 +31,55 @@ class TerminalToolbar: NSToolbar, NSToolbarDelegate {
func toolbar(_ toolbar: NSToolbar, func toolbar(_ toolbar: NSToolbar,
itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier,
willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? { 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) let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
toolbarItem.isEnabled = true
toolbarItem.view = self.titleTextField 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: 32, height: 1)
toolbarItem.maxSize = NSSize(width: 1024, height: self.titleTextField.intrinsicContentSize.height)
toolbarItem.isEnabled = true
return toolbarItem return toolbarItem
} }
func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
return [Self.identifier] return [Self.identifier, .space]
} }
func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { 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.
fileprivate class CenteredDynamicLabel: NSTextField {
override func viewDidMoveToSuperview() {
// Truncate the title when it gets too long, cutting it off with an ellipsis.
cell?.truncatesLastVisibleLine = true
cell?.lineBreakMode = .byCharWrapping
// 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
} }
} }

View File

@ -45,19 +45,10 @@ class TerminalWindow: NSWindow {
self.toolbar = TerminalToolbar(identifier: "Toolbar") self.toolbar = TerminalToolbar(identifier: "Toolbar")
} }
// We directly hide the view containing the title text because if we use the // We have to wait before setting the titleVisibility or else it prevents
// `titleVisibility` property for this it prevents the window from hiding the // the window from hiding the tab bar when we get down to a single tab.
// tab bar when we get down to a single tab. DispatchQueue.main.async {
if let toolbarTitleView = contentView?.superview?.subviews.first(where: { self.titleVisibility = .hidden
$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 { } else {
// "expanded" places the toolbar below the titlebar, so setting this style and // "expanded" places the toolbar below the titlebar, so setting this style and