apprt/gtk-ng: split close confirmation

pull/8207/head
Mitchell Hashimoto 2025-08-10 13:35:26 -07:00
parent 441af8389b
commit ca4e38ff03
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 75 additions and 25 deletions

View File

@ -133,6 +133,7 @@ pub const CloseConfirmationDialog = extern struct {
const C = Common(Self, Private);
pub const as = C.as;
pub const ref = C.ref;
pub const refSink = C.refSink;
pub const unref = C.unref;
const private = C.private;
@ -179,12 +180,14 @@ pub const Target = enum(c_int) {
app,
tab,
window,
surface,
pub fn title(self: Target) [*:0]const u8 {
return switch (self) {
.app => i18n._("Quit Ghostty?"),
.tab => i18n._("Close Tab?"),
.window => i18n._("Close Window?"),
.surface => i18n._("Close Split?"),
};
}
@ -193,6 +196,7 @@ pub const Target = enum(c_int) {
.app => i18n._("All terminal sessions will be terminated."),
.tab => i18n._("All terminal sessions in this tab will be terminated."),
.window => i18n._("All terminal sessions in this window will be terminated."),
.surface => i18n._("The currently running process in this split will be terminated."),
};
}

View File

@ -130,6 +130,10 @@ pub const SplitTree = extern struct {
/// propTree function for a lot more details.
rebuild_pending: bool,
/// Used to store state about a pending surface close for the
/// close dialog.
pending_close: ?Surface.Tree.Node.Handle,
pub var offset: c_int = 0;
};
@ -138,6 +142,10 @@ pub const SplitTree = extern struct {
// Initialize our actions
self.initActions();
// Initialize some basic state
const priv = self.private();
priv.pending_close = null;
}
fn initActions(self: *Self) void {
@ -511,22 +519,62 @@ pub const SplitTree = extern struct {
.window, .tab => return,
// Remove the surface from the tree.
.surface => {
// TODO: close confirmation
.surface => {},
}
// Find the surface in the tree.
const core = surface.core() orelse return;
// Reset our pending close state
const priv = self.private();
priv.pending_close = null;
// Find the surface in the tree to verify this is valid and
// set our pending close handle.
priv.pending_close = handle: {
const tree = self.getTree() orelse return;
const handle: Surface.Tree.Node.Handle = handle: {
var it = tree.iterator();
while (it.next()) |entry| {
if (entry.view == surface) break :handle entry.handle;
if (entry.view == surface) {
break :handle entry.handle;
}
}
return;
};
// If we don't need to confirm then just close immediately.
if (!core.needsConfirmQuit()) {
closeConfirmationClose(
null,
self,
);
return;
}
// Show a confirmation dialog
const dialog: *CloseConfirmationDialog = .new(.surface);
_ = CloseConfirmationDialog.signals.@"close-request".connect(
dialog,
*Self,
closeConfirmationClose,
self,
.{},
);
dialog.present(self.as(gtk.Widget));
}
fn closeConfirmationClose(
_: ?*CloseConfirmationDialog,
self: *Self,
) callconv(.c) void {
// Get the handle we're closing
const priv = self.private();
const handle = priv.pending_close orelse return;
priv.pending_close = null;
// Remove it from the tree.
var new_tree = tree.remove(
const old_tree = self.getTree() orelse return;
var new_tree = old_tree.remove(
Application.default().allocator(),
handle,
) catch |err| {
@ -535,8 +583,6 @@ pub const SplitTree = extern struct {
};
defer new_tree.deinit();
self.setTree(&new_tree);
},
}
}
fn propSurfaceFocused(