-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Actions.FindEmptyWorkspace
-- Description :  Find an empty workspace.
-- Copyright   :  (c) Miikka Koskinen 2007
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  arcatan@kapsi.fi
-- Stability   :  stable
-- Portability :  unportable
--
-- Find an empty workspace.
--
-----------------------------------------------------------------------------

module XMonad.Actions.FindEmptyWorkspace (
    -- * Usage
    -- $usage
    viewEmptyWorkspace, tagToEmptyWorkspace, sendToEmptyWorkspace
  ) where

import XMonad.Prelude
import XMonad
import XMonad.StackSet

-- $usage
--
-- To use, import this module into your @xmonad.hs@:
--
-- >   import XMonad.Actions.FindEmptyWorkspace
--
-- and add the desired keybindings, for example:
--
--  >   , ((modm,                xK_m    ), viewEmptyWorkspace)
--  >   , ((modm .|. shiftMask,  xK_m    ), tagToEmptyWorkspace)
--
-- Now you can jump to an empty workspace with @mod-m@. @Mod-shift-m@
-- will tag the current window to an empty workspace and view it.
--
-- For detailed instructions on editing your key bindings, see
-- <https://xmonad.org/TUTORIAL.html#customizing-xmonad the tutorial>.

-- | Find the first hidden empty workspace in a StackSet. Returns
-- Nothing if all workspaces are in use. Function searches currently
-- focused workspace, other visible workspaces (when in Xinerama) and
-- hidden workspaces in this order.
findEmptyWorkspace :: StackSet i l a s sd -> Maybe (Workspace i l a)
findEmptyWorkspace :: forall i l a s sd. StackSet i l a s sd -> Maybe (Workspace i l a)
findEmptyWorkspace = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (forall a. Maybe a -> Bool
isNothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a. Workspace i l a -> Maybe (Stack a)
stack) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {i} {l} {a} {sid} {sd}.
StackSet i l a sid sd -> [Workspace i l a]
allWorkspaces
  where
    allWorkspaces :: StackSet i l a sid sd -> [Workspace i l a]
allWorkspaces StackSet i l a sid sd
ss = (forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
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
current) StackSet i l a sid sd
ss forall a. a -> [a] -> [a]
:
                       (forall a b. (a -> b) -> [a] -> [b]
map forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
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]
visible) StackSet i l a sid sd
ss forall a. [a] -> [a] -> [a]
++ forall {i} {l} {a} {sid} {sd}.
StackSet i l a sid sd -> [Workspace i l a]
hidden StackSet i l a sid sd
ss

withEmptyWorkspace :: (WorkspaceId -> X ()) -> X ()
withEmptyWorkspace :: (WorkspaceId -> X ()) -> X ()
withEmptyWorkspace WorkspaceId -> X ()
f = do
    WindowSet
ws <- forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets XState -> WindowSet
windowset
    forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
whenJust (forall i l a s sd. StackSet i l a s sd -> Maybe (Workspace i l a)
findEmptyWorkspace WindowSet
ws) (WorkspaceId -> X ()
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall i l a. Workspace i l a -> i
tag)

-- | Find and view an empty workspace. Do nothing if all workspaces are
-- in use.
viewEmptyWorkspace :: X ()
viewEmptyWorkspace :: X ()
viewEmptyWorkspace = (WorkspaceId -> X ()) -> X ()
withEmptyWorkspace ((WindowSet -> WindowSet) -> X ()
windows forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s i l a sd.
(Eq s, Eq i) =>
i -> StackSet i l a s sd -> StackSet i l a s sd
view)

-- | Tag current window to an empty workspace and view it. Do nothing if
-- all workspaces are in use.
tagToEmptyWorkspace :: X ()
tagToEmptyWorkspace :: X ()
tagToEmptyWorkspace = (WorkspaceId -> X ()) -> X ()
withEmptyWorkspace forall a b. (a -> b) -> a -> b
$ \WorkspaceId
w -> (WindowSet -> WindowSet) -> X ()
windows forall a b. (a -> b) -> a -> b
$ forall s i l a sd.
(Eq s, Eq i) =>
i -> StackSet i l a s sd -> StackSet i l a s sd
view WorkspaceId
w forall b c a. (b -> c) -> (a -> b) -> a -> c
. 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
shift WorkspaceId
w

-- | Send current window to an empty workspace. Do nothing if
-- all workspaces are in use.
sendToEmptyWorkspace :: X ()
sendToEmptyWorkspace :: X ()
sendToEmptyWorkspace = (WorkspaceId -> X ()) -> X ()
withEmptyWorkspace forall a b. (a -> b) -> a -> b
$ \WorkspaceId
w -> (WindowSet -> WindowSet) -> X ()
windows forall a b. (a -> b) -> a -> b
$ 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
shift WorkspaceId
w