/ root / pages / xmonad_status.html
You're using an old link! - Thankfully, you no longer need to specify a nonstandard port (8080) to access my site. You could've used the more standard: http://pbrisbin.com/pages/xmonad_status.html.
One of the hardest things for new XMonad users is setting up the status bars. This is mostly due to the myriad options available; here, I outline step-by-step how I do it.
Sat, 05 Dec 2009 18:50:44 -0500
One of the trickiest things for a new user of XMonad is adding a statusbar. This is mainly because xmonad's statusbar support is so transparent and extensible, that any documentation for setting it up could be completely different from any other. Do you want a dynamicLog? a customLog? xmobar? dzen? one bar? two?
Here I'll outline my method. Two separate dzen2 bars aligned to look like one
bar across the top of your screen. The left, fed by an xmonad dynamicLogWithPP
to show workspaces (with coloring and ugencyHooks), the current layout, and
the current window title. The right, fed by conky -c ~/.dzen_conkyrc
to show music, system stats and of course the time.
Many thanks go to moljac and lifeafter2am on the Arch forums. They offered their xmonad.hs's to me and helped get me setup this way.
Full desktop:
With an urgencyHook notification:

To achieve this, we set up a dynamicLog in xmonad.hs and adjust our main function to output to this bar and also spawn our right bar as fed by conky.
The following imports will need to be added to your xmonad.hs in order to get this working the way I'll describe:
import XMonad.Util.Run import XMonad.Hooks.DynamicLog import XMonad.Hooks.UrgencyHook import XMonad.Hooks.ManageDocks import System.IO
Your main function should look something like this:
-- Main main = do d <- spawnPipe myStatusBar -- the d here... spawn myOtherBar xmonad $ withUrgencyHook NoUrgencyHook $ defaultConfig { terminal = myTerminal , workspaces = myWorkspaces , borderWidth = myBorderWidth , normalBorderColor = myNormalBorderColor , focusedBorderColor = myFocusedBorderColor , layoutHook = myLayout , manageHook = myManageHook , keys = myKeys , logHook = myLogHook d -- ... must match the d here }
The portions relevant to this tutorial are spawnPipe myStatusBar which feeds xmonad's output to our first status bar (yet undefined), spawn myOtherBar which will launch our conky dzen (also yet undefined) and the logHook function which will determine what's outputted by xmonad.
d, myStatusBar, and myOtherBar are variable names that can be whatever you want, just be consistent when you reference them.
Your logHook will setup the output of workspaces, layouts, and titles to dzen2. You can determine formatting, padding, shortening, etc. Directly below this function is where I like to define the my*Bar variables just to keep it in the same area of my config.
Here's a commented version of myLogHook which, hopefully, is illustrative enough to not warrant further explanation.
-- Status Bars myLogHook h = dynamicLogWithPP $ defaultPP -- the h here... -- display current workspace as darkgrey on light grey (opposite of default colors) { ppCurrent = dzenColor "#303030" "#909090" . pad -- display other workspaces which contain windows as a brighter grey , ppHidden = dzenColor "#909090" "" . pad -- display other workspaces with no windows as a normal grey , ppHiddenNoWindows = dzenColor "#606060" "" . pad -- display the current layout as a brighter grey , ppLayout = dzenColor "#909090" "" . pad -- if a window on a hidden workspace needs my attention, wrap its workspace with bright red braces , ppUrgent = wrap (dzenColor "#ff0000" "" "{") (dzenColor "#ff0000" "" "}") . pad -- show the current window's title as a brighter grey and bracketed, also shorten if it goes over 40 characters , ppTitle = wrap "^fg(#909090)[ " " ]^fg()" . shorten 40 -- no separator between workspaces , ppWsSep = "" -- put a few spaces between each object , ppSep = " " , ppOutput = hPutStrLn h -- ... must match the h here } -- sets up dzen options for two bars displayed as one spanning my 1920 px wide monitor myStatusBar = "dzen2 -p -ta l -fn Verdana-8 -x 0 -y 0 -w 700 -h 15 -fg '#606060' -bg '#303030' -e 'onexit=ungrabmouse'" myOtherBar = "conky -c ~/.dzen_conkyrc | dzen2 -p -ta r -fn Verdana-8 -x 700 -y 0 -w 1220 -h 15 -fg '#606060' -bg '#303030' -e 'onexit=ungrabmouse'"
Lastly, you'll need to add two little things to make sure you leave a gap for the new statusbar:
-- add avoidStruts to your layoutHook like so myLayout = avoidStruts $ Tall ||| Wide ||| Full ... -- add manageDocks to your managehook myManageHook = composeAll [ className =? "Mplayer" --> doFloat , className =? "Zenity" --> doFloat ] <+> manageDocks
The above expects a 1920 px wide monitor, it expects an xft-capable dzen2,
and it expects a file at ~/.dzen_conkyrc to populate myOtherBar
(sample available here).
Also, the default xmonad --restart keybinding will leave dzen and conky zombie processes. My live xmonad.hs has a M-q keybinding to get around this; feel free to steal it.
Happy haskelling!
So I think I've come up with an interesting way to do this whole dzen thing. One that leverages the fact that our WM's config is written in our WM's language It involves defining a function that builds dzen command strings, then passing in some defined geometries based on monitor size, etc.
First step, setup a "theme config" in your xmonad.hs like so:
-- variables for use in makeDzen, and mylogHook myDzenFont = "Verdana-8" -- xft enabled dzen req'd conkyFile = "~/.dzen_conkyrc" -- populates the right status bar colorWhite = "#ffffff" -- white colorRed = "#ff0000" -- bright red colorGrey0 = "#303030" -- grey colorGrey1 = "#606060" -- light grey colorGrey2 = "#909090" -- lighter grey barHeight = 17 monitorWidth = 1920 -- two bars span this width leftBarWidth = 700 -- the right bar will span difference
Now you've got some named values to use in your other functions.
And here's a short function I wrote to accept dzen geometry and text alignment and return the dzen command string. By using the variables defined above, we can now do something like this:
-- custom function to build dzen commands makeDzen x y w h a = "dzen2 -p" ++ " -ta " ++ a ++ " -x " ++ show x ++ " -y " ++ show y ++ " -w " ++ show w ++ " -h " ++ show h ++ " -fn '" ++ myDzenFont ++ "'" ++ " -fg '" ++ colorGrey1 ++ "'" ++ " -bg '" ++ colorGrey0 ++ "' -e ''" -- define the bars myLeftBar = makeDzen 0 0 leftBarWidth barHeight "l" myRightBar = "conky -c " ++ conkyFile ++ " | " ++ makeDzen leftBarWidth 0 (monitorWidth - leftBarWidth) barHeight "r"
And we can even use the color configs in an updated version of myLogHook. Notice some other functions in the where clause:
-- LogHook myLogHook h = (dynamicLogWithPP $ defaultPP { ppCurrent = dzenColor colorGrey0 colorGrey2 . pad , ppHidden = dzenFG colorGrey2 . pad , ppHiddenNoWindows = dzenFG colorGrey1 . pad , ppLayout = dzenFG colorGrey1 . pad , ppUrgent = myWrap colorRed "{" "}" . pad , ppTitle = myWrap colorGrey2 "[ " " ]" . shorten 40 , ppWsSep = "" , ppSep = " " , ppOutput = hPutStrLn h }) >> updatePointer (Relative 0.95 0.95) where dzenFG c = dzenColor c "" myWrap c l r = wrap (dzenFG c l) (dzenFG c r)
Ain't haskell a great way to configure a WM?
Well, continuing with the above changes, I've taken this a bit further. I've been reading Real World Haskell lately and was looking for an outlet to try and make everything in that book a bit more relevant.
I realized I could define a data type to represent a Dzen. I could give it constructors like x offset, y offset, font, colors, etc. Then I read about writing a custom instance of Show which tells haskell how to print a String representation of this new data type.
Note - Some might say this overcomplicates a pretty straightforward task. I'm not touting it as some importable module that people should start using as a dzen solution in XMonad. I just find it a really interesting approach. You should probably just declare a simple string for your dzen commands and KISS. That said, I think my memory usage has actually gone down slightly since using this approach ;).
Here are my data and instance functions for my new Dzen type:
data TextAlign = LeftAlign | RightAlign | Centered instance Show TextAlign where show LeftAlign = "l" show RightAlign = "r" show Centered = "c" -- see /usr/share/doc/dzen2/README data DzenConf = DzenConf { x_position :: Int -- x position , y_position :: Int -- y position , width :: Int -- width , height :: Int -- line height , alignment :: TextAlign -- alignment of title window , font :: String -- font , fg_color :: String -- foreground color , bg_color :: String -- background color , exec :: String -- exec flags, ex: "onstart=lower" , input :: String -- stdin, ex: "conky -c ~/.dzen_conkyrc" , addargs :: [String] -- additional arguments, ex: ["-p", "-tw", "5"] } instance Show DzenConf where show d = unwords $ addstdin (input d) [ "dzen2" , "-fn", quote $ font d , "-fg", quote $ fg_color d , "-bg", quote $ bg_color d , "-ta", show $ alignment d , "-x" , show $ x_position d , "-y" , show $ y_position d , "-w" , show $ width d , "-h" , show $ height d , "-e" , quote $ exec d ] ++ addargs d where -- only add the "|" if stdin is defined addstdin s xs = if null s then xs else s:"|":xs quote s = "'" ++ s ++ "'"
I know... so wtf good is this anyway?
-- -- well, now you can do this: -- main = do spawn . show $ myRightBar d <- spawnPipe . show $ myLeftBar xmonad $ defaultConfig { ... , logHook = myLogHook d , ... } -- -- where the bars are defined like so: -- -- fully define the left bar myLeftBar :: DzenConf myLeftBar = DzenConf { x_position = 0 , y_position = 0 , width = leftBarWidth , height = barHeight , alignment = LeftAlign , font = myFont , fg_color = colorFG , bg_color = colorBG , exec = "onstart=lower" , input = [] , addargs = ["-p"] } -- only define what's different on the right bar myRightBar :: DzenConf myRightBar = myLeftBar { x_position = leftBarWidth , width = rightBarWidth , alignment = RightAlign , input = "conky -c ~/.dzen_conkyrc" }
All of this within our window manager's config file. Call me a nerd, but I think that's crazy.
pbrisbin dot com 2010
on Sat, 10 Jul 2010 12:50:09 -0400, nwt wrote:
on Sun, 11 Jul 2010 11:40:13 -0400, me wrote: