From c5f7751a84ccea6f5e87e67e32a97e359baa0589 Mon Sep 17 00:00:00 2001 From: Michal Janeczek Date: Mon, 31 Mar 2008 13:19:06 +0200 Subject: XMonad.Actions.CycleRecentWS: initial import darcs-hash:20080331111906-285cf-90722dd61a71e2e58711134f3665efb6986cc044.gz --- XMonad/Actions/CycleRecentWS.hs | 85 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 XMonad/Actions/CycleRecentWS.hs (limited to 'XMonad/Actions/CycleRecentWS.hs') diff --git a/XMonad/Actions/CycleRecentWS.hs b/XMonad/Actions/CycleRecentWS.hs new file mode 100644 index 0000000..19ff548 --- /dev/null +++ b/XMonad/Actions/CycleRecentWS.hs @@ -0,0 +1,85 @@ +----------------------------------------------------------------------------- +-- | +-- Module : XMonad.Actions.CycleRecentWS +-- Copyright : (c) Michal Janeczek +-- License : BSD3-style (see LICENSE) +-- +-- Maintainer : Michal Janeczek +-- Stability : unstable +-- Portability : unportable +-- +-- Provides bindings to cycle through most recently used workspaces +-- with repeated presses of a single key (as long as modifier key is +-- held down). This is similar to how many window managers handle +-- window switching. +-- +----------------------------------------------------------------------------- + +module XMonad.Actions.CycleRecentWS ( + -- * Usage + -- $usage + cycleRecentWS, + cycleWindowSets +) where + +import XMonad hiding (workspaces) +import XMonad.StackSet + +-- $usage +-- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@ file: +-- +-- > import XMonad.Actions.CycleRecentWS +-- > +-- > , ((modMask x, xK_Tab), cycleRecentWS [xK_Alt_L] xK_Tab xK_grave) +-- +-- For detailed instructions on editing your key bindings, see +-- "XMonad.Doc.Extending#Editing_key_bindings". + +-- | Cycle through most recent workspaces with repeated presses of a key, while +-- a modifier key is held down. The recency of workspaces previewed while browsing +-- to the target workspace is not affected. That way a stack of most recently used +-- workspaces is maintained, similarly to how many window managers handle window +-- switching. For best effects use the same modkey+key combination as the one used +-- to invoke this action. +cycleRecentWS :: [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 () +cycleRecentWS = cycleWindowSets options + where options w = map (view `flip` w) (recentTags w) + recentTags w = map tag $ tail (workspaces w) ++ [head (workspaces w)] + + +cycref :: [a] -> Int -> a +cycref l i = l !! (i `mod` length l) + +-- | Cycle through a finite list of WindowSets with repeated presses of a key, while +-- a modifier key is held down. For best effects use the same modkey+key combination +-- as the one used to invoke this action. +cycleWindowSets :: (WindowSet -> [WindowSet]) -- ^ A function used to create a list of WindowSets to choose from + -> [KeySym] -- ^ A list of modifier keys used when invoking this action. + -- As soon as one of them is released, the final WindowSet is chosen and the action exits. + -> KeySym -- ^ Key used to preview next WindowSet from the list of generated options + -> KeySym -- ^ Key used to preview previous WindowSet from the list of generated options. + -- If it's the same as nextOption key, it is effectively ignored. + -> X () +cycleWindowSets genOptions mods keyNext keyPrev = do + options <- gets $ genOptions . windowset + XConf {theRoot = root, display = d} <- ask + let event = allocaXEvent $ \p -> do + maskEvent d (keyPressMask .|. keyReleaseMask) p + KeyEvent {ev_event_type = t, ev_keycode = c} <- getEvent p + s <- keycodeToKeysym d c 0 + return (t, s) + let setOption n = do windows $ const $ options `cycref` n + (t, s) <- io event + case () of + () | t == keyPress && s == keyNext -> setOption (n+1) + | t == keyPress && s == keyPrev -> setOption (n-1) + | t == keyRelease && s `elem` mods -> return () + | otherwise -> setOption n + io $ grabKeyboard d root False grabModeAsync grabModeAsync currentTime + setOption 0 + io $ ungrabKeyboard d currentTime -- cgit v1.2.3