##### Personal tools

- Home
- Log in

##### Views

- Page
- Discussion
- View source
- History

# Xmonad/Config archive/John Goerzen's Configuration

### From HaskellWiki

< Xmonad | Config archive

I'm going to take you step-by-step through the process of configuring Xmonad, setting up a status bar with xmobar, setting up a tray with trayer, and making it all play nicely together. I use this exact configuration on everything from a 1024x600 Eee PC to a 1920x1200 24" workstation, and it works well on all of them.

I assume that you have read the About xmonad page as well as the xmonad guided tour already.

Before you begin, here is a screenshot of my desktop:

And here is a screenshot that points out what I'm talking about when I talk about the status bar and the tray:

## 1 Preliminaries

First you'll want to install xmonad. You can find instructions for that on xmonad.org. I'm going to assume xmonad 0.8 here.

This guide will work for any operating system. I happen to use Debian, so when I talk about installing software, I can give you Debian commands. But you can run xmonad all over the place; just substitute the appropriate commands for your system.

To install xmonad on Debian squeeze, you can just run:

`apt-get install xmonad libghc6-xmonad-contrib-dev libghc6-xmonad-dev dwm-tools`

For Debian wheezy (and recent above), run:

`apt-get install xmonad libghc-xmonad-contrib-dev libghc-xmonad-dev suckless-tools`

This installs xmonad itself, everything you need to configure it, and dwm-tools, which provides the Mod-P launching feature. If you're not on squeeze or wheezy, consult the xmonad download site -- note that there are etch binaries there, too. If you're downloading the etch binaries, you'll need the etch ghc6 and libghc6-*-dev*.deb binaries as well.

Set up xmonad in your .xsession as directed in the xmonad guided tour. You should have xmonad up and running before continuing.

## 2 Customizing xmonad

So the first thing you will want to do is customize xmonad.

Make a directory called ~/.xmonad, and in there, create a file named xmonad.hs. We'll start off with importing some of the utility modules we will use:

    import XMonad
    import XMonad.Hooks.DynamicLog
    import XMonad.Hooks.ManageDocks
    import XMonad.Util.Run(spawnPipe)
    import XMonad.Util.EZConfig(additionalKeys)
    import System.IO

Next, a basic configuration -- which is the same as the default -- is this:

    main = do
        xmonad $ defaultConfig

Over at the how to write a config file page -- which you should go read right now -- there are instructions for testing your config file. You should be able to save the above file, with the import lines plus the other two, and validate it with ghci, then press Mod-q to load it up. Another way to validate your xmonad.hs is to simply run `xmonad --recompile' in a terminal. You'll see errors if it's bad, and nothing if it's good.

Now how about something real? Replace the lines starting with main with:

    main = do
        xmonad $ defaultConfig
            { manageHook = manageDocks <+> manageHook defaultConfig
            , layoutHook = avoidStruts  $  layoutHook defaultConfig
            }

(Disclaimer: The author in reality does not use this 'comma first' style. However, since it is the style used in xmonad, xmonad-contrib and most all xmonad.hs files, he has kindly consented to allow your friendly wiki gardeners to convert the original Haskell from 'comma last' style. This should make copying pieces from other configs a bit easier.)

Also, ghc sees tab characters as eight spaces, so to prevent confusion ensure your editor produces eight space tabs or expands tabs to spaces when editing haskell files. XMonad convention is to always expand tabs and (mostly) indent by four space increments. Wikibooks has a great explanation of layout rules and indentation in haskell.

    -- real Goerzen config style
    main = do
      xmonad $ defaultConfig {
             manageHook = manageDocks <+> manageHook defaultConfig,
             layoutHook = avoidStruts  $  layoutHook defaultConfig
             }

What this does is take the default configuration (defaultConfig) and modify two aspects of it -- the manageHook and layoutHook. This particular recipe comes from the Xmonad FAQ and adds the support we need for a status bar and dock. For more ways to customize how and where windows are created, see the manageHook examples in XMonad General Configuration Tips.

I'll show my completed file at the end of this page, but for now let's add a few additional things in. By default, the Mod key is Alt, which is also used in Emacs. Sometimes Emacs and xmonad want to use the same key for different actions. Rather than remap every common key, I just change Mod to be the Windows key that's between Ctrl and Alt. So I add this line after layoutHook:

            , modMask = mod4Mask     -- Rebind Mod to the Windows key

The two dashes are a comment to the end of the line.

I also want to bind Mod-Shift-z to lock my screen with the screensaver, control-PrintScreen to take a snapshot of one window, and Printscreen to take a snapshot of the entire screen. My config file, starting with main, now looks like:

    main = do
        xmonad $ defaultConfig
            { manageHook = manageDocks <+> manageHook defaultConfig
            , layoutHook = avoidStruts  $  layoutHook defaultConfig
            , modMask = mod4Mask     -- Rebind Mod to the Windows key
            } `additionalKeys`
            [ ((mod4Mask .|. shiftMask, xK_z), spawn "xscreensaver-command -lock")
            , ((controlMask, xK_Print), spawn "sleep 0.2; scrot -s")
            , ((0, xK_Print), spawn "scrot")
            ]

You can find the names for keys in the haskell-X11 source package in the files Graphics/X11/Types.hsc and Graphics.X11.ExtraTypes.hsc.

To support screen capture, run apt-get install scrot. I will cover setting up the screensaver later in this tutorial.

Did you notice the 0 in the xK_Print line? The first part of the (0, xK_Print) tuple states what modifier keys (ctrl, alt, etc.) have to be held down for a pattern to match. For the PrintScreen key, we don't need anything to be held down, and the zero indicates that. The 'sleep' before running the 'scrot -s' command is to leave time for keys to be released before scrot -s tries to grab the keyboard.

## 3 Installing xmobar

Next, it's time to get started with xmobar, the status bar. You can use xmobar or dzen2. dzen2 probably has a few more features, but xmobar has lower resource utilization and is considerably easier and more reliable to set up. I found it does more than everything I need, and recommend it.

You can download xmobar from its homepage, linked to above. That page also has compilation and installation instructions. As of Sept. 17, 2008, I also maintain a Darcs tree. Most patches have been merged back as of xmobar 0.9.1, but a couple patches that shorten the number formatting are unapplied. You can download my tree and merge with the official tree with:

`darcs get http://darcs.complete.org/xmobar`

