aboutsummaryrefslogblamecommitdiffstats
path: root/XMonad/Hooks/XPropManage.hs
blob: 1e4b135911a50171fda6ca02b75148cfd28242fb (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13

                                                                             
                                          









                                                                             
                                 






                                                      


                                      
 



                               
                                



                                                                         
  
                                    




















                                                                                                               
                                                                                                       










                                                                                      





                                                                   







                                                                                                 


                                                                            




                                                
-----------------------------------------------------------------------------
-- |
-- Module       : XMonad.Hooks.XPropManage
-- Copyright    : (c) Karsten Schoelzel <kuser@gmx.de>
-- License      : BSD
--
-- Maintainer   : Karsten Schoelzel <kuser@gmx.de>
-- Stability    : unstable
-- Portability  : unportable
--
-- A ManageHook matching on XProperties.
-----------------------------------------------------------------------------

module XMonad.Hooks.XPropManage (
                 -- * Usage
                 -- $usage
                 xPropManageHook, XPropMatch, pmX, pmP
                 ) where

import Data.Char (chr)
import Data.List (concat)
import Data.Monoid (mconcat, Endo(..))
    
import Control.Monad.Reader

import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras

import XMonad
import XMonad.ManageHook ((-->))

-- $usage
-- 
-- Add something like the following lines to Config.hs to use this module
--
-- > import XMonad.Hooks.XPropManage
-- 
-- > manageHook = xPropManageHook xPropMatches 
-- >
-- > xPropMatches :: [XPropMatch]
-- > xPropMatches = [ ([ (wM_CLASS, any ("gimp"==)))], (\w -> float w >> return (W.shift "2")))
-- >                , ([ (wM_COMMAND, any ("screen" ==)), (wM_CLASS, any ("xterm" ==))], pmX (addTag "screen"))
-- >                , ([ (wM_NAME, any ("Iceweasel" `isInfixOf`))], pmP (W.shift "3"))
-- >                ]
--
-- Properties known to work: wM_CLASS, wM_NAME, wM_COMMAND
--
-- A XPropMatch consists of a list of conditions and function telling what to do.
--
-- The list entries are pairs of an XProperty to match on (like wM_CLASS, wM_NAME)^1,
-- and an function which matches onto the value of the property (represented as a List
-- of Strings).
--
-- If a match succeeds the function is called immediately, can perform any action and then return
-- a function to apply in 'windows' (see Operations.hs). So if the action does only work on the
-- WindowSet use just 'pmP function'.
--
-- \*1 You can get the available properties of an application with the xprop utility. STRING properties
-- should work fine. Others might not work.
--

type XPropMatch = ([(Atom, [String] -> Bool)], (Window -> X (WindowSet -> WindowSet)))

pmX :: (Window -> X ()) -> Window -> X (WindowSet -> WindowSet)
pmX f w = f w >> return id

pmP :: (WindowSet -> WindowSet) -> Window -> X (WindowSet -> WindowSet)
pmP f _ = return f

xPropManageHook :: [XPropMatch] -> ManageHook
xPropManageHook tms = mconcat $ map propToHook tms
    where
      propToHook (ms, f) = liftM and (mapM mkQuery ms) --> mkHook f
      mkQuery (a, tf)    = fmap tf (getQuery a)
      mkHook func        = ask >>= Query . lift . fmap Endo . func 

getProp :: Display -> Window -> Atom -> X ([String])
getProp d w p = do
    prop <- io $ catch (getTextProperty d w p >>= wcTextPropertyToTextList d) (\_ -> return [[]])
    let filt q | q == wM_COMMAND = concat . map splitAtNull
               | otherwise       = id
    return (filt p prop)

getQuery ::  Atom -> Query [String]
getQuery p = ask >>= \w ->  Query . lift $ withDisplay $ \d -> getProp d w p

splitAtNull :: String -> [String]
splitAtNull s = case dropWhile (== (chr 0)) s of
    "" -> []
    s' -> w : splitAtNull s''
          where (w, s'') = break (== (chr 0)) s'