diff options
| author | martin rudalics | 2023-02-12 10:33:11 +0100 |
|---|---|---|
| committer | Eli Zaretskii | 2023-02-18 19:24:59 +0200 |
| commit | 9f508cef85df64ccbafada477bbb17a8439bc839 (patch) | |
| tree | a5b47bb28e0906bdf4c4e237f77aa4a631700458 | |
| parent | 5190ea6259a5fd13ba5e87b92b20f450658cf532 (diff) | |
| download | emacs-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.texi | 233 | ||||
| -rw-r--r-- | lisp/window.el | 169 | ||||
| -rw-r--r-- | src/window.c | 33 |
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 |
| 630 | with @var{window} as the selected window without needlessly running | 630 | with @var{window} as the selected window without needlessly running |
| 631 | @code{buffer-list-update-hook}. | 631 | @code{buffer-list-update-hook}. |
| 632 | |||
| 633 | Note that this macro temporarily puts the window management code in a | ||
| 634 | unstable state. In particular, the most recently window (see below) | ||
| 635 | will not necessarily match the selected one. Hence, functions like | ||
| 636 | @code{get-lru-window} and @code{get-mru-window} may return unexpected | ||
| 637 | results 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 | |||
| 650 | integer that does increase monotonically with each call of | 656 | integer 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 |
| 652 | window with the lowest use time is usually called the least recently | 658 | window with the lowest use time is usually called the least recently |
| 653 | used window while the window with the highest use time is called the | 659 | used window. The window with the highest use time is called the most |
| 654 | most recently used one (@pxref{Cyclic Window Ordering}). | 660 | recently used one (@pxref{Cyclic Window Ordering}) and is usually the |
| 661 | selected 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 |
| 658 | This function marks @var{window} as being the most recently used | 665 | This function marks @var{window} as being the second most recently used |
| 659 | one. This can be useful when writing certain @code{pop-to-buffer} | 666 | one. It does nothing if @var{window} is the selected window or the |
| 660 | scenarios (@pxref{Switching Buffers}). @var{window} must be a live | 667 | selected window does not have the highest use time among all windows |
| 661 | window and defaults to the selected one. | 668 | which 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 |
| 2757 | This function tries to display @var{buffer} by choosing an existing | 2764 | This function tries to display @var{buffer} by choosing an existing |
| 2758 | window and displaying the buffer in that window. It can fail if all | 2765 | window and displaying the buffer in that window. It first tries to find |
| 2759 | windows are dedicated to other buffers (@pxref{Dedicated Windows}). | 2766 | a window that has not been used recently (@pxref{Cyclic Window |
| 2767 | Ordering}) on any frame specified by a @code{lru-frames} @var{alist} | ||
| 2768 | entry, falling back to the selected frame if no such entry exists. It | ||
| 2769 | also prefers windows that satisfy the constraints specified by | ||
| 2770 | @code{window-min-width} and @code{window-min-height} @var{alist} | ||
| 2771 | entries; preferring full-width windows if no @code{window-min-width} | ||
| 2772 | entry is found. Finally, it will not return a window whose use time is | ||
| 2773 | higher than that specified by any @code{lru-time} entry provided by | ||
| 2774 | @var{alist}. | ||
| 2775 | |||
| 2776 | If no less recently used window is found, this function will try to use | ||
| 2777 | some other window, preferably a large window on some visible frame. It | ||
| 2778 | can fail if all windows are dedicated to other buffers (@pxref{Dedicated | ||
| 2779 | Windows}). | ||
| 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 |
| 2763 | This function is like @code{display-buffer-use-some-window}, but will | 2783 | This function is similar to @code{display-buffer-use-some-window}, but |
| 2764 | not reuse the current window, and will use the least recently | 2784 | will try harder to not use the a recently used window. In particular, |
| 2765 | switched-to window. | 2785 | it does not use the selected window. In addition, it will first try to |
| 2786 | reuse a window that shows @var{buffer} already, base the decision | ||
| 2787 | whether it should use a window showing another buffer on that window's | ||
| 2788 | use time alone and pop up a new window if no usable window is found. | ||
| 2789 | |||
| 2790 | Finally, this function will bump the use time (@pxref{Selecting | ||
| 2791 | Windows}) of any window it returns in order to avoid that further | ||
| 2792 | invocations will use that window for showing another buffer. An | ||
| 2793 | application that wants to display several buffers in a row can help this | ||
| 2794 | function by providing a @code{lru-time} @var{alist} entry it has | ||
| 2795 | initially set to the value of the selected window's use time. Each | ||
| 2796 | invocation of this function will then bump the use time of the window | ||
| 2797 | returned to a value higher than that and a subsequent invocation will | ||
| 2798 | inhibit 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 | |||
| 3032 | window. All action functions that choose a window should process this | 3065 | window. All action functions that choose a window should process this |
| 3033 | entry. | 3066 | entry. |
| 3034 | 3067 | ||
| 3068 | @vindex window-min-width@r{, a buffer display action alist entry} | ||
| 3069 | @item window-min-width | ||
| 3070 | The value specifies a minimum width of the window used, in canonical | ||
| 3071 | frame columns. The special value @code{full-width} means the window | ||
| 3072 | chosen should be one has no other windows on the left or right it in its | ||
| 3073 | frame. | ||
| 3074 | |||
| 3075 | This entry is currently honored by @code{display-buffer-use-some-window} | ||
| 3076 | and @code{display-buffer-use-least-recent-window} who try hard to avoid | ||
| 3077 | returning a less recently used window that does not satisfy it. | ||
| 3078 | |||
| 3079 | Note that providing such an entry alone does not necessarily make the | ||
| 3080 | window as wide as specified by its value. To actually resize an | ||
| 3081 | existing window or make a new window as wide as specified by that value, | ||
| 3082 | a @code{window-width} entry specifying that value should be provided as | ||
| 3083 | well. Such a @code{window-width} entry can, however, specify a | ||
| 3084 | completely different value or ask the window width to be fit to that of | ||
| 3085 | its buffer in which case the @code{window-min-width} entry provides the | ||
| 3086 | guaranteed 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 |
| 3037 | The value specifies a minimum height of the window used, in lines. If | 3090 | The value specifies a minimum height of the window used, in canonical |
| 3038 | a window is not or cannot be made as high as specified by this entry, | 3091 | frame lines. The special value @code{full-height} means the window |
| 3039 | the window is not considered for use. The only client of this entry | 3092 | chosen should be a full-height window, one has no other windows above or |
| 3040 | is presently @code{display-buffer-below-selected}. | 3093 | below it in its frame. |
| 3094 | |||
| 3095 | This entry is currently honored by @code{display-buffer-below-selected} | ||
| 3096 | which does not use a window that is not as high as specified by this | ||
| 3097 | entry. 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 | ||
| 3099 | returning a less recently used window if it does not satisfy this | ||
| 3100 | constraint. | ||
| 3041 | 3101 | ||
| 3042 | Note that providing such an entry alone does not necessarily make the | 3102 | Note that providing such an entry alone does not necessarily make the |
| 3043 | window as tall as specified by its value. To actually resize an | 3103 | window 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 | |||
| 3166 | processed only under certain conditions which are specified right | 3226 | processed only under certain conditions which are specified right |
| 3167 | after this list. | 3227 | after this list. |
| 3168 | 3228 | ||
| 3229 | @vindex lru-frames@r{, a buffer display action alist entry} | ||
| 3230 | @item lru-frames | ||
| 3231 | The value specifies the set of frames to search for window that can be | ||
| 3232 | used 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 | ||
| 3235 | recently used window showing some other buffer. Its values are the same | ||
| 3236 | as for the @code{reusable-frames} entry described above. | ||
| 3237 | |||
| 3238 | @vindex lru-time@r{, a buffer display action alist entry} | ||
| 3239 | @item lru-time | ||
| 3240 | The value is supposed to specify a use time (@pxref{Selecting Windows}). | ||
| 3241 | This 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 | ||
| 3243 | recently used window showing some other buffer. If a window's use time | ||
| 3244 | is higher than the value specified by this option, these action | ||
| 3245 | functions 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 | ||
| 3249 | If non-@code{nil}, such an entry will cause @code{display-buffer} to | ||
| 3250 | bump the use time (@pxref{Selecting Windows}) of the window it uses. | ||
| 3251 | This should avoid that this window is later used by action functions | ||
| 3252 | like @code{display-buffer-use-some-window} and | ||
| 3253 | @code{display-buffer-use-least-recent-window} for showing another | ||
| 3254 | buffer. | ||
| 3255 | |||
| 3256 | There is a fine difference between using this entry and using the action | ||
| 3257 | function @code{display-buffer-use-least-recent-window}. Calling the | ||
| 3258 | latter means to only bump the use times of windows that function uses | ||
| 3259 | for displaying the buffer. The entry described here will cause | ||
| 3260 | @code{display-buffer} to bump the use time of @emph{any} window used for | ||
| 3261 | displaying 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 |
| 3171 | The value specifies an alist of frame parameters to give a new frame, | 3265 | The 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}, | |||
| 3321 | that means not to split this way. | 3415 | that means not to split this way. |
| 3322 | @end defopt | 3416 | @end defopt |
| 3323 | 3417 | ||
| 3324 | @defopt display-buffer-avoid-small-windows | ||
| 3325 | If non-@code{nil}, this should be a number. Windows that have fewer | ||
| 3326 | lines than that will be avoided when choosing an existing window. The | ||
| 3327 | value is interpreted in units of the frame's canonical line height, | ||
| 3328 | like @code{window-total-height} does (@pxref{Window Sizes}). | ||
| 3329 | @end defopt | ||
| 3330 | |||
| 3331 | @defopt even-window-sizes | 3418 | @defopt even-window-sizes |
| 3332 | This variable, if non-@code{nil}, causes @code{display-buffer} to even | 3419 | This variable, if non-@code{nil}, causes @code{display-buffer} to even |
| 3333 | window sizes whenever it reuses an existing window, and that window is | 3420 | window 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 |
| 3993 | selected window usually already has the user's attention. | 4080 | selected 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 | 4083 | Many applications call @code{display-buffer} from within window |
| 3997 | buffers in sequence and making sure that all these buffers are shown | 4084 | excursions produced by @code{with-selected-window} or |
| 3998 | orderly in the resulting window configuration. Again, the standard | 4085 | @code{select-window} calls with a non-@code{nil} @var{norecord} |
| 3999 | action functions @code{display-buffer-pop-up-window} and | 4086 | argument. This is almost always a bad idea because the window selected |
| 4000 | @code{display-buffer-use-some-window} are not very suited for this | 4087 | within such an excursion is usually not the window selected in the |
| 4001 | purpose due to their somewhat chaotic nature in more complex | 4088 | configuration presented to the user. |
| 4002 | configurations. | 4089 | |
| 4090 | If, for example, a user had added an @code{inhibit-same-window} alist | ||
| 4091 | entry, that entry would have avoided the window selected within the | ||
| 4092 | scope of the excursion and not the window selected in the resulting | ||
| 4093 | configuration. Even if no such entry has been added, the resulting | ||
| 4094 | behavior might be strange. While in a frame containing one live | ||
| 4095 | window, evaluating the following form | ||
| 4003 | 4096 | ||
| 4004 | To produce a window configuration displaying multiple buffers (or | 4097 | @example |
| 4005 | different views of one and the same buffer) in one and the same | 4098 | @group |
| 4006 | display cycle, Lisp programmers will unavoidably have to write | 4099 | (progn |
| 4007 | their own action functions. A few tricks listed below might help in | 4100 | (split-window) |
| 4008 | this regard. | 4101 | (display-buffer "*Messages*")) |
| 4102 | @end group | ||
| 4103 | @end example | ||
| 4009 | 4104 | ||
| 4010 | @itemize @bullet | 4105 | will display a window showing the @file{*Messages*} buffer at the bottom |
| 4011 | @item | 4106 | and leave the other window selected. Evaluating the next form |
| 4012 | Making windows atomic (@pxref{Atomic Windows}) avoids breaking an | ||
| 4013 | existing window composition when popping up a new window. | ||
| 4014 | The new window will pop up outside the composition instead. | ||
| 4015 | 4107 | ||
| 4016 | @item | 4108 | @example |
| 4017 | Temporarily dedicating windows to their buffers (@pxref{Dedicated | 4109 | @group |
| 4018 | Windows}) avoids using a window for displaying a different | 4110 | (with-selected-window (split-window) |
| 4019 | buffer. A non-dedicated window will be used instead. | 4111 | (display-buffer "*Messages*")) |
| 4112 | @end group | ||
| 4113 | @end example | ||
| 4020 | 4114 | ||
| 4021 | @item | 4115 | will display @file{*Messages*} in a window on the top and select it |
| 4022 | Calling @code{window-preserve-size} (@pxref{Preserving Window Sizes}) | 4116 | which is usually not what @code{display-buffer} is supposed to do. |
| 4023 | will try to keep the size of the argument window unchanged when | ||
| 4024 | popping up a new window. You have to make sure that another window in | ||
| 4025 | the same combination can be shrunk instead, though. | ||
| 4026 | 4117 | ||
| 4027 | @item | 4118 | On the other hand, while evaluating the following form |
| 4028 | Side windows (@pxref{Side Windows}) can be used for displaying | ||
| 4029 | specific buffers always in a window at the same position of a frame. | ||
| 4030 | This permits grouping buffers that do not compete for being shown at | ||
| 4031 | the same time on a frame and showing any such buffer in the same window | ||
| 4032 | without disrupting the display of other buffers. | ||
| 4033 | 4119 | ||
| 4034 | @item | 4120 | @example |
| 4035 | Child frames (@pxref{Child Frames}) can be used to display a buffer | 4121 | @group |
| 4036 | within the screen estate of the selected frame without disrupting that | 4122 | (progn |
| 4037 | frame's window configuration and without the overhead associated with | 4123 | (split-window) |
| 4038 | full-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 | |||
| 4128 | will 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 | |||
| 4139 | will not. | ||
| 4041 | 4140 | ||
| 4141 | Also, 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 | ||
| 4144 | window to have the highest use time among all windows, may fail to | ||
| 4145 | produce a window according to their specifications. | ||
| 4146 | |||
| 4147 | Hence, an application that relies on using a window excursion should try | ||
| 4148 | to postpone the @code{display-buffer} call until after the excursion has | ||
| 4149 | terminated. | ||
| 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. | ||
| 2489 | This is used by `get-lru-window'. The value is interpreted in units | ||
| 2490 | of 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. |
| 2497 | Return a full-width window if possible. A minibuffer window is | 2489 | Return 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 | ||
| 2519 | Any other value of ALL-FRAMES means consider all windows on the | 2511 | Any other value of ALL-FRAMES means consider all windows on the |
| 2520 | selected frame and no others. | 2512 | selected frame and no others." |
| 2521 | |||
| 2522 | `display-buffer-avoid-small-windows', if non-nil, is also taken into | ||
| 2523 | consideration. Windows whose height is smaller that the value of that | ||
| 2524 | variable 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 | |||
| 7274 | dedicated flag to that value. In any other case, reset WINDOW's | 7259 | dedicated flag to that value. In any other case, reset WINDOW's |
| 7275 | dedicated flag to nil. | 7260 | dedicated flag to nil. |
| 7276 | 7261 | ||
| 7262 | If ALIST contains a non-nil `bump-use-time' entry, bump use time | ||
| 7263 | of WINDOW so further calls of `display-buffer-use-some-window' | ||
| 7264 | and `display-buffer-use-least-recent-window' will try to avoid | ||
| 7265 | it. | ||
| 7266 | |||
| 7277 | Return WINDOW if BUFFER and WINDOW are live." | 7267 | Return 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. |
| 8507 | This `display-buffer' action function is like | 8501 | Do not return a minibuffer window or a window dedicated to its |
| 8508 | `display-buffer-use-some-window', but will cycle through windows | 8502 | buffer. ALIST is a buffer display action alist as compiled by |
| 8509 | when displaying buffers repeatedly, and if there's only a single | 8503 | `display-buffer'. The following ALIST entries are honored: |
| 8510 | window, 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 | |||
| 8519 | If ALIST contains a non-nil `inhibit-same--window' entry, do not | ||
| 8520 | return 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. | ||
| 8616 | This is similar to `display-buffer-use-some-window' but tries | ||
| 8617 | hard to avoid using a window recently used by `display-buffer'. | ||
| 8618 | |||
| 8619 | Distinctive 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 | |||
| 8653 | If a window is found, bump the use time of that window to the | ||
| 8654 | highest use time after the selected window. This makes it less | ||
| 8655 | probable that a future invocation of this function uses that | ||
| 8656 | window 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. |
| 8569 | ALIST is an association list of action symbols and values. See | 8686 | ALIST 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 | ||
| 763 | DEFUN ("window-use-time", Fwindow_use_time, Swindow_use_time, 0, 1, 0, | 763 | DEFUN ("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. |
| 765 | WINDOW must be a live window and defaults to the selected one. | 765 | WINDOW must specify a live window and defaults to the selected one. |
| 766 | The window with the highest use time is the most recently selected | 766 | |
| 767 | one. The window with the lowest use time is the least recently | 767 | The window with the highest use time is usually the one most recently |
| 768 | selected one. */) | 768 | selected by calling `select-window' with NORECORD nil. The window with |
| 769 | the lowest use time is usually the least recently selected one chosen in | ||
| 770 | such a way. | ||
| 771 | |||
| 772 | Note 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 | ||
| 774 | DEFUN ("window-bump-use-time", Fwindow_bump_use_time, | 779 | DEFUN ("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. |
| 777 | WINDOW must be a live window and defaults to the selected one. */) | 782 | WINDOW must specify a live window. |
| 783 | |||
| 784 | If WINDOW is not selected and the selected window has the highest use | ||
| 785 | time of all windows, set the use time of WINDOW to that of the selected | ||
| 786 | window, increase the use time of the selected window by one and return | ||
| 787 | the 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 | ||
| 787 | DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0, | 804 | DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0, |