From: martin rudalics <rudalics@gmx.at>
To: Tom Gillespie <tgbugs@gmail.com>
Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org, larsi@gnus.org
Subject: Re: [PATCH] Fix display-buffer-use-some-window to honor reusable-frames
Date: Thu, 2 Feb 2023 17:39:44 +0100 [thread overview]
Message-ID: <f1e2663d-7819-3b1b-6a12-d04a554c4d73@gmx.at> (raw)
In-Reply-To: <e90c0a73-5f07-231b-fc36-e84fe67d96db@gmx.at>
[-- Attachment #1: Type: text/plain, Size: 1665 bytes --]
> And note one thing: When you call 'get-lru-window' twice in a row, it
> will usually _not_ return a window it has internally considered as
> "second best" provided it finds a best one.
>
> Consider a frame with three windows, one of them full width and the
> other two, including the selected one, not full width. In this case
> 'get-lru-window' will always return the full width window even if it has
> a higher use time than the not selected, not full width one.
A tentative solution for this and the other problems mentioned in this
thread is in the attached diff. It should be able to digest the
following form.
(let* ((window (selected-window))
use-time)
;; Make window at bottom mru.
(select-window (split-window))
;; Make window on right mru.
(select-window (split-window window nil t))
;; Make initial window mru so the lru window is the one at bottom.
(select-window window)
(setq use-time (window-use-time))
(display-buffer
(get-buffer-create "*foo*")
`((display-buffer-use-least-recent-window)
(window-min-width . full-width)
(lru-time . ,use-time)
))
(display-buffer
(get-buffer-create "*bar*")
`((display-buffer-use-least-recent-window)
(window-min-width . full-width)
(lru-time . ,use-time)
)))
Note how it uses a non-full-width window for *bar* despite the fact that
we would have preferred a full-width one. And note the settings of
lru-time to the use time of the selected window before the first
'display-buffer' call. Commenting out these lru-time settings will make
it use as window for *bar* the window it previously used for *foo*.
martin
[-- Attachment #2: Gillespie.diff --]
[-- Type: text/x-patch, Size: 5529 bytes --]
diff --git a/lisp/window.el b/lisp/window.el
index a11293d372..a0e09ab492 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,92 @@ 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.
+
+- `not-this-window' non-nil means to never return the selected
+ window. Even if this entry is not present, try to avoid
+ returning 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 'not-this-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
next prev parent reply other threads:[~2023-02-02 16:39 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-27 5:17 [PATCH] Fix display-buffer-use-some-window to honor reusable-frames Tom Gillespie
2023-01-27 5:25 ` Tom Gillespie
2023-01-27 6:19 ` Tom Gillespie
2023-01-27 13:03 ` Eli Zaretskii
2023-01-28 10:46 ` martin rudalics
2023-01-28 11:12 ` Eli Zaretskii
2023-01-28 15:35 ` martin rudalics
2023-01-28 16:02 ` Eli Zaretskii
2023-01-29 17:39 ` martin rudalics
2023-01-29 18:41 ` Eli Zaretskii
2023-01-29 18:50 ` Tom Gillespie
2023-01-30 16:43 ` martin rudalics
2023-01-30 17:38 ` Eli Zaretskii
2023-01-30 17:57 ` martin rudalics
2023-01-30 18:04 ` Eli Zaretskii
2023-01-31 8:45 ` martin rudalics
2023-01-31 14:01 ` Eli Zaretskii
2023-02-01 10:45 ` martin rudalics
2023-02-01 17:38 ` Eli Zaretskii
2023-02-01 18:33 ` martin rudalics
2023-01-28 19:04 ` Tom Gillespie
2023-01-28 20:01 ` Tom Gillespie
2023-01-29 17:39 ` martin rudalics
2023-01-29 19:02 ` Tom Gillespie
2023-01-30 16:44 ` martin rudalics
2023-01-30 17:43 ` Tom Gillespie
2023-01-30 17:58 ` martin rudalics
2023-01-30 19:40 ` Tom Gillespie
2023-01-30 22:45 ` Tom Gillespie
2023-01-31 8:46 ` martin rudalics
2023-01-31 18:38 ` Tom Gillespie
2023-02-01 9:08 ` martin rudalics
2023-02-01 17:19 ` Tom Gillespie
2023-02-01 18:32 ` martin rudalics
2023-02-02 16:39 ` martin rudalics [this message]
2023-02-02 19:57 ` Tom Gillespie
2023-02-03 9:09 ` martin rudalics
2023-02-11 15:44 ` Eli Zaretskii
2023-02-11 18:15 ` Tom Gillespie
2023-02-12 9:33 ` martin rudalics
2023-02-18 17:46 ` Eli Zaretskii
2023-02-20 9:03 ` martin rudalics
2023-02-20 11:55 ` Eli Zaretskii
2023-02-20 18:14 ` martin rudalics
2023-02-21 12:02 ` Eli Zaretskii
2023-01-31 8:46 ` martin rudalics
2023-01-29 17:48 ` Juri Linkov
2023-01-29 18:48 ` Eli Zaretskii
2023-02-06 10:01 ` martin rudalics
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=f1e2663d-7819-3b1b-6a12-d04a554c4d73@gmx.at \
--to=rudalics@gmx.at \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=larsi@gnus.org \
--cc=tgbugs@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.