-----------------------------------------------------------------------------
-- |
-- Module      :  XMonad.Actions.CycleWS
-- Description :  Cycle through workspaces.
-- Copyright   :  (c) Joachim Breitner <mail@joachim-breitner.de>,
--                    Nelson Elhage <nelhage@mit.edu> (`toggleWS' function)
-- License     :  BSD3-style (see LICENSE)
--
-- Maintainer  :  Joachim Breitner <mail@joachim-breitner.de>
-- Stability   :  unstable
-- Portability :  unportable
--
-- Provides bindings to cycle forward or backward through the list of
-- workspaces, to move windows between workspaces, and to cycle
-- between screens.  More general combinators provide ways to cycle
-- through workspaces in various orders, to only cycle through some
-- subset of workspaces, and to cycle by more than one workspace at a
-- time.
--
-- Note that this module now subsumes the functionality of the former
-- @XMonad.Actions.RotView@.  Former users of @rotView@ can simply replace
-- @rotView True@ with @moveTo Next (Not emptyWS)@, and so on.
--
-- If you want to exactly replicate the action of @rotView@ (cycling
-- through workspace in order lexicographically by tag, instead of in
-- the order specified in the config), it can be implemented as:
--
-- > rotView b  = do t <- findWorkspace getSortByTag (bToDir b) (Not emptyWS) 1
-- >                 windows . greedyView $ t
-- >   where bToDir True  = Next
-- >         bToDir False = Prev
--
-----------------------------------------------------------------------------

module XMonad.Actions.CycleWS (
                                -- * Usage
                                -- $usage

                                -- * Moving between workspaces
                                -- $moving

                                nextWS
                              , prevWS
                              , shiftToNext
                              , shiftToPrev

                                -- * Toggling the previous workspace
                                -- $toggling
                              , toggleWS
                              , toggleWS'
                              , toggleOrView

                                -- * Moving between screens (xinerama)

                              , nextScreen
                              , prevScreen
                              , shiftNextScreen
                              , shiftPrevScreen
                              , swapNextScreen
                              , swapPrevScreen

                                -- * Moving between workspaces, take two!
                                -- $taketwo

                              , Direction1D(..)
                              , WSType(..)
                              , emptyWS
                              , hiddenWS
                              , anyWS
                              , wsTagGroup
                              , ignoringWSs

                              , shiftTo
                              , moveTo
                              , doTo

                                -- * The mother-combinator

                              , findWorkspace
                              , toggleOrDoSkip
                              , skipTags

                              , screenBy

                             ) where

import XMonad.Prelude (find, findIndex, isJust, isNothing, liftM2)
import XMonad hiding (workspaces)
import qualified XMonad.Hooks.WorkspaceHistory as WH
import XMonad.StackSet hiding (filter)
import XMonad.Util.Types
import XMonad.Util.WorkspaceCompare

-- $usage
-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file:
--
-- > import XMonad.Actions.CycleWS
-- >
-- > -- a basic CycleWS setup
-- >
-- >   , ((modm,               xK_Down),  nextWS)
-- >   , ((modm,               xK_Up),    prevWS)
-- >   , ((modm .|. shiftMask, xK_Down),  shiftToNext)
-- >   , ((modm .|. shiftMask, xK_Up),    shiftToPrev)
-- >   , ((modm,               xK_Right), nextScreen)
-- >   , ((modm,               xK_Left),  prevScreen)
-- >   , ((modm .|. shiftMask, xK_Right), shiftNextScreen)
-- >   , ((modm .|. shiftMask, xK_Left),  shiftPrevScreen)
-- >   , ((modm,               xK_z),     toggleWS)
--
-- If you want to follow the moved window, you can use both actions:
--
-- >   , ((modm .|. shiftMask, xK_Down), shiftToNext >> nextWS)
-- >   , ((modm .|. shiftMask, xK_Up),   shiftToPrev >> prevWS)
--
-- You can also get fancier with 'moveTo', 'shiftTo', and 'findWorkspace'.
-- For example:
--
-- >   , ((modm     , xK_f), moveTo Next emptyWS)  -- find a free workspace
-- >   , ((modm .|. controlMask, xK_Right),        -- a crazy keybinding!
-- >         do t <- findWorkspace getSortByXineramaRule Next (Not emptyWS) 2
-- >            windows . view $ t                                         )
--
-- For detailed instructions on editing your key bindings, see
-- "XMonad.Doc.Extending#Editing_key_bindings".
--
-- When using the toggle functions, in order to ensure that the workspace
-- to which you switch is the previously viewed workspace, use the
-- 'logHook' in "XMonad.Hooks.WorkspaceHistory".

{- $moving

The following commands for moving the view and windows between
workspaces are somewhat inflexible, but are very simple and probably
Do The Right Thing for most users.

All of the commands in this section cycle through workspaces in the
order in which they are given in your config.

-}

-- | Switch to the next workspace.
nextWS :: X ()
nextWS :: X ()
nextWS = Int -> X ()
switchWorkspace Int
1

-- | Switch to the previous workspace.
prevWS :: X ()
prevWS :: X ()
prevWS = Int -> X ()
switchWorkspace (-Int
1)

-- | Move the focused window to the next workspace.
shiftToNext :: X ()
shiftToNext :: X ()
shiftToNext = Int -> X ()
shiftBy Int
1

-- | Move the focused window to the previous workspace.
shiftToPrev :: X ()
shiftToPrev :: X ()
shiftToPrev = Int -> X ()
shiftBy (-Int
1)

-- $toggling

-- | Toggle to the workspace displayed previously.
toggleWS :: X ()
toggleWS :: X ()
toggleWS = [WorkspaceId] -> X ()
toggleWS' []

-- | Toggle to the previous workspace while excluding some workspaces.
--
-- > -- Ignore the scratchpad workspace while toggling:
-- > ("M-b", toggleWS' ["NSP"])
toggleWS' :: [WorkspaceId] -> X ()
toggleWS' :: [WorkspaceId] -> X ()
toggleWS' [WorkspaceId]
skips = [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept [WorkspaceId]
skips X (Maybe WorkspaceId) -> (Maybe WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe WorkspaceId -> (WorkspaceId -> X ()) -> X ())
-> (WorkspaceId -> X ()) -> Maybe WorkspaceId -> X ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe WorkspaceId -> (WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
whenJust ((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)

-- | 'XMonad.StackSet.greedyView' a workspace, or if already there, view
-- the previously displayed workspace ala weechat. Change @greedyView@ to
-- @toggleOrView@ in your workspace bindings as in the 'XMonad.StackSet.view'
-- faq at <http://haskell.org/haskellwiki/Xmonad/Frequently_asked_questions>.
-- For more flexibility see 'toggleOrDoSkip'.
toggleOrView :: WorkspaceId -> X ()
toggleOrView :: WorkspaceId -> X ()
toggleOrView = [WorkspaceId]
-> (WorkspaceId -> WindowSet -> WindowSet) -> WorkspaceId -> X ()
toggleOrDoSkip [] 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
greedyView

-- | Allows ignoring listed workspace tags (such as scratchpad's \"NSP\"), and
-- running other actions such as view, shift, etc.  For example:
--
-- > import qualified XMonad.StackSet as W
-- > import XMonad.Actions.CycleWS
-- >
-- > -- toggleOrView for people who prefer view to greedyView
-- > toggleOrView' = toggleOrDoSkip [] W.view
-- >
-- > -- toggleOrView ignoring scratchpad and named scratchpad workspace
-- > toggleOrViewNoSP = toggleOrDoSkip ["NSP"] W.greedyView
toggleOrDoSkip :: [WorkspaceId] -> (WorkspaceId -> WindowSet -> WindowSet)
                                  -> WorkspaceId -> X ()
toggleOrDoSkip :: [WorkspaceId]
-> (WorkspaceId -> WindowSet -> WindowSet) -> WorkspaceId -> X ()
toggleOrDoSkip [WorkspaceId]
skips WorkspaceId -> WindowSet -> WindowSet
f WorkspaceId
toWS = do
    WorkspaceId
cur <- (XState -> WorkspaceId) -> X WorkspaceId
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (WindowSet -> WorkspaceId
forall i l a s sd. StackSet i l a s sd -> i
currentTag (WindowSet -> WorkspaceId)
-> (XState -> WindowSet) -> XState -> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XState -> WindowSet
windowset)
    if WorkspaceId
toWS WorkspaceId -> WorkspaceId -> Bool
forall a. Eq a => a -> a -> Bool
== WorkspaceId
cur
        then [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept [WorkspaceId]
skips X (Maybe WorkspaceId) -> (Maybe WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Maybe WorkspaceId -> (WorkspaceId -> X ()) -> X ())
-> (WorkspaceId -> X ()) -> Maybe WorkspaceId -> X ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Maybe WorkspaceId -> (WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a. Monad m => Maybe a -> (a -> m ()) -> m ()
whenJust ((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
f)
        else (WindowSet -> WindowSet) -> X ()
windows (WorkspaceId -> WindowSet -> WindowSet
f WorkspaceId
toWS)

-- | List difference ('\\') for workspaces and tags. Removes workspaces
-- matching listed tags from the given workspace list.
skipTags :: (Eq i) => [Workspace i l a] -> [i] -> [Workspace i l a]
skipTags :: [Workspace i l a] -> [i] -> [Workspace i l a]
skipTags [Workspace i l a]
wss [i]
ids = (Workspace i l a -> Bool) -> [Workspace i l a] -> [Workspace i l a]
forall a. (a -> Bool) -> [a] -> [a]
filter ((i -> [i] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [i]
ids) (i -> Bool) -> (Workspace i l a -> i) -> Workspace i l a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace i l a -> i
forall i l a. Workspace i l a -> i
tag) [Workspace i l a]
wss

-- | Ignoring the skips, find the best candidate for the last viewed hidden
-- workspace.
lastViewedHiddenExcept :: [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept :: [WorkspaceId] -> X (Maybe WorkspaceId)
lastViewedHiddenExcept [WorkspaceId]
skips = do
    [WorkspaceId]
hs <- (XState -> [WorkspaceId]) -> X [WorkspaceId]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((XState -> [WorkspaceId]) -> X [WorkspaceId])
-> (XState -> [WorkspaceId]) -> X [WorkspaceId]
forall a b. (a -> b) -> a -> b
$ (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> [Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId]
forall a b. (a -> b) -> [a] -> [b]
map Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag ([Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId])
-> (XState -> [Workspace WorkspaceId (Layout Window) Window])
-> XState
-> [WorkspaceId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Workspace WorkspaceId (Layout Window) Window]
 -> [WorkspaceId] -> [Workspace WorkspaceId (Layout Window) Window])
-> [WorkspaceId]
-> [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [Workspace WorkspaceId (Layout Window) Window]
-> [WorkspaceId] -> [Workspace WorkspaceId (Layout Window) Window]
forall i l a. Eq i => [Workspace i l a] -> [i] -> [Workspace i l a]
skipTags [WorkspaceId]
skips ([Workspace WorkspaceId (Layout Window) Window]
 -> [Workspace WorkspaceId (Layout Window) Window])
-> (XState -> [Workspace WorkspaceId (Layout Window) Window])
-> XState
-> [Workspace WorkspaceId (Layout Window) Window]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet -> [Workspace WorkspaceId (Layout Window) Window]
forall i l a sid sd. StackSet i l a sid sd -> [Workspace i l a]
hidden (WindowSet -> [Workspace WorkspaceId (Layout Window) Window])
-> (XState -> WindowSet)
-> XState
-> [Workspace WorkspaceId (Layout Window) Window]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XState -> WindowSet
windowset
    [WorkspaceId] -> Maybe WorkspaceId -> Maybe WorkspaceId
forall a. [a] -> Maybe a -> Maybe a
choose [WorkspaceId]
hs (Maybe WorkspaceId -> Maybe WorkspaceId)
-> ([WorkspaceId] -> Maybe WorkspaceId)
-> [WorkspaceId]
-> Maybe WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (WorkspaceId -> Bool) -> [WorkspaceId] -> Maybe WorkspaceId
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find (WorkspaceId -> [WorkspaceId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [WorkspaceId]
hs) ([WorkspaceId] -> Maybe WorkspaceId)
-> X [WorkspaceId] -> X (Maybe WorkspaceId)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> X [WorkspaceId]
WH.workspaceHistory
    where choose :: [a] -> Maybe a -> Maybe a
choose []    Maybe a
_           = Maybe a
forall a. Maybe a
Nothing
          choose (a
h:[a]
_) Maybe a
Nothing     = a -> Maybe a
forall a. a -> Maybe a
Just a
h
          choose [a]
_     vh :: Maybe a
vh@(Just a
_) = Maybe a
vh

switchWorkspace :: Int -> X ()
switchWorkspace :: Int -> X ()
switchWorkspace Int
d = Int -> X WorkspaceId
wsBy Int
d X WorkspaceId -> (WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (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
greedyView

shiftBy :: Int -> X ()
shiftBy :: Int -> X ()
shiftBy Int
d = Int -> X WorkspaceId
wsBy Int
d X WorkspaceId -> (WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (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 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

wsBy :: Int -> X WorkspaceId
wsBy :: Int -> X WorkspaceId
wsBy = X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
-> Direction1D -> WSType -> Int -> X WorkspaceId
findWorkspace X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
getSortByIndex Direction1D
Next WSType
anyWS

{- $taketwo

A few more general commands are also provided, which allow cycling
through subsets of workspaces.

For example,

>   moveTo Next emptyWS

will move to the first available workspace with no windows, and

>   shiftTo Prev (WSIs $ return (('p' `elem`) . tag))

will move the focused window backwards to the first workspace containing
the letter 'p' in its name. =)

-}

{-# DEPRECATED EmptyWS             "Use emptyWS instead." #-}
{-# DEPRECATED HiddenWS            "Use hiddenWS instead." #-}
{-# DEPRECATED NonEmptyWS          "Use Not emptyWS instead." #-}
{-# DEPRECATED HiddenNonEmptyWS    "Use hiddenWS :&: Not emptyWS instead." #-}
{-# DEPRECATED HiddenEmptyWS       "Use hiddenWS :&: emptyWS instead." #-}
{-# DEPRECATED AnyWS               "Use anyWS instead." #-}
{-# DEPRECATED WSTagGroup          "Use wsTagGroup instead." #-}
-- | What type of workspaces should be included in the cycle?
data WSType = EmptyWS     -- ^ cycle through empty workspaces
            | NonEmptyWS  -- ^ cycle through non-empty workspaces
            | HiddenWS    -- ^ cycle through non-visible workspaces
            | HiddenNonEmptyWS  -- ^ cycle through non-empty non-visible workspaces
            | HiddenEmptyWS  -- ^ cycle through empty non-visible workspaces
            | AnyWS       -- ^ cycle through all workspaces
            | WSTagGroup Char
                          -- ^ cycle through workspaces in the same group, the
                          --   group name is all characters up to the first
                          --   separator character or the end of the tag
            | WSIs (X (WindowSpace -> Bool))
                          -- ^ cycle through workspaces satisfying
                          --   an arbitrary predicate
            | WSType :&: WSType -- ^ cycle through workspaces satisfying both
                                --   predicates.
            | WSType :|: WSType -- ^ cycle through workspaces satisfying one of
                                --   the predicates.
            | Not WSType -- ^ cycle through workspaces not satisfying the predicate

-- | Convert a WSType value to a predicate on workspaces.
wsTypeToPred :: WSType -> X (WindowSpace -> Bool)
wsTypeToPred :: WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
EmptyWS    = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Stack Window) -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe (Stack Window) -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window
    -> Maybe (Stack Window))
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace WorkspaceId (Layout Window) Window
-> Maybe (Stack Window)
forall i l a. Workspace i l a -> Maybe (Stack a)
stack)
wsTypeToPred WSType
NonEmptyWS = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Stack Window) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe (Stack Window) -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window
    -> Maybe (Stack Window))
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace WorkspaceId (Layout Window) Window
-> Maybe (Stack Window)
forall i l a. Workspace i l a -> Maybe (Stack a)
stack)
wsTypeToPred WSType
HiddenWS   = do [WorkspaceId]
hs <- (XState -> [WorkspaceId]) -> X [WorkspaceId]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> [Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId]
forall a b. (a -> b) -> [a] -> [b]
map Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag ([Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId])
-> (XState -> [Workspace WorkspaceId (Layout Window) Window])
-> XState
-> [WorkspaceId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet -> [Workspace WorkspaceId (Layout Window) Window]
forall i l a sid sd. StackSet i l a sid sd -> [Workspace i l a]
hidden (WindowSet -> [Workspace WorkspaceId (Layout Window) Window])
-> (XState -> WindowSet)
-> XState
-> [Workspace WorkspaceId (Layout Window) Window]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XState -> WindowSet
windowset)
                             (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (\Workspace WorkspaceId (Layout Window) Window
w -> Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag Workspace WorkspaceId (Layout Window) Window
w WorkspaceId -> [WorkspaceId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [WorkspaceId]
hs)
wsTypeToPred WSType
HiddenNonEmptyWS  = do Workspace WorkspaceId (Layout Window) Window -> Bool
ne <- WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
NonEmptyWS
                                    Workspace WorkspaceId (Layout Window) Window -> Bool
hi <- WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
HiddenWS
                                    (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (\Workspace WorkspaceId (Layout Window) Window
w -> Workspace WorkspaceId (Layout Window) Window -> Bool
hi Workspace WorkspaceId (Layout Window) Window
w Bool -> Bool -> Bool
&& Workspace WorkspaceId (Layout Window) Window -> Bool
ne Workspace WorkspaceId (Layout Window) Window
w)
wsTypeToPred WSType
HiddenEmptyWS  = do Workspace WorkspaceId (Layout Window) Window -> Bool
ne <- WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
EmptyWS
                                 Workspace WorkspaceId (Layout Window) Window -> Bool
hi <- WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
HiddenWS
                                 (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (\Workspace WorkspaceId (Layout Window) Window
w -> Workspace WorkspaceId (Layout Window) Window -> Bool
hi Workspace WorkspaceId (Layout Window) Window
w Bool -> Bool -> Bool
&& Workspace WorkspaceId (Layout Window) Window -> Bool
ne Workspace WorkspaceId (Layout Window) Window
w)
wsTypeToPred WSType
AnyWS      = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> Workspace WorkspaceId (Layout Window) Window -> Bool
forall a b. a -> b -> a
const Bool
True)
wsTypeToPred (WSTagGroup Char
sep) = do WorkspaceId
cur <- Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall l a. Workspace WorkspaceId l a -> WorkspaceId
groupName(Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> (WindowSet -> Workspace WorkspaceId (Layout Window) Window)
-> WindowSet
-> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
-> Workspace WorkspaceId (Layout Window) Window
forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
workspace(Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
 -> Workspace WorkspaceId (Layout Window) Window)
-> (WindowSet
    -> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail)
-> WindowSet
-> Workspace WorkspaceId (Layout Window) Window
forall b c a. (b -> c) -> (a -> b) -> a -> c
.WindowSet
-> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
current (WindowSet -> WorkspaceId) -> X WindowSet -> X WorkspaceId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (XState -> WindowSet) -> X WindowSet
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets XState -> WindowSet
windowset
                                   (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall a b. (a -> b) -> a -> b
$ (WorkspaceId
cur WorkspaceId -> WorkspaceId -> Bool
forall a. Eq a => a -> a -> Bool
==)(WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall l a. Workspace WorkspaceId l a -> WorkspaceId
groupName
                                   where groupName :: Workspace WorkspaceId l a -> WorkspaceId
groupName = (Char -> Bool) -> WorkspaceId -> WorkspaceId
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=Char
sep)(WorkspaceId -> WorkspaceId)
-> (Workspace WorkspaceId l a -> WorkspaceId)
-> Workspace WorkspaceId l a
-> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
.Workspace WorkspaceId l a -> WorkspaceId
forall i l a. Workspace i l a -> i
tag
wsTypeToPred (WSIs X (Workspace WorkspaceId (Layout Window) Window -> Bool)
p ) = X (Workspace WorkspaceId (Layout Window) Window -> Bool)
p
wsTypeToPred (WSType
p :&: WSType
q) = (Bool -> Bool -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Bool -> Bool -> Bool
(&&) ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> Workspace WorkspaceId (Layout Window) Window
 -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X ((Workspace WorkspaceId (Layout Window) Window -> Bool)
      -> Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
p X ((Workspace WorkspaceId (Layout Window) Window -> Bool)
   -> Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
q
wsTypeToPred (WSType
p :|: WSType
q) = (Bool -> Bool -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Bool -> Bool -> Bool
(||) ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> Workspace WorkspaceId (Layout Window) Window
 -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X ((Workspace WorkspaceId (Layout Window) Window -> Bool)
      -> Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
p X ((Workspace WorkspaceId (Layout Window) Window -> Bool)
   -> Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
q
wsTypeToPred (Not WSType
p  ) = (Bool -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Bool
not ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
p

-- | Cycle through empty workspaces
emptyWS :: WSType
emptyWS :: WSType
emptyWS = X (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
WSIs (X (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> WSType)
-> ((Workspace WorkspaceId (Layout Window) Window -> Bool)
    -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> WSType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
forall a b. (a -> b) -> a -> b
$ Maybe (Stack Window) -> Bool
forall a. Maybe a -> Bool
isNothing (Maybe (Stack Window) -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window
    -> Maybe (Stack Window))
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace WorkspaceId (Layout Window) Window
-> Maybe (Stack Window)
forall i l a. Workspace i l a -> Maybe (Stack a)
stack

-- | Cycle through non-visible workspaces
hiddenWS :: WSType
hiddenWS :: WSType
hiddenWS = X (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
WSIs (X (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> WSType)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> WSType
forall a b. (a -> b) -> a -> b
$ do
  [WorkspaceId]
hs <- (XState -> [WorkspaceId]) -> X [WorkspaceId]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> [Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId]
forall a b. (a -> b) -> [a] -> [b]
map Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag ([Workspace WorkspaceId (Layout Window) Window] -> [WorkspaceId])
-> (XState -> [Workspace WorkspaceId (Layout Window) Window])
-> XState
-> [WorkspaceId]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet -> [Workspace WorkspaceId (Layout Window) Window]
forall i l a sid sd. StackSet i l a sid sd -> [Workspace i l a]
hidden (WindowSet -> [Workspace WorkspaceId (Layout Window) Window])
-> (XState -> WindowSet)
-> XState
-> [Workspace WorkspaceId (Layout Window) Window]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XState -> WindowSet
windowset)
  (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall a b. (a -> b) -> a -> b
$ (WorkspaceId -> [WorkspaceId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [WorkspaceId]
hs) (WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
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

-- | Cycle through all workspaces
anyWS :: WSType
anyWS :: WSType
anyWS = X (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
WSIs (X (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> WSType)
-> ((Workspace WorkspaceId (Layout Window) Window -> Bool)
    -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> WSType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
forall a b. (a -> b) -> a -> b
$ Bool -> Workspace WorkspaceId (Layout Window) Window -> Bool
forall a b. a -> b -> a
const Bool
True

-- | Cycle through workspaces that are not in the given list. This could, for
--   example, be used for skipping the workspace reserved for
--   "XMonad.Util.NamedScratchpad":
--
-- >  moveTo Next $ hiddenWS :&: Not emptyWS :&: ignoringWSs [scratchpadWorkspaceTag]
--
ignoringWSs :: [WorkspaceId] -> WSType
ignoringWSs :: [WorkspaceId] -> WSType
ignoringWSs [WorkspaceId]
ts = X (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
WSIs (X (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> WSType)
-> ((Workspace WorkspaceId (Layout Window) Window -> Bool)
    -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> WSType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType)
-> (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
forall a b. (a -> b) -> a -> b
$ (WorkspaceId -> [WorkspaceId] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [WorkspaceId]
ts) (WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
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

-- | Cycle through workspaces in the same group, the
--   group name is all characters up to the first
--   separator character or the end of the tag
wsTagGroup :: Char -> WSType
wsTagGroup :: Char -> WSType
wsTagGroup Char
sep = X (Workspace WorkspaceId (Layout Window) Window -> Bool) -> WSType
WSIs (X (Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> WSType)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> WSType
forall a b. (a -> b) -> a -> b
$ do
  WorkspaceId
cur <- Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall l a. Workspace WorkspaceId l a -> WorkspaceId
groupName (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> (WindowSet -> Workspace WorkspaceId (Layout Window) Window)
-> WindowSet
-> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
-> Workspace WorkspaceId (Layout Window) Window
forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
workspace (Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
 -> Workspace WorkspaceId (Layout Window) Window)
-> (WindowSet
    -> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail)
-> WindowSet
-> Workspace WorkspaceId (Layout Window) Window
forall b c a. (b -> c) -> (a -> b) -> a -> c
. WindowSet
-> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
current (WindowSet -> WorkspaceId) -> X WindowSet -> X WorkspaceId
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (XState -> WindowSet) -> X WindowSet
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets XState -> WindowSet
windowset
  (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Workspace WorkspaceId (Layout Window) Window -> Bool)
 -> X (Workspace WorkspaceId (Layout Window) Window -> Bool))
-> (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
forall a b. (a -> b) -> a -> b
$ (WorkspaceId
cur WorkspaceId -> WorkspaceId -> Bool
forall a. Eq a => a -> a -> Bool
==) (WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall l a. Workspace WorkspaceId l a -> WorkspaceId
groupName
  where groupName :: Workspace WorkspaceId l a -> WorkspaceId
groupName = (Char -> Bool) -> WorkspaceId -> WorkspaceId
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
sep) (WorkspaceId -> WorkspaceId)
-> (Workspace WorkspaceId l a -> WorkspaceId)
-> Workspace WorkspaceId l a
-> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Workspace WorkspaceId l a -> WorkspaceId
forall i l a. Workspace i l a -> i
tag


-- | View the next workspace in the given direction that satisfies
--   the given condition.
moveTo :: Direction1D -> WSType -> X ()
moveTo :: Direction1D -> WSType -> X ()
moveTo Direction1D
dir WSType
t = Direction1D
-> WSType
-> X ([Workspace WorkspaceId (Layout Window) Window]
      -> [Workspace WorkspaceId (Layout Window) Window])
-> (WorkspaceId -> X ())
-> X ()
doTo Direction1D
dir WSType
t X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
getSortByIndex ((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
greedyView)

-- | Move the currently focused window to the next workspace in the
--   given direction that satisfies the given condition.
shiftTo :: Direction1D -> WSType -> X ()
shiftTo :: Direction1D -> WSType -> X ()
shiftTo Direction1D
dir WSType
t = Direction1D
-> WSType
-> X ([Workspace WorkspaceId (Layout Window) Window]
      -> [Workspace WorkspaceId (Layout Window) Window])
-> (WorkspaceId -> X ())
-> X ()
doTo Direction1D
dir WSType
t X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
getSortByIndex ((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 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)

-- | Using the given sort, find the next workspace in the given
-- direction of the given type, and perform the given action on it.
doTo :: Direction1D -> WSType -> X WorkspaceSort -> (WorkspaceId -> X ()) -> X ()
doTo :: Direction1D
-> WSType
-> X ([Workspace WorkspaceId (Layout Window) Window]
      -> [Workspace WorkspaceId (Layout Window) Window])
-> (WorkspaceId -> X ())
-> X ()
doTo Direction1D
dir WSType
t X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
srt WorkspaceId -> X ()
act = X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
-> Direction1D -> WSType -> Int -> X WorkspaceId
findWorkspace X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
srt Direction1D
dir WSType
t Int
1 X WorkspaceId -> (WorkspaceId -> X ()) -> X ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= WorkspaceId -> X ()
act

-- | Given a function @s@ to sort workspaces, a direction @dir@, a
--   predicate @p@ on workspaces, and an integer @n@, find the tag of
--   the workspace which is @n@ away from the current workspace in
--   direction @dir@ (wrapping around if necessary), among those
--   workspaces, sorted by @s@, which satisfy @p@.
--
--   For some useful workspace sorting functions, see
--   "XMonad.Util.WorkspaceCompare".
--
--   For ideas of what to do with a workspace tag once obtained, note
--   that 'moveTo' and 'shiftTo' are implemented by applying @(>>=
--   (windows . greedyView))@ and @(>>= (windows . shift))@, respectively,
--   to the output of 'findWorkspace'.
findWorkspace :: X WorkspaceSort -> Direction1D -> WSType -> Int -> X WorkspaceId
findWorkspace :: X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
-> Direction1D -> WSType -> Int -> X WorkspaceId
findWorkspace X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
s Direction1D
dir WSType
t Int
n = X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> Int
-> X WorkspaceId
findWorkspaceGen X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
s (WSType -> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsTypeToPred WSType
t) (Direction1D -> Int -> Int
forall p. Num p => Direction1D -> p -> p
maybeNegate Direction1D
dir Int
n)
  where
    maybeNegate :: Direction1D -> p -> p
maybeNegate Direction1D
Next p
d = p
d
    maybeNegate Direction1D
Prev p
d = -p
d

findWorkspaceGen :: X WorkspaceSort -> X (WindowSpace -> Bool) -> Int -> X WorkspaceId
findWorkspaceGen :: X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
-> X (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> Int
-> X WorkspaceId
findWorkspaceGen X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
_ X (Workspace WorkspaceId (Layout Window) Window -> Bool)
_ Int
0 = (XState -> WorkspaceId) -> X WorkspaceId
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (WindowSet -> WorkspaceId
forall i l a s sd. StackSet i l a s sd -> i
currentTag (WindowSet -> WorkspaceId)
-> (XState -> WindowSet) -> XState -> WorkspaceId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. XState -> WindowSet
windowset)
findWorkspaceGen X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
sortX X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsPredX Int
d = do
    Workspace WorkspaceId (Layout Window) Window -> Bool
wsPred <- X (Workspace WorkspaceId (Layout Window) Window -> Bool)
wsPredX
    [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
sort   <- X ([Workspace WorkspaceId (Layout Window) Window]
   -> [Workspace WorkspaceId (Layout Window) Window])
sortX
    WindowSet
ws     <- (XState -> WindowSet) -> X WindowSet
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets XState -> WindowSet
windowset
    let cur :: Workspace WorkspaceId (Layout Window) Window
cur     = Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
-> Workspace WorkspaceId (Layout Window) Window
forall i l a sid sd. Screen i l a sid sd -> Workspace i l a
workspace (WindowSet
-> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
current WindowSet
ws)
        sorted :: [Workspace WorkspaceId (Layout Window) Window]
sorted  = [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
sort (WindowSet -> [Workspace WorkspaceId (Layout Window) Window]
forall i l a sid sd. StackSet i l a sid sd -> [Workspace i l a]
workspaces WindowSet
ws)
        pivoted :: [Workspace WorkspaceId (Layout Window) Window]
pivoted = let ([Workspace WorkspaceId (Layout Window) Window]
a,[Workspace WorkspaceId (Layout Window) Window]
b) = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> [Workspace WorkspaceId (Layout Window) Window]
-> ([Workspace WorkspaceId (Layout Window) Window],
    [Workspace WorkspaceId (Layout Window) Window])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span ((WorkspaceId -> WorkspaceId -> Bool
forall a. Eq a => a -> a -> Bool
/= Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag Workspace WorkspaceId (Layout Window) Window
cur) (WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
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) [Workspace WorkspaceId (Layout Window) Window]
sorted in [Workspace WorkspaceId (Layout Window) Window]
b [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
forall a. [a] -> [a] -> [a]
++ [Workspace WorkspaceId (Layout Window) Window]
a
        ws' :: [Workspace WorkspaceId (Layout Window) Window]
ws'     = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> [Workspace WorkspaceId (Layout Window) Window]
-> [Workspace WorkspaceId (Layout Window) Window]
forall a. (a -> Bool) -> [a] -> [a]
filter Workspace WorkspaceId (Layout Window) Window -> Bool
wsPred [Workspace WorkspaceId (Layout Window) Window]
pivoted
        mCurIx :: Maybe Int
mCurIx  = Workspace WorkspaceId (Layout Window) Window
-> [Workspace WorkspaceId (Layout Window) Window] -> Maybe Int
findWsIndex Workspace WorkspaceId (Layout Window) Window
cur [Workspace WorkspaceId (Layout Window) Window]
ws'
        d' :: Int
d'      = if Int
d Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0 then Int
d Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1 else Int
d
        next :: Workspace WorkspaceId (Layout Window) Window
next    = if [Workspace WorkspaceId (Layout Window) Window] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Workspace WorkspaceId (Layout Window) Window]
ws'
                      then Workspace WorkspaceId (Layout Window) Window
cur
                      else case Maybe Int
mCurIx of
                            Maybe Int
Nothing -> [Workspace WorkspaceId (Layout Window) Window]
ws' [Workspace WorkspaceId (Layout Window) Window]
-> Int -> Workspace WorkspaceId (Layout Window) Window
forall a. [a] -> Int -> a
!! (Int
d' Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` [Workspace WorkspaceId (Layout Window) Window] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Workspace WorkspaceId (Layout Window) Window]
ws')
                            Just Int
ix -> [Workspace WorkspaceId (Layout Window) Window]
ws' [Workspace WorkspaceId (Layout Window) Window]
-> Int -> Workspace WorkspaceId (Layout Window) Window
forall a. [a] -> Int -> a
!! ((Int
ix Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
d) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` [Workspace WorkspaceId (Layout Window) Window] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Workspace WorkspaceId (Layout Window) Window]
ws')
    WorkspaceId -> X WorkspaceId
forall (m :: * -> *) a. Monad m => a -> m a
return (WorkspaceId -> X WorkspaceId) -> WorkspaceId -> X WorkspaceId
forall a b. (a -> b) -> a -> b
$ Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag Workspace WorkspaceId (Layout Window) Window
next

findWsIndex :: WindowSpace -> [WindowSpace] -> Maybe Int
findWsIndex :: Workspace WorkspaceId (Layout Window) Window
-> [Workspace WorkspaceId (Layout Window) Window] -> Maybe Int
findWsIndex Workspace WorkspaceId (Layout Window) Window
ws = (Workspace WorkspaceId (Layout Window) Window -> Bool)
-> [Workspace WorkspaceId (Layout Window) Window] -> Maybe Int
forall a. (a -> Bool) -> [a] -> Maybe Int
findIndex ((WorkspaceId -> WorkspaceId -> Bool
forall a. Eq a => a -> a -> Bool
== Workspace WorkspaceId (Layout Window) Window -> WorkspaceId
forall i l a. Workspace i l a -> i
tag Workspace WorkspaceId (Layout Window) Window
ws) (WorkspaceId -> Bool)
-> (Workspace WorkspaceId (Layout Window) Window -> WorkspaceId)
-> Workspace WorkspaceId (Layout Window) Window
-> Bool
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)

-- | View next screen
nextScreen :: X ()
nextScreen :: X ()
nextScreen = Int -> X ()
switchScreen Int
1

-- | View prev screen
prevScreen :: X ()
prevScreen :: X ()
prevScreen = Int -> X ()
switchScreen (-Int
1)

switchScreen :: Int -> X ()
switchScreen :: Int -> X ()
switchScreen Int
d = do ScreenId
s <- Int -> X ScreenId
screenBy Int
d
                    Maybe WorkspaceId
mws <- ScreenId -> X (Maybe WorkspaceId)
screenWorkspace ScreenId
s
                    case Maybe WorkspaceId
mws of
                         Maybe WorkspaceId
Nothing -> () -> X ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                         Just WorkspaceId
ws -> (WindowSet -> WindowSet) -> X ()
windows (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
ws)

{- | Get the 'ScreenId' /d/ places over. Example usage is a variation of the
the default screen keybindings:

>     -- mod-{w,e}, Switch to previous/next Xinerama screen
>     -- mod-shift-{w,e}, Move client to previous/next Xinerama screen
>     --
>     [((m .|. modm, key), sc >>= screenWorkspace >>= flip whenJust (windows . f))
>         | (key, sc) <- zip [xK_w, xK_e] [(screenBy (-1)),(screenBy 1)]
>         , (f, m) <- [(W.view, 0), (W.shift, shiftMask)]]

-}
screenBy :: Int -> X ScreenId
screenBy :: Int -> X ScreenId
screenBy Int
d = do WindowSet
ws <- (XState -> WindowSet) -> X WindowSet
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets XState -> WindowSet
windowset
                --let ss = sortBy screen (screens ws)
                let now :: ScreenId
now = Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
-> ScreenId
forall i l a sid sd. Screen i l a sid sd -> sid
screen (WindowSet
-> Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail
forall i l a sid sd. StackSet i l a sid sd -> Screen i l a sid sd
current WindowSet
ws)
                ScreenId -> X ScreenId
forall (m :: * -> *) a. Monad m => a -> m a
return (ScreenId -> X ScreenId) -> ScreenId -> X ScreenId
forall a b. (a -> b) -> a -> b
$ (ScreenId
now ScreenId -> ScreenId -> ScreenId
forall a. Num a => a -> a -> a
+ Int -> ScreenId
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
d) ScreenId -> ScreenId -> ScreenId
forall a. Integral a => a -> a -> a
`mod` Int -> ScreenId
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Screen WorkspaceId (Layout Window) Window ScreenId ScreenDetail]
-> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (WindowSet
-> [Screen
      WorkspaceId (Layout Window) Window ScreenId ScreenDetail]
forall i l a s sd. StackSet i l a s sd -> [Screen i l a s sd]
screens WindowSet
ws))

-- | Swap current screen with next screen
swapNextScreen :: X ()
swapNextScreen :: X ()
swapNextScreen = Int -> X ()
swapScreen Int
1

-- | Swap current screen with previous screen
swapPrevScreen :: X ()
swapPrevScreen :: X ()
swapPrevScreen = Int -> X ()
swapScreen (-Int
1)

swapScreen :: Int -> X ()
swapScreen :: Int -> X ()
swapScreen Int
d = do ScreenId
s <- Int -> X ScreenId
screenBy Int
d
                  Maybe WorkspaceId
mws <- ScreenId -> X (Maybe WorkspaceId)
screenWorkspace ScreenId
s
                  case Maybe WorkspaceId
mws of
                    Maybe WorkspaceId
Nothing -> () -> X ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                    Just WorkspaceId
ws -> (WindowSet -> WindowSet) -> X ()
windows (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
greedyView WorkspaceId
ws)

-- | Move focused window to workspace on next screen
shiftNextScreen :: X ()
shiftNextScreen :: X ()
shiftNextScreen = Int -> X ()
shiftScreenBy Int
1

-- | Move focused window to workspace on prev screen
shiftPrevScreen :: X ()
shiftPrevScreen :: X ()
shiftPrevScreen = Int -> X ()
shiftScreenBy (-Int
1)

shiftScreenBy :: Int -> X ()
shiftScreenBy :: Int -> X ()
shiftScreenBy Int
d = do ScreenId
s <- Int -> X ScreenId
screenBy Int
d
                     Maybe WorkspaceId
mws <- ScreenId -> X (Maybe WorkspaceId)
screenWorkspace ScreenId
s
                     case Maybe WorkspaceId
mws of
                         Maybe WorkspaceId
Nothing -> () -> X ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
                         Just WorkspaceId
ws -> (WindowSet -> WindowSet) -> X ()
windows (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
ws)