alexluigit / dirvish

A polished Dired with batteries included.
GNU General Public License v3.0
815 stars 45 forks source link

[Bug] dirvish-side window not restored correctly after exiting minibuffer #194

Open ajgrf opened 1 year ago

ajgrf commented 1 year ago

Thank you for the bug report

Bug description

After exiting the minibuffer, the dirvish-side buffer moves to a new window, while the sidebar window switches to *Dirvish-temp* instead.

Steps to reproduce

  1. Call dirvish-side to open the sidebar.
  2. With the sidebar window selected, call any command which focuses the minibuffer. A simple M-x works.
  3. Exit the minibuffer by finishing your command or cancelling it with C-g.

If the sidebar window is merely open (but not selected) when the minibuffer is focused, the issue does not occur.

Expected behavior

I expect the window configuration to be the same before and after focusing the minibuffer.

OS

Linux

Emacs Version

28

Emacs Configurations

https://gitlab.com/ajgrf/dotfiles

Error callstack

No response

Anything else

asciinema recording of the issue.

ajgrf commented 1 year ago

Seems to have something to do with switch-to-buffer-obey-display-actions. When I set it to nil (the default), the issue goes away. I'd much rather find a proper fix than have to change that variable, though.

ajgrf commented 1 year ago

I spent some time trying to debug this, but in the end I decided to just unset switch-to-buffer-obey-display-actions and rewrite the parts of my config that depended on it. Feel free to close this issue if you want.

MagicRB commented 1 year ago

I ran into the same thing just now, will search for a somewhat proper fix as setting switch-to-buffer-obey-display-actions is not an option.

MagicRB commented 1 year ago
  (defun dirvish-side-obey-display-actions (original-function &rest original-arguments)
    (let ((switch-to-buffer-obey-display-actions nil))
      (message "test")
      (apply original-function original-arguments)))
  (advice-add 'dirvish-side :around #'dirvish-side-obey-display-actions)

I tried that, but it doesn't really work, interestingly it works if I (debug-on-variable-change 'switch-to-buffer-obey-display-actions)

MagicRB commented 1 year ago

I found a very awful, but working, fix

(defun dirvish-side-buffer-p (buffer-or-name)
  "Return t if BUFFER-OR-NAME is a dirvish buffer and a side buffer."
  (with-current-buffer buffer-or-name
    (let ((dv (dirvish-curr)))
        (if (and dv (member 'side (dv-type dv)))
            t
          nil))))

(defun dirvish-ignore-display-buffer (original-function buffer-or-name &rest original-arguments)
  (let ((switch-to-buffer-obey-display-actions (not (dirvish-side-buffer-p buffer-or-name))))
    (apply original-function buffer-or-name original-arguments)))
(advice-add 'switch-to-buffer :around #'dirvish-ignore-display-buffer)
indigoviolet commented 1 year ago

@alexluigit any suggestions here? @MagicRB's fix breaks other things for me, but this bug is also annoying

jacksondm33 commented 1 month ago

It seems the issue is switch-to-buffer calls pop-to-buffer-same-window which uses the display-buffer-same-window action. display-buffer-same-window fails when the window is dedicated, though, so display-buffer uses a different action instead. This should be able to be fixed by temporarily setting the window dedication to nil before calling switch-to-buffer. In fact, I found a function in dirvish-fd.el that does exactly this:

(defun dirvish-fd-switch-to-buffer (buffer)
  "Switch to BUFFER with window undedicated."
  (let ((dedicated (window-dedicated-p)) (win (selected-window)))
    (set-window-dedicated-p win nil)
    (prog1 (switch-to-buffer buffer)
      (set-window-dedicated-p win dedicated))))