content: -----------------------------------------------------------------------------
  -- |
  -- Module      :  XMonad.Actions.FindEmptyWorkspace
  -- 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 Data.List
  import Data.Maybe ( isNothing )
  
  import XMonad
  import XMonad.StackSet
  
  -- $usage
  --
  -- To use, import this module into your @~\/.xmonad\/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
  -- "XMonad.Doc.Extending#Editing_key_bindings".
  
  -- | 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 = find (isNothing . stack) . allWorkspaces
    where
      allWorkspaces ss = (workspace . current) ss :
                         (map workspace . visible) ss ++ hidden ss
  
  withEmptyWorkspace :: (WorkspaceId -> X ()) -> X ()
  withEmptyWorkspace f = do
      ws <- gets windowset
      whenJust (findEmptyWorkspace ws) (f . tag)
  
  -- | Find and view an empty workspace. Do nothing if all workspaces are
  -- in use.
  viewEmptyWorkspace :: X ()
  viewEmptyWorkspace = withEmptyWorkspace (windows . view)
  
  -- | Tag current window to an empty workspace and view it. Do nothing if
  -- all workspaces are in use.
  tagToEmptyWorkspace :: X ()
  tagToEmptyWorkspace = withEmptyWorkspace $ \w -> windows $ view w . shift w
  
  -- | Send current window to an empty workspace. Do nothing if
  -- all workspaces are in use.
  sendToEmptyWorkspace :: X ()
  sendToEmptyWorkspace = withEmptyWorkspace $ \w -> windows $ shift w
  