diff --git a/lisp/window.el b/lisp/window.el index 604b9868921..155b0b55482 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -4948,6 +4968,13 @@ frame-auto-hide-function :group 'frames :version "26.1") +(defvar window-delete-frame-functions nil + "A list of functions to handle the frame deletion. +Each of functions is called with two arguments: FRAME and KILL where +KILL means the buffer shown in window will be killed. When one of functions +returns a non-nil value then `window--delete' will not delete the frame. +The function can also perform own action instead of deleting the frame.") + (defun window--delete (&optional window dedicated-only kill) "Delete WINDOW if possible. WINDOW must be a live window and defaults to the selected one. @@ -4962,6 +4989,10 @@ window--delete ((eq deletable 'frame) (let ((frame (window-frame window))) (cond + ((run-hook-with-args-until-success + 'window-delete-frame-functions + frame kill) + nil) (kill (delete-frame frame)) ((functionp (frame-parameter frame 'auto-hide-function)) diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 6ab6324540e..2f7578b842b 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -2659,6 +2659,17 @@ tab-switcher-mouse-select (goto-char (posn-point (event-end event))) (tab-switcher-select)) + +(defun tab-bar-window-delete-frame (frame _kill) + "Handle frame deletion in `tab-bar-mode'. +When there are more than one tab on the selected frame, then close +the current tab. In this case return t to not delete the frame +in `window--delete'." + (and tab-bar-mode (> (length (funcall tab-bar-tabs-function frame)) 1) + (progn (tab-bar-close-tab) t))) + +(add-hook 'window-delete-frame-functions #'tab-bar-window-delete-frame) + (defun tab-bar--reusable-frames (all-frames) (cond