diff --git a/lisp/window.el b/lisp/window.el index a11293d372..dffcc14ac3 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8497,16 +8497,6 @@ display-buffer-in-previous-window (when (setq window (or best-window second-best-window)) (window--display-buffer buffer window 'reuse alist)))) -(defun display-buffer-use-least-recent-window (buffer alist) - "Display BUFFER in an existing window, but that hasn't been used lately. -This `display-buffer' action function is like -`display-buffer-use-some-window', but will cycle through windows -when displaying buffers repeatedly, and if there's only a single -window, it will split the window." - (when-let ((window (display-buffer-use-some-window - buffer (cons (cons 'inhibit-same-window t) alist)))) - (window-bump-use-time window))) - (defun display-buffer-use-some-window (buffer alist) "Display BUFFER in an existing window. Search for a usable window, set that window to the buffer, and @@ -8559,6 +8549,91 @@ display-buffer-use-some-window (unless (cdr (assq 'inhibit-switch-frame alist)) (window--maybe-raise-frame (window-frame window))))))) +(defun display-buffer--lru-window (alist) + "Return the least recently used window according to ALIST. +Do not return a minibuffer window or a window dedicated to its +buffer. The following ALIST entries have a special meaning: + +- `lru-frames' specifies the frames to investigate and has the + same meaning as the ALL-FRAMES argument of `get-lru-window'. + +- `lru-time' specifies a use time. Do not return a window whose + use time is higher than this. + +- `window-min-width' specifies a preferred minimum width in + canonical frame columns. If it is the constant `full-width', + ask for a full-width window. + +- `window-min-height' specifies a preferred minimum height in + canonical frame lines. If it is the constant `full-height', + ask for a full-height window. + +If ALIST contains a non-nil `inhibit-same--window' entry, never +return the selected window." + (let ((windows + (window-list-1 nil 'nomini (cdr (assq 'lru-frames alist)))) + (lru-time (cdr (assq 'lru-time alist))) + (min-width (cdr (assq 'window-min-width alist))) + (min-height (cdr (assq 'window-min-height alist))) + (not-selected (cdr (assq 'inhibit-same-window alist))) + best-window best-time second-best-window second-best-time time) + (dolist (window windows) + (when (and (not (window-dedicated-p window)) + (or (not not-selected) (not (eq window (selected-window))))) + (setq time (window-use-time window)) + (unless (and (numberp lru-time) (> time lru-time)) + (if (or (eq window (selected-window)) + (and min-width + (or (and (numberp min-width) + (< (window-width window) min-width)) + (and (eq min-width 'full-width) + (not (window-full-width-p window))))) + (and min-height + (or (and (numberp min-height) + (< (window-height window) min-height)) + (and (eq min-height 'full-height) + (not (window-full-height-p window)))))) + ;; This window is either selected or does not meet the size + ;; restrictions - so it's only a second best choice. Try to + ;; find a more recently used one that fits. + (when (or (not second-best-time) (< time second-best-time)) + (setq second-best-time time) + (setq second-best-window window)) + ;; This window is not selected and does meet the size + ;; restrictions. It's the best choice so far. + (when (or (not best-time) (< time best-time)) + (setq best-time time) + (setq best-window window)))))) + (or best-window second-best-window))) + +(defun display-buffer-use-least-recent-window (buffer alist) + "..." + (let* ((alist (cons (cons 'inhibit-same-window t) alist)) + (window + (or (display-buffer-reuse-window buffer alist) + (let ((window (display-buffer--lru-window alist))) + (when (window-live-p window) + (let* ((quit-restore (window-parameter window 'quit-restore)) + (quad (nth 1 quit-restore))) + ;; If the window was used by `display-buffer' before, try to + ;; resize it to its old height but don't signal an error. + (when (and (listp quad) + (integerp (nth 3 quad)) + (> (nth 3 quad) (window-total-height window))) + (condition-case nil + (window-resize + window (- (nth 3 quad) (window-total-height window))) + (error nil))) + (prog1 + (window--display-buffer buffer window 'reuse alist) + (window--even-window-sizes window) + (unless (cdr (assq 'inhibit-switch-frame alist)) + (window--maybe-raise-frame (window-frame window))))))) + (display-buffer-pop-up-window buffer alist)))) + (when window + (window-bump-use-time window) + window))) + (defun display-buffer-no-window (_buffer alist) "Display BUFFER in no window. ALIST is an association list of action symbols and values. See