diff --git a/src/apprt/gtk/class/split_tree.zig b/src/apprt/gtk/class/split_tree.zig index 3b6dcb4a9..755b51e9a 100644 --- a/src/apprt/gtk/class/split_tree.zig +++ b/src/apprt/gtk/class/split_tree.zig @@ -112,6 +112,25 @@ pub const SplitTree = extern struct { }, ); }; + + pub const @"is-split" = struct { + pub const name = "is-split"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .default = false, + .accessor = gobject.ext.typedAccessor( + Self, + bool, + .{ + .getter = getIsSplit, + }, + ), + }, + ); + }; }; pub const signals = struct { @@ -210,6 +229,14 @@ pub const SplitTree = extern struct { } } + // Bind is-split property for new surface + _ = self.as(gobject.Object).bindProperty( + "is-split", + surface.as(gobject.Object), + "is-split", + .{ .sync_create = true }, + ); + // Create our tree var single_tree = try Surface.Tree.init(alloc, surface); defer single_tree.deinit(); @@ -511,6 +538,18 @@ pub const SplitTree = extern struct { )); } + fn getIsSplit(self: *Self) bool { + const tree: *const Surface.Tree = self.private().tree orelse &.empty; + if (tree.isEmpty()) return false; + + const root_handle: Surface.Tree.Node.Handle = .root; + const root = tree.nodes[root_handle.idx()]; + return switch (root) { + .leaf => false, + .split => true, + }; + } + //--------------------------------------------------------------- // Virtual methods @@ -816,6 +855,9 @@ pub const SplitTree = extern struct { v.grabFocus(); } + // Our split status may have changed + self.as(gobject.Object).notifyByPspec(properties.@"is-split".impl.param_spec); + // Our active surface may have changed self.as(gobject.Object).notifyByPspec(properties.@"active-surface".impl.param_spec); @@ -873,6 +915,7 @@ pub const SplitTree = extern struct { properties.@"has-surfaces".impl, properties.@"is-zoomed".impl, properties.tree.impl, + properties.@"is-split".impl, }); // Bindings diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 616ec54f5..fb933073c 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -275,6 +275,24 @@ pub const Surface = extern struct { }, ); }; + + pub const @"is-split" = struct { + pub const name = "is-split"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .default = false, + .accessor = gobject.ext.privateFieldAccessor( + Self, + Private, + &Private.offset, + "is_split", + ), + }, + ); + }; }; pub const signals = struct { @@ -503,6 +521,10 @@ pub const Surface = extern struct { /// A weak reference to an inspector window. inspector: ?*InspectorWindow = null, + // True if the current surface is a split, this is used to apply + // unfocused-split-* options + is_split: bool = false, + // Template binds child_exited_overlay: *ChildExited, context_menu: *gtk.PopoverMenu, @@ -601,6 +623,16 @@ pub const Surface = extern struct { return @intFromBool(config.@"bell-features".border); } + /// Callback used to determine whether unfocused-split-fill / unfocused-split-opacity + /// should be applied to the surface + fn closureShouldUnfocusedSplitBeShown( + _: *Self, + focused: c_int, + is_split: c_int, + ) callconv(.c) c_int { + return @intFromBool(focused == 0 and is_split != 0); + } + pub fn toggleFullscreen(self: *Self) void { signals.@"toggle-fullscreen".impl.emit( self, @@ -2829,6 +2861,7 @@ pub const Surface = extern struct { class.bindTemplateCallback("notify_mouse_shape", &propMouseShape); class.bindTemplateCallback("notify_bell_ringing", &propBellRinging); class.bindTemplateCallback("should_border_be_shown", &closureShouldBorderBeShown); + class.bindTemplateCallback("should_unfocused_split_be_shown", &closureShouldUnfocusedSplitBeShown); // Properties gobject.ext.registerProperties(class, &.{ @@ -2847,6 +2880,7 @@ pub const Surface = extern struct { properties.title.impl, properties.@"title-override".impl, properties.zoom.impl, + properties.@"is-split".impl, }); // Signals diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index f22f2c09a..ad971e991 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -115,6 +115,20 @@ Overlay terminal_page { label: bind template.mouse-hover-url; } + [overlay] + // 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.focused, template.is-split) as ; + transition-duration: 0; + + DrawingArea { + styles [ + "unfocused-split", + ] + } + } + // Event controllers for interactivity EventControllerFocus { enter => $focus_enter();