diff --git a/src/Surface.zig b/src/Surface.zig index dca9c6316..0d39e6dcd 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -3913,9 +3913,9 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool }, ), - .move_current_tab => |position| try self.rt_app.performAction( + .move_tab => |position| try self.rt_app.performAction( .{ .surface = self }, - .move_current_tab, + .move_tab, position, ), diff --git a/src/apprt/action.zig b/src/apprt/action.zig index 703becbd8..20d480e63 100644 --- a/src/apprt/action.zig +++ b/src/apprt/action.zig @@ -100,8 +100,10 @@ pub const Action = union(Key) { /// Toggle the visibility of all Ghostty terminal windows. toggle_visibility, - /// Move current tab given a position - move_current_tab: isize, + /// Moves a tab by a relative offset. + /// Adjusts the tab position based on `offset` (e.g., -1 for left, +1 for right). + /// If the new position is out of bounds, it wraps around cyclically within the tab range. + move_tab: isize, /// Jump to a specific tab. Must handle the scenario that the tab /// value is invalid. @@ -193,7 +195,7 @@ pub const Action = union(Key) { toggle_window_decorations, toggle_quick_terminal, toggle_visibility, - move_current_tab, + move_tab, goto_tab, goto_split, resize_split, diff --git a/src/apprt/glfw.zig b/src/apprt/glfw.zig index 49eecab32..1dde97c9c 100644 --- a/src/apprt/glfw.zig +++ b/src/apprt/glfw.zig @@ -213,7 +213,7 @@ pub const App = struct { .toggle_quick_terminal, .toggle_visibility, .goto_tab, - .move_current_tab, + .move_tab, .inspector, .render_inspector, .quit_timer, diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 595e8e5b6..6b302493f 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -456,7 +456,7 @@ pub fn performAction( .new_tab => try self.newTab(target), .goto_tab => self.gotoTab(target, value), - .move_current_tab => self.moveCurrentTab(target, value), + .move_tab => self.moveTab(target, value), .new_split => try self.newSplit(target, value), .resize_split => self.resizeSplit(target, value), .equalize_splits => self.equalizeSplits(target), @@ -528,19 +528,19 @@ fn gotoTab(_: *App, target: apprt.Target, tab: apprt.action.GotoTab) void { } } -fn moveCurrentTab(_: *App, target: apprt.Target, position: isize) void { +fn moveTab(_: *App, target: apprt.Target, position: isize) void { switch (target) { .app => {}, .surface => |v| { const window = v.rt_surface.container.window() orelse { log.info( - "moveCurrentTab invalid for container={s}", + "moveTab invalid for container={s}", .{@tagName(v.rt_surface.container)}, ); return; }; - window.moveCurrentTab(v.rt_surface, @intCast(position)); + window.moveTab(v.rt_surface, @intCast(position)); }, } } diff --git a/src/apprt/gtk/Window.zig b/src/apprt/gtk/Window.zig index 8fb6cac77..1ef6f9c24 100644 --- a/src/apprt/gtk/Window.zig +++ b/src/apprt/gtk/Window.zig @@ -457,7 +457,7 @@ pub fn gotoNextTab(self: *Window, surface: *Surface) void { } /// Move the current tab for a surface. -pub fn moveCurrentTab(self: *Window, surface: *Surface, position: c_int) void { +pub fn moveTab(self: *Window, surface: *Surface, position: c_int) void { const tab = surface.container.tab() orelse { log.info("surface is not attached to a tab bar, cannot navigate", .{}); return; diff --git a/src/apprt/gtk/notebook.zig b/src/apprt/gtk/notebook.zig index dce729989..46245ce99 100644 --- a/src/apprt/gtk/notebook.zig +++ b/src/apprt/gtk/notebook.zig @@ -184,6 +184,22 @@ pub const Notebook = union(enum) { } pub fn moveTab(self: Notebook, tab: *Tab, position: c_int) void { + const page_idx = self.getTabPosition(tab) orelse return; + + const max = self.nPages() -| 1; + var new_position: c_int = page_idx + position; + + if (new_position < 0) { + new_position = max + new_position + 1; + } else if (new_position > max) { + new_position = new_position - max - 1; + } + + if (new_position == page_idx) return; + self.reorderPage(tab, new_position); + } + + pub fn reorderPage(self: Notebook, tab: *Tab, position: c_int) void { switch (self) { .gtk_notebook => |notebook| { c.gtk_notebook_reorder_child(notebook, @ptrCast(tab.box), position); @@ -191,21 +207,7 @@ pub const Notebook = union(enum) { .adw_tab_view => |tab_view| { if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable; const page = c.adw_tab_view_get_page(tab_view, @ptrCast(tab.box)); - - const page_idx = self.getTabPosition(tab) orelse return; - - const max = self.nPages() -| 1; - var new_position: c_int = page_idx + position; - - if (new_position < 0) { - new_position = max; - } else if (new_position > max) { - new_position = 0; - } - - if (new_position == page_idx) return; - - _ = c.adw_tab_view_reorder_page(tab_view, page, new_position); + _ = c.adw_tab_view_reorder_page(tab_view, page, position); }, } } diff --git a/src/input/Binding.zig b/src/input/Binding.zig index 943a704c4..c4d5c6cdf 100644 --- a/src/input/Binding.zig +++ b/src/input/Binding.zig @@ -300,8 +300,10 @@ pub const Action = union(enum) { /// Go to the tab with the specific number, 1-indexed. goto_tab: usize, - /// Move current tab to a position - move_current_tab: isize, + /// Moves a tab by a relative offset. + /// Adjusts the tab position based on `offset` (e.g., -1 for left, +1 for right). + /// If the new position is out of bounds, it wraps around cyclically within the tab range. + move_tab: isize, /// Toggle the tab overview. /// This only works with libadwaita enabled currently. @@ -649,7 +651,7 @@ pub const Action = union(enum) { .next_tab, .last_tab, .goto_tab, - .move_current_tab, + .move_tab, .toggle_tab_overview, .new_split, .goto_split,