    -----------------------------------------------------------------------------
    -- |
    -- 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 = (Workspace i l a -> Bool)
    -> [Workspace i l a] -> Maybe (Workspace i l a)
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find (Maybe (Stack a) -> Bool
    forall a. Maybe a -> Bool
    isNothing (Maybe (Stack a) -> Bool)
    -> (Workspace i l a -> Maybe (Stack a)) -> Workspace i l a -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Workspace i l a -> Maybe (Stack a)
    forall i l a. Workspace i l a -> Maybe (Stack a)
    stack) ([Workspace i l a] -> Maybe (Workspace i l a))
    -> (StackSet i l a s sd -> [Workspace i l a])
    -> StackSet i l a s sd
    -> Maybe (Workspace i l a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackSet i l a s sd -> [Workspace i l a]
    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 = (Screen i l a sid sd -> Workspace i l a
    forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
    workspace (Screen i l a sid sd -> Workspace i l a)
    -> (StackSet i l a sid sd -> Screen i l a sid sd)
    -> StackSet i l a sid sd
    -> Workspace i l a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackSet i l a sid sd -> Screen i l a sid sd
    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 Workspace i l a -> [Workspace i l a] -> [Workspace i l a]
    forall a. a -> [a] -> [a]
    :
                           ((Screen i l a sid sd -> Workspace i l a)
    -> [Screen i l a sid sd] -> [Workspace i l a]
    forall a b. (a -> b) -> [a] -> [b]
    map Screen i l a sid sd -> Workspace i l a
    forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
    workspace ([Screen i l a sid sd] -> [Workspace i l a])
    -> (StackSet i l a sid sd -> [Screen i l a sid sd])
    -> StackSet i l a sid sd
    -> [Workspace i l a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . StackSet i l a sid sd -> [Screen i l a sid sd]
    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 [Workspace i l a] -> [Workspace i l a] -> [Workspace i l a]
    forall a. [a] -> [a] -> [a]
    ++ StackSet i l a sid sd -> [Workspace i l 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 <- (XState -> WindowSet) -> X WindowSet
    forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
    gets XState -> WindowSet
    windowset
        Maybe (Workspace WorkspaceId (Layout Window) Window)
    -> (Workspace WorkspaceId (Layout Window) Window -> X ()) -> X ()
    forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
    whenJust (WindowSet -> Maybe (Workspace WorkspaceId (Layout Window) Window)
    forall i l a s sd. StackSet i l a s sd -> Maybe (Workspace i l a)
    findEmptyWorkspace WindowSet
    ws) (WorkspaceId -> X ()
    f (WorkspaceId -> X ())
    -> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
    -> Workspace WorkspaceId (Layout Window) Window
    -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
    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 ((WindowSet -> WindowSet) -> X ())
    -> (WorkspaceId -> WindowSet -> WindowSet) -> WorkspaceId -> X ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WorkspaceId -> WindowSet -> WindowSet
    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 ((WorkspaceId -> X ()) -> X ()) -> (WorkspaceId -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \WorkspaceId
    w -> (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WindowSet -> WindowSet) -> X ()
    forall a b. (a -> b) -> a -> b
    $ WorkspaceId -> WindowSet -> WindowSet
    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 (WindowSet -> WindowSet)
    -> (WindowSet -> WindowSet) -> WindowSet -> WindowSet
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . WorkspaceId -> WindowSet -> WindowSet
    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 ((WorkspaceId -> X ()) -> X ()) -> (WorkspaceId -> X ()) -> X ()
    forall a b. (a -> b) -> a -> b
    $ \WorkspaceId
    w -> (WindowSet -> WindowSet) -> X ()
    windows ((WindowSet -> WindowSet) -> X ())
    -> (WindowSet -> WindowSet) -> X ()
    forall a b. (a -> b) -> a -> b
    $ WorkspaceId -> WindowSet -> WindowSet
    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