Subject: Re: bug#36680: 27.0.50; undo-tree visualizer flickering with display-buffer-reuse-frames -> t

From: martin rudalics <[email-masked]>
Date: Thu, 18 Jul 2019 09:49:47 +0200

>> As said, this is not the problem.

You probably should have used an 'inhibit-switch-frame' ALIST entry
then.

 > BTW, the call tree looks like
 >
 > undo-tree-visualize > switch-to-buffer-other-window
 >                      > pop-to-buffer with t ACTION
 >                      > display-buffer with t ACTION
 >                      > display-buffer-reuse-window
 >
 > and the last blindly uses the first window in
 >
 >    (get-buffer-window-list buffer 'nomini frames)
 >
 > which can be a window of a different frame even if there is a suitable
 > window in the selected frame.  That's not good IMHO.

OK.  Then please, try the attached patch.  Note that when there's no
suitable window on the selected frame you will still get the annoying
behavior.

Thanks, martin
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index b5ca053e46..1035739e2b 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -2536,7 +2536,8 @@ Buffer Display Action Functions
 
 @defun display-buffer-reuse-window buffer alist
 This function tries to display @var{buffer} by finding a window that
-is already displaying it.
+is already displaying it.  Windows on the selected frame are preferred
+to windows on other frames.
 
 If @var{alist} has a non-@code{nil} @code{inhibit-same-window} entry,
 the selected window is not eligible for reuse.  The set of frames to
diff --git a/lisp/window.el b/lisp/window.el
index 726d022dfe..8cb9670ae4 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7332,25 +7332,26 @@ display-buffer--maybe-same-window
 
 (defun display-buffer-reuse-window (buffer alist)
   "Return a window that is already displaying BUFFER.
-Return nil if no usable window is found.
+Preferably use a window on the selected frame if such a window
+exists.  Return nil if no usable window is found.
 
-If ALIST has a non-nil `inhibit-same-window' entry, the selected
+If ALIST has a non-nil 'inhibit-same-window' entry, the selected
 window is not eligible for reuse.
 
-If ALIST contains a `reusable-frames' entry, its value determines
+If ALIST contains a 'reusable-frames' entry, its value determines
 which frames to search for a reusable window:
   nil -- the selected frame (actually the last non-minibuffer frame)
   A frame   -- just that frame
-  `visible' -- all visible frames
+  'visible' -- all visible frames
   0   -- all frames on the current terminal
   t   -- all frames.
 
-If ALIST contains no `reusable-frames' entry, search just the
+If ALIST contains no 'reusable-frames' entry, search just the
 selected frame if `display-buffer-reuse-frames' and
 `pop-up-frames' are both nil; search all frames on the current
 terminal if either of those variables is non-nil.
 
-If ALIST has a non-nil `inhibit-switch-frame' entry, then in the
+If ALIST has a non-nil 'inhibit-switch-frame' entry, then in the
 event that a window on another frame is chosen, avoid raising
 that frame."
   (let* ((alist-entry (assq 'reusable-frames alist))
@@ -7364,9 +7365,21 @@ display-buffer-reuse-window
 	 (window (if (and (eq buffer (window-buffer))
 			  (not (cdr (assq 'inhibit-same-window alist))))
 		     (selected-window)
-		   (car (delq (selected-window)
-			      (get-buffer-window-list buffer 'nomini
-						      frames))))))
+                   ;; Preferably use a window on the selected frame,
+                   ;; if such a window exists (Bug#36680).
+                   (let* ((windows (delq (selected-window)
+                                         (get-buffer-window-list
+                                          buffer 'nomini frames)))
+                          (first (car windows))
+                          (this-frame (selected-frame)))
+                     (cond
+                      ((eq (window-frame first) this-frame)
+                       first)
+                      ((catch 'found
+                         (dolist (next (cdr windows))
+                           (when (eq (window-frame next) this-frame)
+                             (throw 'found next)))))
+                      (t first))))))
     (when (window-live-p window)
       (prog1 (window--display-buffer buffer window 'reuse alist)
 	(unless (cdr (assq 'inhibit-switch-frame alist))