From c6da845f33e54d6bcae2eb5491337b06e8e10982 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 11 Feb 2025 11:11:41 -0800 Subject: [PATCH] macos: ensure previously key window regains key on toggle_visibility Fixes #5690 When we hide the app and then show it again, the previously key window is lost. This is because we are not using unhide and are manually doing it (and we're not using unhide for good reasons commented in the source already). Modify our hidden state to include what the key window was (as a weak ref) and restore it when we show the app again. --- macos/Sources/App/macOS/AppDelegate.swift | 49 +++++++++++++++++------ 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/macos/Sources/App/macOS/AppDelegate.swift b/macos/Sources/App/macOS/AppDelegate.swift index c6d723a5f..9d300e91f 100644 --- a/macos/Sources/App/macOS/AppDelegate.swift +++ b/macos/Sources/App/macOS/AppDelegate.swift @@ -93,7 +93,7 @@ class AppDelegate: NSObject, } /// Tracks the windows that we hid for toggleVisibility. - private var hiddenWindows: [Weak] = [] + private var hiddenState: ToggleVisibilityState? = nil /// The observer for the app appearance. private var appearanceObserver: NSKeyValueObservation? = nil @@ -217,8 +217,8 @@ class AppDelegate: NSObject, } func applicationDidBecomeActive(_ notification: Notification) { - // If we're back then clear the hidden windows - self.hiddenWindows = [] + // If we're back manually then clear the hidden state because macOS handles it. + self.hiddenState = nil // First launch stuff if (!applicationHasBecomeActive) { @@ -716,14 +716,8 @@ class AppDelegate: NSObject, guard let keyWindow = NSApp.keyWindow, !keyWindow.styleMask.contains(.fullScreen) else { return } - // We need to keep track of the windows that were visible because we only - // want to bring back these windows if we remove the toggle. - // - // We also ignore fullscreen windows because they don't hide anyways. - self.hiddenWindows = NSApp.windows.filter { - $0.isVisible && - !$0.styleMask.contains(.fullScreen) - }.map { Weak($0) } + // Keep track of our hidden state to restore properly + self.hiddenState = .init() NSApp.hide(nil) return } @@ -734,8 +728,8 @@ class AppDelegate: NSObject, // Bring all windows to the front. Note: we don't use NSApp.unhide because // that will unhide ALL hidden windows. We want to only bring forward the // ones that we hid. - self.hiddenWindows.forEach { $0.value?.orderFrontRegardless() } - self.hiddenWindows = [] + hiddenState?.restore() + hiddenState = nil } private struct DerivedConfig { @@ -755,4 +749,33 @@ class AppDelegate: NSObject, self.quickTerminalPosition = config.quickTerminalPosition } } + + private struct ToggleVisibilityState { + let hiddenWindows: [Weak] + let keyWindow: Weak? + + init() { + // We need to know the key window so that we can bring focus back to the + // right window if it was hidden. + self.keyWindow = if let keyWindow = NSApp.keyWindow { + .init(keyWindow) + } else { + nil + } + + // We need to keep track of the windows that were visible because we only + // want to bring back these windows if we remove the toggle. + // + // We also ignore fullscreen windows because they don't hide anyways. + self.hiddenWindows = NSApp.windows.filter { + $0.isVisible && + !$0.styleMask.contains(.fullScreen) + }.map { Weak($0) } + } + + func restore() { + hiddenWindows.forEach { $0.value?.orderFrontRegardless() } + keyWindow?.value?.makeKey() + } + } }