M-x all-things-emacs

Quick Tip: Easier Window Switching in Emacs

May 1st, 2008 by Rob Christie · 21 Comments

I ran across this thread on easier window switching within emacs using the windmove-xxx commands on gnu.emacs.help a few days ago. It’s always nice to find out about commands I didn’t know about… kinda like C-x M-c M-butterfly. I have always used C-x o and C-x b to move between windows and buffers, but my work monitor is large enough to allow me to split my frame into four windows. Using C-x o to move around has been somewhat of an annoyance. The windmove commands allow you to move up, down, left, and right between windows using a prefix key and the arrows on your keyboard. I have added the following to my .emacs:

(windmove-default-keybindings 'meta)

If you invoke the command without an argument then shift is used as the prefix. I also had to place this below the turning on of pc-selection-mode because it also sets the M-up, M-down, M-left, and M-right keys.

Tags: quick · tips

21 responses so far ↓

  • 1 Luke Hoersten // May 1, 2008 at 7:23 pm

    I was unable to get this to work on Mac OS X. I’m going to try Ubuntu when I get home. Any hints for Mac OS X? I’m new to it.

  • 2 Knusper // May 1, 2008 at 8:22 pm

    Ah… Nice trick… :)

  • 3 Rob Christie // May 1, 2008 at 9:36 pm

    @Luke – I am using carbon emacs on Mac OS X. What version are you using?

  • 4 Seung-Cheol Jung // May 2, 2008 at 1:19 am

    It works perfectly for me on the zenitani’s carbon emacs.

  • 5 Jia // May 6, 2008 at 12:48 pm

    This is a nice one. Thanks a lot.

  • 6 Andy Norris // May 6, 2008 at 6:20 pm

    I’m an Emacs heretic, and defined a whole mess of CUA-style bindings (C-o for find-file, C-s for save-buffer, etc.), so my arrow keys are spoken for with things like M-left as backward-word.

    But I’ve found C-n for other-window and C-b for switch-to-buffer to be quite nice in my 3 window setup.

  • 7 Michael // May 6, 2008 at 8:46 pm

    Works like a champ in Aquamacs

  • 8 Cheezwizard // May 8, 2008 at 10:49 pm

    Does this work in XEMACS

  • 9 Ustun // May 10, 2008 at 11:40 am

    brilliant!

  • 10 Prashanth // May 20, 2008 at 8:45 am

    Great tip ! I tried the (windmove-default-keybindings ‘meta) and works fine on my Powerbook with 10.4.5 and CarbonEmacs

  • 11 piyo // May 23, 2008 at 3:57 pm

    windmove is great stuff. This is just my personal preference, but I bind the movement to a first-person shooting game like “WASD” key layout: C-l {C-e, C-s, C-d, C-f}. (Yes, C-l is a prefix key for me.) This helps me on those remoted ssh sessions to linux emacs. (well, okay, Meta/Alt Arrow-Key seems to be going through, but Control or Shift Arrow-Key doesn’t).

    If you use GNU screen, you can also do this directional window movement tip (e.g. ‘bind “^d” focus down’).

    Coming back to emacs: I use winner-mode in combination with windmove to give me more control with the windows. winner-mode is like a “browser back button” for your ever-changing windows configurations.

  • 12 Alex V. Koval // Jun 12, 2008 at 6:57 am

    In my Linux, I bind keys the following way:
    Alt+Up = previous frame
    Alt+Down = next frame
    Ctrl+Shift+Right = next file
    Ctrl+Shift+Left = prev file
    Ctrl+Shift+Up = next file (including special buffers *)
    Ctrl+Shift+Down = prev special file
    Ctrl+Tab = buffer switch

    The idea is that this way you can easily go next/prev file without need to ‘cycle’.

    My exact emacs config can be found here:
    http://public.halogen-dg.com/browser/alex-emacs-settings/dotemacs-alex-common.el

  • 13 l30 // Sep 12, 2008 at 3:04 pm

    That one was very nice.. I was about to give up.
    tks!

  • 14 Harris // Sep 17, 2008 at 5:45 am

    Works well, Thanks!

  • 15 antonios // Oct 8, 2008 at 1:39 pm

    This was very helpful! Thanks!

  • 16 boycer // Nov 15, 2008 at 2:06 pm

    windmove does not work on XEmacs without some help. First, be sure and get an older version of windmove.el that does not call the function ‘window-inside-edges’. I downloaded windmove.el Version: 0.93 (beta) from here:

    http://hovav.net/elisp/windmove-0.93.el

    Next, you need to put some code in your init.el file that sits in the folder .xemacs/ (found in your home directory on *nix machines). The first line just loads the windmove code. After that is code was written by Hovav Shacham, the author of windmove.el, so that windmove will work on XEmacs:

    ;;; This is a hack written by Hovav Shacham, author of the windmove package, so that 
    ;;; windmove will work in xemacs
    ;;;--- begin hack ---
     
    ;; simulate `window-edges' using `window-pixel-edges'; from
    ;; Nix , based on tapestry.el.
    (defun window-edges (&optional window)
      (let ((edges (window-pixel-edges window))
            tmp)
        (setq tmp edges)
        (setcar tmp (/ (car tmp) (face-width 'default)))
        (setq tmp (cdr tmp))
        (setcar tmp (/ (car tmp) (face-height 'default)))
        (setq tmp (cdr tmp))
        (setcar tmp (/ (car tmp) (face-width 'default)))
        (setq tmp (cdr tmp))
        (setcar tmp (/ (car tmp) (face-height 'default)))
        edges))
     
    ;; simulate `window-at' with `walk-windows'
    (defun window-at (x y &optional frame)
      (let ((f (if (null frame)
                   (selected-frame)
                 frame)))
        (let ((guess-wind nil))
          (walk-windows (function (lambda (w)
                                    (let ((w-edges (window-edges w)))
                                      (if (and (eq f (window-frame w))
                                               ( (nth 2 w-edges) x)
                                               ( (nth 3 w-edges) y))
                                          (setq guess-wind w)))))
                        t                   ; walk minibuffers
                        t)                  ; walk all frames
          guess-wind)))
     
    ;; redo `windmove-coordinates-of-position' without compute-motion
    (defun walk-screen-lines (lines goal)
      (cond
       ((> (window-point) goal) (1- lines))
       ((= (window-point) goal) lines)
       (t (vertical-motion 1)
          (walk-screen-lines (1+ lines) goal))))
    (defun windmove-coordinates-of-position (pos &optional window)
      (let* ((w (if (null window)
                    (selected-window)
                  window))
             (b (window-buffer w)))
        (save-selected-window
          (select-window w)
          (save-excursion
            (let* ((y (progn (goto-char (window-start))
                             (walk-screen-lines 0 pos)))
                   (x (- (progn (goto-char pos)
                                (current-column))
                         (progn (goto-char (window-start))
                                (vertical-motion y)
                                (current-column)))))
              (cons x y))))))            
     
    ;; for some reason, XEmacs is more conservative in reporting `frame-width'
    ;; and `frame-height'; we apparently need to get rid of the 1- in each.
    (defun windmove-frame-edges (window)
      (let ((frame (if window
                       (window-frame window)
                     (selected-frame))))
        (let ((x-min 0)
              (y-min 0)
              (x-max (frame-width frame))
              (y-max (frame-height frame)))
          (list x-min y-min x-max y-max))))
     
    ;;;--- end hack --- 
     
    Now, its good to set windmove's default key binding at XEmacs startup by adding the following like of code to the init.el file:
     
    ;;;Use shift-arrows to move from window to window
    (windmove-default-keybindings)

    good luck -rdb

  • 17 E Jones // Jan 7, 2009 at 9:06 pm

    This:
    (windmove-default-keybindings ‘meta)

    works great in standard windowed emacs, but it doesn’t work in console emacs (i.e. ‘emacs -nw’). To make it work in console mode, I have to use:

    (global-set-key [(alt left)]  'windmove-left)
    (global-set-key [(alt up)]    'windmove-up)
    (global-set-key [(alt right)] 'windmove-right)
    (global-set-key [(alt down)]  'windmove-down)

    But this doesn’t work in standard (windowed) emacs. Does anyone know a good way to switch configuration based on whether I’m running emacs in non-windowed mode or not?

  • 18 E Jones // Jan 7, 2009 at 10:55 pm

    To answer my own question – here’s how to get it to work in X or console mode:

    (if window-system
        (windmove-default-keybindings 'meta)
      (progn
        (global-set-key [(alt left)]  'windmove-left)
        (global-set-key [(alt up)]    'windmove-up)
        (global-set-key [(alt right)] 'windmove-right)
        (global-set-key [(alt down)]  'windmove-down)))
  • 19 Erik Iverson // Jan 21, 2009 at 7:10 pm

    As a side comment, I took a look at what commands I use most often using command-frequency.el over a few weeks’ time. I then looked at the default keybindings for C- and found that I never used C-t (among other single letter keybindings).

    Therefore, I bound the other-window function (C-x o) to C-t, and haven’t looked back. It’s easy to get to any window just by holding down Control and hitting ‘t’ until I get there. I will try this out to see if I like it better though.

    Thanks.

  • 20 vinz // Jun 7, 2009 at 9:59 pm

    Hey,
    thank you so much E Jones ! that’s really powerfull, and that’s exactly what I was looking for.
    Looking forward to learning new tips like this.
    Thanks

  • 21 Elliot // Jun 12, 2013 at 11:10 am

    Thanks for this…still useful years later…