xmonad logo

      xmonad

      overview

Introduction

xmonad is a tiling window manager for X11. It is inspired directly by the dwm (and indirectly, wmii) window manager, and, to a lesser extent, Ion. This document covers the installation and configuration of xmonad, from a slightly technical perspective. For its features and use, see the guided tour.

Xmonad provides an almost complete reimplementation of dwm's functionality, with the following differences (as of June 2007):

  • Full Xinerama support, for multihead displays
  • Per-workspace tiling algorithms
  • True fullscreen tiling
  • External status bars
  • Layout mirroring
  • State preservation during restarts
  • Written in a high level language
  • Codebase 1/3 the size of dwm, 1/5 the size of wmii.
  • Standard library of contributed extensions
  • Designed for easier, external extension

The dwm/wmii/xmonad genre of window managers are notably different to Ion, in general being smaller, faster and simpler, with an emphasis on dynamic retiling. Xmonad can be distinguished from ion by its:

  • Per-screen floating layer
  • Dynamic tiling
  • Less flexible window arrangment
  • External status bar programs
  • Codebase 1/40 the size of ion
  • Written in a high level language
  • Simpler configuration
  • Configuration and extension in Haskell, not lua
  • Compilation-and-restart for configuration

And, briefly, in contrast to the ratpoison/stumpwm family:

  • Automated ("dynamic") window tiling, as they're created (not manual splitting)
  • Less flexible window arrangment
  • Compilation-and-restart for dynamic extension (stumpwm uses lisp dynamically, ratpoison isn't dynamically extensible)
  • Much smaller code base
Community and information

There's an active community of developers and users around xmonad. The best places to join in, to find out more about xmonad, are:

Compilation

Your operating system distribution may have binary packages for xmonad (hopefully), or at least its dependancies. However, if it doesn't, or if you ever need to configure it, you'll want to get at, and compile the source. Configuration via compilation is pretty easy, as is building it in the first place. Let's walk through the process of installing xmonad 0.2 from source.

Get a Haskell compiler

The first thing to do is ensure you have a recent version of ghc, the Haskell compiler we use. It runs on dozens of platform and architecture combinations, and should be available as a package for your distro. The best version to use, as of June 2007, is GHC 6.6 or 6.6.1. You can find what version you have with:

    $ ghc --version
    The Glorious Glasgow Haskell Compilation System, version 6.6

Make sure you have the core Haskell libraries

Once you've got GHC, you'll need to just double check it was installed with the core Haskell libraries:

You can check if you have these standard libraries with:

    $ ghc-pkg list

Which should list Cabal, mtl and unix, amongst other things. If these libraries aren't available, you'll need to install them from Hackage.

Install the X11 and X11-extras (Xinerama) bindings

The following applies only if your system doesn't come with packages for xmonad. If it does, you should probably use those. If it doesn't, you will need to build the other dependent packages (don't worry, its trivial).

To call into X11, and to use Xinerama, from Haskell, xmonad uses foreign bindings to the C libraries. They are provided by two packages:

You need to build and install these if they aren't provided by your package system. The process of building all Haskell packages is identical. We will illustrate how to build X11 and X11-extras, but the same applies for other libraries, and xmonad itself:

    $ wget http://hackage.haskell.org/packages/archive/X11/1.2.2/X11-1.2.2.tar.gz
    $ tar xzf X11-1.2.2.tar.gz 
    $ cd X11-1.2.2
    $ runhaskell Setup.hs configure --prefix=$HOME
    $ runhaskell Setup.hs build
    $ runhaskell Setup.hs install --user
    Reading package info from ".installed-pkg-config" ... done.
    Saving old package config file... done.
    Writing new package config file... done.

And you've built the X11 bindings. Now do the same for X11-extras (Xinerama support):

    $ wget http://hackage.haskell.org/packages/archive/X11-extras/0.2/X11-extras-0.2.tar.gz
    $ tar xzf X11-extras-0.2.tar.gz
    $ runhaskell Setup.lhs configure --prefix=$HOME
    ...
    checking X11/extensions/Xinerama.h usability... yes
    checking X11/extensions/Xinerama.h presence... yes
    checking for X11/extensions/Xinerama.h... yes
    ...
    $ runhaskell Setup.lhs build
    $ runhaskell Setup.lhs install --user
    ...
    Registering X11-extras-0.2...  /home/dons/bin/ghc-pkg update .installed-pkg-config
    Reading package info from ".installed-pkg-config" ... done.
    Saving old package config file... done.
    Writing new package config file... done.

And all dependencies are in place. Now we can build xmonad.

Build xmonad

xmonad is just another cabalised package. You can grab the stable branch from hackage.haskell.org, here. Build as for other cabal packages:

    $ wget http://hackage.haskell.org/packages/archive/xmonad/0.2/xmonad-0.2.tar.gz
    $ tar xzf xmonad-0.2.tar.gz
    $ runhaskell Setup.lhs configure --prefix=$HOME
    $ runhaskell Setup.lhs build
    $ runhaskell Setup.lhs install --user

And that's it. Compiled, and ready to go.

Grab dmenu and dzen

Extra programs that make life with xmonad a lot easier: dmenu and dzen. dmenu provides a simple popup menu for launching programs, dzen provides customisable status bars. You can get them here:

We'll assume you've got dmenu and dzen installed, in the following sections.

Starting xmonad

The simplest way to start xmonad is to modify your .xsession or .xinitrc and add the line:

    $HOME/bin/xmonad

as the last line of your file, commenting out any previous window manager. Now, when you log in to X, xmonad will start, (by default in tall tiling mode, with no status bar), and you'll be presented with an empty screen:

From here, and assuming you can find the mod1 modifier key (usually 'alt'), you can launch clients and access the rest of the window manager's features. The basic key bindings are:

mod-shift-return launch xterm
mod-p launch dmenu
mod-space cycle through available layout algorithms
mod-c kill a client window
mod-j move focus to the next window on the screen (also mod-tab)
mod-k move focus to the previous window
mod-return swap current window, with window in master pane
mod-shift-j swap current window with its next neighbour
mod-shift-k swap current window with its previous neighbour
mod-h shrink the size of the master pane
mod-l grow the size of the master pane
mod-comma move clients into the master pane
mod-period move clients out of the master pane
mod-q dynamically reload xmonad, with a new configuration
mod-shift-q quit xmonad
mod-1 .. 9 move to workspace ("virtual desktop"/"window group") number 'n'
mod-shift- 1 .. 9 move current client to workspace number 'n'
mod- w,e,r move to Xinerama screens 1, 2 or 3.

To learn more about how to use these bindings to achieve your desired workspace configuration, see The Guided Tour. An example of a fully set up workspace, with status bars:

xmonad natively supports Xinerama, allowing several physical screens to show separate workspaces. You may run different status bars, and different layouts on each screen, and jump between them dynamically.

Dmenu

If you installed dmenu, you can use it now to launch programs, with mod-p. It will appear as a menu at the top of the screen. Type in the initial letters of a program, and hit return, the program should then launch.

Dzen

dzen is a simple popup status bar program, which reads text from standard input, and displays it in a nice X window. It can be used as a flexible status bar in xmonad. A simple way to use it, is to write a shell script which prints some text you want to use, to standard output. Then to pipe that text into dzen.

For example, the following script prints the time in various cities, the cpu clock, the system load, and batter life, on an openbsd machine, to stdout:

    #!/bin/sh
    while true ; do
        au=`date +"%H.%M %a %b %d"`
        uk=`TZ=GMT date +"UK %H.%M"`
        us=`TZ=America/New_York date +"NY %H.%M"`
        ca=`TZ=America/Los_Angeles date +"SF %H.%M"`
        hw=`/sbin/sysctl hw.setperf | sed "s/.*=//" | perl -anle 'print (0.6 + ($F[0]) / 100)'`
        ut=`uptime | sed 's/.*://; s/,//g'`
        bt=`/usr/sbin/apm | sed -n 's/.*: \([^ ]*\).*$/\1/;2p;4p' | xargs printf "apm %s%%, AC %s\n"`
        printf "%s | %s | %s | %s | %s Ghz | %s |%s\n" "$au" "$uk" "$us" "$ca" "$hw" "$bt" "$ut"
        sleep 60
    done 

You can then launch dzen at start up, with this as input:

    # .xsession

    status | dzen2 -ta r -fg '#a8a3f7' -bg '#3f3c6d' \
                -fn '-xos4-terminus-medium-r-normal--16-160-72-72-c-80-iso8859-1' &

    urxvt &
    $HOME/bin/xmonad

Normally, xmonad will attempt to use the entire screen to render windows. This interferes with a status bar. To support a status bar, xmonad leaves a `gap', specified in the Config file. For the above font, dzen needs an 18 pixel gap at the top of the screen. This is specified in the xmonad configuration file as:

    defaultGaps :: [(Int,Int,Int,Int)]
    defaultGaps = [(18,0,0,0)]

Which sets aside space for 18 pixel high status bars on physical screen 1. When started, xmonad and dzen together look like:

Tiling and Layout

xmonad supports, by default, 3 layout algorithms. Actually, it supports 2, fullscreen and tall mode, the 3rd, wide mode, is a logical mirror of tall mode, and is computed from it.

Tall mode

Wide mode

Full screen

Configuration

Configuration and extension of xmonad are done by editing and recompiling the file Config.hs. For example, to change the window border colour and size, we'd edit Config.hs to use the lines:

    focusedBorderColor = "#5fbf77"
    borderWidth = 3

We then recompile and reinstall xmonad into the $PATH, which will compile your configuration changes into the xmonad binary.

    $ runhaskell Setup.lhs build
    $ rm `which xmonad` 
    $ runhaskell Setup.lhs install --user
    Installing: /home/dons/lib/xmonad-0.2/ghc-6.6 & /home/dons/bin xmonad-0.2...
    copy /usr/obj/cabal/xmonad/xmonad to /home/dons/bin/xmonad

To load the configuration changes, type mod-q, which dynamically reloads xmonad, including the state of the old version. Changes should be reflected immediately.

Layout algorithms themselves are simple Haskell functions, and may be written directly in Config.hs. You can also define other Haskell modules, and import them. This is a good way to write larger extensions. xmonad comes with a library of such extensions.

Happy hacking, and may your X days be more productive!