Subject: bug#79098: 31.0.50; quit-window raises frame, steals focus

From: Óscar Fuentes <[email-masked]>
Date: Sun, 27 Jul 2025 02:22:44 +0200

> emacs -Q
>
> Split window so window 1 shows *scratch* and window 2 shows *Messages*
>
> Eval this in *scratch* and, before 5 seconds, switch the focus to some
> other application's frame that obscures Emacs' frame:
>
> (run-with-timer
>  5 nil
>  (lambda ()
>    (quit-window nil (other-window-for-scrolling))))
>
> When the timer executes, Emacs' frame will be raised and given focus.
>
> Something similar happens in MSWindows, so this is not an artifact
> specific to my desktop manager (KDE 6.3 on my case.)

quit-window calls quit-restore-window, which calls
window--quit-restore-select-window, and this function introduced the
problem:

commit 9f4347e00c02c3aa436118425a0cda2bc7f69d51
Author: Juri Linkov <[email-masked]>
Date:   Thu Apr 17 21:21:29 2025 +0300

    Don't switch to another frame if window is not on the selected frame.
    
    * lisp/window.el (window--quit-restore-select-window):
    Add optional arg 'frame'.  Don't switch to another frame
    if window is not on the selected frame (bug#71386).
    (quit-restore-window): Provide the 'frame' arg
    to 'window--quit-restore-select-window' calls.
    Patch by martin rudalics <[email-masked]>.
    
    * test/lisp/tab-bar-tests.el (tab-bar-tests-quit-restore-window):
    No need to reselect the frame after 'quit-window'.

diff --git a/lisp/window.el b/lisp/window.el
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -5338,166 +5338,173 @@
-(defun window--quit-restore-select-window (window)
+(defun window--quit-restore-select-window (window &optional frame)
   "Select WINDOW after having quit another one.
 Do not select an inactive minibuffer window."
   (when (and (window-live-p window)
              (or (not (window-minibuffer-p window))
                  (minibuffer-window-active-p window)))
-    (select-window window)))
+    ;; If WINDOW is not on the selected frame, don't switch to
+    ;; another frame.
+    (unless (and (eq frame (selected-frame))
+		 (not (eq frame (window-frame window))))
+      (setq frame (window-frame window))
+      (set-frame-selected-window frame window)
+      (select-frame-set-input-focus frame))))