diff --git a/src/Surface.zig b/src/Surface.zig index b7ce3ede7..2b72691a6 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -917,6 +917,9 @@ pub fn keyCallback( }, .{ .instant = {} }); }, + .previous_tab => self.rt_surface.gotoPreviousTab(), + .next_tab => self.rt_surface.gotoNextTab(), + .close_window => { _ = self.app_mailbox.push(.{ .close = self }, .{ .instant = {} }); }, diff --git a/src/apprt/gtk.zig b/src/apprt/gtk.zig index 453b27d67..2a9483507 100644 --- a/src/apprt/gtk.zig +++ b/src/apprt/gtk.zig @@ -291,18 +291,8 @@ const Window = struct { /// Close the tab for the given notebook page. This will automatically /// handle closing the window if there are no more tabs. fn closeTab(self: *Window, page: *c.GtkNotebookPage) void { - // Get the page index from the page - var value: c.GValue = std.mem.zeroes(c.GValue); - defer c.g_value_unset(&value); - _ = c.g_value_init(&value, c.G_TYPE_INT); - c.g_object_get_property( - @ptrCast(*c.GObject, @alignCast(@alignOf(c.GObject), page)), - "position", - &value, - ); - // Remove the page - const page_idx = c.g_value_get_int(&value); + const page_idx = getNotebookPageIndex(page); c.gtk_notebook_remove_page(self.notebook, page_idx); const remaining = c.gtk_notebook_get_n_pages(self.notebook); @@ -323,6 +313,34 @@ const Window = struct { self.closeTab(getNotebookPage(@ptrCast(*c.GObject, surface.gl_area)) orelse return); } + /// Go to the previous tab for a surface. + fn gotoPreviousTab(self: *Window, surface: *Surface) void { + const page = getNotebookPage(@ptrCast(*c.GObject, surface.gl_area)) orelse return; + const page_idx = getNotebookPageIndex(page); + if (page_idx > 0) { + c.gtk_notebook_set_current_page(self.notebook, page_idx - 1); + self.focusCurrentTab(); + } + } + + /// Go to the next tab for a surface. + fn gotoNextTab(self: *Window, surface: *Surface) void { + const page = getNotebookPage(@ptrCast(*c.GObject, surface.gl_area)) orelse return; + const page_idx = getNotebookPageIndex(page); + const max = c.gtk_notebook_get_n_pages(self.notebook) -| 1; + if (page_idx < max) { + c.gtk_notebook_set_current_page(self.notebook, page_idx + 1); + self.focusCurrentTab(); + } + } + + /// Grabs focus on the currently selected tab. + fn focusCurrentTab(self: *Window) void { + const page_idx = c.gtk_notebook_get_current_page(self.notebook); + const widget = c.gtk_notebook_get_nth_page(self.notebook, page_idx); + _ = c.gtk_widget_grab_focus(widget); + } + fn gtkTabAddClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void { const self = userdataSelf(ud.?); self.newTab() catch |err| { @@ -356,6 +374,19 @@ const Window = struct { )); } + fn getNotebookPageIndex(page: *c.GtkNotebookPage) c_int { + var value: c.GValue = std.mem.zeroes(c.GValue); + defer c.g_value_unset(&value); + _ = c.g_value_init(&value, c.G_TYPE_INT); + c.g_object_get_property( + @ptrCast(*c.GObject, @alignCast(@alignOf(c.GObject), page)), + "position", + &value, + ); + + return c.g_value_get_int(&value); + } + fn userdataSelf(ud: *anyopaque) *Window { return @ptrCast(*Window, @alignCast(@alignOf(Window), ud)); } @@ -553,6 +584,14 @@ pub const Surface = struct { self.window.closeSurface(self); } + pub fn gotoPreviousTab(self: *Surface) void { + self.window.gotoPreviousTab(self); + } + + pub fn gotoNextTab(self: *Surface) void { + self.window.gotoNextTab(self); + } + pub fn setShouldClose(self: *Surface) void { _ = self; } diff --git a/src/config.zig b/src/config.zig index c83198abc..280a71d70 100644 --- a/src/config.zig +++ b/src/config.zig @@ -278,6 +278,16 @@ pub const Config = struct { .{ .key = .t, .mods = .{ .super = true } }, .{ .new_tab = {} }, ); + try result.keybind.set.put( + alloc, + .{ .key = .left_bracket, .mods = .{ .super = true, .shift = true } }, + .{ .previous_tab = {} }, + ); + try result.keybind.set.put( + alloc, + .{ .key = .right_bracket, .mods = .{ .super = true, .shift = true } }, + .{ .next_tab = {} }, + ); if (comptime builtin.target.isDarwin()) { try result.keybind.set.put( alloc, diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 9ba82e1de..ba2c8a098 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -155,6 +155,12 @@ pub const Action = union(enum) { /// Open a new tab new_tab: void, + /// Go to the previous tab + previous_tab: void, + + /// Go to the next tab + next_tab: void, + /// Close the current window or tab close_window: void,