mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-05 19:08:17 +00:00
macos: tahoe terminal tabs shows title
This commit is contained in:
@@ -18,7 +18,7 @@ class TerminalController: BaseTerminalController {
|
||||
case "tabs":
|
||||
if #available(macOS 26.0, *) {
|
||||
// TODO: Switch to Tahoe when ready
|
||||
"TerminalTabsTitlebarVentura"
|
||||
"TerminalTabsTitlebarTahoe"
|
||||
} else {
|
||||
"TerminalTabsTitlebarVentura"
|
||||
}
|
||||
@@ -409,15 +409,15 @@ class TerminalController: BaseTerminalController {
|
||||
// We need to clear any windows beyond this because they have had
|
||||
// a keyEquivalent set previously.
|
||||
guard tab <= 9 else {
|
||||
window.keyEquivalent2 = ""
|
||||
window.keyEquivalent = ""
|
||||
continue
|
||||
}
|
||||
|
||||
let action = "goto_tab:\(tab)"
|
||||
if let equiv = ghostty.config.keyboardShortcut(for: action) {
|
||||
window.keyEquivalent2 = "\(equiv)"
|
||||
window.keyEquivalent = "\(equiv)"
|
||||
} else {
|
||||
window.keyEquivalent2 = ""
|
||||
window.keyEquivalent = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -82,17 +82,16 @@ class TerminalWindow: NSWindow {
|
||||
|
||||
// MARK: Tab Key Equivalents
|
||||
|
||||
// TODO: rename once Legacy window removes
|
||||
var keyEquivalent2: String? = nil {
|
||||
var keyEquivalent: String? = nil {
|
||||
didSet {
|
||||
// When our key equivalent is set, we must update the tab label.
|
||||
guard let keyEquivalent2 else {
|
||||
guard let keyEquivalent else {
|
||||
keyEquivalentLabel.attributedStringValue = NSAttributedString()
|
||||
return
|
||||
}
|
||||
|
||||
keyEquivalentLabel.attributedStringValue = NSAttributedString(
|
||||
string: "\(keyEquivalent2) ",
|
||||
string: "\(keyEquivalent) ",
|
||||
attributes: [
|
||||
.font: NSFont.systemFont(ofSize: NSFont.smallSystemFontSize),
|
||||
.foregroundColor: isKeyWindow ? NSColor.labelColor : NSColor.secondaryLabelColor,
|
||||
|
@@ -3,6 +3,9 @@ import SwiftUI
|
||||
|
||||
/// `macos-titlebar-style = tabs` for macOS 26 (Tahoe) and later.
|
||||
class TitlebarTabsTahoeTerminalWindow: TerminalWindow, NSToolbarDelegate {
|
||||
/// The view model for SwiftUI views
|
||||
private var viewModel = ViewModel()
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
@@ -15,7 +18,23 @@ class TitlebarTabsTahoeTerminalWindow: TerminalWindow, NSToolbarDelegate {
|
||||
toolbar.delegate = self
|
||||
toolbar.centeredItemIdentifiers.insert(.title)
|
||||
self.toolbar = toolbar
|
||||
//toolbarStyle = .unifiedCompact
|
||||
toolbarStyle = .unifiedCompact
|
||||
}
|
||||
|
||||
// MARK: NSWindow
|
||||
|
||||
override var title: String {
|
||||
didSet {
|
||||
viewModel.title = title
|
||||
}
|
||||
}
|
||||
|
||||
override func update() {
|
||||
super.update()
|
||||
|
||||
if let glass = titlebarContainer?.firstDescendant(withClassName: "NSGlassContainerView") {
|
||||
glass.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: NSToolbarDelegate
|
||||
@@ -34,7 +53,7 @@ class TitlebarTabsTahoeTerminalWindow: TerminalWindow, NSToolbarDelegate {
|
||||
switch itemIdentifier {
|
||||
case .title:
|
||||
let item = NSToolbarItem(itemIdentifier: .title)
|
||||
item.view = NSHostingView(rootView: TitleItem())
|
||||
item.view = NSHostingView(rootView: TitleItem(viewModel: viewModel))
|
||||
item.visibilityPriority = .user
|
||||
item.isEnabled = true
|
||||
return item
|
||||
@@ -43,6 +62,11 @@ class TitlebarTabsTahoeTerminalWindow: TerminalWindow, NSToolbarDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: SwiftUI
|
||||
|
||||
class ViewModel: ObservableObject {
|
||||
@Published var title: String = "👻 Ghostty"
|
||||
}
|
||||
}
|
||||
|
||||
extension NSToolbarItem.Identifier {
|
||||
@@ -51,9 +75,21 @@ extension NSToolbarItem.Identifier {
|
||||
}
|
||||
|
||||
extension TitlebarTabsTahoeTerminalWindow {
|
||||
/// Displays the window title
|
||||
struct TitleItem: View {
|
||||
@ObservedObject var viewModel: ViewModel
|
||||
|
||||
var title: String {
|
||||
// An empty title makes this view zero-sized and NSToolbar on macOS
|
||||
// tahoe just deletes the item when that happens. So we use a space
|
||||
// instead to ensure there's always some size.
|
||||
viewModel.title.isEmpty ? " " : viewModel.title
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Text("HELLO THIS IS A PRETTY LONG TITLE")
|
||||
Text(title)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user