diff --git a/lisp/window.el b/lisp/window.el index e9d57652ec6..31c2ae50792 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -2615,7 +2615,36 @@ get-largest-window (setq best-window window)))) best-window)) -(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames) +(defun window-indirect-buffer-p (&optional window buffer-or-name) + "Return non-nil if specified WINDOW is indirectly related to BUFFER-OR-NAME. +WINDOW must be a live window and defaults to the selected window. +BUFFER-OR-NAME may be a buffer or the name of an existing buffer and +defaults to the current buffer. + +WINODW is indirectly related to BUFFER-OR-NAME if one of the following +conditions hold: + +- BUFFER-OR-NAME specifies an indirect buffer and WINDOW's buffer is its + base buffer. + +- WINDOW's buffer is an indirect buffer whose base buffer is the buffer + specified by BUFFER-OR-NAME. + +- Both, WINDOW's buffer and the buffer specified by BUFFER-OR-NAME, are + indirect buffer's sharing the same base buffer. + +Return nil if none of the above holds." + (let* ((window (window-normalize-window window t)) + (window-buffer (window-buffer window)) + (window-base-buffer (buffer-base-buffer window-buffer)) + (buffer (window-normalize-buffer buffer-or-name)) + (buffer-base-buffer (buffer-base-buffer buffer))) + (or (eq buffer-base-buffer window-buffer) + (eq window-base-buffer buffer) + (and buffer-base-buffer + (eq buffer-base-buffer window-base-buffer))))) + +(defun get-buffer-window-list (&optional buffer-or-name minibuf all-frames indirect) "Return list of all windows displaying BUFFER-OR-NAME, or nil if none. BUFFER-OR-NAME may be a buffer or the name of an existing buffer and defaults to the current buffer. If the selected window displays @@ -2644,11 +2673,17 @@ get-buffer-window-list - A frame means consider all windows on that frame only. Anything else means consider all windows on the selected frame -and no others." +and no others. + +INDIRECT non-nil means to include in the list returned all windows that +are indirectly related to BUFFER-OR-NAME, that is, all windows for which +`window-indirect-buffer-p' with the window and the buffer specified by +BUFFER-OR-NAME as arguments returns non-nil." (let ((buffer (window-normalize-buffer buffer-or-name)) windows) (dolist (window (window-list-1 (selected-window) minibuf all-frames)) - (when (eq (window-buffer window) buffer) + (when (or (eq (window-buffer window) buffer) + (and indirect (window-indirect-buffer-p window buffer))) (setq windows (cons window windows)))) (nreverse windows))) @@ -8239,20 +8274,24 @@ display-buffer-reuse-window node `(elisp) Buffer Display Action Functions'. It should be called only by `display-buffer' or a function directly or indirectly called by the latter." - (let* ((alist-entry (assq 'reusable-frames alist)) - (frames (cond (alist-entry (cdr alist-entry)) + (let* ((reusable-frames (assq 'reusable-frames alist)) + (reuse-indirect (assq 'reuse-indirect alist)) + (frames (cond (reusable-frames (cdr reusable-frames)) ((window--pop-up-frames alist) 0) (display-buffer-reuse-frames 0) (t (last-nonminibuffer-frame)))) - (window (if (and (eq buffer (window-buffer)) + (window (if (and (or (eq buffer (window-buffer)) + (and reuse-indirect + (window-indirect-buffer-p nil buffer))) (not (cdr (assq 'inhibit-same-window alist)))) (selected-window) ;; 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))) + (let* ((windows + (delq (selected-window) + (get-buffer-window-list + buffer 'nomini frames reuse-indirect))) (first (car windows)) (this-frame (selected-frame))) (cond