    ----------------------------------------------------------------------------
    -- |
    -- Module      :  XMonad.Actions.BluetileCommands
    -- Copyright   :  (c) Jan Vornberger 2009
    -- License     :  BSD3-style (see LICENSE)
    --
    -- Maintainer  :  jan.vornberger@informatik.uni-oldenburg.de
    -- Stability   :  unstable
    -- Portability :  not portable
    --
    -- This is a list of selected commands that can be made available using
    -- "XMonad.Hooks.ServerMode" to allow external programs to control
    -- the window manager. Bluetile (<http://projects.haskell.org/bluetile/>)
    -- uses this to enable its dock application to do things like changing
    -- workspaces and layouts.
    --
    -----------------------------------------------------------------------------

    module XMonad.Actions.BluetileCommands (
        -- * Usage
        -- $usage
        bluetileCommands
        ) where

    import XMonad
    import qualified XMonad.StackSet as W
    import XMonad.Layout.LayoutCombinators
    import System.Exit

    -- $usage
    --
    -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@:
    --
    -- >    import XMonad.Hooks.ServerMode
    -- >    import XMonad.Actions.BluetileCommands
    --
    -- Then edit your @handleEventHook@:
    --
    -- > main = xmonad defaultConfig { handleEventHook = serverModeEventHook' bluetileCommands }
    --
    -- See the documentation of "XMonad.Hooks.ServerMode" for details on
    -- how to actually invoke the commands from external programs.

    workspaceCommands :: Int -> X [(String, X ())]
    workspaceCommands sid = asks (workspaces . config) >>= \spaces -> return
                                [(("greedyView" ++ show i),
                                    activateScreen sid >> windows (W.greedyView i))
                                    | i <- spaces ]

    layoutCommands :: Int -> [(String, X ())]
    layoutCommands sid = [ ("layout floating"    , activateScreen sid >>
                                                        sendMessage (JumpToLayout "Floating"))
                         , ("layout tiled1"      , activateScreen sid >>
                                                        sendMessage (JumpToLayout "Tiled1"))
                         , ("layout tiled2"      , activateScreen sid >>
                                                        sendMessage (JumpToLayout "Tiled2"))
                         , ("layout fullscreen"  , activateScreen sid >>
                                                        sendMessage (JumpToLayout "Fullscreen"))
                         ]

    masterAreaCommands :: Int -> [(String, X ())]
    masterAreaCommands sid = [ ("increase master n", activateScreen sid >>
                                                        sendMessage (IncMasterN 1))
                             , ("decrease master n", activateScreen sid >>
                                                        sendMessage (IncMasterN (-1)))
                             ]

    quitCommands :: [(String, X ())]
    quitCommands = [ ("quit bluetile", io (exitWith ExitSuccess))
                   , ("quit bluetile and start metacity", restart "metacity" False)
                   ]

    bluetileCommands :: X [(String, X ())]
    bluetileCommands = do
        let restartCommand = [ ("restart bluetile", restart "bluetile" True) ]
        wscmds0 <- workspaceCommands 0
        wscmds1 <- workspaceCommands 1
        return $ restartCommand
                    ++ wscmds0 ++ layoutCommands 0 ++ masterAreaCommands 0 ++ quitCommands
                    ++ wscmds1 ++ layoutCommands 1 ++ masterAreaCommands 1 ++ quitCommands

    activateScreen :: Int -> X ()
    activateScreen sid = screenWorkspace (S sid) >>= flip whenJust (windows . W.view)