From 3d3551d1edf0dee6ca4d0ec4f1956e025fdcb74a Mon Sep 17 00:00:00 2001 From: rhodes-b <59537185+rhodes-b@users.noreply.github.com> Date: Sat, 20 Sep 2025 22:45:17 -0500 Subject: [PATCH] add n_siblings member, and when splits are created / removed update the number of siblings for the remaining nodes --- src/apprt/gtk/class/split_tree.zig | 8 +--- src/apprt/gtk/class/surface.zig | 61 +++++++++++++++--------------- src/apprt/gtk/ui/1.2/surface.blp | 2 +- src/datastruct/split_tree.zig | 16 +++++++- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 012db91f2..3b6dcb4a9 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -710,13 +710,7 @@ pub const SplitTree = extern struct { // We never CLEAR our last_focused because the property is specifically // the last focused surface. We let the weakref clear itself when // the surface is destroyed. - if (!surface.getFocused()) { - // If we have more than 1 active surface and we aren't focused we want to apply unfocused-split-fill - if (self.getTree()) |tree| { - if (tree.nodes.len > 1) surface.setUnfocusedSplit(); - } - return; - } + if (!surface.getFocused()) return; self.private().last_focused.set(surface); // Our active surface probably changed diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index dc6637655..165195469 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -153,24 +153,6 @@ pub const Surface = extern struct { ); }; - pub const @"unfocused-split" = struct { - pub const name = "unfocused-split"; - const impl = gobject.ext.defineProperty( - name, - Self, - bool, - .{ - .default = true, - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "unfocused_split", - ), - }, - ); - }; - pub const @"min-size" = struct { pub const name = "min-size"; const impl = gobject.ext.defineProperty( @@ -292,6 +274,26 @@ pub const Surface = extern struct { }, ); }; + + pub const @"n-siblings" = struct { + pub const name = "n-siblings"; + const impl = gobject.ext.defineProperty( + name, + Self, + u64, + .{ + .default = 0, + .minimum = 0, + .maximum = std.math.maxInt(c_uint), + .accessor = gobject.ext.privateFieldAccessor( + Self, + Private, + &Private.offset, + "n_siblings", + ), + }, + ); + }; }; pub const signals = struct { @@ -453,7 +455,6 @@ pub const Surface = extern struct { /// The current focus state of the terminal based on the /// focus events. focused: bool = true, - unfocused_split: bool = false, /// Whether this surface is "zoomed" or not. A zoomed surface /// shows up taking the full bounds of a split view. @@ -521,6 +522,8 @@ pub const Surface = extern struct { /// A weak reference to an inspector window. inspector: ?*InspectorWindow = null, + n_siblings: u64 = 0, + // Template binds child_exited_overlay: *ChildExited, context_menu: *gtk.PopoverMenu, @@ -623,9 +626,10 @@ pub const Surface = extern struct { /// should be applied to the surface fn closureShouldUnfocusedSplitBeShown( _: *Self, - unfocused_split: c_int, + focused: c_int, + n_siblings: c_int, ) callconv(.c) c_int { - return @intFromBool(unfocused_split != 0); + return @intFromBool(focused == 0 and n_siblings > 0); } pub fn toggleFullscreen(self: *Self) void { @@ -1332,7 +1336,6 @@ pub const Surface = extern struct { priv.mouse_shape = .text; priv.mouse_hidden = false; priv.focused = true; - priv.unfocused_split = false; priv.size = .{ .width = 0, .height = 0 }; // If our configuration is null then we get the configuration @@ -1520,11 +1523,11 @@ pub const Surface = extern struct { return self.private().focused; } - /// If unfocused add the unfocused-split widget for this surface - pub fn setUnfocusedSplit(self: *Self) void { + /// Set number of siblings related to this surface. + pub fn setNSiblings(self: *Self, siblings: u64) void { const priv = self.private(); - priv.unfocused_split = !priv.focused; - self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); + priv.n_siblings = siblings; + self.as(gobject.Object).notifyByPspec(properties.@"n-siblings".impl.param_spec); } /// Change the configuration for this surface. @@ -2025,10 +2028,6 @@ pub const Surface = extern struct { _ = glib.idleAddOnce(idleFocus, self.ref()); self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec); - // remove unfocused-split-fill and unfocused-split-opacity - priv.unfocused_split = false; - self.as(gobject.Object).notifyByPspec(properties.@"unfocused-split".impl.param_spec); - // Bell stops ringing as soon as we gain focus self.setBellRinging(false); } @@ -2814,7 +2813,6 @@ pub const Surface = extern struct { properties.@"error".impl, properties.@"font-size-request".impl, properties.focused.impl, - properties.@"unfocused-split".impl, properties.@"min-size".impl, properties.@"mouse-shape".impl, properties.@"mouse-hidden".impl, @@ -2823,6 +2821,7 @@ pub const Surface = extern struct { properties.title.impl, properties.@"title-override".impl, properties.zoom.impl, + properties.@"n-siblings".impl, }); // Signals diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index 0b9a77133..35d897525 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -119,7 +119,7 @@ Overlay terminal_page { // Apply unfocused-split-fill and unfocused-split-opacity to current surface // this is only applied when a tab has more than one surface Revealer { - reveal-child: bind $should_unfocused_split_be_shown(template.unfocused-split) as ; + reveal-child: bind $should_unfocused_split_be_shown(template.focused, template.n-siblings) as ; transition-duration: 0; DrawingArea { diff --git a/src/datastruct/split_tree.zig b/src/datastruct/split_tree.zig index 28b45ceed..212711e3d 100644 --- a/src/datastruct/split_tree.zig +++ b/src/datastruct/split_tree.zig @@ -507,12 +507,16 @@ pub fn SplitTree(comptime V: type) type { // We need to increase the reference count of all the nodes. try refNodes(gpa, nodes); - return .{ + const result: Self = .{ .arena = arena, .nodes = nodes, // Splitting always resets zoom state. .zoomed = null, }; + + result.updateNodesNumberSiblings(); + + return result; } /// Remove a node from the tree. @@ -556,6 +560,8 @@ pub fn SplitTree(comptime V: type) type { // Increase the reference count of all the nodes. try refNodes(gpa, nodes); + result.updateNodesNumberSiblings(); + return result; } @@ -865,6 +871,14 @@ pub fn SplitTree(comptime V: type) type { }; } + /// Set the number of siblings for each split in the tree + fn updateNodesNumberSiblings(self: *const Self) void { + var it = self.iterator(); + while (it.next()) |entry| { + entry.view.setNSiblings(self.nodes.len - 1); + } + } + /// Spatial representation of the split tree. See spatial. pub const Spatial = struct { /// The slots of the spatial representation in the same order