diff --git a/include/ghostty.h b/include/ghostty.h index 29da8f37b..4275bad7e 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -565,6 +565,7 @@ typedef enum { GHOSTTY_ACTION_CLOSE_TAB, GHOSTTY_ACTION_NEW_SPLIT, GHOSTTY_ACTION_CLOSE_ALL_WINDOWS, + GHOSTTY_ACTION_TOGGLE_MAXIMIZE, GHOSTTY_ACTION_TOGGLE_FULLSCREEN, GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW, GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS, diff --git a/src/Surface.zig b/src/Surface.zig index ce00d8237..53890e287 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -646,6 +646,16 @@ pub fn init( // an initial size shouldn't stop our terminal from working. log.warn("unable to set initial window size: {s}", .{err}); }; + + if (config.@"window-maximize") { + rt_app.performAction( + .{ .surface = self }, + .toggle_maximize, + {}, + ) catch |err| { + log.warn("unable to maximize window: {s}", .{err}); + }; + } } if (config.title) |title| { @@ -4168,6 +4178,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool {}, ), + .toggle_maximize => try self.rt_app.performAction( + .{ .surface = self }, + .toggle_maximize, + {}, + ), + .toggle_fullscreen => try self.rt_app.performAction( .{ .surface = self }, .toggle_fullscreen, diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 25e1cd640..fe2039e52 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -92,6 +92,9 @@ pub const Action = union(Key) { /// Close all open windows. close_all_windows, + /// Toggle maximized window state. + toggle_maximize, + /// Toggle fullscreen mode. toggle_fullscreen: Fullscreen, @@ -231,6 +234,7 @@ pub const Action = union(Key) { close_tab, new_split, close_all_windows, + toggle_maximize, toggle_fullscreen, toggle_tab_overview, toggle_window_decorations, diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 8094baeb8..686a70ddb 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -237,6 +237,7 @@ pub const App = struct { .color_change, .pwd, .config_change, + .toggle_maximize, => log.info("unimplemented action={}", .{action}), } } diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 70fc182e5..f49d275de 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -507,6 +507,7 @@ pub fn performAction( .app => null, .surface => |v| v, }), + .toggle_maximize => self.toggleMaximize(target), .toggle_fullscreen => self.toggleFullscreen(target, value), .new_tab => try self.newTab(target), @@ -709,6 +710,22 @@ fn controlInspector( surface.controlInspector(mode); } +fn toggleMaximize(_: *App, target: apprt.Target) void { + switch (target) { + .app => {}, + .surface => |v| { + const window = v.rt_surface.container.window() orelse { + log.info( + "toggleMaximize invalid for container={s}", + .{@tagName(v.rt_surface.container)}, + ); + return; + }; + window.toggleMaximize(); + }, + } +} + fn toggleFullscreen( _: *App, target: apprt.Target, diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 8f111cbc9..599a4d184 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -522,6 +522,15 @@ pub fn toggleTabOverview(self: *Window) void { } } +/// Toggle the maximized state for this window. +pub fn toggleMaximize(self: *Window) void { + if (c.gtk_window_is_maximized(self.window) == 0) { + c.gtk_window_maximize(self.window); + } else { + c.gtk_window_unmaximize(self.window); + } +} + /// Toggle fullscreen for this window. pub fn toggleFullscreen(self: *Window) void { const is_fullscreen = c.gtk_window_is_fullscreen(self.window); diff --git a/src/config/Config.zig b/src/config/Config.zig index 144796554..310b11623 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1214,6 +1214,13 @@ keybind: Keybinds = .{}, @"window-position-x": ?i16 = null, @"window-position-y": ?i16 = null, +/// Whether to start the window in a maximized state. This is only related to +/// the X11 window manager's concept of maximization. In other words, this +/// will set the _NET_WM_STATE property to _NET_WM_STATE_MAXIMIZED_VERT and +/// _NET_WM_STATE_MAXIMIZED_HORZ on launch. This will not affect the window +/// size or position. This is only supported on Linux. +@"window-maximize": bool = false, + /// Whether to enable saving and restoring window state. Window state includes /// their position, size, tabs, splits, etc. Some window state requires shell /// integration, such as preserving working directories. See `shell-integration` diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 2fdbc4cba..48725fb13 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -391,6 +391,9 @@ pub const Action = union(enum) { /// This only works for macOS currently. close_all_windows: void, + /// Toggle maximized window state. This only works on Linux. + toggle_maximize: void, + /// Toggle fullscreen mode of window. toggle_fullscreen: void, @@ -737,6 +740,7 @@ pub const Action = union(enum) { .close_surface, .close_tab, .close_window, + .toggle_maximize, .toggle_fullscreen, .toggle_window_decorations, .toggle_secure_input,