{-# LANGUAGE LambdaCase #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Util.ExclusiveScratchpads
-- Description :  Named scratchpads that can be mutually exclusive.
-- Copyright   :  Bruce Forte (2017)
-- License     :  BSD-style (see LICENSE)
--
-- Maintainer  :  Bruce Forte
-- Stability   :  unstable
-- Portability :  unportable
--
-- Named scratchpads that can be mutually exclusive.
--
-----------------------------------------------------------------------------

module XMonad.Util.ExclusiveScratchpads
  {-# DEPRECATED "Use the exclusive scratchpad functionality of \"XMonad.Util.NamedScratchpad\" insead." #-}
  (
  -- * Usage
  -- $usage
  mkXScratchpads,
  xScratchpadsManageHook,
  -- * Keyboard related
  scratchpadAction,
  hideAll,
  resetExclusiveSp,
  -- * Mouse related
  setNoexclusive,
  resizeNoexclusive,
  floatMoveNoexclusive,
  -- * Types
  ExclusiveScratchpad(..),
  ExclusiveScratchpads,
  -- * Hooks
  nonFloating,
  defaultFloating,
  customFloating
  ) where

import XMonad.Prelude
import XMonad
import XMonad.Actions.Minimize
import XMonad.Actions.TagWindows (addTag,delTag)
import XMonad.Hooks.ManageHelpers (doRectFloat,isInProperty)

import qualified XMonad.StackSet as W
import qualified Data.List.NonEmpty as NE

-- $usage
--
-- For this module to work properly, you need to use "XMonad.Layout.BoringWindows" and
-- "XMonad.Layout.Minimize", please refer to the documentation of these modules for more
-- information on how to configure them.
--
-- To use this module, put the following in your @xmonad.hs@:
--
-- > import XMonad.Utils.ExclusiveScratchpads
-- > import XMonad.ManageHook (title,appName)
-- > import qualified XMonad.StackSet as W
--
-- Add exclusive scratchpads, for example:
--
-- > exclusiveSps = mkXScratchpads [ ("htop",   "urxvt -name htop -e htop", title =? "htop")
-- >                               , ("xclock", "xclock", appName =? "xclock")
-- >                               ] $ customFloating $ W.RationalRect (1/4) (1/4) (1/2) (1/2)
--
-- The scratchpads don\'t have to be exclusive, you can create them like this (see 'ExclusiveScratchpad'):
--
-- > regularSps   = [ XSP "term" "urxvt -name scratchpad" (appName =? "scratchpad") defaultFloating [] ]
--
-- Create a list that contains all your scratchpads like this:
--
-- > scratchpads = exclusiveSps ++ regularSps
--
-- Add the hooks to your managehook (see "XMonad.Doc.Extending#Editing_the_manage_hook" or
-- <https://xmonad.org/TUTORIAL.html#final-touches the tutorial>); e.g.,
--
-- > manageHook = myManageHook <> xScratchpadsManageHook scratchpads
--
-- And finally add some keybindings (see <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>):
--
-- > , ((modMask, xK_h), scratchpadAction scratchpads "htop")
-- > , ((modMask, xK_c), scratchpadAction scratchpads "xclock")
-- > , ((modMask, xK_t), scratchpadAction scratchpads "term")
-- > , ((modMask, xK_h), hideAll scratchpads)
--
-- Now you can get your scratchpads by pressing the corresponding keys, if you
-- have the @htop@ scratchpad on your current screen and you fetch the @xclock@
-- scratchpad then @htop@ gets hidden.
--
-- If you move a scratchpad it still gets hidden when you fetch a scratchpad of
-- the same family, to change that behaviour and make windows not exclusive
-- anymore when they get resized or moved add these mouse bindings
-- (see "XMonad.Doc.Extending#Editing_mouse_bindings"):
--
-- >     , ((mod4Mask, button1), floatMoveNoexclusive scratchpads)
-- >     , ((mod4Mask, button3), resizeNoexclusive scratchpads)
--
-- To reset a moved scratchpad to the original position that you set with its hook,
-- call @resetExclusiveSp@ when it is in focus. For example if you want to extend
-- Mod-Return to reset the placement when a scratchpad is in focus but keep the
-- default behaviour for tiled windows, set these key bindings:
--
-- > , ((modMask, xK_Return), windows W.swapMaster >> resetExclusiveSp scratchpads)
--
-- __Note:__ This is just an example, in general you can add more than two
-- exclusive scratchpads and multiple families of such.

data ExclusiveScratchpad = XSP { ExclusiveScratchpad -> String
name   :: String       -- ^ Name of the scratchpad
                               , ExclusiveScratchpad -> String
cmd    :: String       -- ^ Command to spawn the scratchpad
                               , ExclusiveScratchpad -> Query Bool
query  :: Query Bool   -- ^ Query to match the scratchpad
                               , ExclusiveScratchpad -> ManageHook
hook   :: ManageHook   -- ^ Hook to specify the placement policy
                               , ExclusiveScratchpad -> [String]
exclusive :: [String]  -- ^ Names of exclusive scratchpads
                               }

type ExclusiveScratchpads = [ExclusiveScratchpad]

-- -----------------------------------------------------------------------------------

-- | Create 'ExclusiveScratchpads' from @[(name,cmd,query)]@ with a common @hook@
mkXScratchpads :: [(String,String,Query Bool)]  -- ^ List of @(name,cmd,query)@ of the
                                                --   exclusive scratchpads
               -> ManageHook                    -- ^ The common @hook@ that they use
               -> ExclusiveScratchpads
mkXScratchpads :: [(String, String, Query Bool)]
-> ManageHook -> ExclusiveScratchpads
mkXScratchpads [(String, String, Query Bool)]
xs ManageHook
h = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl ExclusiveScratchpads
-> (String, String, Query Bool) -> ExclusiveScratchpads
accumulate [] [(String, String, Query Bool)]
xs
  where
    accumulate :: ExclusiveScratchpads
-> (String, String, Query Bool) -> ExclusiveScratchpads
accumulate ExclusiveScratchpads
a (String
n,String
c,Query Bool
q) = String
-> String
-> Query Bool
-> ManageHook
-> [String]
-> ExclusiveScratchpad
XSP String
n String
c Query Bool
q ManageHook
h (forall a. (a -> Bool) -> [a] -> [a]
filter (String
nforall a. Eq a => a -> a -> Bool
/=) [String]
names) forall a. a -> [a] -> [a]
: ExclusiveScratchpads
a
    names :: [String]
names = forall a b. (a -> b) -> [a] -> [b]
map (\(String
n,String
_,Query Bool
_) -> String
n) [(String, String, Query Bool)]
xs

-- | Create 'ManageHook' from 'ExclusiveScratchpads'
xScratchpadsManageHook :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads from
                                                --   which a 'ManageHook' should be generated
                       -> ManageHook
xScratchpadsManageHook :: ExclusiveScratchpads -> ManageHook
xScratchpadsManageHook = forall m. Monoid m => [m] -> m
composeAll forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\ExclusiveScratchpad
sp -> ExclusiveScratchpad -> Query Bool
query ExclusiveScratchpad
sp forall (m :: * -> *) a. (Monad m, Monoid a) => m Bool -> m a -> m a
--> ExclusiveScratchpad -> ManageHook
hook ExclusiveScratchpad
sp)

-- | Pop up/hide the scratchpad by name and possibly hide its exclusive
scratchpadAction :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads
                 -> String                -- ^ Name of the scratchpad to toggle
                 -> X ()
scratchpadAction :: ExclusiveScratchpads -> String -> X ()
scratchpadAction ExclusiveScratchpads
xs String
n =
  let ys :: ExclusiveScratchpads
ys = forall a. (a -> Bool) -> [a] -> [a]
filter ((String
nforall a. Eq a => a -> a -> Bool
==)forall b c a. (b -> c) -> (a -> b) -> a -> c
.ExclusiveScratchpad -> String
name) ExclusiveScratchpads
xs in

  case ExclusiveScratchpads
ys of []     -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
             (ExclusiveScratchpad
sp:ExclusiveScratchpads
_) -> let q :: Query Bool
q = ExclusiveScratchpad -> Query Bool
query ExclusiveScratchpad
sp in forall a. (WindowSet -> X a) -> X a
withWindowSet forall a b. (a -> b) -> a -> b
$ \WindowSet
s -> do
                       [Window]
ws <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall a. Query a -> Window -> X a
runQuery Query Bool
q) forall a b. (a -> b) -> a -> b
$ forall a i l s sd. Eq a => StackSet i l a s sd -> [a]
W.allWindows WindowSet
s

                       case [Window]
ws of []    -> do forall (m :: * -> *). MonadIO m => String -> m ()
spawn (ExclusiveScratchpad -> String
cmd ExclusiveScratchpad
sp)
                                              ExclusiveScratchpads -> String -> X ()
hideOthers ExclusiveScratchpads
xs String
n
                                              (WindowSet -> WindowSet) -> X ()
windows forall i l a s sd. StackSet i l a s sd -> StackSet i l a s sd
W.shiftMaster

                                  (Window
w:[Window]
_) -> do Window -> X ()
toggleWindow Window
w
                                              X Bool -> X () -> X ()
whenX (forall a. Query a -> Window -> X a
runQuery Query Bool
isExclusive Window
w) (ExclusiveScratchpads -> String -> X ()
hideOthers ExclusiveScratchpads
xs String
n)
  where
    toggleWindow :: Window -> X ()
toggleWindow Window
w = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Bool -> Bool -> Bool
(&&) (forall a. Query a -> Window -> X a
runQuery Query Bool
isMaximized Window
w) (Window -> X Bool
onCurrentScreen Window
w) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
      Bool
True  -> X Bool -> X () -> X ()
whenX (Window -> X Bool
onCurrentScreen Window
w) (Window -> X ()
minimizeWindow Window
w)
      Bool
False -> do (WindowSet -> WindowSet) -> X ()
windows (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a s i l sd.
(Ord a, Eq s, Eq i) =>
i -> a -> StackSet i l a s sd -> StackSet i l a s sd
W.shiftWin Window
w forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall i l a s sd. StackSet i l a s sd -> i
W.currentTag)
                  Window -> X ()
maximizeWindowAndFocus Window
w
                  (WindowSet -> WindowSet) -> X ()
windows forall i l a s sd. StackSet i l a s sd -> StackSet i l a s sd
W.shiftMaster

    onCurrentScreen :: Window -> X Bool
onCurrentScreen Window
w = forall a. (WindowSet -> X a) -> X a
withWindowSet (forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Window
w forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a sid sd. StackSet i l a sid sd -> [a]
currentWindows)

-- | Hide all 'ExclusiveScratchpads' on the current screen
hideAll :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads
        -> X ()
hideAll :: ExclusiveScratchpads -> X ()
hideAll ExclusiveScratchpads
xs = Query Bool -> (Window -> X ()) -> X ()
mapWithCurrentScreen Query Bool
q Window -> X ()
minimizeWindow
  where q :: Query Bool
q = [Query Bool] -> Query Bool
joinQueries (forall a b. (a -> b) -> [a] -> [b]
map ExclusiveScratchpad -> Query Bool
query ExclusiveScratchpads
xs) forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
<&&> Query Bool
isExclusive forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
<&&> Query Bool
isMaximized

-- | If the focused window is a scratchpad, the scratchpad gets reset to the original
-- placement specified with the hook and becomes exclusive again
resetExclusiveSp :: ExclusiveScratchpads -- ^ List of exclusive scratchpads
                 -> X ()
resetExclusiveSp :: ExclusiveScratchpads -> X ()
resetExclusiveSp ExclusiveScratchpads
xs = (Window -> X ()) -> X ()
withFocused forall a b. (a -> b) -> a -> b
$ \Window
w -> X Bool -> X () -> X ()
whenX (ExclusiveScratchpads -> Window -> X Bool
isScratchpad ExclusiveScratchpads
xs Window
w) forall a b. (a -> b) -> a -> b
$ do
  let ys :: X ExclusiveScratchpads
ys = forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Query a -> Window -> X a
runQuery Window
w forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExclusiveScratchpad -> Query Bool
query) ExclusiveScratchpads
xs

  X Bool -> X () -> X ()
