Subject: Re: bug#76911: dedicated side windows lose their dedication upon reuse

From: martin rudalics <[email-masked]>
Date: Tue, 18 Mar 2025 10:02:34 +0100

>> So a dedicated flag that does not equal 'side' might cause the problem
 >> here.  If it persists, I can write some code for 'display-buffer' so we
 >> can find the offender.
 >
 > But I want the strong dedication semantics. Specifically, I'm looking
 > for something like an omnipresent always available panel I can summon
 > and dismiss any time with a simple keybinding. I also have facilities
 > for cycling its size and extracting the omnipresent thing into a
 > conventional window temporarily. I want not only strong dedication,
 > but also no-other-window and no-delete-other-windows, which I
 > set. Modulo bugs, it all seems to work.

You might be asking a bit too much here: The side windows mechanism does
its own handling of dedicatedness which means that if you specify
'display-buffer-in-side-window' for a buffer-2 and the window at that
slot is strongly dedicated to buffer-1, buffer-2 will be still displayed
in that window.  There's no other way because I cannot display buffer-2
reasonably anywhere else.

BTW why do you set 'no-delete-other-windows' for a side window?  You
cannot avoid an error when incidentally doing C-x 5 1 in it I suppose.

 > For finding those bugs, maybe we need a history of recent window
 > changes we can examine after something has gone wrong. Just today I
 > got into a weird state in which I had two side windows with the same
 > slot and have no idea how I got into that state or how I'd repro.

As a matter of fact, this should never happen.  You could try running
Emacs with the patch below - it might help to detect such a situation.

martin

diff --git a/lisp/window.el b/lisp/window.el
index 1e8f4e323bc..dd7a463aa3b 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -7824,6 +7824,12 @@ window--display-buffer
          (dolist (parameter parameters)
            (set-window-parameter
             window (car parameter) (cdr parameter)))))
+    (with-current-buffer (get-buffer-create "*display-buffer-history*")
+      (goto-char (point-max))
+      (insert (format " window: %s" window)
+	      (format " [%s]" type)
+	      (format " alist: %s" alist)
+	      (format " parameters: %s\n" (window-parameters window))))
      window))

  (defun window--maybe-raise-frame (frame)
@@ -8220,6 +8226,9 @@ display-buffer
  	(split-window-keep-point t)
  	;; Handle the old form of the first argument.
  	(inhibit-same-window (and action (not (listp action)))))
+    (with-current-buffer (get-buffer-create "*display-buffer-history*")
+      (goto-char (point-max))
+      (insert (format "buffer: %s" buffer) (format " action: %s\n" action)))
      (unless (listp action) (setq action nil))
      (let* ((user-action
              (display-buffer-assq-regexp