Skip to content

Commit 5909070

Browse files
committed
gtk: add option to always display the tab bar
Also fixes crashes in both vanilla GTK and Adwaita implementations of `closeTab`, which erroneously close windows twice when there are no more tabs left (we probably already handle it somewhere else).
1 parent f0d2760 commit 5909070

File tree

4 files changed

+20
-39
lines changed

4 files changed

+20
-39
lines changed

src/apprt/gtk/Window.zig

+2
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ pub fn init(self: *Window, app: *App) !void {
295295
c.adw_tab_bar_set_view(tab_bar, self.notebook.adw.tab_view);
296296

297297
if (!app.config.@"gtk-wide-tabs") c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
298+
c.adw_tab_bar_set_autohide(tab_bar, @intFromBool(!app.config.@"window-always-show-tabs"));
298299

299300
const tab_bar_widget: *c.GtkWidget = @ptrCast(@alignCast(tab_bar));
300301
switch (self.app.config.@"gtk-tabs-location") {
@@ -346,6 +347,7 @@ pub fn init(self: *Window, app: *App) !void {
346347
c.adw_tab_bar_set_view(tab_bar, adw.tab_view);
347348

348349
if (!app.config.@"gtk-wide-tabs") c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
350+
c.adw_tab_bar_set_autohide(tab_bar, @intFromBool(!app.config.@"window-always-show-tabs"));
349351
},
350352

351353
.gtk => {},

src/apprt/gtk/notebook_adw.zig

-20
Original file line numberDiff line numberDiff line change
@@ -134,26 +134,6 @@ pub const NotebookAdw = struct {
134134

135135
const page = c.adw_tab_view_get_page(self.tab_view, @ptrCast(tab.box)) orelse return;
136136
c.adw_tab_view_close_page(self.tab_view, page);
137-
138-
// If we have no more tabs we close the window
139-
if (self.nPages() == 0) {
140-
const window = tab.window.window;
141-
142-
// libadw versions <= 1.3.x leak the final page view
143-
// which causes our surface to not properly cleanup. We
144-
// unref to force the cleanup. This will trigger a critical
145-
// warning from GTK, but I don't know any other workaround.
146-
// Note: I'm not actually sure if 1.4.0 contains the fix,
147-
// I just know that 1.3.x is broken and 1.5.1 is fixed.
148-
// If we know that 1.4.0 is fixed, we can change this.
149-
if (!adwaita.versionAtLeast(1, 4, 0)) {
150-
c.g_object_unref(tab.box);
151-
}
152-
153-
// `self` will become invalid after this call because it will have
154-
// been freed up as part of the process of closing the window.
155-
c.gtk_window_destroy(window);
156-
}
157137
}
158138
};
159139

src/apprt/gtk/notebook_gtk.zig

+13-19
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ pub const NotebookGtk = struct {
3131
};
3232
c.gtk_notebook_set_tab_pos(gtk_notebook, notebook_tab_pos);
3333
c.gtk_notebook_set_scrollable(gtk_notebook, 1);
34-
c.gtk_notebook_set_show_tabs(gtk_notebook, 0);
3534
c.gtk_notebook_set_show_border(gtk_notebook, 0);
3635

3736
// This enables all Ghostty terminal tabs to be exchanged across windows.
@@ -81,6 +80,7 @@ pub const NotebookGtk = struct {
8180
log.warn("currentTab", .{});
8281
const page = self.currentPage() orelse return null;
8382
const child = c.gtk_notebook_get_nth_page(self.notebook, page);
83+
8484
return @ptrCast(@alignCast(
8585
c.g_object_get_data(@ptrCast(child), Tab.GHOSTTY_TAB) orelse return null,
8686
));
@@ -164,9 +164,7 @@ pub const NotebookGtk = struct {
164164
c.gtk_notebook_set_tab_reorderable(self.notebook, box_widget, 1);
165165
c.gtk_notebook_set_tab_detachable(self.notebook, box_widget, 1);
166166

167-
if (self.nPages() > 1) {
168-
c.gtk_notebook_set_show_tabs(self.notebook, 1);
169-
}
167+
self.updateShowTabs(window);
170168

171169
// Switch to the new tab
172170
c.gtk_notebook_set_current_page(self.notebook, page_idx);
@@ -183,20 +181,21 @@ pub const NotebookGtk = struct {
183181
c.gtk_notebook_remove_page(self.notebook, page_idx);
184182

185183
const remaining = self.nPages();
186-
switch (remaining) {
187-
// If we have no more tabs we close the window
188-
0 => c.gtk_window_destroy(tab.window.window),
189-
190-
// If we have one more tab we hide the tab bar
191-
1 => c.gtk_notebook_set_show_tabs(self.notebook, 0),
192-
193-
else => {},
194-
}
195184

196185
// If we have remaining tabs, we need to make sure we grab focus.
197186
if (remaining > 0)
198187
(self.currentTab() orelse return).window.focusCurrentTab();
199188
}
189+
190+
fn updateShowTabs(self: *NotebookGtk, window: *Window) void {
191+
const show_tabs = switch (self.nPages()) {
192+
0 => false,
193+
1 => window.app.config.@"window-always-show-tabs",
194+
else => true,
195+
};
196+
197+
c.gtk_notebook_set_show_tabs(self.notebook, @intFromBool(show_tabs));
198+
}
200199
};
201200

202201
fn getNotebookPageIndex(page: *c.GtkNotebookPage) c_int {
@@ -245,12 +244,7 @@ fn gtkPageRemoved(
245244
log.warn("gtkPageRemoved", .{});
246245
const window: *Window = @ptrCast(@alignCast(ud.?));
247246

248-
// Hide the tab bar if we only have one tab after removal
249-
const remaining = c.gtk_notebook_get_n_pages(window.notebook.gtk.notebook);
250-
251-
if (remaining == 1) {
252-
c.gtk_notebook_set_show_tabs(window.notebook.gtk.notebook, 0);
253-
}
247+
window.notebook.gtk.updateShowTabs(window);
254248
}
255249

256250
fn gtkSwitchPage(_: *c.GtkNotebook, page: *c.GtkWidget, _: usize, ud: ?*anyopaque) callconv(.C) void {

src/config/Config.zig

+5
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,11 @@ keybind: Keybinds = .{},
13361336
/// * `end` - Insert the new tab at the end of the tab list.
13371337
@"window-new-tab-position": WindowNewTabPosition = .current,
13381338

1339+
/// Whether tabs should always be displayed, regardless of how many tabs
1340+
/// are open. If false (default), the tab bar is only displayed when there
1341+
/// are two or more tabs.
1342+
@"window-always-show-tabs": bool = false,
1343+
13391344
/// Background color for the window titlebar. This only takes effect if
13401345
/// window-theme is set to ghostty. Currently only supported in the GTK app
13411346
/// runtime.

0 commit comments

Comments
 (0)