From 5f9d4f9733b7638d191e6e948f0d436255e83b63 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 30 Sep 2024 10:02:34 -0700 Subject: [PATCH] macos: fullscreen=true with non-native fullscreen works Fixes #1377 --- .../Terminal/TerminalController.swift | 53 ++++++++++--------- .../Features/Terminal/TerminalManager.swift | 28 ++++++---- macos/Sources/Ghostty/Ghostty.Config.swift | 20 +++++++ 3 files changed, 67 insertions(+), 34 deletions(-) diff --git a/macos/Sources/Features/Terminal/TerminalController.swift b/macos/Sources/Features/Terminal/TerminalController.swift index 873b93bcb..97d4b769d 100644 --- a/macos/Sources/Features/Terminal/TerminalController.swift +++ b/macos/Sources/Features/Terminal/TerminalController.swift @@ -199,6 +199,34 @@ class TerminalController: BaseTerminalController } } + /// Toggle fullscreen for the given mode. + func toggleFullscreen(mode: FullscreenMode) { + // We need a window to fullscreen + guard let window = self.window else { return } + + // TODO: handle changing fullscreen modes at runtime + // This is where we'd handle this. + + // Initialize our style for the window. This may fail for various reasons so + // we also guard below. + if self.fullscreenStyle == nil { + self.fullscreenStyle = mode.style(for: window) + } + guard let fullscreenStyle else { return } + + if fullscreenStyle.isFullscreen { + fullscreenStyle.exit() + } else { + fullscreenStyle.enter() + } + + // 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: - NSWindowController override func windowWillLoad() { @@ -531,9 +559,6 @@ class TerminalController: BaseTerminalController guard let target = notification.object as? Ghostty.SurfaceView else { return } guard target == self.focusedSurface else { return } - // We need a window to fullscreen - guard let window = self.window else { return } - // Get the fullscreen mode we want to toggle let fullscreenMode: FullscreenMode if let any = notification.userInfo?[Ghostty.Notification.FullscreenModeKey], @@ -544,26 +569,6 @@ class TerminalController: BaseTerminalController return } - // TODO: handle changing fullscreen modes at runtime - // This is where we'd handle this. - - // Initialize our style for the window. This may fail for various reasons so - // we also guard below. - if self.fullscreenStyle == nil { - self.fullscreenStyle = fullscreenMode.style(for: window) - } - guard let fullscreenStyle else { return } - - if fullscreenStyle.isFullscreen { - fullscreenStyle.exit() - } else { - fullscreenStyle.enter() - } - - // 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) - } + toggleFullscreen(mode: fullscreenMode) } } diff --git a/macos/Sources/Features/Terminal/TerminalManager.swift b/macos/Sources/Features/Terminal/TerminalManager.swift index 6e246de83..f71e198ee 100644 --- a/macos/Sources/Features/Terminal/TerminalManager.swift +++ b/macos/Sources/Features/Terminal/TerminalManager.swift @@ -65,17 +65,25 @@ class TerminalManager { let c = createWindow(withBaseConfig: base) let window = c.window! - // We want to go fullscreen if we're configured for new windows to go fullscreen - var toggleFullScreen = ghostty.config.windowFullscreen - - // If the previous focused window prior to creating this window is fullscreen, - // then this window also becomes fullscreen. - if let parent = focusedSurface?.window, parent.styleMask.contains(.fullScreen) { - toggleFullScreen = true - } - - if (toggleFullScreen && !window.styleMask.contains(.fullScreen)) { + // If the previous focused window was native fullscreen, the new window also + // becomes native fullscreen. + if let parent = focusedSurface?.window, + parent.styleMask.contains(.fullScreen) { window.toggleFullScreen(nil) + } else if ghostty.config.windowFullscreen { + switch (ghostty.config.windowFullscreenMode) { + case .native: + // Native has to be done immediately so that our stylemask contains + // fullscreen for the logic later in this method. + c.toggleFullscreen(mode: .native) + + case .nonNative, .nonNativeVisibleMenu: + // If we're non-native then we have to do it on a later loop + // so that the content view is setup. + DispatchQueue.main.async { + c.toggleFullscreen(mode: self.ghostty.config.windowFullscreenMode) + } + } } // If our app isn't active, we make it active. All new_window actions diff --git a/macos/Sources/Ghostty/Ghostty.Config.swift b/macos/Sources/Ghostty/Ghostty.Config.swift index 76f85d2a3..49b78d909 100644 --- a/macos/Sources/Ghostty/Ghostty.Config.swift +++ b/macos/Sources/Ghostty/Ghostty.Config.swift @@ -219,6 +219,26 @@ extension Ghostty { return v } + var windowFullscreenMode: FullscreenMode { + let defaultValue: FullscreenMode = .native + guard let config = self.config else { return defaultValue } + var v: UnsafePointer? = nil + let key = "macos-non-native-fullscreen" + guard ghostty_config_get(config, &v, key, UInt(key.count)) else { return defaultValue } + guard let ptr = v else { return defaultValue } + let str = String(cString: ptr) + return switch str { + case "false": + .native + case "true": + .nonNative + case "visible-menu": + .nonNativeVisibleMenu + default: + defaultValue + } + } + var windowTitleFontFamily: String? { guard let config = self.config else { return nil } var v: UnsafePointer? = nil