]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve handling of dedicated flag for side windows (Bug#48493)
authorpillule <pillule@riseup.net>
Mon, 14 Jun 2021 07:59:11 +0000 (09:59 +0200)
committerMartin Rudalics <rudalics@gmx.at>
Mon, 14 Jun 2021 07:59:11 +0000 (09:59 +0200)
* doc/lispref/windows.texi (Buffers and Windows): Mention the
special handling of side windows and add a reference.
(Buffer Display Action Alists): Say explicitly that
`display-buffer-in-side-window' is dedicating to side by default.
(Dedicated Windows): Add case (4) and explain its meaning, add
a reference.
(Displaying Buffers in Side Windows): Move the paragraph about
`switch-to-(prev|next)-buffer' into a new item to emphasize the
special meaning of dedication for side windows.
* lisp/window.el (set-window-buffer-start-and-point): Restore
side dedication.
(switch-to-prev-buffer, switch-to-next-buffer): Correct return
value that should be nil instead of the same buffer in case of
no change.
(delete-windows-on): Restore side dedication.
(replace-buffer-in-windows): Update the docstring, restore side
dedication.
(quit-restore-window): Rearrange the logic so that strongly
dedicated windows are eventually deleted first.  Restore the
side dedication.  In the final case try to
`switch-to-prev-buffer' before deleting a window (Bug#48367).

doc/lispref/windows.texi
lisp/window.el

index 3b6f74b89cf5587a4685b0c3b5b0706f6ac5b4d8..26f85df160e2d03bf05f6199bb2c8c52a4193070 100644 (file)
@@ -2191,12 +2191,13 @@ the name of an existing buffer; if omitted or @code{nil}, it defaults to
 the current buffer.
 
 The replacement buffer in each window is chosen via
-@code{switch-to-prev-buffer} (@pxref{Window History}).  Any dedicated
-window displaying @var{buffer-or-name} is deleted if possible
-(@pxref{Dedicated Windows}).  If such a window is the only window on its
-frame and there are other frames on the same terminal, the frame is
-deleted as well.  If the dedicated window is the only window on the only
-frame on its terminal, the buffer is replaced anyway.
+@code{switch-to-prev-buffer} (@pxref{Window History}).  With the
+exception of side windows (@pxref{Side Windows}), any dedicated window
+displaying @var{buffer-or-name} is deleted if possible (@pxref{Dedicated
+Windows}).  If such a window is the only window on its frame and there
+are other frames on the same terminal, the frame is deleted as well.
+If the dedicated window is the only window on the only frame on its
+terminal, the buffer is replaced anyway.
 @end deffn
 
 
@@ -3013,6 +3014,8 @@ If non-@code{nil}, such an entry tells @code{display-buffer} to mark
 any window it creates as dedicated to its buffer (@pxref{Dedicated
 Windows}).  It does that by calling @code{set-window-dedicated-p} with
 the chosen window as first argument and the entry's value as second.
+Side windows are by default dedicated with the value @code{side}
+((@pxref{Side Window Options and Functions}).
 
 @vindex preserve-size@r{, a buffer display action alist entry}
 @item preserve-size
@@ -4061,18 +4064,19 @@ slightly different, see below.
 
    Functions supposed to remove a buffer from a window or a window from
 a frame can behave specially when a window they operate on is dedicated.
-We will distinguish three basic cases, namely where (1) the window is
+We will distinguish four basic cases, namely where (1) the window is
 not the only window on its frame, (2) the window is the only window on
-its frame but there are other frames on the same terminal left, and (3)
-the window is the only window on the only frame on the same terminal.
+its frame but there are other frames on the same terminal left, (3)
+the window is the only window on the only frame on the same terminal,
+and (4) the dedication's value is @code{side}
+(@pxref{Displaying Buffers in Side Windows}).
 
    In particular, @code{delete-windows-on} (@pxref{Deleting Windows})
-handles case (2) by deleting the associated frame and case (3) by
-showing another buffer in that frame's only window.  The function
+handles case (2) by deleting the associated frame and cases (3) and (4)
+by showing another buffer in that frame's only window.  The function
 @code{replace-buffer-in-windows} (@pxref{Buffers and Windows}) which is
 called when a buffer gets killed, deletes the window in case (1) and
 behaves like @code{delete-windows-on} otherwise.
-@c FIXME: Does replace-buffer-in-windows _delete_ a window in case (1)?
 
    When @code{bury-buffer} (@pxref{Buffer List}) operates on the
 selected window (which shows the buffer that shall be buried), it
@@ -4335,6 +4339,25 @@ means to use a slot following (that is, below or on the right of) the
 middle slot.  Hence, all windows on a specific side are ordered by their
 @code{slot} value.  If unspecified, the window is located in the middle
 of the specified side.
+
+@item dedicated
+The dedicated flag (@pxref{Dedicated Windows}) has a slightly different
+meaning for side windows.  When a side window is created, that flag is
+set to the value @code{side} to prevent @code{display-buffer} to use the
+window in other action functions.  Its value persists across invocations
+of @code{quit-window}, @code{kill-buffer}, @code{previous-buffer} and
+@code{next-buffer}.
+
+In particular, these commands will refrain from showing, in a side
+window, buffers that have not been displayed in that window before.
+They will also refrain from having a normal, non-side window show a
+buffer that has been already displayed in a side window.  A notable
+exception to the latter rule occurs when an application, after
+displaying a buffer, resets that buffer’s local variables.  To override
+these rules and always delete a side window with @code{quit-window} or
+@code{kill-buffer}, and eventually prevent the use of
+@code{previous-buffer} and @code{next-buffer}, set this value to
+@code{t} or specify a value via @code{display-buffer-mark-dedicated}.
 @end table
 
 If you specify the same slot on the same side for two or more different
@@ -4355,16 +4378,6 @@ Functions}) unless it is explicitly specified as target of that
 action.  Note also that @code{delete-other-windows} cannot make a side
 window the only window on its frame (@pxref{Deleting Windows}).
 
-   Once set up, side windows also change the behavior of the commands
-@code{switch-to-prev-buffer} and @code{switch-to-next-buffer}
-(@pxref{Window History}).  In particular, these commands will refrain
-from showing, in a side window, buffers that have not been displayed in
-that window before.  They will also refrain from having a normal,
-non-side window show a buffer that has been already displayed in a side
-window.  A notable exception to the latter rule occurs when an
-application, after displaying a buffer, resets that buffer's local
-variables.
-
 
 @node Side Window Options and Functions
 @subsection Side Window Options and Functions
index ff4a39a2a0ae186903cc72789f0d1d003b7cb98b..6afc519e2881edb20a8fe49a9b2f9b498e3f5f18 100644 (file)
@@ -4526,8 +4526,10 @@ point to POINT.  If WINDOW is selected this also sets BUFFER's
 before was current this also makes BUFFER the current buffer."
   (setq window (window-normalize-window window t))
   (let ((selected (eq window (selected-window)))
-       (current (eq (window-buffer window) (current-buffer))))
+       (current (eq (window-buffer window) (current-buffer)))
+        (dedicated-side (eq (window-dedicated-p window) 'side)))
     (set-window-buffer window buffer)
+    (and dedicated-side (set-window-dedicated-p window 'side))
     (when (and selected current)
       (set-buffer buffer))
     (when start
@@ -4661,11 +4663,11 @@ This function is called by `prev-buffer'."
       ;; Scan WINDOW's previous buffers first, skipping entries of next
       ;; buffers.
       (dolist (entry (window-prev-buffers window))
-       (when (and (setq new-buffer (car entry))
+       (when (and (not (eq (car entry) old-buffer))
+                   (setq new-buffer (car entry))
                   (or (buffer-live-p new-buffer)
                       (not (setq killed-buffers
                                  (cons new-buffer killed-buffers))))
-                  (not (eq new-buffer old-buffer))
                    (or (null pred) (funcall pred new-buffer))
                   ;; When BURY-OR-KILL is nil, avoid switching to a
                   ;; buffer in WINDOW's next buffers list.
@@ -4828,11 +4830,11 @@ This function is called by `next-buffer'."
       ;; Scan WINDOW's reverted previous buffers last (must not use
       ;; nreverse here!)
       (dolist (entry (reverse (window-prev-buffers window)))
-       (when (and (setq new-buffer (car entry))
+       (when (and (not (eq new-buffer (car entry)))
+                   (setq new-buffer (car entry))
                   (or (buffer-live-p new-buffer)
                       (not (setq killed-buffers
                                  (cons new-buffer killed-buffers))))
-                  (not (eq new-buffer old-buffer))
                    (or (null pred) (funcall pred new-buffer)))
           (if (switch-to-prev-buffer-skip-p skip window new-buffer)
              (setq skipped (or skipped new-buffer))
@@ -5059,9 +5061,10 @@ window's lists of previous and next buffers."
        (all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame))))
     (dolist (window (window-list-1 nil nil all-frames))
       (if (eq (window-buffer window) buffer)
-         (let ((deletable (window-deletable-p window)))
+         (let ((deletable (window-deletable-p window))
+                (dedicated (window-dedicated-p window)))
            (cond
-            ((and (eq deletable 'frame) (window-dedicated-p window))
+            ((and (eq deletable 'frame) dedicated)
              ;; Delete frame if and only if window is dedicated.
              (delete-frame (window-frame window)))
             ((eq deletable t)
@@ -5070,7 +5073,10 @@ window's lists of previous and next buffers."
             (t
              ;; In window switch to previous buffer.
              (set-window-dedicated-p window nil)
-             (switch-to-prev-buffer window 'bury))))
+             (switch-to-prev-buffer window 'bury)
+              ;; Restore the dedicated 'side' flag.
+              (when (eq dedicated 'side)
+                (set-window-dedicated-p window 'side)))))
        ;; If a window doesn't show BUFFER, unrecord BUFFER in it.
        (unrecord-window-buffer window buffer)))))
 
@@ -5079,10 +5085,10 @@ window's lists of previous and next buffers."
 BUFFER-OR-NAME may be a buffer or the name of an existing buffer
 and defaults to the current buffer.
 
-When a window showing BUFFER-OR-NAME is dedicated, that window is
-deleted.  If that window is the only window on its frame, the
-frame is deleted too when there are other frames left.  If there
-are no other frames left, some other buffer is displayed in that
+With the exception of side windows, when a window showing BUFFER-OR-NAME
+is dedicated, that window is deleted.  If that window is the only window
+on its frame, the frame is deleted too when there are other frames left.
+If there are no other frames left, some other buffer is displayed in that
 window.
 
 This function removes the buffer denoted by BUFFER-OR-NAME from
@@ -5091,10 +5097,14 @@ all window-local buffer lists."
   (let ((buffer (window-normalize-buffer buffer-or-name)))
     (dolist (window (window-list-1 nil nil t))
       (if (eq (window-buffer window) buffer)
-         (unless (window--delete window t t)
-           ;; Switch to another buffer in window.
-           (set-window-dedicated-p window nil)
-           (switch-to-prev-buffer window 'kill))
+          ;; Delete a dedicated window unless it is a side window.
+          (let ((dedicated-side (eq (window-dedicated-p window) 'side)))
+            (when (or dedicated-side (not (window--delete window t t)))
+              ;; Switch to another buffer in that window.
+              (set-window-dedicated-p window nil)
+              (if (switch-to-prev-buffer window 'kill)
+                  (and dedicated-side (set-window-dedicated-p window 'side))
+                (window--delete window nil 'kill))))
        ;; Unrecord BUFFER in WINDOW.
        (unrecord-window-buffer window buffer)))))
 
@@ -5116,6 +5126,10 @@ buffer.  If WINDOW is not deleted, reset its `quit-restore'
 parameter to nil.  See Info node `(elisp) Quitting Windows' for
 more details.
 
+If WINDOW's dedicated flag is t, try to delete WINDOW.  If it
+equals the value 'side', restore that value when WINDOW is not
+deleted.
+
 Optional second argument BURY-OR-KILL tells how to proceed with
 the buffer of WINDOW.  The following values are handled:
 
@@ -5142,8 +5156,12 @@ nil means to not handle the buffer in a particular way.  This
                         (dolist (buf (window-prev-buffers window))
                           (unless (eq (car buf) buffer)
                             (throw 'prev-buffer (car buf))))))
+         (dedicated (window-dedicated-p window))
         quad entry)
     (cond
+     ;; First try to delete dedicated windows that are not side windows.
+     ((and dedicated (not (eq dedicated 'side))
+           (window--delete window 'dedicated (eq bury-or-kill 'kill))))
      ((and (not prev-buffer)
           (eq (nth 1 quit-restore) 'tab)
           (eq (nth 3 quit-restore) buffer))
@@ -5186,6 +5204,9 @@ nil means to not handle the buffer in a particular way.  This
       ;; Restore WINDOW's previous buffer, start and point position.
       (set-window-buffer-start-and-point
        window (nth 0 quad) (nth 1 quad) (nth 2 quad))
+      ;; Restore the 'side' dedicated flag as well.
+      (when (eq dedicated 'side)
+        (set-window-dedicated-p window 'side))
       ;; Deal with the buffer we just removed from WINDOW.
       (setq entry (and (eq bury-or-kill 'append)
                       (assq buffer (window-prev-buffers window))))
@@ -5212,9 +5233,14 @@ nil means to not handle the buffer in a particular way.  This
       (set-window-parameter window 'quit-restore nil)
       ;; Make sure that WINDOW is no more dedicated.
       (set-window-dedicated-p window nil)
-      (unless (switch-to-prev-buffer window bury-or-kill)
-        ;; Delete WINDOW if there is no previous buffer (Bug#48367).
-        (window--delete window nil (eq bury-or-kill 'kill)))))
+      ;; Try to switch to a previous buffer.  Delete the window only if
+      ;; that is not possible (Bug#48367).
+      (if (switch-to-prev-buffer window bury-or-kill)
+          (when (eq dedicated 'side)
+            (set-window-dedicated-p window 'side))
+        (window--delete window nil (eq bury-or-kill 'kill))
+        (when (window-live-p (nth 2 quit-restore))
+          (select-window (nth 2 quit-restore))))))
 
     ;; Deal with the buffer.
     (cond