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

From: Juri Linkov <[email-masked]>
Date: Sun, 28 Oct 2018 21:29:33 +0200

> What you probably want is a facility to clone a window.  I have no
> idea how to do that and which semantics to attach to a cloned window.

I guess a cloned window implies the same state with a different
identity.

> You can put a window state into any valid window, usually the frame's
> root window.

I see no difference, still the same problem is that
window-state-put doesn't create a new window:

(let* ((orig-window (catch 'live
                      (walk-window-subtree
                       (lambda (window)
                         (when (window-live-p window)
                           (throw 'live window)))
                       (frame-root-window (selected-frame)))))
       (orig-window-state (window-state-get (frame-root-window (selected-frame)) 'writable)))
  (window-state-put orig-window-state (frame-root-window (selected-frame)) 'safe)
  (eq orig-window (catch 'live
                    (walk-window-subtree
                     (lambda (window)
                       (when (window-live-p window)
                         (throw 'live window)))
                     (frame-root-window (selected-frame))))))

returns t that indicates the problem.

Thus such ugly hack is required to workaround this problem:

(let* ((orig-window (catch 'live
                      (walk-window-subtree
                       (lambda (window)
                         (when (window-live-p window)
                           (throw 'live window)))
                       (frame-root-window (selected-frame)))))
       (orig-window-state (window-state-get (frame-root-window (selected-frame)) 'writable)))

  ;; Hack alert!  Create a new window
  (delete-other-windows) (split-window) (delete-window)

  (window-state-put orig-window-state (frame-root-window (selected-frame)) 'safe)
  (eq orig-window (catch 'live
                    (walk-window-subtree
                     (lambda (window)
                       (when (window-live-p window)
                         (throw 'live window)))
                     (frame-root-window (selected-frame))))))

correctly returns nil.

> Just that under the hood 'window-state-put' will do the
> 'delete-other-windows' then.

Now I see the root of this problem: it's because 'delete-other-windows'
keeps one window and reuses it for the restored state.

So a proper fix for 'window-state-put' should use a cloned window
like you proposed.