diff options
Diffstat (limited to 'XMonad/Actions')
-rw-r--r-- | XMonad/Actions/Workscreen.hs | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/XMonad/Actions/Workscreen.hs b/XMonad/Actions/Workscreen.hs new file mode 100644 index 0000000..80f1b37 --- /dev/null +++ b/XMonad/Actions/Workscreen.hs @@ -0,0 +1,109 @@ +----------------------------------------------------------------------------- +-- | +-- Module : XMonad.Actions.Workscreen +-- Copyright : (c) 2012 kedals0 +-- License : BSD3-style (see LICENSE) +-- +-- Maintainer : Dal <kedasl0@gmail.com> +-- 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 |