Add config setting to turn non-native fullscreen on or off

This commit is contained in:
Thorsten Ball
2023-07-29 21:05:49 +02:00
committed by Mitchell Hashimoto
parent 850bf3e945
commit b56ffa6285
9 changed files with 45 additions and 14 deletions

View File

@ -239,7 +239,7 @@ typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
typedef void (*ghostty_runtime_close_surface_cb)(void *, bool); typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e); typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
typedef void (*ghostty_runtime_goto_tab_cb)(void *, int32_t); typedef void (*ghostty_runtime_goto_tab_cb)(void *, int32_t);
typedef void (*ghostty_runtime_toggle_fullscreen_cb)(void *); typedef void (*ghostty_runtime_toggle_fullscreen_cb)(void *, bool);
typedef struct { typedef struct {
void *userdata; void *userdata;

View File

@ -110,8 +110,12 @@ struct ContentView: View {
// currently focused window. // currently focused window.
guard let window = self.window else { return } guard let window = self.window else { return }
guard window.isKeyWindow else { return } guard window.isKeyWindow else { return }
self.fsHandler.toggleFullscreen(window: window) // Check whether we use non-native fullscreen
guard let useNonNativeFullscreenAny = notification.userInfo?[Ghostty.Notification.NonNativeFullscreenKey] else { return }
guard let useNonNativeFullscreen = useNonNativeFullscreenAny as? Bool else { return }
self.fsHandler.toggleFullscreen(window: window, nonNativeFullscreen: useNonNativeFullscreen)
// After toggling fullscreen we need to focus the terminal again. // After toggling fullscreen we need to focus the terminal again.
self.focused = true self.focused = true
} }

View File

@ -7,12 +7,27 @@ class FullScreenHandler {
var previousStyleMask: NSWindow.StyleMask? var previousStyleMask: NSWindow.StyleMask?
var isInFullscreen: Bool = false var isInFullscreen: Bool = false
func toggleFullscreen(window: NSWindow) { // We keep track of whether we entered non-native fullscreen in case
// a user goes to fullscreen, changes the config to disable non-native fullscreen
// and then wants to toggle it off
var isInNonNativeFullscreen: Bool = false
func toggleFullscreen(window: NSWindow, nonNativeFullscreen: Bool) {
if isInFullscreen { if isInFullscreen {
leaveFullscreen(window: window) if nonNativeFullscreen || isInNonNativeFullscreen {
leaveFullscreen(window: window)
isInNonNativeFullscreen = false
} else {
window.toggleFullScreen(nil)
}
isInFullscreen = false isInFullscreen = false
} else { } else {
enterFullscreen(window: window) if nonNativeFullscreen {
enterFullscreen(window: window)
isInNonNativeFullscreen = true
} else {
window.toggleFullScreen(nil)
}
isInFullscreen = true isInFullscreen = true
} }
} }

View File

@ -63,7 +63,7 @@ extension Ghostty {
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) }, close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) }, focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) }, goto_tab_cb: { userdata, n in AppState.gotoTab(userdata, n: n) },
toggle_fullscreen_cb: { userdata in AppState.toggleFullscreen(userdata) } toggle_fullscreen_cb: { userdata, nonNativeFullscreen in AppState.toggleFullscreen(userdata, useNonNativeFullscreen: nonNativeFullscreen) }
) )
// Create the ghostty app. // Create the ghostty app.
@ -219,12 +219,15 @@ extension Ghostty {
} }
} }
static func toggleFullscreen(_ userdata: UnsafeMutableRawPointer?) { static func toggleFullscreen(_ userdata: UnsafeMutableRawPointer?, useNonNativeFullscreen: Bool) {
// togo: use non-native fullscreen
guard let surface = self.surfaceUserdata(from: userdata) else { return } guard let surface = self.surfaceUserdata(from: userdata) else { return }
NotificationCenter.default.post( NotificationCenter.default.post(
name: Notification.ghosttyToggleFullscreen, name: Notification.ghosttyToggleFullscreen,
object: surface, object: surface,
userInfo: [:] userInfo: [
Notification.NonNativeFullscreenKey: useNonNativeFullscreen,
]
) )
} }

View File

@ -81,6 +81,7 @@ extension Ghostty.Notification {
/// Toggle fullscreen of current window /// Toggle fullscreen of current window
static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen") static let ghosttyToggleFullscreen = Notification.Name("com.mitchellh.ghostty.toggleFullscreen")
static let NonNativeFullscreenKey = ghosttyToggleFullscreen.rawValue
} }
// Make the input enum hashable. // Make the input enum hashable.

