mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
fix(gtk): add close confirmation for tabs
This commit is contained in:

committed by
Mitchell Hashimoto

parent
126c0505e2
commit
b7b5b9bbf5
@ -121,10 +121,71 @@ pub fn remove(self: *Tab) void {
|
|||||||
self.window.closeTab(self);
|
self.window.closeTab(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to check if any surface in the split hierarchy needs close confirmation
|
||||||
|
const needsConfirm = struct {
|
||||||
|
fn check(elem: Surface.Container.Elem) bool {
|
||||||
|
return switch (elem) {
|
||||||
|
.surface => |s| s.core_surface.needsConfirmQuit(),
|
||||||
|
.split => |s| check(s.top_left) or check(s.bottom_right),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}.check;
|
||||||
|
|
||||||
|
/// Close the tab, asking for confirmation if any surface requests it.
|
||||||
|
fn closeWithConfirmation(tab: *Tab) void {
|
||||||
|
switch (tab.elem) {
|
||||||
|
.surface => |s| s.close(s.core_surface.needsConfirmQuit()),
|
||||||
|
.split => |s| {
|
||||||
|
if (needsConfirm(s.top_left) or needsConfirm(s.bottom_right)) {
|
||||||
|
const alert = c.gtk_message_dialog_new(
|
||||||
|
tab.window.window,
|
||||||
|
c.GTK_DIALOG_MODAL,
|
||||||
|
c.GTK_MESSAGE_QUESTION,
|
||||||
|
c.GTK_BUTTONS_YES_NO,
|
||||||
|
"Close this tab?",
|
||||||
|
);
|
||||||
|
c.gtk_message_dialog_format_secondary_text(
|
||||||
|
@ptrCast(alert),
|
||||||
|
"All terminal sessions in this tab will be terminated.",
|
||||||
|
);
|
||||||
|
|
||||||
|
// We want the "yes" to appear destructive.
|
||||||
|
const yes_widget = c.gtk_dialog_get_widget_for_response(
|
||||||
|
@ptrCast(alert),
|
||||||
|
c.GTK_RESPONSE_YES,
|
||||||
|
);
|
||||||
|
c.gtk_widget_add_css_class(yes_widget, "destructive-action");
|
||||||
|
|
||||||
|
// We want the "no" to be the default action
|
||||||
|
c.gtk_dialog_set_default_response(
|
||||||
|
@ptrCast(alert),
|
||||||
|
c.GTK_RESPONSE_NO,
|
||||||
|
);
|
||||||
|
|
||||||
|
_ = c.g_signal_connect_data(alert, "response", c.G_CALLBACK(>kTabCloseConfirmation), tab, null, c.G_CONNECT_DEFAULT);
|
||||||
|
c.gtk_widget_show(alert);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tab.remove();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn gtkTabCloseClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
|
pub fn gtkTabCloseClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
|
||||||
const tab: *Tab = @ptrCast(@alignCast(ud));
|
const tab: *Tab = @ptrCast(@alignCast(ud));
|
||||||
const window = tab.window;
|
tab.closeWithConfirmation();
|
||||||
window.closeTab(tab);
|
}
|
||||||
|
|
||||||
|
fn gtkTabCloseConfirmation(
|
||||||
|
alert: *c.GtkMessageDialog,
|
||||||
|
response: c.gint,
|
||||||
|
ud: ?*anyopaque,
|
||||||
|
) callconv(.C) void {
|
||||||
|
c.gtk_window_destroy(@ptrCast(alert));
|
||||||
|
if (response == c.GTK_RESPONSE_YES) {
|
||||||
|
const tab: *Tab = @ptrCast(@alignCast(ud));
|
||||||
|
tab.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
||||||
@ -146,6 +207,6 @@ pub fn gtkTabClick(
|
|||||||
const self: *Tab = @ptrCast(@alignCast(ud));
|
const self: *Tab = @ptrCast(@alignCast(ud));
|
||||||
const gtk_button = c.gtk_gesture_single_get_current_button(@ptrCast(gesture));
|
const gtk_button = c.gtk_gesture_single_get_current_button(@ptrCast(gesture));
|
||||||
if (gtk_button == c.GDK_BUTTON_MIDDLE) {
|
if (gtk_button == c.GDK_BUTTON_MIDDLE) {
|
||||||
self.remove();
|
self.closeWithConfirmation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user