aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormartin rudalics2023-02-12 10:33:11 +0100
committerEli Zaretskii2023-02-18 19:24:59 +0200
commit9f508cef85df64ccbafada477bbb17a8439bc839 (patch)
treea5b47bb28e0906bdf4c4e237f77aa4a631700458
parent5190ea6259a5fd13ba5e87b92b20f450658cf532 (diff)
downloademacs-9f508cef85df64ccbafada477bbb17a8439bc839.tar.gz
emacs-9f508cef85df64ccbafada477bbb17a8439bc839.zip
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.
-rw-r--r--doc/lispref/windows.texi233
-rw-r--r--lisp/window.el169
-rw-r--r--src/window.c33
3 files changed, 339 insertions, 96 deletions
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index 441e7f1b16d..1ec645721ca 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -629,6 +629,12 @@ example, by calling @code{select-window} with argument @var{norecord}
629@code{nil}. Hence, this macro is the preferred way to temporarily work 629@code{nil}. Hence, this macro is the preferred way to temporarily work
630with @var{window} as the selected window without needlessly running 630with @var{window} as the selected window without needlessly running
631@code{buffer-list-update-hook}. 631@code{buffer-list-update-hook}.
632
633Note that this macro temporarily puts the window management code in a
634unstable state. In particular, the most recently window (see below)
635will not necessarily match the selected one. Hence, functions like
636@code{get-lru-window} and @code{get-mru-window} may return unexpected
637results when called from within the scope of this macro.
632@end defmac 638@end defmac
633 639
634@defmac with-selected-frame frame forms@dots{} 640@defmac with-selected-frame frame forms@dots{}
@@ -650,15 +656,16 @@ The @dfn{use time} of a window is not really a time value, but an
650integer that does increase monotonically with each call of 656integer that does increase monotonically with each call of
651@code{select-window} with a @code{nil} @var{norecord} argument. The 657@code{select-window} with a @code{nil} @var{norecord} argument. The
652window with the lowest use time is usually called the least recently 658window with the lowest use time is usually called the least recently
653used window while the window with the highest use time is called the 659used window. The window with the highest use time is called the most
654most recently used one (@pxref{Cyclic Window Ordering}). 660recently used one (@pxref{Cyclic Window Ordering}) and is usually the
661selected window unless @code{with-selected-window} has been used.
655@end defun 662@end defun
656 663
657@defun window-bump-use-time &optional window 664@defun window-bump-use-time &optional window
658This function marks @var{window} as being the most recently used 665This function marks @var{window} as being the second most recently used
659one. This can be useful when writing certain @code{pop-to-buffer} 666one. It does nothing if @var{window} is the selected window or the
660scenarios (@pxref{Switching Buffers}). @var{window} must be a live 667selected window does not have the highest use time among all windows
661window and defaults to the selected one. 668which may happen within the scope of @code{with-selected-window}.
662@end defun 669@end defun
663 670
664@anchor{Window Group}Sometimes several windows collectively and 671@anchor{Window Group}Sometimes several windows collectively and
@@ -2755,14 +2762,40 @@ before.
2755 2762
2756@defun display-buffer-use-some-window buffer alist 2763@defun display-buffer-use-some-window buffer alist
2757This function tries to display @var{buffer} by choosing an existing 2764This function tries to display @var{buffer} by choosing an existing
2758window and displaying the buffer in that window. It can fail if all 2765window and displaying the buffer in that window. It first tries to find
2759windows are dedicated to other buffers (@pxref{Dedicated Windows}). 2766a window that has not been used recently (@pxref{Cyclic Window
2767Ordering}) on any frame specified by a @code{lru-frames} @var{alist}
2768entry, falling back to the selected frame if no such entry exists. It
2769also prefers windows that satisfy the constraints specified by
2770@code{window-min-width} and @code{window-min-height} @var{alist}
2771entries; preferring full-width windows if no @code{window-min-width}
2772entry is found. Finally, it will not return a window whose use time is
2773higher than that specified by any @code{lru-time} entry provided by
2774@var{alist}.
2775
2776If no less recently used window is found, this function will try to use
2777some other window, preferably a large window on some visible frame. It
2778can fail if all windows are dedicated to other buffers (@pxref{Dedicated
2779Windows}).
2760@end defun 2780@end defun
2761 2781
2762@defun display-buffer-use-least-recent-window buffer alist 2782@defun display-buffer-use-least-recent-window buffer alist
2763This function is like @code{display-buffer-use-some-window}, but will 2783This function is similar to @code{display-buffer-use-some-window}, but
2764not reuse the current window, and will use the least recently 2784will try harder to not use the a recently used window. In particular,
2765switched-to window. 2785it does not use the selected window. In addition, it will first try to
2786reuse a window that shows @var{buffer} already, base the decision
2787whether it should use a window showing another buffer on that window's
2788use time alone and pop up a new window if no usable window is found.
2789
2790Finally, this function will bump the use time (@pxref{Selecting
2791Windows}) of any window it returns in order to avoid that further
2792invocations will use that window for showing another buffer. An
2793application that wants to display several buffers in a row can help this
2794function by providing a @code{lru-time} @var{alist} entry it has
2795initially set to the value of the selected window's use time. Each
2796invocation of this function will then bump the use time of the window
2797returned to a value higher than that and a subsequent invocation will
2798inhibit this function to use a window it returned earlier.
2766@end defun 2799@end defun
2767 2800
2768@defun display-buffer-in-direction buffer alist 2801@defun display-buffer-in-direction buffer alist
@@ -3032,12 +3065,39 @@ The value specifies an alist of window parameters to give the chosen
3032window. All action functions that choose a window should process this 3065window. All action functions that choose a window should process this
3033entry. 3066entry.
3034 3067
3068@vindex window-min-width@r{, a buffer display action alist entry}
3069@item window-min-width
3070The value specifies a minimum width of the window used, in canonical
3071frame columns. The special value @code{full-width} means the window
3072chosen should be one has no other windows on the left or right it in its
3073frame.
3074
3075This entry is currently honored by @code{display-buffer-use-some-window}
3076and @code{display-buffer-use-least-recent-window} who try hard to avoid
3077returning a less recently used window that does not satisfy it.
3078
3079Note that providing such an entry alone does not necessarily make the
3080window as wide as specified by its value. To actually resize an
3081existing window or make a new window as wide as specified by that value,
3082a @code{window-width} entry specifying that value should be provided as
3083well. Such a @code{window-width} entry can, however, specify a
3084completely different value or ask the window width to be fit to that of
3085its buffer in which case the @code{window-min-width} entry provides the
3086guaranteed minimum width of the window used.
3087
3035@vindex window-min-height@r{, a buffer display action alist entry} 3088@vindex window-min-height@r{, a buffer display action alist entry}
3036@item window-min-height 3089@item window-min-height
3037The value specifies a minimum height of the window used, in lines. If 3090The value specifies a minimum height of the window used, in canonical
3038a window is not or cannot be made as high as specified by this entry, 3091frame lines. The special value @code{full-height} means the window
3039the window is not considered for use. The only client of this entry 3092chosen should be a full-height window, one has no other windows above or
3040is presently @code{display-buffer-below-selected}. 3093below it in its frame.
3094
3095This entry is currently honored by @code{display-buffer-below-selected}
3096which does not use a window that is not as high as specified by this
3097entry. It's also honored by @code{display-buffer-use-some-window} and
3098@code{display-buffer-use-least-recent-window} which try hard to avoid
3099returning a less recently used window if it does not satisfy this
3100constraint.
3041 3101
3042Note that providing such an entry alone does not necessarily make the 3102Note that providing such an entry alone does not necessarily make the
3043window as tall as specified by its value. To actually resize an 3103window as tall as specified by its value. To actually resize an
@@ -3166,6 +3226,40 @@ preserve both, its width and its height. This entry should be
3166processed only under certain conditions which are specified right 3226processed only under certain conditions which are specified right
3167after this list. 3227after this list.
3168 3228
3229@vindex lru-frames@r{, a buffer display action alist entry}
3230@item lru-frames
3231The value specifies the set of frames to search for window that can be
3232used to display the buffer. It is honored by
3233@code{display-buffer-use-some-window} and
3234@code{display-buffer-use-least-recent-window} when trying to find a less
3235recently used window showing some other buffer. Its values are the same
3236as for the @code{reusable-frames} entry described above.
3237
3238@vindex lru-time@r{, a buffer display action alist entry}
3239@item lru-time
3240The value is supposed to specify a use time (@pxref{Selecting Windows}).
3241This entry is honored by @code{display-buffer-use-some-window} and
3242@code{display-buffer-use-least-recent-window} when trying to find a less
3243recently used window showing some other buffer. If a window's use time
3244is higher than the value specified by this option, these action
3245functions will not consider such a window for displaying the buffer.
3246
3247@vindex bump-use-time@r{, a buffer display action alist entry}
3248@item bump-use-time
3249If non-@code{nil}, such an entry will cause @code{display-buffer} to
3250bump the use time (@pxref{Selecting Windows}) of the window it uses.
3251This should avoid that this window is later used by action functions
3252like @code{display-buffer-use-some-window} and
3253@code{display-buffer-use-least-recent-window} for showing another
3254buffer.
3255
3256There is a fine difference between using this entry and using the action
3257function @code{display-buffer-use-least-recent-window}. Calling the
3258latter means to only bump the use times of windows that function uses
3259for displaying the buffer. The entry described here will cause
3260@code{display-buffer} to bump the use time of @emph{any} window used for
3261displaying a buffer.
3262
3169@vindex pop-up-frame-parameters@r{, a buffer display action alist entry} 3263@vindex pop-up-frame-parameters@r{, a buffer display action alist entry}
3170@item pop-up-frame-parameters 3264@item pop-up-frame-parameters
3171The value specifies an alist of frame parameters to give a new frame, 3265The value specifies an alist of frame parameters to give a new frame,
@@ -3321,13 +3415,6 @@ window has at least that many columns. If the value is @code{nil},
3321that means not to split this way. 3415that means not to split this way.
3322@end defopt 3416@end defopt
3323 3417
3324@defopt display-buffer-avoid-small-windows
3325If non-@code{nil}, this should be a number. Windows that have fewer
3326lines than that will be avoided when choosing an existing window. The
3327value is interpreted in units of the frame's canonical line height,
3328like @code{window-total-height} does (@pxref{Window Sizes}).
3329@end defopt
3330
3331@defopt even-window-sizes 3418@defopt even-window-sizes
3332This variable, if non-@code{nil}, causes @code{display-buffer} to even 3419This variable, if non-@code{nil}, causes @code{display-buffer} to even
3333window sizes whenever it reuses an existing window, and that window is 3420window sizes whenever it reuses an existing window, and that window is
@@ -3992,53 +4079,75 @@ related to the new window. For non-input related actions
3992@code{display-buffer-below-selected} might be preferable because the 4079@code{display-buffer-below-selected} might be preferable because the
3993selected window usually already has the user's attention. 4080selected window usually already has the user's attention.
3994 4081
3995@item Handle subsequent invocations of @code{display-buffer} 4082@item Take care about which window is selected
3996@code{display-buffer} is not overly well suited for displaying several 4083Many applications call @code{display-buffer} from within window
3997buffers in sequence and making sure that all these buffers are shown 4084excursions produced by @code{with-selected-window} or
3998orderly in the resulting window configuration. Again, the standard 4085@code{select-window} calls with a non-@code{nil} @var{norecord}
3999action functions @code{display-buffer-pop-up-window} and 4086argument. This is almost always a bad idea because the window selected
4000@code{display-buffer-use-some-window} are not very suited for this 4087within such an excursion is usually not the window selected in the
4001purpose due to their somewhat chaotic nature in more complex 4088configuration presented to the user.
4002configurations. 4089
4090If, for example, a user had added an @code{inhibit-same-window} alist
4091entry, that entry would have avoided the window selected within the
4092scope of the excursion and not the window selected in the resulting
4093configuration. Even if no such entry has been added, the resulting
4094behavior might be strange. While in a frame containing one live
4095window, evaluating the following form
4003 4096
4004 To produce a window configuration displaying multiple buffers (or 4097@example
4005different views of one and the same buffer) in one and the same 4098@group
4006display cycle, Lisp programmers will unavoidably have to write 4099(progn
4007their own action functions. A few tricks listed below might help in 4100 (split-window)
4008this regard. 4101 (display-buffer "*Messages*"))
4102@end group
4103@end example
4009 4104
4010@itemize @bullet 4105will display a window showing the @file{*Messages*} buffer at the bottom
4011@item 4106and leave the other window selected. Evaluating the next form
4012Making windows atomic (@pxref{Atomic Windows}) avoids breaking an
4013existing window composition when popping up a new window.
4014The new window will pop up outside the composition instead.
4015 4107
4016@item 4108@example
4017Temporarily dedicating windows to their buffers (@pxref{Dedicated 4109@group
4018Windows}) avoids using a window for displaying a different 4110(with-selected-window (split-window)
4019buffer. A non-dedicated window will be used instead. 4111 (display-buffer "*Messages*"))
4112@end group
4113@end example
4020 4114
4021@item 4115will display @file{*Messages*} in a window on the top and select it
4022Calling @code{window-preserve-size} (@pxref{Preserving Window Sizes}) 4116which is usually not what @code{display-buffer} is supposed to do.
4023will try to keep the size of the argument window unchanged when
4024popping up a new window. You have to make sure that another window in
4025the same combination can be shrunk instead, though.
4026 4117
4027@item 4118On the other hand, while evaluating the following form
4028Side windows (@pxref{Side Windows}) can be used for displaying
4029specific buffers always in a window at the same position of a frame.
4030This permits grouping buffers that do not compete for being shown at
4031the same time on a frame and showing any such buffer in the same window
4032without disrupting the display of other buffers.
4033 4119
4034@item 4120@example
4035Child frames (@pxref{Child Frames}) can be used to display a buffer 4121@group
4036within the screen estate of the selected frame without disrupting that 4122(progn
4037frame's window configuration and without the overhead associated with 4123 (split-window)
4038full-fledged frames as inflicted by @code{display-buffer-pop-up-frame}. 4124 (pop-to-buffer "*Messages*"))
4039@end itemize 4125@end group
4040@end table 4126@end example
4127
4128will correctly select the @file{*Messages*} buffer, the next form
4129
4130@example
4131@group
4132(progn
4133 (split-window)
4134 (with-selected-window (selected-window)
4135 (pop-to-buffer "*Messages*")))
4136@end group
4137@end example
4138
4139will not.
4041 4140
4141Also, invocations of action functions like
4142@code{display-buffer-use-some-window} and
4143@code{display-buffer-use-least-recent-window} that expect the selected
4144window to have the highest use time among all windows, may fail to
4145produce a window according to their specifications.
4146
4147Hence, an application that relies on using a window excursion should try
4148to postpone the @code{display-buffer} call until after the excursion has
4149terminated.
4150@end table
4042 4151
4043@node Window History 4152@node Window History
4044@section Window History 4153@section Window History
diff --git a/lisp/window.el b/lisp/window.el
index 2d9f746d8fb..083fa9bfd2f 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2484,14 +2484,6 @@ and no others."
2484 2484
2485(defalias 'some-window 'get-window-with-predicate) 2485(defalias 'some-window 'get-window-with-predicate)
2486 2486
2487(defcustom display-buffer-avoid-small-windows nil
2488 "If non-nil, windows that have fewer lines than this are avoided.
2489This is used by `get-lru-window'. The value is interpreted in units
2490of the frame's canonical line height, like `window-total-height' does."
2491 :type '(choice (const nil) number)
2492 :version "29.1"
2493 :group 'windows)
2494
2495(defun get-lru-window (&optional all-frames dedicated not-selected no-other) 2487(defun get-lru-window (&optional all-frames dedicated not-selected no-other)
2496 "Return the least recently used window on frames specified by ALL-FRAMES. 2488 "Return the least recently used window on frames specified by ALL-FRAMES.
2497Return a full-width window if possible. A minibuffer window is 2489Return a full-width window if possible. A minibuffer window is
@@ -2517,11 +2509,7 @@ have special meanings:
2517- A frame means consider all windows on that frame only. 2509- A frame means consider all windows on that frame only.
2518 2510
2519Any other value of ALL-FRAMES means consider all windows on the 2511Any other value of ALL-FRAMES means consider all windows on the
2520selected frame and no others. 2512selected frame and no others."
2521
2522`display-buffer-avoid-small-windows', if non-nil, is also taken into
2523consideration. Windows whose height is smaller that the value of that
2524variable will be avoided if larger windows are available."
2525 (let ((windows (window-list-1 nil 'nomini all-frames)) 2513 (let ((windows (window-list-1 nil 'nomini all-frames))
2526 best-window best-time second-best-window second-best-time time) 2514 best-window best-time second-best-window second-best-time time)
2527 (dolist (window windows) 2515 (dolist (window windows)
@@ -2531,9 +2519,6 @@ variable will be avoided if larger windows are available."
2531 (not (window-parameter window 'no-other-window)))) 2519 (not (window-parameter window 'no-other-window))))
2532 (setq time (window-use-time window)) 2520 (setq time (window-use-time window))
2533 (if (or (eq window (selected-window)) 2521 (if (or (eq window (selected-window))
2534 (and display-buffer-avoid-small-windows
2535 (< (window-height window)
2536 display-buffer-avoid-small-windows))
2537 (not (window-full-width-p window))) 2522 (not (window-full-width-p window)))
2538 (when (or (not second-best-time) (< time second-best-time)) 2523 (when (or (not second-best-time) (< time second-best-time))
2539 (setq second-best-time time) 2524 (setq second-best-time time)
@@ -7274,6 +7259,11 @@ entry. Otherwise, if WINDOW is new and the value of
7274dedicated flag to that value. In any other case, reset WINDOW's 7259dedicated flag to that value. In any other case, reset WINDOW's
7275dedicated flag to nil. 7260dedicated flag to nil.
7276 7261
7262If ALIST contains a non-nil `bump-use-time' entry, bump use time
7263of WINDOW so further calls of `display-buffer-use-some-window'
7264and `display-buffer-use-least-recent-window' will try to avoid
7265it.
7266
7277Return WINDOW if BUFFER and WINDOW are live." 7267Return WINDOW if BUFFER and WINDOW are live."
7278 (when (and (buffer-live-p buffer) (window-live-p window)) 7268 (when (and (buffer-live-p buffer) (window-live-p window))
7279 (display-buffer-record-window type window buffer) 7269 (display-buffer-record-window type window buffer)
@@ -7281,6 +7271,10 @@ Return WINDOW if BUFFER and WINDOW are live."
7281 ;; Unless WINDOW already shows BUFFER reset its dedicated flag. 7271 ;; Unless WINDOW already shows BUFFER reset its dedicated flag.
7282 (set-window-dedicated-p window nil) 7272 (set-window-dedicated-p window nil)
7283 (set-window-buffer window buffer)) 7273 (set-window-buffer window buffer))
7274 (when (cdr (assq 'bump-use-time alist))
7275 ;; Bump WINDOW's use time so 'display-buffer--lru-window' will try
7276 ;; to avoid it.
7277 (window-bump-use-time window))
7284 (let ((alist-dedicated (assq 'dedicated alist))) 7278 (let ((alist-dedicated (assq 'dedicated alist)))
7285 ;; Maybe dedicate WINDOW to BUFFER if asked for. 7279 ;; Maybe dedicate WINDOW to BUFFER if asked for.
7286 (cond 7280 (cond
@@ -8502,15 +8496,64 @@ indirectly called by the latter."
8502 (when (setq window (or best-window second-best-window)) 8496 (when (setq window (or best-window second-best-window))
8503 (window--display-buffer buffer window 'reuse alist)))) 8497 (window--display-buffer buffer window 'reuse alist))))
8504 8498
8505(defun display-buffer-use-least-recent-window (buffer alist) 8499(defun display-buffer--lru-window (alist)
8506 "Display BUFFER in an existing window, but that hasn't been used lately. 8500 "Return the least recently used window according to ALIST.
8507This `display-buffer' action function is like 8501Do not return a minibuffer window or a window dedicated to its
8508`display-buffer-use-some-window', but will cycle through windows 8502buffer. ALIST is a buffer display action alist as compiled by
8509when displaying buffers repeatedly, and if there's only a single 8503`display-buffer'. The following ALIST entries are honored:
8510window, it will split the window." 8504
8511 (when-let ((window (display-buffer-use-some-window 8505- `lru-frames' specifies the frames to investigate and has the
8512 buffer (cons (cons 'inhibit-same-window t) alist)))) 8506 same meaning as the ALL-FRAMES argument of `get-lru-window'.
8513 (window-bump-use-time window))) 8507
8508- `lru-time' specifies a use time. Do not return a window whose
8509 use time is higher than this.
8510
8511- `window-min-width' specifies a preferred minimum width in
8512 canonical frame columns. If it is the constant `full-width',
8513 prefer a full-width window.
8514
8515- `window-min-height' specifies a preferred minimum height in
8516 canonical frame lines. If it is the constant `full-height',
8517 prefer a full-height window.
8518
8519If ALIST contains a non-nil `inhibit-same--window' entry, do not
8520return the selected window."
8521 (let ((windows
8522 (window-list-1 nil 'nomini (cdr (assq 'lru-frames alist))))
8523 (lru-time (cdr (assq 'lru-time alist)))
8524 (min-width (cdr (assq 'window-min-width alist)))
8525 (min-height (cdr (assq 'window-min-height alist)))
8526 (not-this-window (cdr (assq 'inhibit-same-window alist)))
8527 best-window best-time second-best-window second-best-time time)
8528 (dolist (window windows)
8529 (when (and (not (window-dedicated-p window))
8530 (or (not not-this-window)
8531 (not (eq window (selected-window)))))
8532 (setq time (window-use-time window))
8533 (unless (and (numberp lru-time) (> time lru-time))
8534 (if (or (eq window (selected-window))
8535 (and min-width
8536 (or (and (numberp min-width)
8537 (< (window-width window) min-width))
8538 (and (eq min-width 'full-width)
8539 (not (window-full-width-p window)))))
8540 (and min-height
8541 (or (and (numberp min-height)
8542 (< (window-height window) min-height))
8543 (and (eq min-height 'full-height)
8544 (not (window-full-height-p window))))))
8545 ;; This window is either selected or does not meet the size
8546 ;; restrictions - so it's only a second best choice. Try to
8547 ;; find a more recently used one that fits.
8548 (when (or (not second-best-time) (< time second-best-time))
8549 (setq second-best-time time)
8550 (setq second-best-window window))
8551 ;; This window is not selected and does meet the size
8552 ;; restrictions. It's the best choice so far.
8553 (when (or (not best-time) (< time best-time))
8554 (setq best-time time)
8555 (setq best-window window))))))
8556 (or best-window second-best-window)))
8514 8557
8515(defun display-buffer-use-some-window (buffer alist) 8558(defun display-buffer-use-some-window (buffer alist)
8516 "Display BUFFER in an existing window. 8559 "Display BUFFER in an existing window.
@@ -8534,7 +8577,11 @@ indirectly called by the latter."
8534 (window--frame-usable-p (last-nonminibuffer-frame)))) 8577 (window--frame-usable-p (last-nonminibuffer-frame))))
8535 (window 8578 (window
8536 ;; Reuse an existing window. 8579 ;; Reuse an existing window.
8537 (or (get-lru-window frame nil not-this-window) 8580 (or (display-buffer--lru-window
8581 ;; If ALIST specifies 'lru-frames' or 'window-min-width'
8582 ;; let them prevail.
8583 (append alist `((lru-frames . ,frame)
8584 (window-min-width . full-width))))
8538 (let ((window (get-buffer-window buffer 'visible))) 8585 (let ((window (get-buffer-window buffer 'visible)))
8539 (unless (and not-this-window 8586 (unless (and not-this-window
8540 (eq window (selected-window))) 8587 (eq window (selected-window)))
@@ -8564,6 +8611,76 @@ indirectly called by the latter."
8564 (unless (cdr (assq 'inhibit-switch-frame alist)) 8611 (unless (cdr (assq 'inhibit-switch-frame alist))
8565 (window--maybe-raise-frame (window-frame window))))))) 8612 (window--maybe-raise-frame (window-frame window)))))))
8566 8613
8614(defun display-buffer-use-least-recent-window (buffer alist)
8615 "Display BUFFER trying to avoid windows used recently.
8616This is similar to `display-buffer-use-some-window' but tries
8617hard to avoid using a window recently used by `display-buffer'.
8618
8619Distinctive features are:
8620
8621- Do not use the selected window.
8622
8623- Try first to reuse a window that shows BUFFER already on a
8624 frame specified by a `reusable-frames' ALIST entry, using the
8625 selected frame if no such entry has been specified.
8626
8627- Next try to show BUFFER in the least recently used window. The
8628 frames to search for such a window can be specified via a
8629 `lru-frames' ALIST entry; if no such entry exists, search the
8630 selected frame only. In addition, try to satisfy constraints
8631 specified by the following ALIST entries, if present:
8632
8633 `lru-time' specifies a use time. Do not return a window whose
8634 use time is higher than this. When calling this action
8635 function repeatedly (presumably to display several buffers in
8636 a row), an application should first save the use time of the
8637 selected window and pass that same value via such an entry in
8638 each call of `display-buffer'. This reduces the probability
8639 that `display-buffer' uses the same window as a previous
8640 call.
8641
8642 `window-min-width' specifies a preferred minimum width in
8643 canonical frame columns. If it is the constant `full-width',
8644 prefer a full-width window.
8645
8646 `window-min-height' specifies a preferred minimum height in
8647 canonical frame lines. If it is the constant `full-height',
8648 prefer a full-height window.
8649
8650- If the preceding steps fail, try to pop up a new window on the
8651 selected frame.
8652
8653If a window is found, bump the use time of that window to the
8654highest use time after the selected window. This makes it less
8655probable that a future invocation of this function uses that
8656window for another buffer."
8657 (let* ((alist (cons (cons 'inhibit-same-window t) alist))
8658 (window
8659 (or (display-buffer-reuse-window buffer alist)
8660 (let ((window (display-buffer--lru-window alist)))
8661 (when (window-live-p window)
8662 (let* ((quit-restore (window-parameter window 'quit-restore))
8663 (quad (nth 1 quit-restore)))
8664 ;; If the window was used by `display-buffer' before, try to
8665 ;; resize it to its old height but don't signal an error.
8666 (when (and (listp quad)
8667 (integerp (nth 3 quad))
8668 (> (nth 3 quad) (window-total-height window)))
8669 (condition-case nil
8670 (window-resize
8671 window (- (nth 3 quad) (window-total-height window)))
8672 (error nil)))
8673 (prog1
8674 (window--display-buffer buffer window 'reuse alist)
8675 (window--even-window-sizes window)
8676 (unless (cdr (assq 'inhibit-switch-frame alist))
8677 (window--maybe-raise-frame (window-frame window)))))))
8678 (display-buffer-pop-up-window buffer alist))))
8679 ;; Don't bump use time twice.
8680 (when (and window (not (cdr (assq 'bump-use-time alist))))
8681 (window-bump-use-time window))
8682 window))
8683
8567(defun display-buffer-no-window (_buffer alist) 8684(defun display-buffer-no-window (_buffer alist)
8568 "Display BUFFER in no window. 8685 "Display BUFFER in no window.
8569ALIST is an association list of action symbols and values. See 8686ALIST is an association list of action symbols and values. See
diff --git a/src/window.c b/src/window.c
index 6201a6f4a36..a94e1d611c7 100644
--- a/src/window.c
+++ b/src/window.c
@@ -762,10 +762,15 @@ future use. */)
762 762
763DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0, 763DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0,
764 doc: /* Return the use time of window WINDOW. 764 doc: /* Return the use time of window WINDOW.
765WINDOW must be a live window and defaults to the selected one. 765WINDOW must specify a live window and defaults to the selected one.
766The window with the highest use time is the most recently selected 766
767one. The window with the lowest use time is the least recently 767The window with the highest use time is usually the one most recently
768selected one. */) 768selected by calling `select-window' with NORECORD nil. The window with
769the lowest use time is usually the least recently selected one chosen in
770such a way.
771
772Note that the use time of a window can be also changed by calling
773`window-bump-use-time' for that window. */)
769 (Lisp_Object window) 774 (Lisp_Object window)
770{ 775{
771 return make_fixnum (decode_live_window (window)->use_time); 776 return make_fixnum (decode_live_window (window)->use_time);
@@ -773,15 +778,27 @@ selected one. */)
773 778
774DEFUN ("window-bump-use-time", Fwindow_bump_use_time, 779DEFUN ("window-bump-use-time", Fwindow_bump_use_time,
775 Swindow_bump_use_time, 0, 1, 0, 780 Swindow_bump_use_time, 0, 1, 0,
776 doc: /* Mark WINDOW as having been most recently used. 781 doc: /* Mark WINDOW as second most recently used.
777WINDOW must be a live window and defaults to the selected one. */) 782WINDOW must specify a live window.
783
784If WINDOW is not selected and the selected window has the highest use
785time of all windows, set the use time of WINDOW to that of the selected
786window, increase the use time of the selected window by one and return
787the new use time of WINDOW. Otherwise, do nothing and return nil. */)
778 (Lisp_Object window) 788 (Lisp_Object window)
779{ 789{
780 struct window *w = decode_live_window (window); 790 struct window *w = decode_live_window (window);
791 struct window *sw = XWINDOW (selected_window);
781 792
782 w->use_time = ++window_select_count; 793 if (w != sw && sw->use_time == window_select_count)
794 {
795 w->use_time = window_select_count;
796 sw->use_time = ++window_select_count;
783 797
784 return Qnil; 798 return make_fixnum (w->use_time);
799 }
800 else
801 return Qnil;
785} 802}
786 803
787DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0, 804DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,