Subject: bug#32850: 27.0.50; window-swap-states doesn't swap window prev/next-buffers

From: Juri Linkov <[email-masked]>
Date: Sat, 27 Oct 2018 23:09:53 +0300

>> But unfortunately set-window-configuration doesn't restore
>> the old values of prev/next-buffers.
>
> That's disputable anyway.  When, in a window excursion, you show some
> buffer in a window, don't you want to record that buffer in that
> window's list of previous buffers after exiting from the excursion?

Thanks for the hint, I see now that the problem is not in
set-window-configuration, but in window-state-put.

In case of set-window-configuration, `(set-window-next-buffers nil nil)'
correctly changes the value of window-next-buffers in the same
window that was stored in window-configuration and that is
currently selected, i.e. this produces the right result
when prev/next-buffers are modified in a new window
(so not in the window shared in window configurations):

(progn (set-buffers)
       ;; Remember window-configuration with prev/next-buffers
       (let ((window-configuration (current-window-configuration)))
         ;; Create a new window
         (delete-other-windows) (split-window) (delete-window)
         ;; Reset prev/next-buffers
         (set-window-prev-buffers nil nil)
         (set-window-next-buffers nil nil)
         ;; This correctly restores remembered prev/next-buffers
         ;; because window-next-buffers are modified in another window
         (set-window-configuration window-configuration)
         ;; window-prev-buffers and window-next-buffers are correct
	 (list (window-prev-buffers) (window-next-buffers))))

But window-state-put has such deficiency with its undocumented
prerequisite that a new unique window should be created manually
before calling window-state-put to put the state into a new
window (to not share it with other window configurations).
This means a need in such ugly hack:

;; Create a new window
(delete-other-windows) (split-window) (delete-window)
;; Put a previous state into the new window
;; to not share it with other window configurations
(window-state-put previously-saved-window-state nil 'safe)
;; Get its window configuration
(current-window-configuration)

Please confirm is `(delete-other-windows) (split-window) (delete-window)'
is the right idiom to create a new window to put the window state into,
or there is a special function to create a window, that I can't find.

> Anyway.  It would be tedious but probably not impossible to provide a
> function that transforms a configuration into a state.  Doing the
> opposite is conceptually questionable, at the very least.

The code above does the opposite, but it requires an ugly workaround
for window-state-put.

> A basic invariant of the windows code is that a valid window cannot
> appear twice on the same or a different frame.  It may, however,
> appear an arbitrary number of times in stored window configurations.

Like the earlier code snippet demonstrates it causes problems when
the same window appears an arbitrary number of times in stored window
configurations.  Thus the need to create a new window to put the state into
(currently window-state-put itself doesn't create a new unique window).