Trying xmonad

For nearly a year now, the cool Haskell folks that procrastinate hang around on Reddit have been boasting about their new and shiny window manager, xmonad. I’ve always wanted to try it, but I always found something less productive to do instead, like playing Dr Mario.

Well, this weekend was the weekend that I gave xmonad a whirl. As far as window managers go, I’m a pretty conservative guy. When I started using Linux back in 2000, I used Window Maker for about a year. After that, I switched to Blackbox, and have been using *box wm’s since then. I went from Blackbox to Fluxbox to Openbox. Thankfully, they all behaved pretty much exactly the same, so it was easy to switch from one to the next. I’ve had the same background image for 4 years and the same Openbox theme for 3 years. If xmonad is gonna get me to switch, it’s gonna have to be pirate awesome (ninjas suck!)


The installation of xmonad is pretty easy if you have GHC and the proper extensions installed. I only needed to install the latest version of the X11 bindings. Installing xmonad is as easy as runhaskell Setup.hs configure && runhaskell Setup.hs build && runhaskell Setup.hs install. Installing the xmonad-contrib package is equally easy.

Using xmonad

I’ve never used a tiling window manager, and at first, I thought it was a little weird. The window manager says where your windows will appear and what size they’ll be. This takes some time getting used to, I’m not even sure I’m comfortable with it, but I’m trying. The tutorial on the official website was a great way to get started. I quickly got comfortable launching a bunch of urxvt windows, so I went and configured xmonad!

Configuring xmonad

Configuration of xmonad is done by modifying a Haskell script, ~/.xmonad/xmonad.hs. I started by changing some key sequences, which is very easy to do. The documentation says that after you are done, you save the file and you try to open xmonad.hs in GHCi. If you get no error, you can reload the window manager (with mod-q, more on that in a bit) and the changes will automagically appear. Now, how cool is that? A way to check your configuration file. Openbox uses an XML file, and there’s no way to know if you screwed something without trying the configuration. And if you decide not to check your configuration in GHCi and just reload xmonad, what happens? You get an xmessage window telling you there’s an error in your configuration file.

Like I said earlier, mod-q restarts xmonad with your current configuration. Now, it doesn’t restart as you would except. The screen doesn’t even flicker. The new configuration just happens. I don’t know the exact mechanism, but I can tell you that the command-line to do that is pretty long: the entire window manager state is passed as an argument to xmonad when it restarts. ps(1) will show you exactly how long.

One thing to be aware of with mod-q is that by default, it assumes that xmonad is in your PATH. If it isn’t, you will need to put the complete path in xmonad.hs.

-- Restart xmonad
, ((modMask              , xK_q     ),
      broadcastMessage ReleaseResources >> restart "/home/vince/usr/bin/xmonad" True)

Floating layer

Some applications don’t work well in a tiled window manager. For example, The Gimp, MPlayer, Pidgin, etc. are better used as floating windows. Fortunately, xmonad is prepared for those: you can float any window you want, and you can even set windows to be automatically floated in your xmonad.hs configuration. Those floating windows are always above the tiled windows, they can be moved around with mod-button1 (the mouse left button) and resized with mod-button3 (the right button.) Note that only the bottom right corner is used for resizing, so you can’t resize to the left, you will need to move your application to the left and then resize it to the right.


Xmonad has a lot of nice third-party modules. All of them are pretty well documented and for those I tried, work as expected. Using those modules is usually just a matter of importing them in xmonad.hs and binding a key sequence to an action they export.

dzen and dmenu

Xmonad follows the general UNIX philosophy of doing one thing and doing it well. It xmonad’s case, that is laying out windows. Xmonad lets other application do tasks it shouldn’t be doing. For example, instead of having its own launcher, the default xmonad configuration has shortcuts for dmenu and gmrun. Also, instead of having its own status bar code, xmonad users can use dzen or xmobar. With the help of a plugin, DynamicLog, you can control what appears on those bars (by piping information to dzen or xmobar.)


A lot of programmers think that “if it’s not C or C++, it’s slow and memory hungry.” That is, of course, a myth, but one that seems to cling with way too many smart programmers. Xmonad is neither slow, nor memory hungry. The system loads in less than a second, and memory usage stays low. You definitely don’t need 32 GB of memory to be able to use it.

Documentation and community

Both are great! The #xmonad IRC channel on Freenode has nearly 100 users, and every time I asked for help, I got a fast, courteous and correct answer (and if you can’t get an answer, keep asking, dons will eventually wake up and answer you. dons++)

The documentation for xmonad is much longer than its code, something rarely heard of in the open source community. There’s a tutorial for users, a tutorial for developers, a tutorial for extension developers, every third-party module has documentation, the entire source code is commented, etc. It’s hard not to find what you are looking for.

Features that are missing

So far, I really like xmonad, I will try it for about a week to see if it can displace Openbox. One thing that I like to do in Openbox is to start a movie in MPlayer and set the window to be displayed on all workspaces, always on top. Xmonad doesn’t seem to have an easy way to toggle a “display on all workspaces” action, but since anyone can code a plugin, I see this as something that I should resolve. There’s also another action that I want to look into, making it possible to disable the border (the red line that indicates the current active window) on a per-window basis.

About these ads

9 thoughts on “Trying xmonad

  1. @John

    For the case of xmonad, a hosted configuration will simply cause xmonad to use defaults, and keep running, rather than preventing the X session from running. No X overrides should be necessary — you’ll just get a warning that there were problems in the config file.

  2. here’s some code that will give you the “sticky” feature (toggle all workspaces)

    –put these at the top
    import XMonad.Actions.CopyWindow
    import qualified XMonad.StackSet as W

    – put this in the keybindings list
    – mod-a copy to all
    – mod-shift-a remove from all but current
    , ((modMask, xK_a ), sequence_ $ [windows $ copy i | i <- XMonad.workspaces conf])
    , ((modMask .|. shiftMask, xK_a ), windows $ kill8 )

    – This is a top-level function
    kill8 ss | Just w <- W.peek ss = (W.insertUp w) $ W.delete w ss
    | otherwise = ss

  3. O man, just try pekwm. I was sitting on xmonad for a long period of time ( because actually I am in love with haskell staff). But pekwm it is realy great minimalistik wm. And the stick option is out of box.

  4. I know this is a bit late (really late… I read this post a year ago and that was late), but here’s a couple of tips: there are some great overlapping layout algorithms. I really like circle and “maginify” (in xmonad-contrib); also, to get rid of the border (I’m not fond of the border in general, and especially the awful red) you can put borderWidth=0 in your call to xmonad. i.e.
    main = do { … , borderWidth=0, … }

  5. Pingback: California Website Design

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s