branch: externals/ement
commit 55e000cf4e426c2b3b5ab57fa93d5774eb1ea1a0
Author: Phil Sainty <p...@catalyst.net.nz>
Commit: Phil Sainty <p...@catalyst.net.nz>

    Use a window-parameter for the compose buffer window auto-height cache
    
    Previously this was a buffer-local variable, which was not correct,
    but was also fine most of the time (as we only care strongly about the
    size of the selected window, and we flush the cache when switching
    between windows, and in most cases a compose buffer will only ever be
    displayed in a single window).
    
    This commit also eliminates the timer-triggered resize from
    `ement-room-compose-buffer-window-buffer-change-handler' as it no
    longer seems necessary, so `post-command-hook' is now the sole trigger
    for resizing.  (The call to `window-preserve-size' added in commit
    7418626abe79fce12f834251d4690dcdf4331dd7 is likely another factor in
    being able to remove this code, although that alone had not been
    sufficient.)
---
 ement-room.el | 106 ++++++++++++++++++++++++++++++++--------------------------
 1 file changed, 58 insertions(+), 48 deletions(-)

diff --git a/ement-room.el b/ement-room.el
index 28de04ce24..dc442d0b43 100644
--- a/ement-room.el
+++ b/ement-room.el
@@ -547,8 +547,6 @@ See also `ement-room-compose-buffer-window-auto-height-max' 
and
 ;; get the correct result in the majority of situations, and it is simple.
 (defvar ement-room-compose-buffer-window-auto-height-resizing-p)
 
-(defvar ement-room-compose-buffer-window-auto-height-cache)
-
 (defcustom ement-room-compose-buffer-window-auto-height-min nil
   "If non-nil, limits the body height of the compose buffer window.
 
@@ -4449,6 +4447,26 @@ is non-nil."
   ;; The following may also clear the cache in order to force a recalculation:
   ;; - `ement-room-compose-buffer-window-state-change-handler'
   ;; - `ement-room-compose-buffer-window-buffer-change-handler'
+  ;;
+  ;; Global mutex `ement-room-compose-buffer-window-auto-height-resizing-p'
+  ;; ensures that we cannot run recursively.  We also resize only the selected
+  ;; window, even if there are compose buffers displayed in other windows which
+  ;; might also be affected.  This conservative approach can prevent desirable
+  ;; resizing in some cases, but restricting our behaviour this way keeps 
things
+  ;; simple so that we needn't consider potential issues such as endless cycles
+  ;; of conflicting resizes.
+  ;;
+  ;; Perfection would in any case be non-trivial -- consider two compose 
windows
+  ;; side-by-side in a horizontal split, each showing a different compose 
buffer
+  ;; with a different desired height.  We cannot have the "correct" size for
+  ;; both simultaneously.  The best thing to do would be to maintain the 
tallest
+  ;; height amongst all conflicting windows at all times -- but that is, again,
+  ;; considerably more complex.
+  ;;
+  ;; Most of the time the window arrangements are expected to be very simple 
and
+  ;; so a more comprehensive solution, while possible, is not worth the added
+  ;; complexity -- our relatively simplistic approach is good enough for the
+  ;; vast majority of situations.
   (unless (or (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-resizing-p)
               (window-full-height-p))
     ;; Manipulate the window body height.
@@ -4458,12 +4476,14 @@ is non-nil."
            (buflines (max 1 (count-screen-lines nil nil t)))
            (cache (if pixelwise
                       (* buflines lineheight)
-                    buflines)))
+                    buflines))
+           (wcache (window-parameter
+                    nil 'ement-room-compose-buffer-window-auto-height-cache)))
       ;; Do nothing if the desired height has not changed.
-      (unless (and (boundp 'ement-room-compose-buffer-window-auto-height-cache)
-                   (eql cache 
ement-room-compose-buffer-window-auto-height-cache))
+      (unless (and wcache (eql cache wcache))
         ;; Otherwise resize the window...
-        (setq-local ement-room-compose-buffer-window-auto-height-cache cache)
+        (set-window-parameter
+         nil 'ement-room-compose-buffer-window-auto-height-cache cache)
         (let* ((ement-room-compose-buffer-window-auto-height-resizing-p t)
                (minheight (if ement-room-compose-buffer-window-auto-height-min
                               (max 1 
ement-room-compose-buffer-window-auto-height-min)
@@ -4517,26 +4537,25 @@ selected or deselected.
 This prevents a compose buffer window being stuck at the wrong
 height (until the number of lines changes again) if something
 other than the auto-height feature resizes the window.  We simply
-flush the height cache for these state changes, thus ensuring the
-required height is recalculated on the next cycle).
+flush the auto-height cache, thus ensuring the required height is
+recalculated on the next cycle).
 
 See also `ement-room-compose-buffer-window-buffer-change-handler'."
+  ;; Ignore the window state changes triggered by our auto-height resizing.
+  ;;
+  ;; Also do nothing if the state change is for the selected window, as
+  ;; the buffer-local `post-command-hook' is already dealing with that
+  ;; case.  We only care about window state changes which are triggered
+  ;; from elsewhere.  This means we skip the case whereby the selected
+  ;; window has just switched to the compose buffer, and so we use
+  ;; `window-buffer-change-functions' as well to capture that case.
+  ;; (See `ement-room-compose-buffer-window-buffer-change-handler'.)
   (when ement-room-compose-buffer-window-auto-height
-    ;; Ignore the window state changes triggered by our auto-height resizing.
-    (unless (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-resizing-p)
-      (let ((buf (current-buffer)))
-        ;; Do nothing if the state change happened while the compose buffer was
-        ;; current, as the buffer-local `post-command-hook' is already dealing
-        ;; with that case.  We only care about window state changes which are
-        ;; triggered from elsewhere.  This means that we skip the case whereby
-        ;; the selected window has just switched to the compose buffer, and so
-        ;; we use `window-buffer-change-functions' as well to capture that 
case.
-        ;; (See `ement-room-compose-buffer-window-buffer-change-handler'.)
-        (with-selected-window win
-          (unless (eq (current-buffer) buf)
-            ;; Clear the height cache for this compose buffer.
-            (when (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-cache)
-              (setq-local ement-room-compose-buffer-window-auto-height-cache 
nil))))))))
+    (unless (or (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-resizing-p)
+                (eq win (selected-window)))
+      ;; Clear the auto-height cache for this window.
+      (set-window-parameter
+       win 'ement-room-compose-buffer-window-auto-height-cache nil))))
 
 (defun ement-room-compose-buffer-window-buffer-change-handler (win)
   "Called via buffer-local `window-buffer-change-functions' in compose buffers.
@@ -4544,41 +4563,32 @@ See also 
`ement-room-compose-buffer-window-buffer-change-handler'."
 Called for any window WIN showing a compose buffer if that window
 has just been created or assigned that buffer.
 
-Like `ement-room-compose-buffer-window-state-change-handler' (see
-which) in purpose, but handling the case where WIN has just
-switched to displaying the compose buffer (which the other
-handler ignores as a side-effect of its conditional logic).
+Flush the auto-height cache for any window which switches to
+displaying a compose buffer, to ensure the required height is
+recalculated on the next cycle.
+
+Also detect whether a composer buffer's window was created for
+that purpose, as this information affects the behaviour of
+`ement-room-compose-buffer-quit-restore-window'.
 
-This function also determines whether the composer buffer's
-window has been newly created, which affects the behaviour of
-`ement-room-compose-buffer-quit-restore-window'."
+See also `ement-room-compose-buffer-window-state-change-handler'."
   (with-selected-window win
-    ;; Clear the height cache for this compose buffer.
     (when ement-room-compose-buffer-window-auto-height
-      (when (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-cache)
-        (setq-local ement-room-compose-buffer-window-auto-height-cache nil)
-        ;; `window-buffer-change-functions' runs /after/ `post-command-hook',
-        ;; so after flushing the cache we need to invoke the resize handler, as
-        ;; otherwise it wouldn't update until after the /subsequent/ command.
-        ;; We don't want to do this while this hook is still running though
-        ;; (the result is inaccurate), so defer it with a timer.
-        (unless (bound-and-true-p 
ement-room-compose-buffer-window-auto-height-resizing-p)
-          (run-with-timer 0 nil (lambda (win)
-                                  (with-selected-window win
-                                    
(ement-room-compose-buffer-window-auto-height)))
-                          win))))
-    ;; Process `ement-room-compose-buffer-window-dedicated' when the compose
-    ;; buffer is first displayed, to decide whether the window should be
-    ;; dedicated to the buffer.
+      ;; Clear the auto-height cache for this window.
+      (set-window-parameter
+       win 'ement-room-compose-buffer-window-auto-height-cache nil))
+    ;; Establish whether we've processed this window before, and whether it was
+    ;; created to display a compose buffer.  We set a window property the first
+    ;; time that we see the window, so if it's set at all, we've seen it 
before.
     (unless (assq 'ement-room-compose-buffer-window-created-p 
(window-parameters win))
-      (let ((createdp (not (window-prev-buffers))))
+      (let ((createdp (not (window-prev-buffers win))))
         (set-window-parameter win 'ement-room-compose-buffer-window-created-p
                               createdp)
         (when (cl-case ement-room-compose-buffer-window-dedicated
                 (created createdp)
                 (auto-height ement-room-compose-buffer-window-auto-height)
                 (t ement-room-compose-buffer-window-dedicated))
-          (set-window-dedicated-p nil t))))))
+          (set-window-dedicated-p win t))))))
 
 (defun ement-room-compose-buffer-quit-restore-window ()
   "Kill the current compose buffer and deal appropriately with its window.

Reply via email to