Subject: Re: bug#51883: 29.0.50; Command to get accidentally deleted frames back

From: Juri Linkov <[email-masked]>
Date: Fri, 14 Jan 2022 10:12:25 +0200

>>> Oh - and the tab-bar - Juri had mentioned it - do we have to do anything
>>> special about it?  In my tests your patch restored the tab-bar correctly
>>> I think.
>>
>> I'm waiting when the Gregory's patch will be pushed to master
>> to start testing the tab-bar with it :-)
>
> I guess Gregory has no access to the repo, so I've tested that
> restoring the tab-bar works correctly, and pushed to master.

I tried to use this, but undelete-frame-mode in the File menu
makes no sense: when you mistakenly deleted a frame, you want
to undelete it immediately, so you open the File menu, and
see the message "No way, you can't undelete the deleted frame,
because you were careless and not enabled a special mode".

So the most useful case for this feature is to get the
accidentally deleted frame back, and it fails to do this.

Instead, it allows undeleting 16 frames in a special mode.
Is there really a human that can delete 16 frames, and then
remember what was on the 16th frame back?

Rereading this thread indicates that the only concern about
enabling this by default was the memory footprint for remembering
16 frames.  OTOH, this feature is really useful for remembering
1 frame.  So this is what should be enabled by default:

diff --git a/lisp/frame.el b/lisp/frame.el
index 599ffe591a..b82a4ae26f 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -2529,6 +2529,12 @@ delete-other-frames
         (if iconify (iconify-frame this) (delete-frame this)))
       (setq this next))))
 
+(defcustom undelete-frame-max 1
+  "Maximum number of frames deleted with `delete-frame'."
+  :type 'integer
+  :group 'frames
+  :version "29.1")
+
 (eval-when-compile (require 'frameset))
 
 (defvar undelete-frame--deleted-frames nil
@@ -2536,7 +2542,7 @@ undelete-frame--deleted-frames
 
 (defun undelete-frame--handle-delete-frame (frame)
   "Save the configuration of frames deleted with `delete-frame'.
-Only the 16 most recently deleted frames are saved."
+Only the `undelete-frame-max' most recently deleted frames are saved."
   (when (frame-live-p frame)
     (setq undelete-frame--deleted-frames
           (cons
@@ -2555,26 +2561,18 @@ undelete-frame--handle-delete-frame
                         (cons '(display . :never)
                               frameset-filter-alist))))
            undelete-frame--deleted-frames))
-    (if (> (length undelete-frame--deleted-frames) 16)
+    (if (> (length undelete-frame--deleted-frames) undelete-frame-max)
         (setq undelete-frame--deleted-frames
               (butlast undelete-frame--deleted-frames)))))
 
-(define-minor-mode undelete-frame-mode
-  "Enable the `undelete-frame' command."
-  :group 'frames
-  :global t
-  (if undelete-frame-mode
-      (add-hook 'delete-frame-functions
-                #'undelete-frame--handle-delete-frame -75)
-    (remove-hook 'delete-frame-functions
-                 #'undelete-frame--handle-delete-frame)
-    (setq undelete-frame--deleted-frames nil)))
+(add-hook 'delete-frame-functions
+          #'undelete-frame--handle-delete-frame -75)
 
 (defun undelete-frame (&optional arg)
   "Undelete a frame deleted with `delete-frame'.
 Without a prefix argument, undelete the most recently deleted
 frame.
-With a numerical prefix argument ARG between 1 and 16, where 1 is
+With a numerical prefix argument ARG between 1 and `undelete-frame-max', where 1 is
 most recently deleted frame, undelete the ARGth deleted frame.
 When called from Lisp, returns the new frame."
   (interactive "P")
@@ -2586,7 +2584,7 @@ undelete-frame
              (frames (frame-list))
              (frameset (nth (1- number) undelete-frame--deleted-frames))
              (graphic (display-graphic-p)))
-        (if (not (<= 1 number 16))
+        (if (not (<= 1 number undelete-frame-max))
             (user-error "%d is not a valid deleted frame number argument"
                         number)
           (if (not frameset)