mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-14 05:46:17 +00:00
gtk/TabView: do not closeTab within close-page signal handler
`TabView` assumes to be the sole owner of all `Tab`s within a Window. As such, it could close the managed `Window` once all tabs are removed from its widget. However, during `AdwTabView::close-page` signal triggered by libadwaita, the `Tab` to be closed will gain an another reference for the duration of the signal, breaking `TabView.closeTab` (called via `Tab.closeWithConfirmation`) assumptions that having no tabs meant they are all destroyed. This commit solves the issue by scheduling `Tab.closeWithConfirmation` to be run after `AdwTabView::close-page` signal has finished processing.
This commit is contained in:
@@ -7,6 +7,7 @@ const std = @import("std");
|
||||
const gtk = @import("gtk");
|
||||
const adw = @import("adw");
|
||||
const gobject = @import("gobject");
|
||||
const glib = @import("glib");
|
||||
|
||||
const Window = @import("Window.zig");
|
||||
const Tab = @import("Tab.zig");
|
||||
@@ -243,7 +244,14 @@ fn adwClosePage(
|
||||
const child = page.getChild().as(gobject.Object);
|
||||
const tab: *Tab = @ptrCast(@alignCast(child.getData(Tab.GHOSTTY_TAB) orelse return 0));
|
||||
self.tab_view.closePageFinish(page, @intFromBool(self.forcing_close));
|
||||
if (!self.forcing_close) tab.closeWithConfirmation();
|
||||
if (!self.forcing_close) {
|
||||
// We cannot trigger a close directly in here as the page will stay
|
||||
// alive until this handler returns, breaking the assumption where
|
||||
// no pages means they are all destroyed.
|
||||
//
|
||||
// Schedule the close request to happen in the next event cycle.
|
||||
_ = glib.idleAddOnce(glibIdleOnceCloseTab, tab);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -269,3 +277,8 @@ fn adwSelectPage(_: *adw.TabView, _: *gobject.ParamSpec, self: *TabView) callcon
|
||||
const title = page.getTitle();
|
||||
self.window.setTitle(std.mem.span(title));
|
||||
}
|
||||
|
||||
fn glibIdleOnceCloseTab(data: ?*anyopaque) callconv(.c) void {
|
||||
const tab: *Tab = @ptrCast(@alignCast(data orelse return));
|
||||
tab.closeWithConfirmation();
|
||||
}
|
||||
|
Reference in New Issue
Block a user