gtk: show/hide tab bar

This commit is contained in:
Yi Ming
2024-11-08 17:21:25 +08:00
parent 75fe0b2dfb
commit d47411dfe9
8 changed files with 55 additions and 1 deletions

View File

@ -534,6 +534,7 @@ typedef enum {
GHOSTTY_ACTION_NEW_SPLIT, GHOSTTY_ACTION_NEW_SPLIT,
GHOSTTY_ACTION_CLOSE_ALL_WINDOWS, GHOSTTY_ACTION_CLOSE_ALL_WINDOWS,
GHOSTTY_ACTION_TOGGLE_FULLSCREEN, GHOSTTY_ACTION_TOGGLE_FULLSCREEN,
GHOSTTY_ACTION_TOGGLE_TAB_BAR,
GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW, GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW,
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS, GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL, GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,

View File

@ -111,7 +111,7 @@ extension Ghostty {
deinit { deinit {
// This will force the didSet callbacks to run which free. // This will force the didSet callbacks to run which free.
self.app = nil self.app = nil
#if os(macOS) #if os(macOS)
NotificationCenter.default.removeObserver(self) NotificationCenter.default.removeObserver(self)
#endif #endif
@ -525,6 +525,8 @@ extension Ghostty {
fallthrough fallthrough
case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS: case GHOSTTY_ACTION_CLOSE_ALL_WINDOWS:
fallthrough fallthrough
case GHOSTTY_ACTION_TOGGLE_TAB_BAR:
fallthrough
case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW: case GHOSTTY_ACTION_TOGGLE_TAB_OVERVIEW:
fallthrough fallthrough
case GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS: case GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS:

View File

@ -4035,6 +4035,12 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
{}, {},
), ),
.toggle_tab_bar => try self.rt_app.performAction(
.{ .surface = self },
.toggle_tab_bar,
{},
),
.toggle_tab_overview => try self.rt_app.performAction( .toggle_tab_overview => try self.rt_app.performAction(
.{ .surface = self }, .{ .surface = self },
.toggle_tab_overview, .toggle_tab_overview,

View File

@ -88,6 +88,9 @@ pub const Action = union(Key) {
/// Toggle fullscreen mode. /// Toggle fullscreen mode.
toggle_fullscreen: Fullscreen, toggle_fullscreen: Fullscreen,
/// Toggle tab bar.
toggle_tab_bar,
/// Toggle tab overview. /// Toggle tab overview.
toggle_tab_overview, toggle_tab_overview,
@ -197,6 +200,7 @@ pub const Action = union(Key) {
new_split, new_split,
close_all_windows, close_all_windows,
toggle_fullscreen, toggle_fullscreen,
toggle_tab_bar,
toggle_tab_overview, toggle_tab_overview,
toggle_window_decorations, toggle_window_decorations,
toggle_quick_terminal, toggle_quick_terminal,

View File

@ -208,6 +208,7 @@ pub const App = struct {
.toggle_split_zoom, .toggle_split_zoom,
.present_terminal, .present_terminal,
.close_all_windows, .close_all_windows,
.toggle_tab_bar,
.toggle_tab_overview, .toggle_tab_overview,
.toggle_window_decorations, .toggle_window_decorations,
.toggle_quick_terminal, .toggle_quick_terminal,

View File

@ -470,6 +470,7 @@ pub fn performAction(
.mouse_visibility => self.setMouseVisibility(target, value), .mouse_visibility => self.setMouseVisibility(target, value),
.mouse_shape => try self.setMouseShape(target, value), .mouse_shape => try self.setMouseShape(target, value),
.mouse_over_link => self.setMouseOverLink(target, value), .mouse_over_link => self.setMouseOverLink(target, value),
.toggle_tab_bar => self.toggleTabBar(target),
.toggle_tab_overview => self.toggleTabOverview(target), .toggle_tab_overview => self.toggleTabOverview(target),
.toggle_window_decorations => self.toggleWindowDecorations(target), .toggle_window_decorations => self.toggleWindowDecorations(target),
.quit_timer => self.quitTimer(value), .quit_timer => self.quitTimer(value),
@ -654,6 +655,23 @@ fn toggleFullscreen(
} }
} }
fn toggleTabBar(_: *App, target: apprt.Target) void {
switch (target) {
.app => {},
.surface => |v| {
const window = v.rt_surface.container.window() orelse {
log.info(
"toggleTabBar invalid for container={s}",
.{@tagName(v.rt_surface.container)},
);
return;
};
window.toggleTabBar();
},
}
}
fn toggleTabOverview(_: *App, target: apprt.Target) void { fn toggleTabOverview(_: *App, target: apprt.Target) void {
switch (target) { switch (target) {
.app => {}, .app => {},

View File

@ -37,6 +37,8 @@ window: *c.GtkWindow,
/// GtkHeaderBar depending on if adw is enabled and linked. /// GtkHeaderBar depending on if adw is enabled and linked.
header: ?*c.GtkWidget, header: ?*c.GtkWidget,
tab_bar: ?*c.AdwTabBar,
/// The tab overview for the window. This is possibly null since there is no /// The tab overview for the window. This is possibly null since there is no
/// taboverview without a AdwApplicationWindow (libadwaita >= 1.4.0). /// taboverview without a AdwApplicationWindow (libadwaita >= 1.4.0).
tab_overview: ?*c.GtkWidget, tab_overview: ?*c.GtkWidget,
@ -74,6 +76,7 @@ pub fn init(self: *Window, app: *App) !void {
.app = app, .app = app,
.window = undefined, .window = undefined,
.header = null, .header = null,
.tab_bar = null,
.tab_overview = null, .tab_overview = null,
.notebook = undefined, .notebook = undefined,
.context_menu = undefined, .context_menu = undefined,
@ -322,6 +325,8 @@ pub fn init(self: *Window, app: *App) !void {
@ptrCast(@alignCast(toolbar_view)), @ptrCast(@alignCast(toolbar_view)),
); );
} }
self.tab_bar = tab_bar;
} else { } else {
switch (self.notebook) { switch (self.notebook) {
.adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0)) { .adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0)) {
@ -349,6 +354,7 @@ pub fn init(self: *Window, app: *App) !void {
if (!app.config.@"gtk-wide-tabs") { if (!app.config.@"gtk-wide-tabs") {
c.adw_tab_bar_set_expand_tabs(tab_bar, 0); c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
} }
self.tab_bar = tab_bar;
}, },
.gtk_notebook => {}, .gtk_notebook => {},
@ -496,6 +502,18 @@ pub fn toggleFullscreen(self: *Window) void {
} }
} }
pub fn toggleTabBar(self: *Window) void {
if (self.tab_bar) |tab_bar| {
const is_visible = c.gtk_widget_get_visible(
@ptrCast(@alignCast(tab_bar)),
) == 1;
c.gtk_widget_set_visible(@ptrCast(@alignCast(tab_bar)), @intFromBool(!is_visible));
} else {
const is_visible = c.gtk_notebook_get_show_tabs(self.notebook.gtk_notebook) == 1;
c.gtk_notebook_set_show_tabs(self.notebook.gtk_notebook, @intFromBool(!is_visible));
}
}
/// Toggle the window decorations for this window. /// Toggle the window decorations for this window.
pub fn toggleWindowDecorations(self: *Window) void { pub fn toggleWindowDecorations(self: *Window) void {
const old_decorated = c.gtk_window_get_decorated(self.window) == 1; const old_decorated = c.gtk_window_get_decorated(self.window) == 1;

View File

@ -306,6 +306,9 @@ pub const Action = union(enum) {
/// If the new position is out of bounds, it wraps around cyclically within the tab range. /// If the new position is out of bounds, it wraps around cyclically within the tab range.
move_tab: isize, move_tab: isize,
/// Toggle the tab bar. This works only on Linux.
toggle_tab_bar: void,
/// Toggle the tab overview. /// Toggle the tab overview.
/// This only works with libadwaita enabled currently. /// This only works with libadwaita enabled currently.
toggle_tab_overview: void, toggle_tab_overview: void,
@ -639,6 +642,7 @@ pub const Action = union(enum) {
.close_surface, .close_surface,
.close_window, .close_window,
.toggle_fullscreen, .toggle_fullscreen,
.toggle_tab_bar,
.toggle_window_decorations, .toggle_window_decorations,
.toggle_secure_input, .toggle_secure_input,
.crash, .crash,