From fe4f4fdc72695d8f5e43f41ce06e34785f02262c Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Tue, 24 Sep 2024 11:18:00 +0200 Subject: [PATCH 1/6] apprt/gtk: fix build with -Dgtk-libadwaita=false --- src/apprt/gtk/Window.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 80bbd0944..50be404eb 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -152,14 +152,15 @@ pub fn init(self: *Window, app: *App) !void { c.gtk_widget_set_tooltip_text(btn, "Main Menu"); c.gtk_menu_button_set_icon_name(@ptrCast(btn), "open-menu-symbolic"); c.gtk_menu_button_set_menu_model(@ptrCast(btn), @ptrCast(@alignCast(app.menu))); - if (self.isAdwWindow()) - c.adw_header_bar_pack_end(@ptrCast(header), btn) - else - c.gtk_header_bar_pack_end(@ptrCast(header), btn); + if (self.isAdwWindow()) { + if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; + c.adw_header_bar_pack_end(@ptrCast(header), btn); + } else c.gtk_header_bar_pack_end(@ptrCast(header), btn); } // If we're using an AdwWindow then we can support the tab overview. if (tab_overview_) |tab_overview| { + if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; assert(self.isAdwWindow()); const btn = c.gtk_toggle_button_new(); @@ -236,6 +237,7 @@ pub fn init(self: *Window, app: *App) !void { // If we have a tab overview then we can set it on our notebook. if (tab_overview_) |tab_overview| { + if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; assert(self.notebook == .adw_tab_view); c.adw_tab_overview_set_view(@ptrCast(tab_overview), self.notebook.adw_tab_view); } @@ -257,6 +259,7 @@ pub fn init(self: *Window, app: *App) !void { initActions(self); if (self.hasAdwToolbar()) { + if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; const toolbar_view: *c.AdwToolbarView = @ptrCast(c.adw_toolbar_view_new()); const header_widget: *c.GtkWidget = @ptrCast(@alignCast(self.header.?)); From 6ef87d298c33523a87a8ba6b9cdc04a4d305084f Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Tue, 24 Sep 2024 11:08:55 +0200 Subject: [PATCH 2/6] apprt/gtk: remove Window.hasAdwToolbar this is the same as isAdwWindow --- src/apprt/gtk/Window.zig | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 50be404eb..4e88dae83 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -258,7 +258,7 @@ pub fn init(self: *Window, app: *App) !void { // Our actions for the menu initActions(self); - if (self.hasAdwToolbar()) { + if (self.isAdwWindow()) { if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; const toolbar_view: *c.AdwToolbarView = @ptrCast(c.adw_toolbar_view_new()); @@ -394,18 +394,9 @@ pub fn deinit(self: *Window) void { /// paths that are not enabled. inline fn isAdwWindow(self: *Window) bool { return (comptime adwaita.versionAtLeast(1, 4, 0)) and - adwaita.enabled(&self.app.config) and - self.app.config.@"gtk-titlebar" and - adwaita.versionAtLeast(1, 4, 0); -} - -/// This must be `inline` so that the comptime check noops conditional -/// paths that are not enabled. -inline fn hasAdwToolbar(self: *Window) bool { - return ((comptime adwaita.versionAtLeast(1, 4, 0)) and adwaita.enabled(&self.app.config) and adwaita.versionAtLeast(1, 4, 0) and - self.app.config.@"gtk-titlebar"); + self.app.config.@"gtk-titlebar"; } /// Add a new tab to this window. From 7b8b58110c99d19026041104d12453e617805c66 Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Tue, 24 Sep 2024 11:09:53 +0200 Subject: [PATCH 3/6] apprt/gtk: store tab_overview in Window struct --- src/apprt/gtk/Window.zig | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 4e88dae83..e23a8abf3 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -35,6 +35,10 @@ window: *c.GtkWindow, /// GtkHeaderBar depending on if adw is enabled and linked. header: ?*c.GtkWidget, +/// The tab overview for the window. This is possibly null since there is no +/// taboverview without a AdwApplicationWindow (libadwaita >= 1.4.0). +tab_overview: ?*c.GtkWidget, + /// The notebook (tab grouping) for this window. /// can be either c.GtkNotebook or c.AdwTabView. notebook: Notebook, @@ -68,6 +72,7 @@ pub fn init(self: *Window, app: *App) !void { .app = app, .window = undefined, .header = null, + .tab_overview = null, .notebook = undefined, .context_menu = undefined, .toast_overlay = undefined, @@ -114,7 +119,7 @@ pub fn init(self: *Window, app: *App) !void { const box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0); // If we are using an AdwWindow then we can support the tab overview. - const tab_overview_: ?*c.GtkWidget = if (self.isAdwWindow()) overview: { + self.tab_overview = if (self.isAdwWindow()) overview: { const tab_overview = c.adw_tab_overview_new(); c.adw_tab_overview_set_enable_new_tab(@ptrCast(tab_overview), 1); _ = c.g_signal_connect_data( @@ -159,7 +164,7 @@ pub fn init(self: *Window, app: *App) !void { } // If we're using an AdwWindow then we can support the tab overview. - if (tab_overview_) |tab_overview| { + if (self.tab_overview) |tab_overview| { if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; assert(self.isAdwWindow()); @@ -236,7 +241,7 @@ pub fn init(self: *Window, app: *App) !void { }; // If we have a tab overview then we can set it on our notebook. - if (tab_overview_) |tab_overview| { + if (self.tab_overview) |tab_overview| { if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; assert(self.notebook == .adw_tab_view); c.adw_tab_overview_set_view(@ptrCast(tab_overview), self.notebook.adw_tab_view); @@ -292,7 +297,7 @@ pub fn init(self: *Window, app: *App) !void { // Set our application window content. The content depends on if // we're using an AdwTabOverview or not. - if (tab_overview_) |tab_overview| { + if (self.tab_overview) |tab_overview| { c.adw_tab_overview_set_child( @ptrCast(tab_overview), @ptrCast(@alignCast(toolbar_view)), From f1474c220d1a4896120058bddbaa6e8ba53a1b48 Mon Sep 17 00:00:00 2001 From: Paul Berg Date: Fri, 27 Sep 2024 09:36:45 +0200 Subject: [PATCH 4/6] bind: add toggle_tab_overview binding --- src/Surface.zig | 6 ++++++ src/apprt/action.zig | 3 +++ src/apprt/glfw.zig | 1 + src/apprt/gtk/App.zig | 18 ++++++++++++++++++ src/apprt/gtk/Window.zig | 9 +++++++++ src/input/Binding.zig | 5 +++++ 6 files changed, 42 insertions(+) diff --git a/src/Surface.zig b/src/Surface.zig index a37f0a7e8..28d66d25d 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3830,6 +3830,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool {}, ), + .toggle_tab_overview => try self.rt_app.performAction( + .{ .surface = self }, + .toggle_tab_overview, + {}, + ), + .toggle_secure_input => try self.rt_app.performAction( .{ .surface = self }, .secure_input, diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 70c189c8f..0941d65c9 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -87,6 +87,9 @@ pub const Action = union(Key) { /// Toggle fullscreen mode. toggle_fullscreen: Fullscreen, + /// Toggle tab overview. + toggle_tab_overview, + /// Toggle whether window directions are shown. toggle_window_decorations, diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 57667afb1..fb31f7c2b 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -194,6 +194,7 @@ pub const App = struct { .toggle_split_zoom, .present_terminal, .close_all_windows, + .toggle_tab_overview, .toggle_window_decorations, .goto_tab, .inspector, diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 45031324a..294954bd4 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -372,6 +372,7 @@ pub fn performAction( .mouse_visibility => self.setMouseVisibility(target, value), .mouse_shape => try self.setMouseShape(target, value), .mouse_over_link => self.setMouseOverLink(target, value), + .toggle_tab_overview => self.toggleTabOverview(target), .toggle_window_decorations => self.toggleWindowDecorations(target), .quit_timer => self.quitTimer(value), @@ -534,6 +535,23 @@ fn toggleFullscreen( } } +fn toggleTabOverview(_: *App, target: apprt.Target) void { + switch (target) { + .app => {}, + .surface => |v| { + const window = v.rt_surface.container.window() orelse { + log.info( + "toggleTabOverview invalid for container={s}", + .{@tagName(v.rt_surface.container)}, + ); + return; + }; + + window.toggleTabOverview(); + }, + } +} + fn toggleWindowDecorations( _: *App, target: apprt.Target, diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index e23a8abf3..ff8735ff9 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -457,6 +457,15 @@ pub fn gotoTab(self: *Window, n: usize) void { } } +/// Toggle tab overview (if present) +pub fn toggleTabOverview(self: *Window) void { + if (self.tab_overview) |tab_overview_widget| { + if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable; + const tab_overview: *c.AdwTabOverview = @ptrCast(@alignCast(tab_overview_widget)); + c.adw_tab_overview_set_open(tab_overview, 1 - c.adw_tab_overview_get_open(tab_overview)); + } +} + /// 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/input/Binding.zig b/src/input/Binding.zig index 45ec24126..f9921a87e 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -298,6 +298,10 @@ pub const Action = union(enum) { /// Go to the tab with the specific number, 1-indexed. goto_tab: usize, + /// Toggle the tab overview. + /// This only works with libadwaita enabled currently. + toggle_tab_overview: void, + /// Create a new split in the given direction. The new split will appear in /// the direction given. new_split: SplitDirection, @@ -607,6 +611,7 @@ pub const Action = union(enum) { .next_tab, .last_tab, .goto_tab, + .toggle_tab_overview, .new_split, .goto_split, .toggle_split_zoom, From be0d71f62df2afdab19a30bb9bd980e0d3288fe0 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 27 Sep 2024 10:15:06 -0700 Subject: [PATCH 5/6] apprt/embedded: add the tab overview to the enum --- include/ghostty.h | 1 + src/apprt/action.zig | 1 + 2 files changed, 2 insertions(+) diff --git a/include/ghostty.h b/include/ghostty.h index 571cbd904..7c81dbe77 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -505,6 +505,7 @@ typedef enum { GHOSTTY_ACTION_NEW_SPLIT, GHOSTTY_ACTION_CLOSE_ALL_WINDOWS, GHOSTTY_ACTION_TOGGLE_FULLSCREEN, + GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW, GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS, GHOSTTY_ACTION_GOTO_TAB, GHOSTTY_ACTION_GOTO_SPLIT, diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 0941d65c9..9ed89b5a3 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -174,6 +174,7 @@ pub const Action = union(Key) { new_split, close_all_windows, toggle_fullscreen, + toggle_tab_overview, toggle_window_decorations, goto_tab, goto_split, From 1bd0999eef4d51a89a82205da93a3309cb5a155a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 27 Sep 2024 10:17:54 -0700 Subject: [PATCH 6/6] macos: add unhandled action --- macos/Sources/Ghostty/Ghostty.App.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/macos/Sources/Ghostty/Ghostty.App.swift b/macos/Sources/Ghostty/Ghostty.App.swift index f0128e2f7..5b2efad3e 100644 --- a/macos/Sources/Ghostty/Ghostty.App.swift +++ b/macos/Sources/Ghostty/Ghostty.App.swift @@ -484,6 +484,8 @@ extension Ghostty { case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS: fallthrough + case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW: + fallthrough case GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS: fallthrough case GHOSTTY_ACTION_PRESENT_TERMINAL: