----------------------------------------------------------------------------- -- | -- Module : XMonad.Actions.Workscreen -- Copyright : (c) 2012 kedals0 -- License : BSD3-style (see LICENSE) -- -- Maintainer : Dal -- Stability : unstable -- Portability: unportable -- -- A workscreen permits to display a set of workspaces on several -- screens. In xinerama mode, when a workscreen is viewed, workspaces -- associated to all screens are visible. -- -- The first workspace of a workscreen is displayed on first screen, -- second on second screen, etc. Workspace position can be easily -- changed. If the current workscreen is called again, workspaces are -- shifted. -- -- This also permits to see all workspaces of a workscreen even if just -- one screen is present, and to move windows from workspace to workscreen. ----------------------------------------------------------------------------- {-# LANGUAGE DeriveDataTypeable #-} module XMonad.Actions.Workscreen ( -- * Usage -- $usage configWorkscreen ,viewWorkscreen ,Workscreen(..) ,shiftToWorkscreen ,fromWorkspace ,expandWorkspace ) where import XMonad hiding (workspaces) import qualified XMonad.StackSet as W import qualified XMonad.Util.ExtensibleState as XS import XMonad.Actions.OnScreen -- $usage -- You can use this module with the following in your @~\/.xmonad\/xmonad.hs@: -- -- > import XMonad.Actions.Workscreen -- > myWorkspaces = let myOldWorkspaces = ["adm","work","mail"] -- > in Workscreen.expandWorkspace 2 myOldWorkspaces -- > myStartupHook = do Workscreen.configWorkscreen (Workscreen.fromWorkspace 2 myWorkspaces) -- > return () -- -- Then, replace normal workspace view and shift keybinding: -- -- > [((m .|. modm, k), f i) -- > | (i, k) <- zip [0..] [1..12] -- > , (f, m) <- [(Workscreen.viewWorkscreen, 0), (Workscreen.shiftToWorkscreen, shiftMask)]] -- -- For detailed instructions on editing your key bindings, see -- "XMonad.Doc.Extending#Editing_key_bindings". data Workscreen = Workscreen{workscreenId::Int,workspaces::[WorkspaceId]} deriving (Show,Typeable) type WorkscreenId=Int data WorkscreenStorage = WorkscreenStorage WorkscreenId [Workscreen] deriving (Show,Typeable) instance ExtensionClass WorkscreenStorage where initialValue = WorkscreenStorage 0 [] -- | Helper to group workspaces. Multiply workspace by screens number. expandWorkspace :: Int -> [WorkspaceId] -> [WorkspaceId] expandWorkspace nscr ws = concat $ map expandId ws where expandId wsId = let t = wsId ++ "_" in map ((++) t . show ) [1..nscr] -- | Create workscreen list from workspace list. Group workspaces to -- packets of screens number size. fromWorkspace :: Int -> [WorkspaceId] -> [Workscreen] fromWorkspace n ws = map (\(a,b) -> Workscreen a b) $ zip [0..] (fromWorkspace' n ws) fromWorkspace' :: Int -> [WorkspaceId] -> [[WorkspaceId]] fromWorkspace' _ [] = [] fromWorkspace' n ws = take n ws : fromWorkspace' n (drop n ws) -- | Initial configuration of workscreens configWorkscreen :: [Workscreen] -> X () configWorkscreen wscrn = XS.put (WorkscreenStorage 0 wscrn) -- | View workscreen of index @WorkscreenId@. If current workscreen is asked -- workscreen, workscreen's workspaces are shifted. viewWorkscreen :: WorkscreenId -> X () viewWorkscreen wscrId = do (WorkscreenStorage c a) <- XS.get let wscr = if wscrId == c then Workscreen wscrId $ shiftWs (workspaces $ a !! wscrId) else a !! wscrId (x,_:ys) = splitAt wscrId a newWorkscreenStorage = WorkscreenStorage wscrId (x ++ [wscr] ++ ys) windows (viewWorkscreen' wscr) XS.put newWorkscreenStorage viewWorkscreen' :: Workscreen -> WindowSet -> WindowSet viewWorkscreen' (Workscreen _ ws) = \s -> foldl wsToSc' s (zip [0..] ws) where wsToSc' s (scr,wsId) = greedyViewOnScreen scr wsId s shiftWs :: [WorkspaceId] -> [WorkspaceId] shiftWs a = drop 1 a ++ take 1 a -- | Shift a window on the first workspace of workscreen -- @WorkscreenId@. shiftToWorkscreen :: WorkscreenId -> X () shiftToWorkscreen wscrId = do (WorkscreenStorage _ a) <- XS.get let ws = head . workspaces $ a !! wscrId windows $ W.shift ws