I use ace-window, and when I have at least two rows and columns of windows. When I invoke ace-window, it does column-major ordering of the windows:

|          |          |
| window 1 | window 3 |
|          |          |
|          |          |
| window 2 | window 4 |
|          |          |

That just never seems right to me; windows 2 and 3 just seem wrong. I want row-major ordering for the window numbers:

|          |          |
| window 1 | window 2 |
|          |          |
|          |          |
| window 3 | window 4 |
|          |          |

How can I get this behavior?

1 Answer 1


ace-window calls window-list when it builds its list of windows using aw-window-list and sorts the windows using aw-window<.

I tried just bypassing the sorting entirely by redefining ace-window's sorting:

(defun aw-window< (wnd1 wnd2) t)

...but ace-window has its own window ring, and uses that somehow when numbering the windows. So after switching, the order is different!

That said, it's easy enough to swap the row/column logic in aw-window<:

(defun aw-window< (wnd1 wnd2)
  "Return true if WND1 is less than WND2.
This is determined by their respective window coordinates.

This modification of what's in ace-window.el numbers the
windows in a row-major way: left to right, top down."
  (let* ((f1 (window-frame wnd1))
         (f2 (window-frame wnd2))
         (e1 (window-edges wnd1))
         (e2 (window-edges wnd2))
         (p1 (frame-position f1))
         (p2 (frame-position f2))
         (nl (or (null (car p1)) (null (car p2)))))
    (cond ((and (not nl) (< (car p1) (car p2)))
           (not aw-reverse-frame-list))
          ((and (not nl) (> (car p1) (car p2)))
          ;; You can read "car" below as "the upper left x-coordinate"
          ;; and "cadr" as "the upper left y-coordinate". The usage here
          ;; is swapped from ace-window.el to change column-major
          ;; ordering to row-major.
          ((< (cadr e1) (cadr e2))
          ((> (cadr e1) (cadr e2))
          ((< (car e1) (car e2))

...which is identical to the source code, except for exchanging the car and cadr usage.

I haven't fully figured out why the first approach -- using an always-true or always-nil predicate -- doesn't work, but it's easy enough to just evaluate the above. I'm sure there's a more elegant way to handle this override but this works. shrug

  • 1
    I think redefining aw-window< is the best you can do.
    – NickD
    Commented Mar 20, 2023 at 13:25
  • I suspect that the reason why always true or always false doesn't work is because the majority of sort implementations rely on the comparator operation being consistent between comparisons.
    – mtraceur
    Commented Sep 8, 2023 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.