mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-15 10:30:25 -08:00
Fix 'display-buffer-use-least-recent-window'
* src/window.c (Fwindow_use_time): Doc fix. (Fwindow_bump_use_time): Bump use time of the seleceted window as well. Doc fix. * lisp/window.el (display-buffer-avoid-small-windows): Remove. All users changed. (window--display-buffer): Bump window use time when requested. (display-buffer--lru-window): New function. (display-buffer-use-some-window): Use it. (display-buffer-use-least-recent-window): Rewrite and enhance doc string. * doc/lispref/windows.texi (Selecting Windows) (Buffer Display Action Functions, Buffer Display Action Alists) (The Zen of Buffer Display): Improve and update documentation of window selection and display facilities.
This commit is contained in:
parent
5190ea6259
commit
9f508cef85
3 changed files with 339 additions and 96 deletions
169
lisp/window.el
169
lisp/window.el
|
|
@ -2484,14 +2484,6 @@ and no others."
|
|||
|
||||
(defalias 'some-window 'get-window-with-predicate)
|
||||
|
||||
(defcustom display-buffer-avoid-small-windows nil
|
||||
"If non-nil, windows that have fewer lines than this are avoided.
|
||||
This is used by `get-lru-window'. The value is interpreted in units
|
||||
of the frame's canonical line height, like `window-total-height' does."
|
||||
:type '(choice (const nil) number)
|
||||
:version "29.1"
|
||||
:group 'windows)
|
||||
|
||||
(defun get-lru-window (&optional all-frames dedicated not-selected no-other)
|
||||
"Return the least recently used window on frames specified by ALL-FRAMES.
|
||||
Return a full-width window if possible. A minibuffer window is
|
||||
|
|
@ -2517,11 +2509,7 @@ have special meanings:
|
|||
- A frame means consider all windows on that frame only.
|
||||
|
||||
Any other value of ALL-FRAMES means consider all windows on the
|
||||
selected frame and no others.
|
||||
|
||||
`display-buffer-avoid-small-windows', if non-nil, is also taken into
|
||||
consideration. Windows whose height is smaller that the value of that
|
||||
variable will be avoided if larger windows are available."
|
||||
selected frame and no others."
|
||||
(let ((windows (window-list-1 nil 'nomini all-frames))
|
||||
best-window best-time second-best-window second-best-time time)
|
||||
(dolist (window windows)
|
||||
|
|
@ -2531,9 +2519,6 @@ variable will be avoided if larger windows are available."
|
|||
(not (window-parameter window 'no-other-window))))
|
||||
(setq time (window-use-time window))
|
||||
(if (or (eq window (selected-window))
|
||||
(and display-buffer-avoid-small-windows
|
||||
(< (window-height window)
|
||||
display-buffer-avoid-small-windows))
|
||||
(not (window-full-width-p window)))
|
||||
(when (or (not second-best-time) (< time second-best-time))
|
||||
(setq second-best-time time)
|
||||
|
|
@ -7274,6 +7259,11 @@ entry. Otherwise, if WINDOW is new and the value of
|
|||
dedicated flag to that value. In any other case, reset WINDOW's
|
||||
dedicated flag to nil.
|
||||
|
||||
If ALIST contains a non-nil `bump-use-time' entry, bump use time
|
||||
of WINDOW so further calls of `display-buffer-use-some-window'
|
||||
and `display-buffer-use-least-recent-window' will try to avoid
|
||||
it.
|
||||
|
||||
Return WINDOW if BUFFER and WINDOW are live."
|
||||
(when (and (buffer-live-p buffer) (window-live-p window))
|
||||
(display-buffer-record-window type window buffer)
|
||||
|
|
@ -7281,6 +7271,10 @@ Return WINDOW if BUFFER and WINDOW are live."
|
|||
;; Unless WINDOW already shows BUFFER reset its dedicated flag.
|
||||
(set-window-dedicated-p window nil)
|
||||
(set-window-buffer window buffer))
|
||||
(when (cdr (assq 'bump-use-time alist))
|
||||
;; Bump WINDOW's use time so 'display-buffer--lru-window' will try
|
||||
;; to avoid it.
|
||||
(window-bump-use-time window))
|
||||
(let ((alist-dedicated (assq 'dedicated alist)))
|
||||
;; Maybe dedicate WINDOW to BUFFER if asked for.
|
||||
(cond
|
||||
|
|
@ -8502,15 +8496,64 @@ indirectly called by the latter."
|
|||
(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--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. ALIST is a buffer display action alist as compiled by
|
||||
`display-buffer'. The following ALIST entries are honored:
|
||||
|
||||
- `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',
|
||||
prefer a full-width window.
|
||||
|
||||
- `window-min-height' specifies a preferred minimum height in
|
||||
canonical frame lines. If it is the constant `full-height',
|
||||
prefer a full-height window.
|
||||
|
||||
If ALIST contains a non-nil `inhibit-same--window' entry, do not
|
||||
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-this-window (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-this-window)
|
||||
(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-some-window (buffer alist)
|
||||
"Display BUFFER in an existing window.
|
||||
|
|
@ -8534,7 +8577,11 @@ indirectly called by the latter."
|
|||
(window--frame-usable-p (last-nonminibuffer-frame))))
|
||||
(window
|
||||
;; Reuse an existing window.
|
||||
(or (get-lru-window frame nil not-this-window)
|
||||
(or (display-buffer--lru-window
|
||||
;; If ALIST specifies 'lru-frames' or 'window-min-width'
|
||||
;; let them prevail.
|
||||
(append alist `((lru-frames . ,frame)
|
||||
(window-min-width . full-width))))
|
||||
(let ((window (get-buffer-window buffer 'visible)))
|
||||
(unless (and not-this-window
|
||||
(eq window (selected-window)))
|
||||
|
|
@ -8564,6 +8611,76 @@ indirectly called by the latter."
|
|||
(unless (cdr (assq 'inhibit-switch-frame alist))
|
||||
(window--maybe-raise-frame (window-frame window)))))))
|
||||
|
||||
(defun display-buffer-use-least-recent-window (buffer alist)
|
||||
"Display BUFFER trying to avoid windows used recently.
|
||||
This is similar to `display-buffer-use-some-window' but tries
|
||||
hard to avoid using a window recently used by `display-buffer'.
|
||||
|
||||
Distinctive features are:
|
||||
|
||||
- Do not use the selected window.
|
||||
|
||||
- Try first to reuse a window that shows BUFFER already on a
|
||||
frame specified by a `reusable-frames' ALIST entry, using the
|
||||
selected frame if no such entry has been specified.
|
||||
|
||||
- Next try to show BUFFER in the least recently used window. The
|
||||
frames to search for such a window can be specified via a
|
||||
`lru-frames' ALIST entry; if no such entry exists, search the
|
||||
selected frame only. In addition, try to satisfy constraints
|
||||
specified by the following ALIST entries, if present:
|
||||
|
||||
`lru-time' specifies a use time. Do not return a window whose
|
||||
use time is higher than this. When calling this action
|
||||
function repeatedly (presumably to display several buffers in
|
||||
a row), an application should first save the use time of the
|
||||
selected window and pass that same value via such an entry in
|
||||
each call of `display-buffer'. This reduces the probability
|
||||
that `display-buffer' uses the same window as a previous
|
||||
call.
|
||||
|
||||
`window-min-width' specifies a preferred minimum width in
|
||||
canonical frame columns. If it is the constant `full-width',
|
||||
prefer a full-width window.
|
||||
|
||||
`window-min-height' specifies a preferred minimum height in
|
||||
canonical frame lines. If it is the constant `full-height',
|
||||
prefer a full-height window.
|
||||
|
||||
- If the preceding steps fail, try to pop up a new window on the
|
||||
selected frame.
|
||||
|
||||
If a window is found, bump the use time of that window to the
|
||||
highest use time after the selected window. This makes it less
|
||||
probable that a future invocation of this function uses that
|
||||
window for another buffer."
|
||||
(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))))
|
||||
;; Don't bump use time twice.
|
||||
(when (and window (not (cdr (assq 'bump-use-time alist))))
|
||||
(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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue