[xmonad] Visual hints for XMonad actions

Mario Pastorelli pastorelli.mario at gmail.com
Sat Dec 15 00:21:10 CET 2012

Hi XMonad users,
I'm playing a little bit with XMonad and its primitives to see how the 
core works. One idea is to create a set of visible hints that the user 
can display when an action is taken. For example, when the user changes 
the workspace to the previous workspace, then a left arrow appears in 
the centre of the screen. Those hints are very similar to what happen on 
other WMs and personally very useful. With this idea in mind I started 
to think about requirements: they should be always visible (on top of 
the stack) such that the user can see them but they should be 
not-intrusive so that they don't disturb the work of the user. They 
should be removed automatically after sometime. One last thing, I would 
like to stick to the XMonad color configuration.
I started with the left arrow. I get the code idea from 
XMonad.Actions.GridSelect because it shows a grid of windows or 
workspace using XMonad draw primitives. I created the code below which 
draws a left arrow in the centre of the screen and set it in my 
configuration such that when I move the the prev workspace, the arrow is 
showed and then deleted (using ((modMask, xK_Left ), drawArrow xpConfig 
10 (Arrow 200 200) >> prevWS) as configuration in XMonad.hs).
Before I show the code, let me say that the code (almost) works and let 
me make my questions:
1) is the code correct or I'm doing it in a wrong way?
2) how to put the window on top of the stack such that it is always 
visible. For now, for some reason the arrow is not visible when the 
layout is MouseResizableTile (the window is under all the not-floating 
windows) but it is visible with ThreeCol and Full. That's a mistery for 
me and I can't make any progress on that
3) how to ignore the input such that it pass trough the created window
4) the way that I use to kill the window using thread is correct? Can I 
do something better?
5) an open question: is there any way to use composite such that the 
windows can be transparent? I don't think XMonad supports composite, 
that's why it's an open question, but I really would like to add it and 
obtain some of the effects available in WM like Compiz. It's more 
general than what I want to do, I really would like to see the 
transition between screens as in compiz.

Thank you,

data Arrow = Arrow { head_w :: Integer, head_h :: Integer }

drawArrow :: XPConfig -> Integer -> Arrow -> X ()
drawArrow conf span (Arrow { head_w = head_w, head_h = head_h }) =
     gets (screenRect . W.screenDetail . W.current . windowset) >>= \s ->
     let half_w = div head_w 2
         half_h = div head_h 2
         cx = div (fromIntegral $ rect_width s) 2
         cy = div (fromIntegral $ rect_height s) 2
         x0 = fromIntegral $ cx - half_w - span
         y0 = fromIntegral $ cy - half_h - span
         p1 = Point (fromIntegral span) (fromIntegral $ half_h)
         p2 = Point (fromIntegral head_w) (fromIntegral span)
         p3 = Point (fromIntegral head_w) (fromIntegral head_h) in
     withDisplay $ \dpy -> do
         let dflt = defaultScreen dpy
         let scr = defaultScreenOfDisplay dpy
         rootw <- asks theRoot
         win <- liftIO $ mkUnmanagedWindow dpy scr rootw x0 y0 
(fromInteger $ head_w + span)
(fromInteger $ head_h + span)
         liftIO $ mapWindow dpy win
         gc <- liftIO $ createGC dpy win
         bordergc <- liftIO $ createGC dpy win
         liftIO $ do
           Just fgcolor <- initColor dpy $ fgColor conf
           Just bgcolor <- initColor dpy $ bgColor conf
           Just bordercolor <- initColor dpy $ borderColor conf
           setForeground dpy gc bgcolor
           setBackground dpy gc bgcolor
           fillRectangle dpy win gc 0 0 (fromIntegral $ head_w + span) 
(fromIntegral $ head_h + span)
           setForeground dpy gc fgcolor
           setBackground dpy gc bgcolor
           setForeground dpy bordergc bordercolor
           fillPolygon dpy win gc [p1,p2,p3] convex coordModeOrigin
           freeGC dpy gc
           freeGC dpy bordergc

           -- kill the window
           forkIO $ do
               threadDelay(1 * 1000000)
               unmapWindow dpy win
               destroyWindow dpy win
               sync dpy False

           return ()

More information about the xmonad mailing list