diff --git a/CHANGES.md b/CHANGES.md index 93b68e18..9fb87eee 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -65,6 +65,18 @@ When we calculate dragger widths, we first try to get the border width of the focused window, before failing over to using the initial `borderWidth`. + * `XMonad.Actions.CycleRecentWS` + + - Added `cycleRecentNonEmptyWS` function which behaves like `cycleRecentWS` + but is constrainded to non-empty workspaces. + + - Added `toggleRecentWS` and `toggleRecentNonEmptyWS` functions which toggle + between the current and most recent workspace, and continue to toggle back + and forth on repeated presses, rather than cycling through other workspaces. + + - Added `recentWS` function which allows the recency list to be filtered with + a user-provided predicate. + ## 0.16 ### Breaking Changes diff --git a/XMonad/Actions/CycleRecentWS.hs b/XMonad/Actions/CycleRecentWS.hs index 95986ad8..18fe330a 100644 --- a/XMonad/Actions/CycleRecentWS.hs +++ b/XMonad/Actions/CycleRecentWS.hs @@ -19,11 +19,16 @@ module XMonad.Actions.CycleRecentWS ( -- * Usage -- $usage cycleRecentWS, - cycleWindowSets + cycleRecentNonEmptyWS, + cycleWindowSets, + toggleRecentWS, + toggleRecentNonEmptyWS, + toggleWindowSets, + recentWS ) where import XMonad hiding (workspaces) -import XMonad.StackSet +import XMonad.StackSet hiding (filter) -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file: @@ -47,9 +52,41 @@ cycleRecentWS :: [KeySym] -- ^ A list of modifier keys used when invoking this a -> KeySym -- ^ Key used to switch to previous (more recent) workspace. -- If it's the same as the nextWorkspace key, it is effectively ignored. -> X () -cycleRecentWS = cycleWindowSets options - where options w = map (view `flip` w) (recentTags w) - recentTags w = map tag $ tail (workspaces w) ++ [head (workspaces w)] +cycleRecentWS = cycleWindowSets $ recentWS (const True) + + +-- | Like 'cycleRecentWS', but restricted to non-empty workspaces. +cycleRecentNonEmptyWS :: [KeySym] -- ^ A list of modifier keys used when invoking this action. + -- As soon as one of them is released, the final switch is made. + -> KeySym -- ^ Key used to switch to next (less recent) workspace. + -> KeySym -- ^ Key used to switch to previous (more recent) workspace. + -- If it's the same as the nextWorkspace key, it is effectively ignored. + -> X () +cycleRecentNonEmptyWS = cycleWindowSets $ recentWS (not . null . stack) + + +-- | Switch to the most recent workspace. The stack of most recently used workspaces +-- is updated, so repeated use toggles between a pair of workspaces. +toggleRecentWS :: X () +toggleRecentWS = toggleWindowSets $ recentWS (const True) + + +-- | Like 'toggleRecentWS', but restricted to non-empty workspaces. +toggleRecentNonEmptyWS :: X () +toggleRecentNonEmptyWS = toggleWindowSets $ recentWS (not . null . stack) + + +-- | Given a predicate p and the current WindowSet w, create a list of recent WindowSets, +-- most recent first, where the focused workspace satisfies p. +recentWS :: (WindowSpace -> Bool) -- ^ A workspace predicate. + -> WindowSet -- ^ The current WindowSet + -> [WindowSet] +recentWS p w = map (`view` w) recentTags + where recentTags = map tag + $ filter p + $ map workspace (visible w) + ++ hidden w + ++ [workspace (current w)] cycref :: [a] -> Int -> a @@ -83,3 +120,12 @@ cycleWindowSets genOptions mods keyNext keyPrev = do io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime setOption 0 io $ ungrabKeyboard d currentTime + + +-- | Switch to the first of a finite list of WindowSets. +toggleWindowSets :: (WindowSet -> [WindowSet]) -> X () +toggleWindowSets genOptions = do + options <- gets $ genOptions . windowset + case options of + [] -> return () + o:_ -> windows (const o)