----------------------------------------------------------------------------- -- | -- Module : XMonad.Actions.OnScreen -- Copyright : (c) 2009 Nils Schweinsberg -- License : BSD3-style (see LICENSE) -- -- Maintainer : Nils Schweinsberg -- Stability : unstable -- Portability : unportable -- -- Control workspaces on different screens (in xinerama mode). -- ----------------------------------------------------------------------------- module XMonad.Actions.OnScreen ( -- * Usage -- $usage onScreen , viewOnScreen , greedyViewOnScreen , onlyOnScreen ) where import XMonad.StackSet import Control.Monad(guard) import Data.List import Data.Maybe(fromMaybe) import Data.Function(on) -- $usage -- -- This module provides an easy way to control, what you see on other screens in -- xinerama mode without having to focus them. Put this into your -- @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Actions.OnScreen -- -- Then add the appropriate keybindings, for example replace your current keys -- to switch the workspaces with this at the bottom of your keybindings: -- -- > ++ -- > [ ((m .|. modm, k), windows (f i)) -- > | (i, k) <- zip (workspaces conf) ([xK_1 .. xK_9] ++ [xK_0]) -- > , (f, m) <- [ (viewOnScreen 0, 0) -- > , (viewOnScreen 1, controlMask) -- > , (greedyView, controlMask .|. shiftMask) ] -- > ] -- -- This will provide you with the following keybindings: -- -- * modkey + 1-0: -- Switch to workspace 1-0 on screen 0 -- -- * modkey + control + 1-0: -- Switch to workspace 1-0 on screen 1 -- -- * modkey + control + shift + 1-0: -- Default greedyView behaviour -- -- -- A more basic version inside the default keybindings would be: -- -- > , ((modm .|. controlMask, xK_1) windows (viewOnScreen 0 "1")) -- -- where 0 is the first screen and "1" the workspace with the tag "1". -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". -- | Switch to the (hidden) workspace with index 'i' on the screen 'sc'. -- A default function (for example 'view' or 'greedyView') will be run if 'sc' is -- the current screen, no valid screen id or workspace 'i' is already visible. onScreen :: (Eq sid, Eq i) => (i -> StackSet i l a sid sd -> StackSet i l a sid sd) -- ^ default action -> sid -- ^ screen id -> i -- ^ index of the workspace -> StackSet i l a sid sd -- ^ current stack -> StackSet i l a sid sd onScreen defFunc sc i st = fromMaybe (defFunc i st) $ do -- on unfocused current screen guard $ screen (current st) /= sc x <- find ((i==) . tag ) (hidden st) s <- find ((sc==) . screen) (screens st) o <- find ((sc==) . screen) (visible st) let newScreen = s { workspace = x } return st { visible = newScreen : deleteBy ((==) `on` screen) newScreen (visible st) , hidden = workspace o : deleteBy ((==) `on` tag) x (hidden st) } -- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible use 'greedyView' -- to switch the current workspace with workspace 'i'. greedyViewOnScreen :: (Eq sid, Eq i) => sid -- ^ screen id -> i -- ^ index of the workspace -> StackSet i l a sid sd -- ^ current stack -> StackSet i l a sid sd greedyViewOnScreen = onScreen greedyView -- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible use 'view' to -- switch focus to the workspace 'i'. viewOnScreen :: (Eq sid, Eq i) => sid -- ^ screen id -> i -- ^ index of the workspace -> StackSet i l a sid sd -- ^ current stack -> StackSet i l a sid sd viewOnScreen = onScreen view -- | Switch to workspace 'i' on screen 'sc'. If 'i' is visible do nothing. onlyOnScreen :: (Eq sid, Eq i) => sid -- ^ screen id -> i -- ^ index of the workspace -> StackSet i l a sid sd -- ^ current stack -> StackSet i l a sid sd onlyOnScreen = onScreen doNothing where doNothing _ st = st