macOS: fix focus loss when toggling non-native fullscreen mode

This commit is contained in:
Bryan Lee
2025-04-27 03:07:36 +08:00
parent 38445dca2a
commit a9a95e809b
2 changed files with 25 additions and 11 deletions

View File

@ -362,11 +362,17 @@ class BaseTerminalController: NSWindowController,
} }
func fullscreenDidChange() { func fullscreenDidChange() {
// For some reason focus can get lost when we change fullscreen. Regardless of // If we are in on-native fullscreen, try to restore the surface
// mode above we just move it back. // that was focused *before* entering fullscreen
if let focusedSurface { // See: https://github.com/ghostty-org/ghostty/pull/7201
Ghostty.moveFocus(to: focusedSurface) let preferredSurface = (fullscreenStyle as? NonNativeFullscreen)
} .flatMap { $0.isFullscreen ? $0.getSavedFocusedSurface() : nil }
guard let surface = preferredSurface ?? focusedSurface else { return }
// For some reason focus can get lost when we change fullscreen.
// Regardless of mode above we just move it back.
Ghostty.moveFocus(to: surface)
} }
// MARK: Clipboard Confirmation // MARK: Clipboard Confirmation

View File

@ -258,14 +258,16 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
} }
} }
// Unset our saved state, we're restored!
self.savedState = nil
// Focus window // Focus window
window.makeKeyAndOrderFront(nil) window.makeKeyAndOrderFront(nil)
// Notify the delegate // Notify the delegate BEFORE unsetting the saved state
// This way fullscreenDidChange() can still access savedState.focusedSurface
// See: https://github.com/ghostty-org/ghostty/pull/7201
self.delegate?.fullscreenDidChange() self.delegate?.fullscreenDidChange()
// Unset our saved state, we're restored!
self.savedState = nil
} }
private func fullscreenFrame(_ screen: NSScreen) -> NSRect { private func fullscreenFrame(_ screen: NSScreen) -> NSRect {
@ -315,6 +317,10 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
exit() exit()
} }
func getSavedFocusedSurface() -> Ghostty.SurfaceView? {
return savedState?.focusedSurface
}
// MARK: Dock // MARK: Dock
private func hideDock() { private func hideDock() {
@ -344,6 +350,7 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
let styleMask: NSWindow.StyleMask let styleMask: NSWindow.StyleMask
let dock: Bool let dock: Bool
let menu: Bool let menu: Bool
let focusedSurface: Ghostty.SurfaceView?
init?(_ window: NSWindow) { init?(_ window: NSWindow) {
guard let contentView = window.contentView else { return nil } guard let contentView = window.contentView else { return nil }
@ -354,6 +361,7 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle {
self.contentFrame = window.convertToScreen(contentView.frame) self.contentFrame = window.convertToScreen(contentView.frame)
self.styleMask = window.styleMask self.styleMask = window.styleMask
self.dock = window.screen?.hasDock ?? false self.dock = window.screen?.hasDock ?? false
self.focusedSurface = (window as? TerminalWindow)?.windowController.flatMap { $0 as? BaseTerminalController }?.focusedSurface
// We hide the menu only if this window is not on any fullscreen // We hide the menu only if this window is not on any fullscreen
// spaces. We do this because fullscreen spaces already hide the // spaces. We do this because fullscreen spaces already hide the