`darcs pull --repodir=xmobar --all http://code.haskell.org/xmobar`

If you darcs, apt-get install darcs or get it from your distribution or darcs.net.

## 4 Configuring xmonad to use xmobar

So, let's talk a little bit about how xmonad and xmobar fit together. You can piece them together in several different ways.

xmobar accepts input on its stdin, which it can display at an arbitrary position on the screen. It can also easily display other information. We want xmonad to send xmobar the stuff that I have at the upper left of my screenshot: information about available workspaces, current layout, and window manager.

We could, then, have xmonad write this stuff to its stdout, and write `xmonad | xmobar` in ~/.xsession. But it's more elegant and useful, in my opinion, to have xmonad fire up xmobar itself. This is pretty simple. Our main part of xmonad.hs will now look like:

        -- make sure to edit paths to xmobar and .xmobarrc to match your system.
        -- If xmobar is in your $PATH, and its config is in ~/.xmobarrc you don't
        -- need the xmobar path or config file, use: xmproc <- spawnPipe "xmobar"

    main = do
        xmproc <- spawnPipe "/path/to/xmobarbinary /home/jgoerzen/.xmobarrc"
        xmonad $ defaultConfig
            { manageHook = manageDocks <+> manageHook defaultConfig
            , layoutHook = avoidStruts  $  layoutHook defaultConfig
            , logHook = dynamicLogWithPP xmobarPP
                            { ppOutput = hPutStrLn xmproc
                            , ppTitle = xmobarColor "green" "" . shorten 50
                            }
            , modMask = mod4Mask     -- Rebind Mod to the Windows key
            } `additionalKeys`
            [ ((mod4Mask .|. shiftMask, xK_z), spawn "xscreensaver-command -lock")
            , ((controlMask, xK_Print), spawn "sleep 0.2; scrot -s")
            , ((0, xK_Print), spawn "scrot")
            ]

We've added a line right after "main". We fire up xmobar, and pass to it a command-line argument giving the path to its config file -- we will create this file in a minute. Then we also define a logHook. We tell xmonad that the way we get output to xmobar is with the command hPutStrLn xmproc -- this transmits the data via a pipe to xmobar. We also tell it that we want to put the first 50 characters of the window title in the title area.

When using hPutStrLn in your logHook make sure to add StdinReader to your xmobarrc commands and template as described below or xmonad may freeze when the unread pipe fills up.

Save this and test it with ghci.

## 5 Configuring xmobar

Now, before this will work, we have to configure xmobar. Here's a slightly simplified version of what I use, which is mostly similar to the sample you can find in the xmobar source package.

For xmobar-0.9 or earlier

    Config { font = "-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*"
           , bgColor = "black"
           , fgColor = "grey"
           , position = TopW L 90
           , commands = [ Run Weather "EGPF" ["-t"," <tempF>F","-L","64","-H","77","--normal","green","--high","red","--low","lightblue"] 36000
                        , Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
                        , Run Memory ["-t","Mem: <usedratio>%"] 10
                        , Run Swap [] 10
                        , Run Date "%a %b %_d %l:%M" "date" 10
                        , Run StdinReader
                        ]
           , sepChar = "%"
           , alignSep = "}{"
           , template = "%StdinReader% }{ %cpu% | %memory% * %swap%    <fc=#ee9a00>%date%</fc> | %EGPF%"
           }

