-----------------------------------------------------------------------------
-- |
-- Module       : XMonad.Hooks.ManageHelpers
-- Copyright    : (c) Lukas Mai
-- License      : BSD
--
-- Maintainer   : Lukas Mai <l.mai@web.de>
-- Stability    : unstable
-- Portability  : unportable
--
-- This module provides helper functions to be used in @manageHook@. Here's
-- how you might use this:
--
-- > import XMonad.Hooks.ManageHelpers
-- > main =
-- >     xmonad def{
-- >         ...
-- >         manageHook = composeOne [
-- >             isKDETrayWindow -?> doIgnore,
-- >             transience,
-- >             isFullscreen -?> doFullFloat,
-- >             resource =? "stalonetray" -?> doIgnore
-- >         ],
-- >         ...
-- >     }

module XMonad.Hooks.ManageHelpers (
    Side(..),
    composeOne,
    (-?>), (/=?), (<==?), (</=?), (-->>), (-?>>),
    currentWs,
    isInProperty,
    isKDETrayWindow,
    isFullscreen,
    isDialog,
    pid,
    transientTo,
    maybeToDefinite,
    MaybeManageHook,
    transience,
    transience',
    doRectFloat,
    doFullFloat,
    doCenterFloat,
    doSideFloat,
    doFloatAt,
    doFloatDep,
    doHideIgnore,
    Match,
) where

import XMonad
import qualified XMonad.StackSet as W
import XMonad.Util.WindowProperties (getProp32s)

import Data.Maybe
import Data.Monoid

import System.Posix (ProcessID)

-- | Denotes a side of a screen. @S@ stands for South, @NE@ for Northeast
-- etc. @C@ stands for Center.
data Side = SC | NC | CE | CW | SE | SW | NE | NW | C
    deriving (ReadPrec [Side]
ReadPrec Side
Int -> ReadS Side
ReadS [Side]
(Int -> ReadS Side)
-> ReadS [Side] -> ReadPrec Side -> ReadPrec [Side] -> Read Side
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Side]
$creadListPrec :: ReadPrec [Side]
readPrec :: ReadPrec Side
$creadPrec :: ReadPrec Side
readList :: ReadS [Side]
$creadList :: ReadS [Side]
readsPrec :: Int -> ReadS Side
$creadsPrec :: Int -> ReadS Side
Read, Int -> Side -> ShowS
[Side] -> ShowS
Side -> String
(Int -> Side -> ShowS)
-> (Side -> String) -> ([Side] -> ShowS) -> Show Side
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Side] -> ShowS
$cshowList :: [Side] -> ShowS
show :: Side -> String
$cshow :: Side -> String
showsPrec :: Int -> Side -> ShowS
$cshowsPrec :: Int -> Side -> ShowS
Show, Side -> Side -> Bool
(Side -> Side -> Bool) -> (Side -> Side -> Bool) -> Eq Side
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Side -> Side -> Bool
$c/= :: Side -> Side -> Bool
== :: Side -> Side -> Bool
$c== :: Side -> Side -> Bool
Eq)

-- | A ManageHook that may or may not have been executed; the outcome is embedded in the Maybe
type MaybeManageHook = Query (Maybe (Endo WindowSet))
-- | A grouping type, which can hold the outcome of a predicate Query.
-- This is analogous to group types in regular expressions.
-- TODO: create a better API for aggregating multiple Matches logically
data Match a = Match Bool a

-- | An alternative 'ManageHook' composer. Unlike 'composeAll' it stops as soon as
-- a candidate returns a 'Just' value, effectively running only the first match
-- (whereas 'composeAll' continues and executes all matching rules).
composeOne :: [MaybeManageHook] -> ManageHook
composeOne :: [MaybeManageHook] -> ManageHook
composeOne = (MaybeManageHook -> ManageHook -> ManageHook)
-> ManageHook -> [MaybeManageHook] -> ManageHook
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr MaybeManageHook -> ManageHook -> ManageHook
forall (m :: * -> *) b. Monad m => m (Maybe b) -> m b -> m b
try ManageHook
forall m. Monoid m => m
idHook
    where
    try :: m (Maybe b) -> m b -> m b
try m (Maybe b)
q m b
z = do
        Maybe b
x <- m (Maybe b)
q
        case Maybe b
x of
            Just b
h -> b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return b
h
            Maybe b
Nothing -> m b
z

infixr 0 -?>, -->>, -?>>

