all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
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

  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.