Note: With 0.9 < xmobar-version <= 0.9.2 , you will need to add a lowerOnStart line just below position:

    Config { font = "-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*"
           , bgColor = "black"
           , fgColor = "grey"
           , position = TopW L 90
           , lowerOnStart = True
           ....<snip>

Note: With xmobar-version > 0.9.2 , any fields you leave out will be replaced by defaults, and the order doesn't matter.

First, I set the font to use for my bar, as well as the colors. The position options are documented well on the xmobar home page. This says to put my bar in the upper left of the screen, and make it consume 90% of the width of the screen.

In the
commands
list you, well, define commands. The commands are the pieces that generate the content that is available to display, which will later be combined together in the template. I define a weather widget, a CPU widget, memory and swap widgets, a clock, and of course the data from xmonad via the StdinReader.

The template then combines them together. Stuff to be left-justified goes before the } character, things to be centered after it, and things to be right justified after {. I have nothing centered so there is nothing in between them.

Warning: even though the config file uses Haskell syntax, it doesn't accept comments, (and in versions earlier than 0.9.3 doesn't allow you to change the field order, or drop fields.) This is because older versions of xmobar use
reads
to parse the config file.

Save that to ~/.xmobarrc. Now you should be able to press Mod-q and have xmonad load up xmobar, and have it work. (Note: until you add the trayer command to your .xinitrc, as described below, to fill up the other 10% of the screen width, and restart X Windows, your windows may cover the xmobar status bar.)

Replace both occurrences of EGPF with your choice of ICAO weather stations. There is a list of ICAO station codes maintained at ucar.edu. You can of course monitor more than one if you like, see the xmobar home page for more details.

### 5.1 Adding Keyboard LED Indication

My 9.1" Eee doesn't have capslock or numlock lights. Before xmonad, I had an applet to do that, but that's not very efficient now. If you want this, read this section, otherwise skip it.

You'll need two pieces of software for this to work:

1) xmobar >= 0.9.1

2) My ledmon tool, which you can obtain with:

`git clone git://git.complete.org/ledmon`

Or download from its gitweb page.

The CommandReader plugin will be used, which will cause xmobar to fork off ledmon. I compiled ledmon and put the binary in ~/.xmonad/ledmon, then modified my ~/.xmobarrc to look like this:

    Config { font = "-*-Fixed-Bold-R-Normal-*-13-*-*-*-*-*-*-*"
           , bgColor = "black"
           , fgColor = "grey"
           , position = TopW L 90
           , commands = [ Run Weather "EGPF" ["-t"," <tempF>F","-L","64","-H","77","--normal","green","--high","red","--low","lightblue"] 36000
                        , Run Cpu ["-L","3","-H","50","--normal","green","--high","red"] 10
                        , Run Memory ["-t","Mem: <usedratio>%"] 10
                        , Run Swap [] 10
                        , Run Date "%a %b %_d %l:%M" "date" 10
                        , Run StdinReader
                        , Run CommandReader "/home/jgoerzen/.xmonad/ledmon" "LED"
                        ]
           , sepChar = "%"
           , alignSep = "}{"
           , template = "%StdinReader% }{ <fc=#ffff00>%LED%</fc> %cpu% | %memory% * %swap%    <fc=#ee9a00>%date%</fc> | %EGPF%"
           }

That's all there is to it.

(for newer versions than xmobar-0.9, add lowerOnStart)

## 6 Configuring Related Utilities

So now you've got a status bar and xmonad. We still need a few more things: a screensaver, a tray for your apps that have tray icons, a way to set your desktop background, and the like.

For this, we will need a few pieces of software.

`apt-get install trayer xscreensaver`

If you want the Gajim instant messenger client, a battery meter, and a network applet, also:

`apt-get install gajim nm-applet gnome-power-manager`

First, configure xscreensaver how you like it with the xscreensaver-demo command. Now, we will set these things up in ~/.xsession. Your .xsession may wind up looking like this:

    #!/bin/bash

    # Load resources

    xrdb -merge .Xresources

    # Set up an icon tray

    trayer --edge top --align right --SetDockType true --SetPartialStrut true \
     --expand true --width 10 --transparent true --tint 0x191970 --height 12 &

    # Set the background color<

    xsetroot -solid midnightblue

    # Fire up apps

    gajim &

    xscreensaver -no-splash &

    if [ -x /usr/bin/nm-applet ] ; then
       nm-applet --sm-disable &
    fi

    if [ -x /usr/bin/gnome-power-manager ] ; then
       sleep 3
       gnome-power-manager &
    fi

    exec xmonad