unlessX (forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> X ExclusiveScratchpads
ys) forall a b. (a -> b) -> a -> b
$ do
    ManageHook
mh <- forall a. NonEmpty a -> a
NE.head forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasCallStack => [a] -> NonEmpty a
notEmpty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map ExclusiveScratchpad -> ManageHook
hook forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> X ExclusiveScratchpads
ys  -- ys /= [], so `head` is fine
    String
n  <- forall a. NonEmpty a -> a
NE.head forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. HasCallStack => [a] -> NonEmpty a
notEmpty forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map ExclusiveScratchpad -> String
name forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> X ExclusiveScratchpads
ys  -- same

    ((WindowSet -> WindowSet) -> X ()
windows forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Endo a -> a -> a
appEndo forall (m :: * -> *) b c a.
Monad m =>
(b -> m c) -> (a -> m b) -> a -> m c
<=< forall a. Query a -> Window -> X a
runQuery ManageHook
mh) Window
w
    ExclusiveScratchpads -> String -> X ()
hideOthers ExclusiveScratchpads
xs String
n
    String -> Window -> X ()
delTag String
"_XSP_NOEXCLUSIVE" Window
w

  where unlessX :: X Bool -> X () -> X ()
unlessX = X Bool -> X () -> X ()
whenX forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Bool
not

-- -----------------------------------------------------------------------------------

-- | Hide the scratchpad of the same family by name if it's on the focused workspace
hideOthers :: ExclusiveScratchpads -> String -> X ()
hideOthers :: ExclusiveScratchpads -> String -> X ()
hideOthers ExclusiveScratchpads
xs String
n =
  let ys :: [String]
ys = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ExclusiveScratchpad -> [String]
exclusive forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter ((String
nforall a. Eq a => a -> a -> Bool
==)forall b c a. (b -> c) -> (a -> b) -> a -> c
.ExclusiveScratchpad -> String
name) ExclusiveScratchpads
xs
      qs :: [Query Bool]
qs = forall a b. (a -> b) -> [a] -> [b]
map ExclusiveScratchpad -> Query Bool
query forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter ((forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
ys)forall b c a. (b -> c) -> (a -> b) -> a -> c
.ExclusiveScratchpad -> String
name) ExclusiveScratchpads
xs
      q :: Query Bool
q  = [Query Bool] -> Query Bool
joinQueries [Query Bool]
qs forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
<&&> Query Bool
isExclusive forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
<&&> Query Bool
isMaximized in

  Query Bool -> (Window -> X ()) -> X ()
mapWithCurrentScreen Query Bool
q Window -> X ()
minimizeWindow

-- | Conditionally map a function on all windows of the current screen
mapWithCurrentScreen :: Query Bool -> (Window -> X ()) -> X ()
mapWithCurrentScreen :: Query Bool -> (Window -> X ()) -> X ()
mapWithCurrentScreen Query Bool
q Window -> X ()
f = forall a. (WindowSet -> X a) -> X a
withWindowSet forall a b. (a -> b) -> a -> b
$ \WindowSet
s -> do
  [Window]
ws <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall a. Query a -> Window -> X a
runQuery Query Bool
q) forall a b. (a -> b) -> a -> b
$ forall i l a sid sd. StackSet i l a sid sd -> [a]
currentWindows WindowSet
s
  forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Window -> X ()
f [Window]
ws

-- | Extract all windows on the current screen from a StackSet
currentWindows :: W.StackSet i l a sid sd -> [a]
currentWindows :: forall i l a sid sd. StackSet i l a sid sd -> [a]
currentWindows = forall a. Maybe (Stack a) -> [a]
W.integrate' forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a. Workspace i l a -> Maybe (Stack a)
W.stack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
W.workspace forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
W.current

-- | Check if given window is a scratchpad
isScratchpad :: ExclusiveScratchpads -> Window -> X Bool
isScratchpad :: ExclusiveScratchpads -> Window -> X Bool
isScratchpad ExclusiveScratchpads
xs Window
w = forall a. (WindowSet -> X a) -> X a
withWindowSet forall a b. (a -> b) -> a -> b
$ \WindowSet
s -> do
  let q :: Query Bool
