diff --git a/macos/Sources/Features/Terminal/BaseTerminalController.swift b/macos/Sources/Features/Terminal/BaseTerminalController.swift index b502e56e0..36dc5f93c 100644 --- a/macos/Sources/Features/Terminal/BaseTerminalController.swift +++ b/macos/Sources/Features/Terminal/BaseTerminalController.swift @@ -361,14 +361,6 @@ class BaseTerminalController: NSWindowController, } } - func fullscreenDidChange() { - // For some reason focus can get lost when we change fullscreen. Regardless of - // mode above we just move it back. - if let focusedSurface { - Ghostty.moveFocus(to: focusedSurface) - } - } - // MARK: Clipboard Confirmation @objc private func onConfirmClipboardRequest(notification: SwiftUI.Notification) { diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index f384b97ed..cf2dd3348 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -121,9 +121,7 @@ class TerminalController: BaseTerminalController { } - override func fullscreenDidChange() { - super.fullscreenDidChange() - + func fullscreenDidChange() { // When our fullscreen state changes, we resync our appearance because some // properties change when fullscreen or not. guard let focusedSurface else { return } diff --git a/macos/Sources/Helpers/Fullscreen.swift b/macos/Sources/Helpers/Fullscreen.swift index 5233af62d..6094bf844 100644 --- a/macos/Sources/Helpers/Fullscreen.swift +++ b/macos/Sources/Helpers/Fullscreen.swift @@ -171,6 +171,13 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle { guard let savedState = SavedState(window) else { return } self.savedState = savedState + // Get our current first responder on this window. For non-native fullscreen + // we have to restore this because for some reason the operations below + // lose it (see: https://github.com/ghostty-org/ghostty/issues/6999). + // I don't know the root cause here so if we can figure that out there may + // be a nicer way than this. + let firstResponder = window.firstResponder + // We hide the dock if the window is on a screen with the dock. // We must hide the dock FIRST then hide the menu: // If you specify autoHideMenuBar, it must be accompanied by either hideDock or autoHideDock. @@ -207,6 +214,10 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle { // https://github.com/ghostty-org/ghostty/issues/1996 DispatchQueue.main.async { self.window.setFrame(self.fullscreenFrame(screen), display: true) + if let firstResponder { + self.window.makeFirstResponder(firstResponder) + } + self.delegate?.fullscreenDidChange() } } @@ -220,6 +231,9 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle { let center = NotificationCenter.default center.removeObserver(self, name: NSWindow.didChangeScreenNotification, object: window) + // See enter where we do the same thing to understand why. + let firstResponder = window.firstResponder + // Unhide our elements if savedState.dock { unhideDock() @@ -258,6 +272,10 @@ class NonNativeFullscreen: FullscreenBase, FullscreenStyle { } } + if let firstResponder { + window.makeFirstResponder(firstResponder) + } + // Unset our saved state, we're restored! self.savedState = nil