[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: New balance-windows
From: |
Stefan Monnier |
Subject: |
Re: New balance-windows |
Date: |
Tue, 09 Aug 2005 20:05:47 -0400 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (darwin) |
> After `balance-windows' After my new function
> +-------+-------+-------+ +-------+-------+-------+
> | 9 | | | | | | |
> | | | 19 | | 15 | | 20 |
> +-------+ | | | | | |
> | | 29 | | +-------+ 30 | |
> | 19 | +-------+ | | +-------+
> | | | | | 15 | | |
> | | | | | | | |
> +----+--+-------+ 19 | +----+--+-------+ 20 |
> | | | | | | | | | |
> | 19 | | | | | 14 | | | |
> | | | +-------+ | | | +-------+
> | | | 32 | | +----+--+ 31 | |
> +----+--+ | | | | | |
> | | | 22 | | 15 | | 20 |
> | 12 | | | | | | |
> | | | | | | | |
> +-------+-------+-------+ +-------+-------+-------+
For what it's worth, here is another alternative I wrote a few years ago.
Note how it iterates to try and get to a fix point without using the
`preserve-before' argument (which didn't exist at that point).
Stefan
(defun balance-windows-area ()
"Make all visible windows use the same area (approximately)."
(interactive)
(save-selected-window
(let* ((change t)
(resizecount 0)
(wins (window-list nil 'nomini))
(count (length wins))
minresize next (carry 0))
;; Resizing a window changes the size of surrounding windows
;; in complex ways, so it's difficult to set the sizes in a single pass.
;; Instead, we just go through all the windows several times
;; until nothing needs to be CHANGEd.
(while (and change (> count 1))
(setq change nil count (1- count))
(dolist (win wins)
;; We always have to check liveness because enlarging/shrinking
;; always risks deleting windows (although we are very careful
;; to avoid most such cases).
(when (and (window-live-p win) (not (window-fixed-size-p win)))
(select-window win)
(setq next nil)
(while (progn (setq next (next-window next))
(window-fixed-size-p next)))
(let ((diff (- (* (window-height) (window-width))
(* (window-height next) (window-width next)))))
(if (< (car (window-edges)) (car (window-edges next)))
;; The windows are side-by-side
(unless (zerop (setq diff (/ diff (window-height) 2)))
;; Change things more smoothly.
(if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
(shrink-window diff)
(setq change t))
(setq diff (/ diff (window-width) 2))
;; Change things more smoothly.
(if (or (> diff 1) (< diff -1)) (setq diff (/ diff 2)))
(cond
((= diff 0))
;; Try to shrink to balance out with a smaller next window.
;; Enlarging risks killing a window, but if the next-window
;; is adjacent, then it should be safe.
((or (and (> diff 0) (window-safely-shrinkable-p))
(and (< diff 0)
(= (car (window-edges))
(car (window-edges next)))
(not (eq next (frame-first-window)))))
(shrink-window diff)
(setq change t))
;; Resizing is also safe if all windows are big enough.
((> (setq minresize
(- (apply 'min (mapcar 'window-height wins))
window-min-height))
0)
(shrink-window
(if (> diff 0)
(min diff minresize) (max diff (- minresize))))
(setq change t))
;; Let's try yet something else
((and (< diff 0) (window-safely-shrinkable-p next))
(select-window next)
(shrink-window (- diff))
(setq change t)))))))))))