From 5903d7d10f8098146ab83c448f970d9eae993bab Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 11 Aug 2025 09:43:39 -0700 Subject: [PATCH] apprt/gtk-ng: hook up goto_split --- src/apprt/gtk-ng/class/application.zig | 33 +++++++++++++++++++++++++- src/apprt/gtk-ng/class/split_tree.zig | 17 +++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/apprt/gtk-ng/class/application.zig b/src/apprt/gtk-ng/class/application.zig index 7dde0fa93..129147ece 100644 --- a/src/apprt/gtk-ng/class/application.zig +++ b/src/apprt/gtk-ng/class/application.zig @@ -34,6 +34,7 @@ const Common = @import("../class.zig").Common; const WeakRef = @import("../weak_ref.zig").WeakRef; const Config = @import("config.zig").Config; const Surface = @import("surface.zig").Surface; +const SplitTree = @import("split_tree.zig").SplitTree; const Window = @import("window.zig").Window; const CloseConfirmationDialog = @import("close_confirmation_dialog.zig").CloseConfirmationDialog; const ConfigErrorsDialog = @import("config_errors_dialog.zig").ConfigErrorsDialog; @@ -552,6 +553,8 @@ pub const Application = extern struct { .desktop_notification => Action.desktopNotification(self, target, value), + .goto_split => return Action.gotoSplit(target, value), + .goto_tab => return Action.gotoTab(target, value), .initial_size => return Action.initialSize(target, value), @@ -615,7 +618,6 @@ pub const Application = extern struct { // TODO: splits .resize_split, .equalize_splits, - .goto_split, .toggle_split_zoom, => { log.warn("unimplemented action={}", .{action}); @@ -1650,6 +1652,35 @@ const Action = struct { gio_app.sendNotification(n.body, notification); } + pub fn gotoSplit( + target: apprt.Target, + to: apprt.action.GotoSplit, + ) bool { + switch (target) { + .app => return false, + .surface => |core| { + // Design note: we can't use widget actions here because + // we need to know whether there is a goto target for returning + // the proper perform result (boolean). + + const surface = core.rt_surface.surface; + const tree = ext.getAncestor( + SplitTree, + surface.as(gtk.Widget), + ) orelse { + log.warn("surface is not in a split tree, ignoring goto_split", .{}); + return false; + }; + + return tree.goto(switch (to) { + .previous => .previous_wrapped, + .next => .next_wrapped, + else => @panic("TODO"), + }); + }, + } + } + pub fn gotoTab( target: apprt.Target, tab: apprt.action.GotoTab, diff --git a/src/apprt/gtk-ng/class/split_tree.zig b/src/apprt/gtk-ng/class/split_tree.zig index b70f0e2f8..cbaef54ae 100644 --- a/src/apprt/gtk-ng/class/split_tree.zig +++ b/src/apprt/gtk-ng/class/split_tree.zig @@ -258,6 +258,23 @@ pub const SplitTree = extern struct { self.setTree(&new_tree); } + /// Move focus from the currently focused surface to the given + /// direction. Returns true if focus switched to a new surface. + pub fn goto(self: *Self, to: Surface.Tree.Goto) bool { + const tree = self.getTree() orelse return false; + const active = self.getActiveSurfaceHandle() orelse return false; + const target = tree.goto(active, to) orelse return false; + + // If we aren't changing targets then we did nothing. + if (active == target) return false; + + // Get the surface at the target location and grab focus. + const surface = tree.nodes[target].leaf; + surface.grabFocus(); + + return true; + } + fn disconnectSurfaceHandlers(self: *Self) void { const tree = self.getTree() orelse return; var it = tree.iterator();