From f736ee88657420f09b0e7139de8bd2c6d721a8e0 Mon Sep 17 00:00:00 2001 From: Aljoscha Krettek Date: Fri, 18 Jul 2025 14:52:58 +0200 Subject: [PATCH] macos: in new_window action, activate App MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change makes sure that the new window is focused and visible. When commit 33d128bcff2ee529359a844bde50c3aa9dfed460 removed the TerminalManager class and moved its functionality into TerminalController, it accidentally removed app activation for windows triggered by global keybinds. How the bug works: 1. Menu actions (like File → New Window) call AppDelegate.newWindow() which: 2. Calls TerminalController.newWindow() 3. AND explicitly calls NSApp.activate(ignoringOtherApps: true) in the AppDelegate 4. Global keybind actions trigger ghosttyNewWindow() notification handler which: 5. Only calls TerminalController.newWindow() 6. Does NOT call NSApp.activate(ignoringOtherApps: true) 7. While TerminalController.newWindow() does call NSApp.activate(ignoringOtherApps: true) internally, this call happens before the async dispatch that shows the window, so the activation occurs but the window isn't focused when it's actually shown. 8. In the old TerminalManager.newWindow(), the activation happened immediately before the async dispatch, ensuring proper timing for window focus. The fix would be to either move the NSApp.activate() call back into TerminalController.newWindow(), as it was for TerminalManager, or add the activation call to the notification handlers in AppDelegate. --- macos/Sources/Features/Terminal/TerminalController.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index c5e1c413f..7a11ac3ae 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -214,6 +214,10 @@ class TerminalController: BaseTerminalController, TabGroupCloseCoordinator.Contr } } + // All new_window actions force our app to be active, so that the new + // window is focused and visible. + NSApp.activate(ignoringOtherApps: true) + // We're dispatching this async because otherwise the lastCascadePoint doesn't // take effect. Our best theory is there is some next-event-loop-tick logic // that Cocoa is doing that we need to be after.