q = [Query Bool] -> Query Bool
joinQueries forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map ExclusiveScratchpad -> Query Bool
query ExclusiveScratchpads
xs

  [Window]
ws <- forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (forall a. Query a -> Window -> X a
runQuery Query Bool
q) forall a b. (a -> b) -> a -> b
$ forall a i l s sd. Eq a => StackSet i l a s sd -> [a]
W.allWindows WindowSet
s
  forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Window
w [Window]
ws

-- | Build a disjunction from a list of clauses
joinQueries :: [Query Bool] -> Query Bool
joinQueries :: [Query Bool] -> Query Bool
joinQueries = forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall (m :: * -> *). Monad m => m Bool -> m Bool -> m Bool
(<||>) (forall a. X a -> Query a
liftX forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False)

-- | Useful queries
isExclusive, isMaximized :: Query Bool
isExclusive :: Query Bool
isExclusive = forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
notElem String
"_XSP_NOEXCLUSIVE" forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
words forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Query String
stringProperty String
"_XMONAD_TAGS"
isMaximized :: Query Bool
isMaximized = Bool -> Bool
not forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> String -> Query Bool
isInProperty String
"_NET_WM_STATE" String
"_NET_WM_STATE_HIDDEN"

-- -----------------------------------------------------------------------------------

-- | Make a window not exclusive anymore
setNoexclusive :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads
               -> Window                -- ^ Window which should be made not
                                        --   exclusive anymore
               -> X ()
setNoexclusive :: ExclusiveScratchpads -> Window -> X ()
setNoexclusive ExclusiveScratchpads
xs Window
w = X Bool -> X () -> X ()
whenX (ExclusiveScratchpads -> Window -> X Bool
isScratchpad ExclusiveScratchpads
xs Window
w) forall a b. (a -> b) -> a -> b
$ String -> Window -> X ()
addTag String
"_XSP_NOEXCLUSIVE" Window
w

-- | Float and drag the window, make it not exclusive anymore
floatMoveNoexclusive :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads
                     -> Window                -- ^ Window which should be moved
                     -> X ()
floatMoveNoexclusive :: ExclusiveScratchpads -> Window -> X ()
floatMoveNoexclusive ExclusiveScratchpads
xs Window
w = ExclusiveScratchpads -> Window -> X ()
setNoexclusive ExclusiveScratchpads
xs Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Window -> X ()
focus Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Window -> X ()
mouseMoveWindow Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (WindowSet -> WindowSet) -> X ()
windows forall i l a s sd. StackSet i l a s sd -> StackSet i l a s sd
W.shiftMaster

-- | Resize window, make it not exclusive anymore
resizeNoexclusive :: ExclusiveScratchpads  -- ^ List of exclusive scratchpads
                  -> Window                -- ^ Window which should be resized
                  -> X ()
resizeNoexclusive :: ExclusiveScratchpads -> Window -> X ()
resizeNoexclusive ExclusiveScratchpads
xs Window
w = ExclusiveScratchpads -> Window -> X ()
setNoexclusive ExclusiveScratchpads
xs Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Window -> X ()
focus Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Window -> X ()
mouseResizeWindow Window
w
  forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (WindowSet -> WindowSet) -> X ()
windows forall i l a s sd. StackSet i l a s sd -> StackSet i l a s sd
W.shiftMaster

-- -----------------------------------------------------------------------------------

-- | Manage hook that makes the window non-floating
nonFloating :: ManageHook
nonFloating :: ManageHook
nonFloating = forall m. Monoid m => m
idHook

-- | Manage hook that makes the window floating with the default placement
defaultFloating :: ManageHook
defaultFloating :: ManageHook
defaultFloating = ManageHook
doFloat

-- | Manage hook that makes the window floating with custom placement
customFloating :: W.RationalRect  -- ^ @RationalRect x y w h@ that specifies relative position,
                                  --   height and width (see "XMonad.StackSet#RationalRect")
               -> ManageHook
customFloating :: RationalRect -> ManageHook
customFloating = RationalRect -> ManageHook
doRectFloat