-- | q \/=? x. if the result of q equals x, return False
(/=?) :: Eq a => Query a -> a -> Query Bool
Query a
q /=? :: Query a -> a -> Query Bool
/=? a
x = (a -> Bool) -> Query a -> Query Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x) Query a
q

-- | q <==? x. if the result of q equals x, return True grouped with q
(<==?) :: Eq a => Query a -> a -> Query (Match a)
Query a
q <==? :: Query a -> a -> Query (Match a)
<==? a
x = (a -> Match a) -> Query a -> Query (Match a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> a -> Match a
forall a. Eq a => a -> a -> Match a
`eq` a
x) Query a
q
    where
    eq :: a -> a -> Match a
eq a
q' a
x' = Bool -> a -> Match a
forall a. Bool -> a -> Match a
Match (a
q' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x') a
q'

-- | q <\/=? x. if the result of q notequals x, return True grouped with q
(</=?) :: Eq a => Query a -> a -> Query (Match a)
Query a
q </=? :: Query a -> a -> Query (Match a)
</=? a
x = (a -> Match a) -> Query a -> Query (Match a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (a -> a -> Match a
forall a. Eq a => a -> a -> Match a
`neq` a
x) Query a
q
    where
    neq :: a -> a -> Match a
neq a
q' a
x' = Bool -> a -> Match a
forall a. Bool -> a -> Match a
Match (a
q' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x') a
q'

-- | A helper operator for use in 'composeOne'. It takes a condition and an action;
-- if the condition fails, it returns 'Nothing' from the 'Query' so 'composeOne' will
-- go on and try the next rule.
(-?>) :: Query Bool -> ManageHook -> MaybeManageHook
Query Bool
p -?> :: Query Bool -> ManageHook -> MaybeManageHook
-?> ManageHook
f = do
    Bool
x <- Query Bool
p
    if Bool
x then (Endo WindowSet -> Maybe (Endo WindowSet))
-> ManageHook -> MaybeManageHook
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Endo WindowSet -> Maybe (Endo WindowSet)
forall a. a -> Maybe a
Just ManageHook
f else Maybe (Endo WindowSet) -> MaybeManageHook
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Endo WindowSet)
forall a. Maybe a
Nothing

-- | A helper operator for use in 'composeAll'. It takes a condition and a function taking a grouped datum to action.  If 'p' is true, it executes the resulting action.
(-->>) :: Query (Match a) -> (a -> ManageHook) -> ManageHook
Query (Match a)
p -->> :: Query (Match a) -> (a -> ManageHook) -> ManageHook
-->> a -> ManageHook
f = do
    Match Bool
b a
m <- Query (Match a)
p
    if Bool
b then (a -> ManageHook
f a
m) else ManageHook
forall m. Monoid m => m
mempty

-- | A helper operator for use in 'composeOne'.  It takes a condition and a function taking a groupdatum to action.  If 'p' is true, it executes the resulting action.  If it fails, it returns 'Nothing' from the 'Query' so 'composeOne' will go on and try the next rule.
(-?>>) :: Query (Match a) -> (a -> ManageHook) -> MaybeManageHook
Query (Match a)
p -?>> :: Query (Match a) -> (a -> ManageHook) -> MaybeManageHook
-?>> a -> ManageHook
f = do
    Match Bool
b a
m <- Query (Match a)
p
    if Bool
b then (Endo WindowSet -> Maybe (Endo WindowSet))
-> ManageHook -> MaybeManageHook
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap  Endo WindowSet -> Maybe (Endo WindowSet)
forall a. a -> Maybe a
Just (a -> ManageHook
f a
m) else Maybe (Endo WindowSet) -> MaybeManageHook
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Endo WindowSet)
forall a. Maybe a
Nothing

-- | Return the current workspace
currentWs :: Query WorkspaceId
currentWs :: Query String
currentWs = X String -> Query String
forall a. X a -> Query a
liftX ((WindowSet -> X String) -> X String
forall a. (WindowSet -> X a) -> X a
withWindowSet ((WindowSet -> X String) -> X String)
-> (WindowSet -> X String) -> X String
forall a b. (a -> b) -> a -> b
$ String -> X String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> X String)
-> (WindowSet -> String) -> WindowSet -> X String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet -> String
forall i l a s sd. StackSet i l a s sd -> i
W.currentTag)

-- | A predicate to check whether a window is a KDE system tray icon.
isKDETrayWindow :: Query Bool
isKDETrayWindow :: Query Bool
isKDETrayWindow = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window -> (Window -> Query Bool) -> Query Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> X Bool -> Query Bool
forall a. X a -> Query a
liftX (X Bool -> Query Bool) -> X Bool -> Query Bool
forall a b. (a -> b) -> a -> b
$ do
    Maybe [CLong]
r <- String -> Window -> X (Maybe [CLong])
getProp32s String
"_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR" Window
w
    Bool -> X Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> X Bool) -> Bool -> X Bool
forall a b. (a -> b) -> a -> b
$ case Maybe [CLong]
r of
        Just [CLong
_] -> Bool
True
        Maybe [CLong]
_ -> Bool
False

-- | Helper to check if a window property contains certain value.
isInProperty :: String -> String -> Query Bool
isInProperty :: String -> String -> Query Bool
isInProperty String
p String
v = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window -> (Window -> Query Bool) -> Query Bool
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> X Bool -> Query Bool
forall a. X a -> Query a
liftX (X Bool -> Query Bool) -> X Bool -> Query Bool
forall a b. (a -> b) -> a -> b
$ do
    Window
va <- String -> X Window
getAtom String
v
    Maybe [CLong]
r <- String -> Window -> X (Maybe [CLong])
getProp32s String
p Window
w
    Bool -> X Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> X Bool) -> Bool -> X Bool
forall a b. (a -> b) -> a -> b
$ case Maybe [CLong]
r of
        Just [CLong]
xs -> Window -> CLong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Window
va CLong -> [CLong] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [CLong]
xs
        Maybe [CLong]
_ -> Bool
False

-- | A predicate to check whether a window wants to fill the whole screen.
-- See also 'doFullFloat'.
isFullscreen :: Query Bool
isFullscreen :: Query Bool
isFullscreen = String -> String -> Query Bool
isInProperty String
"_NET_WM_STATE" String
"_NET_WM_STATE_FULLSCREEN"

-- | A predicate to check whether a window is a dialog.
isDialog :: Query Bool
isDialog :: Query Bool
isDialog = String -> String -> Query Bool
isInProperty String
"_NET_WM_WINDOW_TYPE" String
"_NET_WM_WINDOW_TYPE_DIALOG"

pid :: Query (Maybe ProcessID)
pid :: Query (Maybe ProcessID)
pid = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window
-> (Window -> Query (Maybe ProcessID)) -> Query (Maybe ProcessID)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> X (Maybe ProcessID) -> Query (Maybe ProcessID)
forall a. X a -> Query a
liftX (X (Maybe ProcessID) -> Query (Maybe ProcessID))
-> X (Maybe ProcessID) -> Query (Maybe ProcessID)
forall a b. (a -> b) -> a -> b
$ do
    Maybe [CLong]
p <- String -> Window -> X (Maybe [CLong])
getProp32s String
"_NET_WM_PID" Window
w
    Maybe ProcessID -> X (Maybe ProcessID)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ProcessID -> X (Maybe ProcessID))
-> Maybe ProcessID -> X (Maybe ProcessID)
forall a b. (a -> b) -> a -> b
$ case Maybe [CLong]
p of
        Just [CLong
x] -> ProcessID -> Maybe ProcessID
forall a. a -> Maybe a
Just (CLong -> ProcessID
forall a b. (Integral a, Num b) => a -> b
fromIntegral CLong
x)
        Maybe [CLong]
_        -> Maybe ProcessID
forall a. Maybe a
Nothing

-- | A predicate to check whether a window is Transient.
-- It holds the result which might be the window it is transient to
-- or it might be 'Nothing'.
transientTo :: Query (Maybe Window)
transientTo :: Query (Maybe Window)
transientTo = do
    Window
w <- Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask
    Display
d <- (X Display -> Query Display
forall a. X a -> Query a
liftX (X Display -> Query Display)
-> ((XConf -> Display) -> X Display)
-> (XConf -> Display)
-> Query Display
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (XConf -> Display) -> X Display
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks) XConf -> Display
display
    IO (Maybe Window) -> Query (Maybe Window)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe Window) -> Query (Maybe Window))
-> IO (Maybe Window) -> Query (Maybe Window)
forall a b. (a -> b) -> a -> b
$ Display -> Window -> IO (Maybe Window)
getTransientForHint Display
d Window
w

-- | A convenience 'MaybeManageHook' that will check to see if a window
-- is transient, and then move it to its parent.
transience :: MaybeManageHook
transience :: MaybeManageHook
transience = Query (Maybe Window)
transientTo Query (Maybe Window)
-> Maybe Window -> Query (Match (Maybe Window))
forall a. Eq a => Query a -> a -> Query (Match a)
</=? Maybe Window
forall a. Maybe a
Nothing Query (Match (Maybe Window))
-> (Maybe Window -> ManageHook) -> MaybeManageHook
forall a. Query (Match a) -> (a -> ManageHook) -> MaybeManageHook
-?>> Maybe Window -> ManageHook
forall a s i l sd.
(Ord a, Eq s, Eq i) =>
Maybe a -> Query (Endo (StackSet i l a s sd))
move
    where
    move :: Maybe a -> Query (Endo (StackSet i l a s sd))
move Maybe a
mw = Query (Endo (StackSet i l a s sd))
-> (a -> Query (Endo (StackSet i l a s sd)))
-> Maybe a
-> Query (Endo (StackSet i l a s sd))
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Query (Endo (StackSet i l a s sd))
forall m. Monoid m => m
idHook ((StackSet i l a s sd -> StackSet i l a s sd)
-> Query (Endo (StackSet i l a s sd))
forall s. (s -> s) -> Query (Endo s)
doF ((StackSet i l a s sd -> StackSet i l a s sd)
 -> Query (Endo (StackSet i l a s sd)))
-> (a -> StackSet i l a s sd -> StackSet i l a s sd)
-> a
-> Query (Endo (StackSet i l a s sd))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> StackSet i l a s sd -> StackSet i l a s sd
forall a s i l sd.
(Ord a, Eq s, Eq i) =>
a -> StackSet i l a s sd -> StackSet i l a s sd
move') Maybe a
mw
    move' :: a -> StackSet i l a s sd -> StackSet i l a s sd
move' a
w StackSet i l a s sd
s = StackSet i l a s sd
-> (i -> StackSet i l a s sd) -> Maybe i -> StackSet i l a s sd
forall b a. b -> (a -> b) -> Maybe a -> b
maybe StackSet i l a s sd
s (i -> StackSet i l a s sd -> StackSet i l a s sd
forall a s i l sd.
(Ord a, Eq s, Eq i) =>
i -> StackSet i l a s sd -> StackSet i l a s sd
`W.shift` StackSet i l a s sd
s) (a -> StackSet i l a s sd -> Maybe i
forall a i l s sd. Eq a => a -> StackSet i l a s sd -> Maybe i
W.findTag a
w StackSet i l a s sd
s)

-- | 'transience' set to a 'ManageHook'
transience' :: ManageHook
transience' :: ManageHook
transience' = MaybeManageHook -> ManageHook
maybeToDefinite MaybeManageHook
transience

-- | converts 'MaybeManageHook's to 'ManageHook's
maybeToDefinite :: MaybeManageHook -> ManageHook
maybeToDefinite :: MaybeManageHook -> ManageHook
maybeToDefinite = (Maybe (Endo WindowSet) -> Endo WindowSet)
-> MaybeManageHook -> ManageHook
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Endo WindowSet -> Maybe (Endo WindowSet) -> Endo WindowSet
forall a. a -> Maybe a -> a
fromMaybe Endo WindowSet
forall m. Monoid m => m
mempty)


-- | Floats the new window in the given rectangle.
doRectFloat :: W.RationalRect  -- ^ The rectangle to float the window in. 0 to 1; x, y, w, h.
            -> ManageHook
doRectFloat :: RationalRect -> ManageHook
doRectFloat RationalRect
r = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window -> (Window -> ManageHook) -> ManageHook
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> (WindowSet -> WindowSet) -> ManageHook
forall s. (s -> s) -> Query (Endo s)
doF (Window -> RationalRect -> WindowSet -> WindowSet
forall a i l s sd.
Ord a =>
a -> RationalRect -> StackSet i l a s sd -> StackSet i l a s sd
W.float Window
w RationalRect
r)

-- | Floats the window and makes it use the whole screen. Equivalent to
-- @'doRectFloat' $ 'W.RationalRect' 0 0 1 1@.
doFullFloat :: ManageHook
doFullFloat :: ManageHook
doFullFloat = RationalRect -> ManageHook
doRectFloat (RationalRect -> ManageHook) -> RationalRect -> ManageHook
forall a b. (a -> b) -> a -> b
$ Rational -> Rational -> Rational -> Rational -> RationalRect
W.RationalRect Rational
0 Rational
0 Rational
1 Rational
1

