/ root / pages / im-layout.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/im-layout.html.
A How-to on setting up a layout in XMonad devoted to an IM client. Using one of the best contrib modules, IMLayout.
Sat, 05 Dec 2009 18:50:44 -0500
One of my favorite modules from xmonad-contrib is the IM layout. It's a tiling algorithm designed to handle your roster and chat windows in the best way possible. Here I'm going to outline how I set this up in my xmonad.hs.
Personally, I want my roster tiled in its own properly sized location on one side, and all other IM related windows floating. I also want any of those IM windows to automatically be pushed to the IM workspace.
Here we can see that my roster is fit in its own little tile on the left, sized properly. The rest of the screen is tiled as a grid of whatever other applications I open. My chat window is always floating.
So, how would you set this up?
This setup is achieved by using the withIM extension of the Grid Layout. So at the top of our xmonad.hs we have to import a few things:
import XMonad.Hooks.ManageDocks import XMonad.Layout.Grid import XMonad.Layout.IM import XMonad.Layout.PerWorkspace
Your xmonad.hs should already have a main function that looks something like this:
-- Main main = do d <- spawnPipe myStatusBar 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 }
As long as you're calling a layoutHook function via the line layoutHook
= myLayout or similar, we're good to go. In that myLayout function is
where we'll add the IM support.
Check out my status bar
how-to for info on those urgencyHook and spawn
lines used to achieve the dzen status bar you see in my shots.
Here's a simple layoutHook using withIM:
-- Layouts myLayout = avoidStruts $ onWorkspace "3-im" imLayout $ Tall ||| Wide ||| Full where imLayout = withIM (1/10) (Role "roster") Grid
Now, there's a few things going on here so let me break it down.
The first line defines the layoutHook itself (myLayout). The $ symbol in haskell just takes whatever's on the right of it and passes it through whatever's on the left, think of it kind of as a filter. So let's start on the right and work back.
First is a list of the layouts I'll want available on each workspace seperated by |||. That list is passed through the onWorkspace filter, this simply sets it up so that the workspace named "3-im" always has that imLayout (which I've still yet to define). All of that is then passed through the avoidStruts filter which makes xmonad avoid putting windows overtop of my dzen status bar. (onWorkspace and avoidStruts are nice, but not explicitly needed to get this imLayout working).
Now below all that, is the where section. I'm declaring imLayout as the Grid Layout with windows of role "roster" placed in the IM tile of size 1%10 or 1/10th the width of my screen. Simple right?
Now you should have a nice IM layout setup, go ahead and M-q, then head to workspace 3 (or whatever) and fire up your IM client
Feel free to stop here, but know that xmonad is still tiling all your dialogs and chat windows. I think that just looks ugly. I prefer anything IM related to be floating; if you feel the same, your manageHook is the way to do it.
The following will be needed in your imports to use some of the things defined in this manageHook:
import qualified XMonad.StackSet as W
And here's my manageHook:
-- Window Management myManageHook = composeAll [ resource =? "desktop_window" --> doIgnore , className =? "Navigator" --> doShift "2-web" , className =? "Gajim.py" --> doShift "3-im" -- send gajim to 3-im , (className =? "Gajim.py" <&&> role =? "roster") --> (ask >>= doF . W.sink) -- and tile the roster , className =? "Gajim.py" --> doFloat -- but float all others , className =? "MPlayer" --> doFloat , className =? "Zenity" --> doFloat , (className =? "Navigator" <&&> resource =? "Dialog") --> doFloat ] <+> manageDocks where role = stringProperty "WM_WINDOW_ROLE"
Holy hell, what's all that?
Three lines apply to to the class "Gajim.py", my IM client, and manageHooks take top down precedence. So what we're saying is this: send all windows of class "Gajim.py" to "3-im", if it's also of role "roster" tile it (the layoutHook will put it in the right place), otherwise float it. Simple and effective.
Note the where section on the bottom. Just like in the layoutHook, we use a term in the function (role) and define it below. This keeps the meat of the function nice and clean.
A window's Class and Role can be determined by a program called xprop, simply run it and click on the window.
Protip: alias xp='xprop | grep "WM_WINDOW_ROLE\|WM_CLASS"'
The above is simply an attempt to share what I've learned in setting up xmonad. It's not how to do it, it's how I do it. I'm no xmonad or haskell developer, so if I've made an error or used the wrong term or metaphor for something, I'm sorry. Send an email to anything at pbrisbin dot com.
My full xmonad.hs can be found here (though it changes daily) and xmonad.org has complete documentation for anything xmonad related.
I found an awesome haskell trick to make this IM layout even more useful:
-- two layouts with the same modifier layoutModifier layoutOne ||| layoutModifier layoutTwo -- can be factored out, like high-school algebra layoutModifier (layoutOne ||| layoutTwo)
This means we can adjust our layout hook to something like this (a simplified version of my live layout hook):
-- Layouts myLayout = avoidStruts $ onWorkspace "3-im" imLayout $ standardLayouts where standardLayouts = Tall ||| Wide ||| Full -- notice withIM is acting on standardLayouts: imLayout = withIM (1/10) (Role "roster") (standardLayouts)
I've defined the function standardLayouts, which we'll use on all workspaces. Then for "3-im", I define imLayout which is the withIM modifier like before, but now it's operating not on just Grid but on all standardLayouts. Now we can tile our roster in that nice 1/10th slot and cycle through all of our standard layouts in the other 9/10ths of the workspace, and the im roster stays untouched, I think that's awesome.
This really highlights what XMonad brings as a WM, something you don't get with any other tilers; because we are using haskell as the config language, we have all of these native tricks at our disposal. And most importantly, it can handle these kinds of 'hacks' without any decrease in speed or stability, mainly because it's not a 'hack' at all, it's haskell.
pbrisbin dot com 2010
on Tue, 20 Jul 2010 14:41:14 -0400, m wrote:
on Thu, 22 Jul 2010 17:50:32 -0400, me wrote:
on Fri, 23 Jul 2010 14:04:10 -0400, m wrote: