apprt/gtk: do not close window if tab overview is open with no tabs

Fixes #8944

When we drag the only tab out of the tab overview, this triggers
an `n-pages` signal with 0 pages. If we close the window in this state,
it causes both Ghostty to exit AND the drag/drop to fail. Even if we
pre-empt Ghostty exiting by modifying the application class, the
drag/drop still fails and the application leaks memory and enters a bad
state.

The solution is to keep the window open if we go to `n-pages == 0` and
we have the tab overview open.

Interestingly, if you click to close the final tab from the tab
overview, Adwaita closes the tab overview so it still triggers the
window closing behavior (this is good).
pull/8955/head
Mitchell Hashimoto 2025-09-29 10:48:16 -07:00
parent a2663692bb
commit 3fdb52e48d
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 15 additions and 2 deletions

View File

@ -524,13 +524,19 @@ pub const Application = extern struct {
if (!config.@"quit-after-last-window-closed") break :q false;
// If the quit timer has expired, quit.
if (priv.quit_timer == .expired) break :q true;
if (priv.quit_timer == .expired) {
log.debug("must_quit due to quit timer expired", .{});
break :q true;
}
// If we have no windows attached to our app, also quit.
if (priv.requested_window and @as(
?*glib.List,
self.as(gtk.Application).getWindows(),
) == null) break :q true;
) == null) {
log.debug("must_quit due to no app windows", .{});
break :q true;
}
// No quit conditions met
break :q false;

View File

@ -1489,6 +1489,13 @@ pub const Window = extern struct {
const priv = self.private();
if (priv.tab_view.getNPages() == 0) {
// If we have no pages left then we want to close window.
// If the tab overview is open, then we don't close the window
// because its a rather abrupt experience. This also fixes an
// issue where dragging out the last tab in the tab overview
// won't cause Ghostty to exit.
if (priv.tab_overview.getOpen() != 0) return;
self.as(gtk.Window).close();
}
}