View File

@ -146,6 +146,7 @@ const DerivedConfig = struct {
clipboard_trim_trailing_spaces: bool, clipboard_trim_trailing_spaces: bool,
confirm_close_surface: bool, confirm_close_surface: bool,
mouse_interval: u64, mouse_interval: u64,
macos_non_native_fullscreen: bool,
pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig { pub fn init(alloc_gpa: Allocator, config: *const configpkg.Config) !DerivedConfig {
var arena = ArenaAllocator.init(alloc_gpa); var arena = ArenaAllocator.init(alloc_gpa);
@ -160,6 +161,7 @@ const DerivedConfig = struct {
.clipboard_trim_trailing_spaces = config.@"clipboard-trim-trailing-spaces", .clipboard_trim_trailing_spaces = config.@"clipboard-trim-trailing-spaces",
.confirm_close_surface = config.@"confirm-close-surface", .confirm_close_surface = config.@"confirm-close-surface",
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms .mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
.macos_non_native_fullscreen = config.@"macos-non-native-fullscreen",
// Assignments happen sequentially so we have to do this last // Assignments happen sequentially so we have to do this last
// so that the memory is captured from allocs above. // so that the memory is captured from allocs above.
@ -1213,7 +1215,7 @@ pub fn keyCallback(
.toggle_fullscreen => { .toggle_fullscreen => {
if (@hasDecl(apprt.Surface, "toggleFullscreen")) { if (@hasDecl(apprt.Surface, "toggleFullscreen")) {
self.rt_surface.toggleFullscreen(); self.rt_surface.toggleFullscreen(self.config.macos_non_native_fullscreen);
} else log.warn("runtime doesn't implement toggleFullscreen", .{}); } else log.warn("runtime doesn't implement toggleFullscreen", .{});
}, },

View File

@ -66,7 +66,7 @@ pub const App = struct {
goto_tab: ?*const fn (SurfaceUD, usize) callconv(.C) void = null, goto_tab: ?*const fn (SurfaceUD, usize) callconv(.C) void = null,
/// Toggle fullscreen for current window. /// Toggle fullscreen for current window.
toggle_fullscreen: ?*const fn (SurfaceUD) callconv(.C) void = null, toggle_fullscreen: ?*const fn (SurfaceUD, bool) callconv(.C) void = null,
}; };
core_app: *CoreApp, core_app: *CoreApp,
@ -374,13 +374,13 @@ pub const Surface = struct {
func(self.opts.userdata, n); func(self.opts.userdata, n);
} }
pub fn toggleFullscreen(self: *Surface) void { pub fn toggleFullscreen(self: *Surface, nonNativeFullscreen: bool) void {
const func = self.app.opts.toggle_fullscreen orelse { const func = self.app.opts.toggle_fullscreen orelse {
log.info("runtime embedder does not toggle_fullscreen", .{}); log.info("runtime embedder does not toggle_fullscreen", .{});
return; return;
}; };
func(self.opts.userdata); func(self.opts.userdata, nonNativeFullscreen);
} }
/// The cursor position from the host directly is in screen coordinates but /// The cursor position from the host directly is in screen coordinates but

View File

@ -483,7 +483,7 @@ const Window = struct {
} }
/// Toggle fullscreen for this window. /// Toggle fullscreen for this window.
fn toggleFullscreen(self: *Window) void { fn toggleFullscreen(self: *Window, _: bool) void {
const is_fullscreen = c.gtk_window_is_fullscreen(self.window); const is_fullscreen = c.gtk_window_is_fullscreen(self.window);
if (is_fullscreen == 0) { if (is_fullscreen == 0) {
c.gtk_window_fullscreen(self.window); c.gtk_window_fullscreen(self.window);

View File

@ -221,6 +221,12 @@ pub const Config = struct {
/// The default value is "detect". /// The default value is "detect".
@"shell-integration": ShellIntegration = .detect, @"shell-integration": ShellIntegration = .detect,
/// If true, fullscreen mode on macOS will not use the native fullscreen,
/// but make the window fullscreen without animations and using a new space.
/// That's faster than the native fullscreen mode since it doesn't use
/// animations.
@"macos-non-native-fullscreen": bool = false,
/// This is set by the CLI parser for deinit. /// This is set by the CLI parser for deinit.
_arena: ?ArenaAllocator = null, _arena: ?ArenaAllocator = null,