diff --git a/src/Surface.zig b/src/Surface.zig index 1442af8695..eedeb4fb5e 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -236,7 +236,7 @@ const DerivedConfig = struct { clipboard_paste_protection: bool, clipboard_paste_bracketed_safe: bool, copy_on_select: configpkg.CopyOnSelect, - confirm_close_surface: bool, + confirm_close_surface: configpkg.ConfirmCloseSurface, cursor_click_to_move: bool, desktop_notifications: bool, font: font.SharedGridSet.DerivedConfig, @@ -784,18 +784,20 @@ pub fn deactivateInspector(self: *Surface) void { /// 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. + // 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; - // 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; - - // We have to talk to the terminal. - self.renderer_state.mutex.lock(); - defer self.renderer_state.mutex.unlock(); - return !self.io.terminal.cursorIsAtPrompt(); + // Check the configuration for confirming close behavior. + return switch (self.config.confirm_close_surface) { + .always => true, + .false => false, + .true => true: { + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + break :true !self.io.terminal.cursorIsAtPrompt(); + }, + }; } /// Called from the app thread to handle mailbox messages to our specific diff --git a/src/config.zig b/src/config.zig index b7e818f8e1..75dbaae02b 100644 --- a/src/config.zig +++ b/src/config.zig @@ -14,6 +14,7 @@ pub const formatEntry = formatter.formatEntry; // Field types pub const ClipboardAccess = Config.ClipboardAccess; +pub const ConfirmCloseSurface = Config.ConfirmCloseSurface; pub const CopyOnSelect = Config.CopyOnSelect; pub const CustomShaderAnimation = Config.CustomShaderAnimation; pub const FontSyntheticStyle = Config.FontSyntheticStyle; diff --git a/src/config/Config.zig b/src/config/Config.zig index 93239772cc..8726fd67ce 100644 --- a/src/config/Config.zig +++ b/src/config/Config.zig @@ -1323,9 +1323,13 @@ keybind: Keybinds = .{}, /// This configuration can only be set via CLI arguments. @"config-default-files": bool = true, -/// Confirms that a surface should be closed before closing it. This defaults to -/// true. If set to false, surfaces will close without any confirmation. -@"confirm-close-surface": bool = true, +/// Confirms that a surface should be closed before closing it. +/// +/// This defaults to `true`. If set to `false`, surfaces will close without +/// any confirmation. This can also be set to `always`, which will always +/// confirm closing a surface, even if shell integration says a process isn't +/// running. +@"confirm-close-surface": ConfirmCloseSurface = .true, /// Whether or not to quit after the last surface is closed. /// @@ -3663,6 +3667,15 @@ const Replay = struct { } }; +/// Valid values for confirm-close-surface +/// c_int because it needs to be extern compatible +/// If this is changed, you must also update ghostty.h +pub const ConfirmCloseSurface = enum(c_int) { + false, + true, + always, +}; + /// Valid values for custom-shader-animation /// c_int because it needs to be extern compatible /// If this is changed, you must also update ghostty.h