diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index 8ad1509d5..0c1417cd0 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -59,7 +59,30 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele let center = NotificationCenter.default center.removeObserver(self) } - + + /// Update the accessory view of each tab according to the keyboard + /// shortcut that activates it (if any). This is called when the key window + /// changes and when a window is closed. + func relabelTabs() { + guard let windows = self.window?.tabbedWindows else { return } + guard let cfg = ghostty.config else { return } + for (index, window) in windows.enumerated().prefix(9) { + let action = "goto_tab:\(index + 1)" + let trigger = ghostty_config_trigger(cfg, action, UInt(action.count)) + guard let equiv = Ghostty.keyEquivalentLabel(key: trigger.key, mods: trigger.mods) else { + continue + } + + let attributes: [NSAttributedString.Key: Any] = [ + .font: NSFont.labelFont(ofSize: 0), + .foregroundColor: window.isKeyWindow ? NSColor.labelColor : NSColor.secondaryLabelColor, + ] + let attributedString = NSAttributedString(string: " \(equiv) ", attributes: attributes) + let text = NSTextField(labelWithAttributedString: attributedString) + window.tab.accessoryView = text + } + } + //MARK: - NSWindowController override func windowWillLoad() { @@ -144,8 +167,14 @@ class TerminalController: NSWindowController, NSWindowDelegate, TerminalViewDele // the view and the window so we had to nil this out to break it but I think this // may now be resolved. We should verify that no memory leaks and we can remove this. self.window?.contentView = nil + + self.relabelTabs() } - + + func windowDidBecomeKey(_ notification: Notification) { + self.relabelTabs() + } + //MARK: - First Responder @IBAction func newWindow(_ sender: Any?) { diff --git a/macos/Sources/Features/Terminal/TerminalManager.swift b/macos/Sources/Features/Terminal/TerminalManager.swift index e904630be..d078bc24f 100644 --- a/macos/Sources/Features/Terminal/TerminalManager.swift +++ b/macos/Sources/Features/Terminal/TerminalManager.swift @@ -87,7 +87,6 @@ class TerminalManager { // Create a new window and add it to the parent let window = createWindow(withBaseConfig: base).window! parent.addTabbedWindow(window, ordered: .above) - relabelTabs(parent) window.makeKeyAndOrderFront(self) } @@ -95,7 +94,13 @@ class TerminalManager { private func createWindow(withBaseConfig base: Ghostty.SurfaceConfiguration?) -> TerminalController { // Initialize our controller to load the window let c = TerminalController(ghostty, withBaseConfig: base) - + + // For new windows, explicitly disallow tabbing with other windows. + // This overrides the value of userTabbingPreference. Rationale: + // Ghostty provides separate "New Tab" and "New Window" actions so + // there's no reason to make "New Window" open in a tab. + c.window!.tabbingMode = .disallowed; + // Create a listener for when the window is closed so we can remove it. let pubClose = NotificationCenter.default.publisher( for: NSWindow.willCloseNotification, @@ -124,12 +129,6 @@ class TerminalManager { // Ensure any publishers we have are cancelled w.closePublisher.cancel() - // Removing the window can change tabs, so we need to relabel all tabs. - // At this point, the window is already removed from the tab bar so - // I don't know a way to only relabel the active tab bar, so just relabel - // all of them. - relabelAllTabs() - // If we remove a window, we reset the cascade point to the key window so that // the next window cascade's from that one. if let focusedWindow = NSApplication.shared.keyWindow { @@ -151,32 +150,7 @@ class TerminalManager { /// Relabels all the tabs with the proper keyboard shortcut. func relabelAllTabs() { for w in windows { - if let window = w.controller.window { - relabelTabs(window) - } - } - } - - /// Update the accessory view of each tab according to the keyboard - /// shortcut that activates it (if any). This is called when the key window - /// changes and when a window is closed. - private func relabelTabs(_ window: NSWindow) { - guard let windows = window.tabbedWindows else { return } - guard let cfg = ghostty.config else { return } - for (index, window) in windows.enumerated().prefix(9) { - let action = "goto_tab:\(index + 1)" - let trigger = ghostty_config_trigger(cfg, action, UInt(action.count)) - guard let equiv = Ghostty.keyEquivalentLabel(key: trigger.key, mods: trigger.mods) else { - continue - } - - let attributes: [NSAttributedString.Key: Any] = [ - .font: NSFont.labelFont(ofSize: 0), - .foregroundColor: window.isKeyWindow ? NSColor.labelColor : NSColor.secondaryLabelColor, - ] - let attributedString = NSAttributedString(string: " \(equiv) ", attributes: attributes) - let text = NSTextField(labelWithAttributedString: attributedString) - window.tab.accessoryView = text + w.controller.relabelTabs() } }