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.
What it looks like
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?
Imports and Main
This post assumes you’ve imported the required modules and you have a main function setup as shown:
-- imports
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Layout.IM
import XMonad.Layout.PerWorkspace
import qualified XMonad.StackSet as W
-- main
main = xmonad $ defaultConfig
{ terminal = myTerminal
, workspaces = myWorkspaces
, borderWidth = myBorderWidth
, normalBorderColor = myNormalBorderColor
, focusedBorderColor = myFocusedBorderColor
, layoutHook = myLayout -- all of our changes will take place in the myLayout
, manageHook = myManageHook -- and myManageHook definitions.
, keys = myKeys
} The Layout Hook
Here’s a simple layoutHook that adds the IM extension on a specific workspace and has the added bonus that you can cycle between all of your “standard” layouts in the space that’s not taken up by the roster.
Also, if your IM client isn’t open, the workspace will behave like any other.
-- Layouts
myLayout = avoidStruts $ onWorkspace "3-im" imLayout $ standardLayouts
where
-- numMasters, resizeIncr, splitRatio
tall = Tall 1 0.02 0.5
-- define the list of standardLayouts
standardLayouts = tall ||| Mirror tall ||| Full
-- notice withIM is acting on it
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 uses the withIM modifier.
This really highlights what XMonad brings as a WM, something you don’t get with most other tilers; because we are using haskell as the config language, we have all kinds of native tricks at our disposal. The reason the above works is that both (someLayout) and (someLayout ||| someOtherLayout ||| yetAnotherLayout) are valid as arguments to withIM due to their identical (existential) types. If the compiler allows it, we can be pretty sure it’ll behave as we intended.
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 if you plan on having your IM Chat windows tiled. I think that’s kind of ugly, so I choose to have any IM-related window besides the roster float by default. My manageHook takes care of that.
The Manage Hook
-- Manage hook
myManageHook = composeAll
[ -- whatever you might already have
, ...
, className =? "Gajim.py" --> doShift "3-chat" -- move all IM windows to IM workspace
, classNotRole ("Gajim.py", "roster") --> doFloat -- and float everything but the roster
, ...
]
where
classNotRole :: (String, String) -> Query Bool
classNotRole (c,r) = className =? c <&&> role /=? r
role = stringProperty "WM_WINDOW_ROLE"The truth is in the comments. This will move all IM windows to the IM workspace, and float anything that’s of the IM Class but not the roster’s Role.
You can use the commandline tool xprop to find out a window’s properties for use in these manageHooks.
Showing 3 comments:
Please log in to post a comment.