From 56ccadd7f1de5df4041d475a1af9c051e034ffbc Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 11 Sep 2023 15:44:08 -0700 Subject: [PATCH] core: app needsConfirmQuit to streamline quitting if no active sessions --- include/ghostty.h | 1 + src/App.zig | 10 ++++++++++ src/Surface.zig | 28 +++++++++++++++------------- src/apprt/embedded.zig | 5 +++++ 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index 56b1fe5dd..eab70bac2 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -316,6 +316,7 @@ bool ghostty_app_tick(ghostty_app_t); void *ghostty_app_userdata(ghostty_app_t); void ghostty_app_keyboard_changed(ghostty_app_t); void ghostty_app_reload_config(ghostty_app_t); +bool ghostty_app_needs_confirm_quit(ghostty_app_t); ghostty_surface_config_s ghostty_surface_config_new(); diff --git a/src/App.zig b/src/App.zig index 942581e3e..4b88c30e7 100644 --- a/src/App.zig +++ b/src/App.zig @@ -168,6 +168,16 @@ pub fn focusedSurface(self: *const App) ?*Surface { return surface; } +/// Returns true if confirmation is needed to quit the app. It is up to +/// the apprt to call this. +pub fn needsConfirmQuit(self: *const App) bool { + for (self.surfaces.items) |v| { + if (v.core_surface.needsConfirmQuit()) return true; + } + + return false; +} + /// Initialize once and return the font discovery mechanism. This remains /// initialized throughout the lifetime of the application because some /// font discovery mechanisms (i.e. fontconfig) are unsafe to reinit. diff --git a/src/Surface.zig b/src/Surface.zig index 505f572f5..922175e2d 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -504,22 +504,24 @@ pub fn deinit(self: *Surface) void { /// Close this surface. This will trigger the runtime to start the /// close process, which should ultimately deinitialize this surface. pub fn close(self: *Surface) void { - const process_alive = process_alive: { - // If the child has exited then our process is certainly not alive. - // We check this first to avoid the locking overhead below. - if (self.child_exited) break :process_alive false; + self.rt_surface.close(self.needsConfirmQuit()); +} - // If we are configured to not hold open surfaces explicitly, just - // always say there is nothing alive. - if (!self.config.confirm_close_surface) break :process_alive false; +/// True if the surface requires confirmation to quit. This should be called +/// by apprt to determine if the surface should confirm before quitting. +pub fn needsConfirmQuit(self: *Surface) bool { + // If the child has exited then our process is certainly not alive. + // We check this first to avoid the locking overhead below. + if (self.child_exited) return false; - // We have to talk to the terminal. - self.renderer_state.mutex.lock(); - defer self.renderer_state.mutex.unlock(); - break :process_alive !self.io.terminal.cursorIsAtPrompt(); - }; + // If we are configured to not hold open surfaces explicitly, just + // always say there is nothing alive. + if (!self.config.confirm_close_surface) return false; - self.rt_surface.close(process_alive); + // We have to talk to the terminal. + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + return !self.io.terminal.cursorIsAtPrompt(); } /// Called from the app thread to handle mailbox messages to our specific diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index e3475cc82..e3b8df6e0 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -787,6 +787,11 @@ pub const CAPI = struct { }; } + /// Returns true if the app needs to confirm quitting. + export fn ghostty_app_needs_confirm_quit(v: *App) bool { + return v.core_app.needsConfirmQuit(); + } + /// Returns initial surface options. export fn ghostty_surface_config_new() apprt.Surface.Options { return .{};