mirror of
https://github.com/xmonad/xmonad-contrib.git
synced 2025-05-18 19:10:21 -07:00
All hints are applied in one single commit, as a commit per hint would result in 80+ separate commits—tihs is really just too much noise. Related: https://github.com/xmonad/xmonad-contrib/issues/537
89 lines
3.2 KiB
Haskell
89 lines
3.2 KiB
Haskell
{-# LANGUAGE ScopedTypeVariables #-}
|
|
-----------------------------------------------------------------------------
|
|
-- |
|
|
-- 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 Control.Exception as E
|
|
import Control.Monad.Trans (lift)
|
|
|
|
import XMonad
|
|
import XMonad.Prelude (Endo (..), chr)
|
|
|
|
-- $usage
|
|
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
|
|
--
|
|
-- > import XMonad.Hooks.XPropManage
|
|
-- > import qualified XMonad.StackSet as W
|
|
-- > import XMonad.Actions.TagWindows
|
|
-- > import Data.List
|
|
--
|
|
-- > 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) = fmap 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 $ E.catch (getTextProperty d w p >>= wcTextPropertyToTextList d) (\(_ :: IOException) -> return [[]])
|
|
let filt q | q == wM_COMMAND = concatMap 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'
|