Subject: Re: bug#58909: 29.0.50; [WIP PATCH] Deleting the last frame of an emacsclient doesn't ask to save

From: Jim Porter <[email-masked]>
Date: Wed, 2 Nov 2022 09:36:52 -0700

On 11/2/2022 5:16 AM, Eli Zaretskii wrote:
>> Date: Tue, 1 Nov 2022 15:39:29 -0700
>> From: Jim Porter <[email-masked]>
>> Cc: [email-masked]
>>
>> Attached is a (hopefully) safer version of my change to 'delete-frame'.
>> In this patch, a hook can only cancel frame deletion if FORCE is
>> non-nil. This way, if there were ever some bug with a hook, you (or some
>> code) can still force-delete the frame.
> 
> Sorry, but I still don't like this.  We currently call this hook via
> safe_call because we don't want to let the hook prevent the deletion
> of the frame.
> 
> I prefer to solve this in server.el, not in lower-level primitives.

Hm, ok. That means I'd need to make sure 'C-x 5 0' calls something other 
than 'delete-frame', so that I could add a prompt to it that can prevent 
deletion of the frame.

Two questions then:

1. If 'delete-frame' is a lower-level primitive, should 'C-x 5 0' call 
it directly, or should there be a higher-level function for it to call? 
If we had some higher-level function, then user-level commands could 
call that, but low-level code could still use 'delete-frame'. This 
user-level command would then be able to run some hook that can prevent 
deletion of the frame.

2. Since server.el has a minor mode (unsurprisingly named 
'server-mode'), maybe one option is to do command remapping. If we remap 
'delete-frame' to some new 'server-delete-frame' when 'server-mode' is 
active, then this should work. See attached for a quick sketch of how 
this would look.

What do you think about one of these?

From 2ce994de124b7609089923090201cbb77fa035bc Mon Sep 17 00:00:00 2001
From: Jim Porter <[email-masked]>
Date: Wed, 2 Nov 2022 09:22:43 -0700
Subject: [PATCH] [WIP] Try using a keymap for server-mode

---
 lisp/server.el | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lisp/server.el b/lisp/server.el
index 90d97c1538..c8f90720f7 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -796,6 +796,18 @@ server-running-p
 	t)
     (file-error nil)))
 
+(defvar-keymap server-keymap
+  "<remap> <delete-frame>" #'server-delete-frame
+  ;; FIXME: Add 'C-x #' to this keymap instead of doing it globally?
+  )
+
+(defun server-delete-frame ()
+  "FIXME: This function is just a quick test implementation to
+override `delete-frame'."
+  (interactive)
+  (save-some-buffers)
+  (delete-frame))
+
 ;;;###autoload
 (define-minor-mode server-mode
   "Toggle Server mode.
@@ -805,6 +817,11 @@ server-mode
 `server-start' for details."
   :global t
   :version "22.1"
+  ;; FIXME: To start a server, you can call `server-mode' or
+  ;; `server-start'.  The latter doesn't activate the minor mode.  To
+  ;; use this keymap, we'd need to make sure we always activate the
+  ;; minor mode.
+  :keymap server-keymap
   ;; Fixme: Should this check for an existing server socket and do
   ;; nothing if there is one (for multiple Emacs sessions)?
   (server-start (not server-mode)))
-- 
2.25.1