Add ifWindow and ifWindows and simplify WindowGo

This patch adds ifWindow and ifWindows as helper functions to
X.A.WindowGo and removes some boilerplate by rewriting other functions
in terms of those. Also some minor simplifications.
This commit is contained in:
Daniel Schoepe 2009-06-24 23:17:11 +00:00
parent 0cb6ac2910
commit dce0b17420

View File

@ -28,13 +28,17 @@ module XMonad.Actions.WindowGo (
runOrRaiseMaster, runOrRaiseMaster,
raiseAndDo, raiseAndDo,
raiseMaster, raiseMaster,
ifWindows,
ifWindow,
raiseHook,
module XMonad.ManageHook module XMonad.ManageHook
) where ) where
import Control.Monad (filterM) import Control.Monad
import Data.Char (toLower) import Data.Char (toLower)
import Data.Monoid
import XMonad (Query(), X(), withWindowSet, runQuery, liftIO) import XMonad (Query(), X(), ManageHook, withWindowSet, runQuery, liftIO, ask)
import Graphics.X11 (Window) import Graphics.X11 (Window)
import XMonad.ManageHook import XMonad.ManageHook
import XMonad.Operations (windows) import XMonad.Operations (windows)
@ -60,6 +64,21 @@ appropriate one, or cover your bases by using instead something like
For detailed instructions on editing your key bindings, see For detailed instructions on editing your key bindings, see
"XMonad.Doc.Extending#Editing_key_bindings". -} "XMonad.Doc.Extending#Editing_key_bindings". -}
-- | If windows that satisfy the query exist, apply the supplied
-- function to them, otherwise run the action given as
-- second parameter.
ifWindows :: Query Bool -> ([Window] -> X ()) -> X () -> X ()
ifWindows qry f el = withWindowSet $ \wins -> do
matches <- filterM (runQuery qry) $ W.allWindows wins
case matches of
[] -> el
ws -> f ws
-- | The same as ifWindows, but applies a ManageHook to the first match
-- instead and discards the other matches
ifWindow :: Query Bool -> ManageHook -> X () -> X ()
ifWindow qry mh = ifWindows qry (windows . appEndo <=< runQuery mh . head)
-- | 'action' is an executable to be run via 'safeSpawnProg' (of "XMonad.Util.Run") if the Window cannot be found. -- | 'action' is an executable to be run via 'safeSpawnProg' (of "XMonad.Util.Run") if the Window cannot be found.
-- Presumably this executable is the same one that you were looking for. -- Presumably this executable is the same one that you were looking for.
runOrRaise :: String -> Query Bool -> X () runOrRaise :: String -> Query Bool -> X ()
@ -96,11 +115,11 @@ raise = raiseMaybe $ return ()
> , ((modm, xK_m), raiseMaybe (runInTerm "-title mutt" "mutt") (title =? "mutt")) > , ((modm, xK_m), raiseMaybe (runInTerm "-title mutt" "mutt") (title =? "mutt"))
-} -}
raiseMaybe :: X () -> Query Bool -> X () raiseMaybe :: X () -> Query Bool -> X ()
raiseMaybe f thatUserQuery = withWindowSet $ \s -> do raiseMaybe f qry = ifWindow qry raiseHook f
maybeResult <- filterM (runQuery thatUserQuery) (W.allWindows s)
case maybeResult of -- | A manage hook that raises the window.
[] -> f raiseHook :: ManageHook
(x:_) -> windows $ W.focusWindow x raiseHook = ask >>= doF . W.focusWindow
-- | See 'runOrRaise' and 'raiseNextMaybe'. Version that allows cycling through matches. -- | See 'runOrRaise' and 'raiseNextMaybe'. Version that allows cycling through matches.
runOrRaiseNext :: String -> Query Bool -> X () runOrRaiseNext :: String -> Query Bool -> X ()
@ -116,18 +135,14 @@ raiseNext = raiseNextMaybe $ return ()
query the next matching window is raised. If no matches are found query the next matching window is raised. If no matches are found
the function f is executed. the function f is executed.
-} -}
raiseNextMaybe :: X () -> Query Bool -> X () raiseNextMaybe :: X () -> Query Bool -> X ()
raiseNextMaybe f thatUserQuery = withWindowSet $ \s -> do raiseNextMaybe f qry = flip (ifWindows qry) f $ \ws -> do
ws <- filterM (runQuery thatUserQuery) (W.allWindows s) foc <- withWindowSet $ return . W.peek
case ws of case foc of
[] -> f Just w | w `elem` ws -> let (_:y:_) = dropWhile (/=w) $ cycle ws -- cannot fail to match
(x:_) -> let go (Just w) | (w `elem` ws) = next w $ cycle ws in windows $ W.focusWindow y
go _ = windows $ W.focusWindow x _ -> windows . W.focusWindow . head $ ws
in go $ W.peek s
where
next w (x:y:_) | x==w = windows $ W.focusWindow y
next w (_:xs) = next w xs
next _ _ = error "raiseNextMaybe: empty list"
-- | Given a function which gets us a String, we try to raise a window with that classname, -- | Given a function which gets us a String, we try to raise a window with that classname,
-- or we then interpret that String as a executable name. -- or we then interpret that String as a executable name.
@ -145,12 +160,8 @@ raiseEditor = raiseVar getEditor
otherwise, the first argument is called otherwise, the first argument is called
See 'raiseMaster' for an example. -} See 'raiseMaster' for an example. -}
raiseAndDo :: X () -> Query Bool -> (Window -> X ())-> X () raiseAndDo :: X () -> Query Bool -> (Window -> X ())-> X ()
raiseAndDo raisef thatUserQuery afterRaise = withWindowSet $ \s -> do raiseAndDo f qry after = ifWindow qry (afterRaise `mappend` raiseHook) f
maybeResult <- filterM (runQuery thatUserQuery) (W.allWindows s) where afterRaise = ask >>= (>> idHook) . liftX . after
case maybeResult of
[] -> raisef
(x:_) -> do windows $ W.focusWindow x
afterRaise x
{- | If a window matching the second arugment is found, the window is focused and the third argument is called; {- | If a window matching the second arugment is found, the window is focused and the third argument is called;
otherwise, the first argument is called. -} otherwise, the first argument is called. -}