From e7cab27c38cd71513941ff990bc1f7c897c814ca Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 28 Jul 2025 07:13:16 -0700 Subject: [PATCH] apprt/gtk-ng: tab bar properties --- src/apprt/gtk-ng/class/window.zig | 103 +++++++++++++++++++++++++++-- src/apprt/gtk-ng/ui/1.5/window.blp | 17 +++-- 2 files changed, 110 insertions(+), 10 deletions(-) diff --git a/src/apprt/gtk-ng/class/window.zig b/src/apprt/gtk-ng/class/window.zig index ce40462f8..1a8902bb9 100644 --- a/src/apprt/gtk-ng/class/window.zig +++ b/src/apprt/gtk-ng/class/window.zig @@ -128,6 +128,57 @@ pub const Window = extern struct { }, ); }; + + pub const @"tabs-autohide" = struct { + pub const name = "tabs-autohide"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .nick = "Autohide Tab Bar", + .blurb = "If true, tab bar should autohide.", + .default = true, + .accessor = gobject.ext.typedAccessor(Self, bool, .{ + .getter = Self.getTabsAutohide, + }), + }, + ); + }; + + pub const @"tabs-wide" = struct { + pub const name = "tabs-wide"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .nick = "Wide Tabs", + .blurb = "If true, tabs will be in the wide expanded style.", + .default = true, + .accessor = gobject.ext.typedAccessor(Self, bool, .{ + .getter = Self.getTabsWide, + }), + }, + ); + }; + + pub const @"tabs-visible" = struct { + pub const name = "tabs-visible"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .nick = "Tab Bar Visiblity", + .blurb = "If true, tab bar should be visible.", + .default = true, + .accessor = gobject.ext.typedAccessor(Self, bool, .{ + .getter = Self.getTabsVisible, + }), + }, + ); + }; }; const Private = struct { @@ -224,10 +275,18 @@ pub const Window = extern struct { fn syncAppearance(self: *Window) void { // TODO: CSD/SSD - // Trigger our headerbar visibility to refresh - self.as(gobject.Object).notifyByPspec(properties.@"headerbar-visible".impl.param_spec); - // Trigger background opacity to refresh - self.as(gobject.Object).notifyByPspec(properties.@"background-opaque".impl.param_spec); + // Trigger all our dynamic properties that depend on the config. + inline for (&.{ + "background-opaque", + "headerbar-visible", + "tabs-autohide", + "tabs-visible", + "tabs-wide", + }) |key| { + self.as(gobject.Object).notifyByPspec( + @field(properties, key).impl.param_spec, + ); + } } fn toggleCssClass(self: *Window, class: [:0]const u8, value: bool) void { @@ -301,6 +360,37 @@ pub const Window = extern struct { return config.@"background-opacity" >= 1.0; } + fn getTabsAutohide(self: *Self) bool { + const priv = self.private(); + const config = if (priv.config) |v| v.get() else return true; + return switch (config.@"window-show-tab-bar") { + // Auto we always autohide... obviously. + .auto => true, + + // Always we never autohide because we always show the tab bar. + .always => false, + + // Never we autohide because it doesn't actually matter, + // since getTabsVisible will return false. + .never => true, + }; + } + + fn getTabsVisible(self: *Self) bool { + const priv = self.private(); + const config = if (priv.config) |v| v.get() else return true; + return switch (config.@"window-show-tab-bar") { + .always, .auto => true, + .never => false, + }; + } + + fn getTabsWide(self: *Self) bool { + const priv = self.private(); + const config = if (priv.config) |v| v.get() else return true; + return config.@"gtk-wide-tabs"; + } + fn propConfig( _: *adw.ApplicationWindow, _: *gobject.ParamSpec, @@ -611,10 +701,13 @@ pub const Window = extern struct { // Properties gobject.ext.registerProperties(class, &.{ properties.@"active-surface".impl, + properties.@"background-opaque".impl, properties.config.impl, properties.debug.impl, properties.@"headerbar-visible".impl, - properties.@"background-opaque".impl, + properties.@"tabs-autohide".impl, + properties.@"tabs-visible".impl, + properties.@"tabs-wide".impl, }); // Bindings diff --git a/src/apprt/gtk-ng/ui/1.5/window.blp b/src/apprt/gtk-ng/ui/1.5/window.blp index 59e722d76..0b3ed8887 100644 --- a/src/apprt/gtk-ng/ui/1.5/window.blp +++ b/src/apprt/gtk-ng/ui/1.5/window.blp @@ -57,7 +57,10 @@ template $GhosttyWindow: Adw.ApplicationWindow { [top] Adw.TabBar tab_bar { + autohide: bind template.tabs-autohide; + expand-tabs: bind template.tabs-wide; view: tab_view; + visible: bind template.tabs-visible; } Box { @@ -69,11 +72,15 @@ template $GhosttyWindow: Adw.ApplicationWindow { Adw.ToastOverlay toast_overlay { Adw.TabView tab_view { - $GhosttySurface surface { - close-request => $surface_close_request(); - clipboard-write => $surface_clipboard_write(); - toggle-fullscreen => $surface_toggle_fullscreen(); - toggle-maximize => $surface_toggle_maximize(); + Adw.TabPage { + title: bind (template.active-surface as <$GhosttySurface>).title; + + child: $GhosttySurface surface { + close-request => $surface_close_request(); + clipboard-write => $surface_clipboard_write(); + toggle-fullscreen => $surface_toggle_fullscreen(); + toggle-maximize => $surface_toggle_maximize(); + }; } } }