xmonad ⋙ metacity (mod GNOME)

by Alexander Kojevnikov

xmonad is an elegantly minimalist and lightning fast window manager for X written in Haskell. I wanted to play with it for a long time: I’m using two 24″ monitors and so have to spend a fair bit of time re-sizing windows and moving them around. A tiling window manager like xmonad takes care of this; in addition you can control all aspects of window placement with the keyboard alone.

The good news is: xmonad plays really well with GNOME. You can keep your GNOME panels, themes, desktop backgrounds, etc – xmonad just replaces Metacity leaving everything else intact.

The bad news is: I should have tried it earlier.

A few notes about xmonad set up and usage:

  • Recommended way to set up xmonad with GNOME is to

    export WINDOW_MANAGER=xmonad
    

    before starting gnome-session, but it didn’t work for me. I tried every suggested place: ~/.gnomerc, ~/.xsession, ~/.profile, ~/.xinitrc; but none of them worked – GNOME always started with Metacity.

    What worked though is this:

    • Create a file in /usr/share/applications called xmonad.desktop:

      [Desktop Entry]
      Type=Application
      Encoding=UTF-8
      Name=Xmonad
      Exec=/usr/bin/xmonad
      NoDisplay=true
      X-GNOME-WMName=Xmonad
      X-GNOME-Bugzilla-Bugzilla=XMonad
      X-GNOME-Bugzilla-Product=xmonad
      X-GNOME-Bugzilla-Component=general
      X-GNOME-Autostart-Phase=WindowManager
      X-GNOME-Provides=windowmanager
      X-GNOME-Autostart-Notify=true
      
    • Change this GConf key from ‘metacity’ to ‘xmonad’:

      /desktop/gnome/session/required_components/windowmanager
      
  • On startup, xmonad doesn’t set the usual left-arrow cursor but inherits an ugly X cursor which looks like it was created in the eighties. To change it, add this line to your ~/.xinitrc file just before you start gnome-session:

    xsetroot -cursor_name left_ptr
    
  • You need to create a config file in ~/.xmonad called xmonad.hs and add this:

    import XMonad
    import XMonad.Config.Gnome
    
    main = xmonad gnomeConfig
    
  • That’s right, the config file is a Haskell program that starts xmonad, which means it’s extremely customisable. Let’s modify it a bit:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    import XMonad
    import XMonad.Config.Gnome
    
    main = do
      xmonad $ gnomeConfig
        { terminal    = "gnome-terminal"
        , modMask     = mod4Mask
        , focusFollowsMouse = False
        , borderWidth = 2
        }
    

    All keyboard short-cuts in xmonad are in the form Mod-X or Mod-Shift-X, where Mod is by default the Alt key. Line 7 tells xmonad to use the Win key – Alt is heavily used by GNOME applications.

  • When touch-typing, some shortcuts are painful to use, Win-Shift-6 probably being the worst. What I wanted is to replace the Mod part with another shortcut, a bit in the Emacs fashion, so that instead of Win-Shift-6 I would have for example a sequence of Ctrl-m and Shift-6.

    mauke on #xmonad was extremely helpful, he came up with this code:

    import XMonad
    import XMonad.Config.Gnome
    import XMonad.Actions.Submap
    
    import Control.Arrow
    import Data.Bits
    import qualified Data.Map as M
    
    main :: IO ()
    main = do
        xmonad $ gnomeConfig
             { terminal = "gnome-terminal"
             , focusFollowsMouse = False
             , borderWidth = 2
             , keys = addPrefix (controlMask, xK_m) (keys gnomeConfig)
             }
    
    addPrefix p ms conf =
        M.singleton p . submap $ M.mapKeys (first chopMod) (ms conf)
        where
        mod = modMask conf
        chopMod = (.&. complement mod)
    

    which worked as advertised. To re-load xmonad after you changed the config file just press Mod-q. It takes just a second to re-compile and leaves all open windows intact.

After using xmonad for 2 days I must say I’m a convert. The keyboard short-cuts feel very natural, it’s not difficult to see the influence of vi. Moving a window to another screen or to another workspace (did I mention workspaces are per screen, which is a really neat feature), switching between workspaces, switching windows, changing layouts, etc… is just a short-cut away.

And as a bonus point, I now have a good reason to become more familiar with Haskell – it’s a very nice language.