-- | Floats a new window using a rectangle computed as a function of
--   the rectangle that it would have used by default.
doFloatDep :: (W.RationalRect -> W.RationalRect) -> ManageHook
doFloatDep :: (RationalRect -> RationalRect) -> ManageHook
doFloatDep RationalRect -> RationalRect
move = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window -> (Window -> ManageHook) -> ManageHook
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> (WindowSet -> WindowSet) -> ManageHook
forall s. (s -> s) -> Query (Endo s)
doF ((WindowSet -> WindowSet) -> ManageHook)
-> ((ScreenId, RationalRect) -> WindowSet -> WindowSet)
-> (ScreenId, RationalRect)
-> ManageHook
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Window -> RationalRect -> WindowSet -> WindowSet
forall a i l s sd.
Ord a =>
a -> RationalRect -> StackSet i l a s sd -> StackSet i l a s sd
W.float Window
w (RationalRect -> WindowSet -> WindowSet)
-> ((ScreenId, RationalRect) -> RationalRect)
-> (ScreenId, RationalRect)
-> WindowSet
-> WindowSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RationalRect -> RationalRect
move (RationalRect -> RationalRect)
-> ((ScreenId, RationalRect) -> RationalRect)
-> (ScreenId, RationalRect)
-> RationalRect
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ScreenId, RationalRect) -> RationalRect
forall a b. (a, b) -> b
snd ((ScreenId, RationalRect) -> ManageHook)
-> Query (ScreenId, RationalRect) -> ManageHook
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< X (ScreenId, RationalRect) -> Query (ScreenId, RationalRect)
forall a. X a -> Query a
liftX (Window -> X (ScreenId, RationalRect)
floatLocation Window
w)

-- | Floats a new window with its original size, and its top left
--   corner at a specific point on the screen (both coordinates should
--   be in the range 0 to 1).
doFloatAt :: Rational -> Rational -> ManageHook
doFloatAt :: Rational -> Rational -> ManageHook
doFloatAt Rational
x Rational
y = (RationalRect -> RationalRect) -> ManageHook
doFloatDep RationalRect -> RationalRect
move
  where
    move :: RationalRect -> RationalRect
move (W.RationalRect Rational
_ Rational
_ Rational
w Rational
h) = Rational -> Rational -> Rational -> Rational -> RationalRect
W.RationalRect Rational
x Rational
y Rational
w Rational
h

-- | Floats a new window with its original size on the specified side of a
-- screen
doSideFloat :: Side -> ManageHook
doSideFloat :: Side -> ManageHook
doSideFloat Side
side = (RationalRect -> RationalRect) -> ManageHook
doFloatDep RationalRect -> RationalRect
move
  where
    move :: RationalRect -> RationalRect
move (W.RationalRect Rational
_ Rational
_ Rational
w Rational
h) = Rational -> Rational -> Rational -> Rational -> RationalRect
W.RationalRect Rational
cx Rational
cy Rational
w Rational
h
      where cx :: Rational
cx =      if Side
side Side -> [Side] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Side
SC,Side
C ,Side
NC] then (Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
w)Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/Rational
2
                 else if Side
side Side -> [Side] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Side
SW,Side
CW,Side
NW] then Rational
0
                 else {- side `elem` [SE,CE,NE] -}   Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
w
            cy :: Rational
cy =      if Side
side Side -> [Side] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Side
CE,Side
C ,Side
CW] then (Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
h)Rational -> Rational -> Rational
forall a. Fractional a => a -> a -> a
/Rational
2
                 else if Side
side Side -> [Side] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Side
NE,Side
NC,Side
NW] then Rational
0
                 else {- side `elem` [SE,SC,SW] -}   Rational
1Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
-Rational
h

-- | Floats a new window with its original size, but centered.
doCenterFloat :: ManageHook
doCenterFloat :: ManageHook
doCenterFloat = Side -> ManageHook
doSideFloat Side
C

-- | Hides window and ignores it.
doHideIgnore :: ManageHook
doHideIgnore :: ManageHook
doHideIgnore = Query Window
forall r (m :: * -> *). MonadReader r m => m r
ask Query Window -> (Window -> ManageHook) -> ManageHook
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Window
w -> X () -> Query ()
forall a. X a -> Query a
liftX (Window -> X ()
hide Window
w) Query () -> ManageHook -> ManageHook
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (WindowSet -> WindowSet) -> ManageHook
forall s. (s -> s) -> Query (Endo s)
doF (Window -> WindowSet -> WindowSet
forall a i l s sd.
Ord a =>
a -> StackSet i l a s sd -> StackSet i l a s sd
W.delete Window
w)