macos: ensure previously key window regains key on toggle_visibility (#5692)

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.
This commit is contained in:
Mitchell Hashimoto
2025-02-11 11:23:48 -08:00
committed by GitHub

View File

@ -93,7 +93,7 @@ class AppDelegate: NSObject,
}
/// Tracks the windows that we hid for toggleVisibility.
private var hiddenWindows: [Weak<NSWindow>] = []
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<NSWindow>]
let keyWindow: Weak<NSWindow>?
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()
}
}
}