----------------------------------------------------------------------------- -- | -- Module : XMonad.Util.WindowProperties -- Copyright : (c) Roman Cheplyaka -- License : BSD-style (see LICENSE) -- -- Maintainer : Roman Cheplyaka -- Stability : unstable -- Portability : unportable -- -- EDSL for specifying window properties; various utilities related to window -- properties. -- ----------------------------------------------------------------------------- module XMonad.Util.WindowProperties ( -- * EDSL for window properties -- $edsl Property(..), hasProperty, focusedHasProperty, allWithProperty, propertyToQuery, -- * Helper functions -- $helpers getProp32, getProp32s) where import XMonad import qualified XMonad.StackSet as W import Foreign.C.Types (CLong) import Control.Monad -- $edsl -- Allows to specify window properties, such as title, classname or -- resource, and to check them. -- -- In contrast to ManageHook properties, these are instances of Show and Read, -- so they can be used in layout definitions etc. For example usage see "XMonad.Layout.IM" -- | Most of the property constructors are quite self-explaining. data Property = Title String | ClassName String | Resource String | Role String -- ^ WM_WINDOW_ROLE property | Machine String -- ^ WM_CLIENT_MACHINE property | And Property Property | Or Property Property | Not Property | Const Bool deriving (Read, Show) infixr 9 `And` infixr 8 `Or` -- | Does given window have this property? hasProperty :: Property -> Window -> X Bool hasProperty p w = runQuery (propertyToQuery p) w -- | Does the focused window have this property? focusedHasProperty :: Property -> X Bool focusedHasProperty p = do ws <- gets windowset let ms = W.stack $ W.workspace $ W.current ws case ms of Just s -> hasProperty p $ W.focus s Nothing -> return False -- | Find all existing windows with specified property allWithProperty :: Property -> X [Window] allWithProperty prop = withDisplay $ \dpy -> do rootw <- asks theRoot (_,_,wins) <- io $ queryTree dpy rootw hasProperty prop `filterM` wins -- | Convert property to 'Query' 'Bool' (see "XMonad.ManageHook") propertyToQuery :: Property -> Query Bool propertyToQuery (Title s) = title =? s propertyToQuery (Resource s) = resource =? s propertyToQuery (ClassName s) = className =? s propertyToQuery (Role s) = stringProperty "WM_WINDOW_ROLE" =? s propertyToQuery (Machine s) = stringProperty "WM_CLIENT_MACHINE" =? s propertyToQuery (And p1 p2) = propertyToQuery p1 <&&> propertyToQuery p2 propertyToQuery (Or p1 p2) = propertyToQuery p1 <||> propertyToQuery p2 propertyToQuery (Not p) = not `fmap` propertyToQuery p propertyToQuery (Const b) = return b -- $helpers -- | Get a window property from atom getProp32 :: Atom -> Window -> X (Maybe [CLong]) getProp32 a w = withDisplay $ \dpy -> io $ getWindowProperty32 dpy a w -- | Get a window property from string getProp32s :: String -> Window -> X (Maybe [CLong]) getProp32s str w = do { a <- getAtom str; getProp32 a w }