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

From: Juri Linkov <[email-masked]>
Date: Sun, 27 Jul 2025 09:41:42 +0300

>> 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.)

I confirm the problem on the Mint MATE desktop.

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

Martin, should we revert this patch?

> 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))))