This uses xsetroot to set my background color. It can also use images; see its manpage for more.

Then we fire up trayer, the icon tray. The options tell it to go on the top right, with a default width of 10% of the screen (to nicely match up with the status bar, which we set to a width of 90% of the screen). We give it a color and a height.

Then we fire up gajim, the screensaver daemon, and if installed, the network manager applet and the power manager.

Finally, we start xmonad.

Mission accomplished!

## 7 Final Touches

There may be some programs that you don't want xmonad to tile. The classic example is Gimp. It pops up all sorts of new windows all the time, and they work best at defined sizes. It makes sense for xmonad to ignore them. Over at the general tips page, there are suggestions on how to accomplish this. The xmonad FAQ has instructions on using xprop to find the class (or other properties) of your window. In the following example if it doesn't work as is, replace Gimp with the class name of your particular install, such as Gimp-2.X or whatever it happens to be. Also note that manageHook runs when windows are created, so you will have to restart the program to be managed if you're dialing in the correct className.

We are going to compose a list like so:

    myManageHook = composeAll
        [ className =? "Gimp"      --> doFloat]

I also don't want xmonad to tile the VNC viewer, because I want to manage its size myself. Very well; I can add it:

    myManageHook = composeAll
        [ className =? "Gimp"      --> doFloat
        , className =? "Vncviewer" --> doFloat
        ]

Now, we tie that in with what we're already doing for the manageHook, so our manageHook bit of main looks like:

        xmonad $ defaultConfig
            { manageHook = manageDocks <+> myManageHook
                            <+> manageHook defaultConfig

The full ~/.xmonad/xmonad.hs now looks like this:

    import XMonad
    import XMonad.Hooks.DynamicLog
    import XMonad.Hooks.ManageDocks
    import XMonad.Util.Run(spawnPipe)
    import XMonad.Util.EZConfig(additionalKeys)
    import System.IO

    myManageHook = composeAll
        [ className =? "Gimp"      --> doFloat
        , className =? "Vncviewer" --> doFloat
        ]

    main = do
        xmproc <- spawnPipe "/path/to/xmobarbinary /home/jgoerzen/.xmobarrc"
        xmonad $ defaultConfig
            { manageHook = manageDocks <+> myManageHook -- make sure to include myManageHook definition from above
                            <+> manageHook defaultConfig
            , layoutHook = avoidStruts  $  layoutHook defaultConfig
            , logHook = dynamicLogWithPP xmobarPP
                            { ppOutput = hPutStrLn xmproc
                            , ppTitle = xmobarColor "green" "" . shorten 50
                            }
            , modMask = mod4Mask     -- Rebind Mod to the Windows key
            } `additionalKeys`
            [ ((mod4Mask .|. shiftMask, xK_z), spawn "xscreensaver-command -lock")
            , ((controlMask, xK_Print), spawn "sleep 0.2; scrot -s")
            , ((0, xK_Print), spawn "scrot")
            ]

## 8 Tips on daily use

Here are a few things that occurred to me as I was learning xmonad.

### 8.1 Minimizing Windows

xmonad doesn't currently have a "minimize" feature. So I've designated workspace 9 for this purpose. When I want to hide a window, I Mod-Shift-9 it. That makes it go away. When I want it back, it's Mod-9, the Mod-j or Mod-k to select it, then Mod-Shift-1 Mod-1 or whatnot to zip it back and go back. It works surprisingly well.

### 8.2 Use of workspaces

I used to use KDE, and I used workspaces there too. But with the ability to so easily zip windows around to different workspaces, and to instantaneously change between them using only the keyboard, it's a lot easier to use.

Also, I find myself not wanting to have quite as many windows open on a given desktop at once. I generally have desktop 1 be for shells, 2 for email/IM, 3 for web, and 9 for music/minimized stuff. But I'm just learning this so far, and may find a better way. Don't hesitate to try different ways of organizing and use what works for you.

## 9 Trouble?

Check ~/.xsession-errors first.

Also, #xmonad on irc.freenode.net is very friendly and helpful. Ask questions and wait in channel for a while, eventually someone will answer if they have something helpful to say. Sometimes in 10 minutes, sometimes in 10 hours.

Retrieved from "https://wiki.haskell.org/index.php?title=Xmonad/Config_archive/John_Goerzen%27s_Configuration&oldid=41805"
Category:

- XMonad configuration

##### Tools

- What links here
- Related changes
- Special pages
- Printable version
- Permanent link