Trouble with dirvish side windows sizing
When zoom-mode is off, the dirvish side window is correctly sized. When zoom-mode is on, the side window occupies half the frame width. This is making using zoom and dirvish together a bit frustrating. I did read the previous discussions on balance-windows and came up dry for this issue. I experimented by moving balance-windows under the zoom ignore check and that works better but unsure what the side effects might be for other usage. I did see that you have the inclination to not make balance-windows optional.
If you're willing to humor this, I've attached a repro that demonstrates the issue with -Q with only zoom and dirvish being installed. I set the window-parameter fixed-size in the code just in case that would help and it does not work.
I run it as emacs -Q -l repro-dirvish-zoom.txt (fking Chrome/github won't let me upload an .el file). Press f7 to pop-up the fixed dirvish side window. Press q to dismiss it. Press C-z to enable zoom-mode. Then f7 again and you'll see the sizing issue. Any ideas?
Much appreciated e grazie,
-Stephane
(defun zoom--update ()
...
(unless (zoom--window-ignored-p)
;; What I changed in zoom
(unless (window-parameter (selected-window) 'fixed-size)
(balance-windows))
(zoom--resize)
;; fix the scrolling but not for image buffers
(unless (derived-mode-p 'image-mode)
(zoom--fix-scroll)))))
Well it's always the same story, in order to work well with Zoom, windows that are supposed to have a certain size should be fixed, and IMHO they should be fixed even regardless Zoom... or at the very least provide an option to make it like that. Why bother creating an Emacs option like dirvish-side-width if the user can resize it anyway?
I did see that you have the inclination to not make balance-windows optional.
Yep, makes little sense to me, in the mean time you can use the following or easily patch Zoom.
(advice-add
#'balance-windows
:before-until
(lambda (&optional window-or-frame)
(backtrace-frame 0 'zoom--update)))
I do mark the window as fixed. This is in my dirvish config in the reproducer:
(add-to-list 'dirvish-side-window-parameters '(fixed-size . t))
I guess that's insufficient and I should somehow mark the buffer, too?
I suspect dirvsh is doing something at some point to revert that option, even if I patch the code in dirvish-side-root-window-fn with something similar to this, the window in the end has window-size-fixed set to nil.
You can see it works as intended by setting window-size-fixed to 'width manually, after the window is created.
I'll see if Alex can address this in dirvish. Surely I can't be the only one to notice this issue. Grazie, Andrea.
P.S. FWIW, when I test fixed-size using eval-expression in the window itself, fixed-size is t. So I'm a bit confused.
P.S. FWIW, when I test fixed-size using eval-expression in the window itself, fixed-size is t. So I'm a bit confused.
We tested different things apparently, I'm not even sure window-size-fixed and the fixed-size window parameter are actually equivalent.
In any case, you can rule out Zoom from the equation, what you want is to be able to set that window fixed somehow, so that invoking balance-windows doesn't affect it.
Also, FWIW, I changed the advice to this, and the fixed-size test passes for the dirvish window and inhibiting balance-windows seems to work regardless of being called from zoom. Perhaps balance-windows is broken. I think it has been in the past.
(defun my/zoom-balance-windows-advice (&optional window-or-frame)
(setq window-or-frame (or (and (windowp window-or-frame) window-or-frame)
(selected-window)))
(or (window-parameter window-or-frame 'fixed-size)
(backtrace-frame 0 'zoom--update)))
I suspect dirvsh is doing something at some point to revert that option
The only occurrence of window-size-fixed relates to the root window is:
https://github.com/alexluigit/dirvish/blob/2f06964137872c32ac716b6fe2df700f971854f8/dirvish.el#L1367
In other words, this is persistent by design.
Why bother creating an Emacs option like
dirvish-side-widthif the user can resize it anyway?
Because of the above setting, the side window always has fixed-width on my end, I'm not able to resize it with ordinary commands like balance-windows or enlarge-window-horizontally, nor with my mouse.
Hope it helps.
Thank you @alexluigit. With emacs -Q and:
(package-initialize)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-install 'dirvish)
(add-to-list 'load-path (expand-file-name "extensions" (file-name-directory (locate-library "dirvish"))))
(require 'dirvish-side)
(dirvish-side)
I can resize the window with the mouse, and balance-windows too is able to resize it. Moreover, with the Dirvish side window selected, window-size-fixed evaluates to nil. What am I missing?
What am I missing?
Just put (dirvish-override-dired-mode) before (dirvish-side) should do the trick. Please let me know if there is any other reliable method to make a window fixed-sized, thanks!
Just put
(dirvish-override-dired-mode)before(dirvish-side)should do the trick.
Ahhh, OK now it makes sense! And everything works properly with the regard the window size, that is, balance-windows doesn't affect, and hence Zoom works too:
(package-initialize)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-install 'zoom)
(zoom-mode)
(package-install 'dirvish)
(add-to-list 'load-path (expand-file-name "extensions" (file-name-directory (locate-library "dirvish"))))
(require 'dirvish-side)
(dirvish-override-dired-mode)
(dirvish-side)
(Probably due to some race condition or something, if you eval the above in a single batch, it doesn't work properly, just run (dirvish-side) later by hand.)
I don't see any issue even if I manually try these steps:
Press f7 to pop-up the fixed dirvish side window. Press q to dismiss it. Press C-z to enable zoom-mode. Then f7 again and you'll see the sizing issue.
@shipmints can you reproduce with the above? Let's start from here, your repro file seems too complex, plus it doesn't work out of the box for me.
Thank you both for keeping at this. I appreciate it. Andrea, your reproducer produces the incorrect dirvish-side window width to begin with. It defaults to 35 but displays as half the frame width when launched. Are you not seeing the same behavior?
The below simplified reproducer, which I ran with Emacs 30.1, illustrates that dirvish-side-width is ignored when zoom-mode is enabled before dirvish-side is launched. If zoom-mode is disabled, dirvish-side-width is respected.
$ emacs -Q -l repro.el
(add-hook 'window-setup-hook
(lambda ()
(set-frame-position nil 0 0)
(set-frame-size nil 200 60)
(select-frame-set-input-focus (selected-frame))))
(setq load-prefer-newer t)
(package-activate-all)
(global-unset-key (kbd "C-z"))
(set-face-attribute 'default nil
:height 240
:background "#101010"
:foreground "white")
(require 'zoom)
(global-set-key (kbd "C-z C-z") #'zoom-mode)
(setq zoom-size '(0.618 . 0.618)) ; golden ratio
(setq zoom-ignored-major-modes '(dirvish-mode
dirvish-directory-view-mode
dirvish-misc-mode
dirvish-special-preview-mode))
(setq zoom-ignored-buffer-name-regexps
(list
(rx bos " ") ; ignore hidden buffers including dirvish " SIDE::" buffer names
))
(zoom-mode)
(require 'dirvish)
(require 'dirvish-side)
(require 'dirvish-history)
(dirvish-override-dired-mode)
(setq dirvish-side-width 50)
(global-set-key (kbd "<f7>") #'dirvish-side)
OK, so there's actually something... if I start with a clean home:
rm -fr /tmp/emacs/
mkdir -p /tmp/emacs/
HOME=/tmp/emacs/ emacs -Q
And I eval:
(package-initialize)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-install 'zoom)
(zoom-mode)
(package-install 'dirvish)
(add-to-list 'load-path (expand-file-name "extensions" (file-name-directory (locate-library "dirvish"))))
(require 'dirvish-side)
(dirvish-override-dired-mode)
(dirvish-side)
Then I see the issue, i.e., the Dirvish window, despite being fixed in the end, it takes half of the screen, meaning that somehow balance-windows is able to interfere with the window size.
@alexluigit can you try this with a clean home? It could be that I/we have some local modification in our regular ~/.emacs.d/ directory.
Thanks for the testing, I guess I figured out the cause. Dirvish uses window-buffer-change-functions to reconstruct the window layout whenever the buffer in the window changes, whereas pre-redisplay-functions seems kick in before this. I'll take a closer look of it.
Curious how @cyrus-and using a "clean home" impacted behavior.
Curious how @cyrus-and using a "clean home" impacted behavior.
Not quite, even with -Q/-q the MELPA directory is reused; it might happen that during tests one modified some package files. Using a clean home ensures that packages are always fetched from the repo.
I believe https://github.com/alexluigit/dirvish/commit/5a3cf2b0a655c841a492f59fd1af4bbb1e6857f5 solved the initial width issue. However, the user options provided by zoom is insufficient to deal with situations where a fixed window layout is required, like in M-x dirvish.
(setq zoom-ignored-major-modes '(dirvish-mode dirvish-directory-view-mode dirvish-misc-mode dirvish-special-preview-mode)) (setq zoom-ignored-buffer-name-regexps (list (rx bos " ") ; ignore hidden buffers including dirvish " SIDE::" buffer names ))
@shipmints , these settings doesn't have any effects as they are evaluated after calling balance-windows, which also explains why you get a very small parent window when zoom-mode is enabled (https://github.com/alexluigit/dirvish/issues/326#issuecomment-2743202957)
Perhaps zoom needs to provide a option to refrain itself from calling balance-windows under some circumstances (I'm aware that it has been brought up multiple times in the issues).
Ref: https://github.com/alexluigit/dirvish/blob/main/docs/CUSTOMIZING.org#file-preview-in-multiple-window-layouts
Perhaps zoom needs to provide a option to refrain itself from calling balance-windows under some circumstances (I'm aware that it has been brought up multiple times in the issues).
My problem here is the fact that this would create inconsistency in the expectations set by Zoom. I would rather provide a way to fully pause the Zoom action when certain conditions are met, that is, also the zoom part, not only the balance one. In this case, IIUC, that would be during those transient Dirvish layout, right? How could one recognise that such layout mode is active? I'm asking but I never actually tried.
Right. Perhaps dirvish itself can offer a pre-layout hook that a zoom user can use to bind a zoom defvar to inhibit zoom--update behavior?
Perhaps dirvish itself can offer a pre-layout hook that a zoom user can use to bind a zoom defvar to inhibit zoom--update behavior?
I was thinking of a more general solution, so that Zoom users could write some predicates that pauses the behaviour, so I was wondering how hard would be to write such predicate for Dirvish.
I would rather provide a way to fully pause the Zoom action when certain conditions are met, that is, also the zoom part, not only the balance one.
Thanks for considering this.
How could one recognise that such layout mode is active?
(when-let* ((dv (dirvish-curr))
(layout (dv-curr-layout dv)))
(message "dirvish is taking over the layout..")
(throw 'skip t))
Put this in the beginning of zoom--handler seems working fine, feel free to try it out.
@alexluigit are you suggesting that zoom--handler incorporate a hook to which one could add a function to test if dirvish-mode layout is active? Do you think it would be a global hook or a buffer-local hook?
@alexluigit are you suggesting that
zoom--handlerincorporate a hook to which one could add a function to test if dirvish-mode layout is active?
Yes. Something like zoom-disable-predicates.
Do you think it would be a global hook or a buffer-local hook?
The code I posted above works because (dv-curr-layout (dirvish-curr)) returns a non-nil value in all windows whenever a transient layout is active. Adding this hook globally is therefore preferable, as the other-window command could otherwise
easily disrupt the layout. To avoid adding the hook globally, you can instead add it locally to dired-mode and all special modes provided by Dirvish. This achieves the same outcome but results in a more verbose configuration.