2011-09-03 12:12:07 +02:00
|
|
|
{-# LANGUAGE DeriveDataTypeable #-}
|
|
|
|
|
2011-09-03 13:09:55 +02:00
|
|
|
module DynamicPerScreenWorkspaces ( screenWorkspaceStorage
|
|
|
|
, WorkspaceScreens
|
2011-09-03 12:12:07 +02:00
|
|
|
, DynamicWorkspaceConfig(..)
|
|
|
|
, dynamicRescreenHook
|
2011-09-03 13:00:38 +02:00
|
|
|
, create
|
|
|
|
, cleanup
|
2011-09-03 13:43:11 +02:00
|
|
|
, focusWindow
|
2011-09-03 12:12:07 +02:00
|
|
|
, view
|
|
|
|
, viewOn
|
|
|
|
, viewOnCurrent
|
|
|
|
) where
|
|
|
|
|
|
|
|
import XMonad hiding (hide)
|
|
|
|
import qualified XMonad.StackSet as W
|
|
|
|
import XMonad.Layout.LayoutModifier (LayoutModifier(..), ModifiedLayout(..))
|
|
|
|
|
|
|
|
import Control.Arrow ((&&&))
|
|
|
|
import Control.Monad
|
|
|
|
import qualified Data.Map as M
|
|
|
|
import Data.Maybe
|
|
|
|
|
|
|
|
import Storage
|
|
|
|
|
|
|
|
|
|
|
|
data DynamicWorkspaceStoreData = DWSD (M.Map Int ScreenId)
|
|
|
|
deriving (Typeable, Show, Read)
|
|
|
|
instance StoreData DynamicWorkspaceStoreData
|
|
|
|
|
|
|
|
screenWorkspaceStorage :: (LayoutClass l a) => l a -> ModifiedLayout (Storage DynamicWorkspaceStoreData) l a
|
|
|
|
screenWorkspaceStorage = storage (DWSD M.empty)
|
|
|
|
|
|
|
|
|
|
|
|
type WorkspaceScreens = Int -> Int -> ScreenId
|
|
|
|
|
|
|
|
data DynamicWorkspaceConfig = DynamicWorkspaceConfig
|
|
|
|
{ defaultWorkspaceScreen :: !WorkspaceScreens
|
|
|
|
, workspaceTag :: !(Int -> WorkspaceId)
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultScreenWorkspaces :: DynamicWorkspaceConfig -> Int -> ScreenId -> [Int]
|
|
|
|
defaultScreenWorkspaces conf n s = filter ((== s) . defaultWorkspaceScreen conf n) [0..]
|
|
|
|
|
|
|
|
|
|
|
|
dynamicRescreenHook :: DynamicWorkspaceConfig -> [ScreenDetail] -> X ()
|
|
|
|
dynamicRescreenHook conf sds = do
|
|
|
|
layout <- asks $ layoutHook . config
|
2011-09-03 13:00:38 +02:00
|
|
|
windows $ cleanup' . \wset -> let (as,bs) = splitAt (length sds) $ map W.workspace (W.current wset:W.visible wset)
|
2011-09-03 12:12:07 +02:00
|
|
|
|
2011-09-03 13:00:38 +02:00
|
|
|
mkWS i = let tag = workspaceTag conf i
|
|
|
|
in W.Workspace tag layout Nothing
|
|
|
|
|
|
|
|
mkScreen sid (Just ws) sd = W.Screen ws sid sd
|
|
|
|
mkScreen sid Nothing sd = W.Screen (mkWS $ nextEmpty' conf (length sds) sid wset) sid sd
|
|
|
|
|
|
|
|
(s:ss) = zipWith3 mkScreen (map S [0..]) (map Just as ++ repeat Nothing) sds
|
|
|
|
in wset {W.current = s, W.visible = ss, W.hidden = bs ++ W.hidden wset}
|
2011-09-03 12:12:07 +02:00
|
|
|
|
|
|
|
workspaceScreen :: DynamicWorkspaceConfig -> Int -> X ScreenId
|
|
|
|
workspaceScreen conf i = do
|
|
|
|
wset <- gets windowset
|
|
|
|
d <- getStoreData
|
2011-09-03 13:09:55 +02:00
|
|
|
|
2011-09-03 12:12:07 +02:00
|
|
|
let defaultScreen = defaultWorkspaceScreen conf (length $ W.screens wset) i
|
|
|
|
return $ case d of
|
|
|
|
Just (DWSD wsscreens) -> do
|
|
|
|
case (M.lookup i wsscreens) of
|
|
|
|
Just s -> s
|
|
|
|
Nothing -> defaultScreen
|
|
|
|
_ ->
|
|
|
|
defaultScreen
|
|
|
|
|
|
|
|
hide :: DynamicWorkspaceConfig -> Int -> WindowSet -> X WindowSet
|
|
|
|
hide conf i wset = gets (W.screens . windowset) >>= foldM (flip hideOn) wset
|
|
|
|
where
|
|
|
|
hideOn s | (workspaceTag conf i) == (W.tag $ W.workspace s) = viewNextEmpty conf (W.screen s)
|
|
|
|
hideOn _ = return
|
|
|
|
|
2011-09-03 13:00:38 +02:00
|
|
|
cleanup' :: WindowSet -> WindowSet
|
|
|
|
cleanup' wset = wset { W.hidden = hidden' }
|
2011-09-03 12:12:07 +02:00
|
|
|
where
|
|
|
|
hidden' = filter (isJust . W.stack) $ W.hidden wset
|
|
|
|
|
|
|
|
viewOn' :: DynamicWorkspaceConfig -> ScreenId -> Int -> WindowSet -> X WindowSet
|
|
|
|
viewOn' conf sid i wset = do
|
|
|
|
let tag = workspaceTag conf i
|
|
|
|
case W.tagMember tag wset of
|
|
|
|
False -> viewEmpty conf sid i wset
|
|
|
|
True -> do
|
|
|
|
wset' <- hide conf i wset
|
|
|
|
let mws = W.lookupWorkspace sid wset'
|
|
|
|
|
|
|
|
return $ case mws of
|
|
|
|
Just ws -> W.view tag . W.view ws $ wset'
|
|
|
|
Nothing -> wset'
|
|
|
|
|
2011-09-03 13:00:38 +02:00
|
|
|
create' :: DynamicWorkspaceConfig -> ScreenId -> Int -> WindowSet -> X WindowSet
|
|
|
|
create' conf sid i wset = do
|
2011-09-03 12:12:07 +02:00
|
|
|
layout <- asks $ layoutHook . config
|
|
|
|
let tag = workspaceTag conf i
|
|
|
|
workspace = W.Workspace tag layout Nothing
|
|
|
|
|
2011-09-03 13:00:38 +02:00
|
|
|
return $ if W.tagMember tag wset then wset else wset { W.hidden = workspace:(W.hidden wset) }
|
|
|
|
|
|
|
|
viewEmpty :: DynamicWorkspaceConfig -> ScreenId -> Int -> WindowSet -> X WindowSet
|
|
|
|
viewEmpty conf sid i = create' conf sid i >=> viewOn' conf sid i
|
2011-09-03 12:12:07 +02:00
|
|
|
|
|
|
|
nextEmpty' ::DynamicWorkspaceConfig -> Int -> ScreenId -> WindowSet -> Int
|
|
|
|
nextEmpty' conf n sid wset = fst $ head $ dropWhile ((`W.tagMember` wset) . snd) $ map (id &&& workspaceTag conf) $ defaultScreenWorkspaces conf n sid
|
|
|
|
|
|
|
|
nextEmpty :: DynamicWorkspaceConfig -> ScreenId -> WindowSet -> Int
|
|
|
|
nextEmpty conf sid wset = nextEmpty' conf (length $ W.screens wset) sid wset
|
|
|
|
|
|
|
|
viewNextEmpty :: DynamicWorkspaceConfig -> ScreenId -> WindowSet -> X WindowSet
|
|
|
|
viewNextEmpty conf sid wset = viewEmpty conf sid (nextEmpty conf sid wset) wset
|
|
|
|
|
|
|
|
windows' :: (WindowSet -> X WindowSet) -> X ()
|
|
|
|
windows' f = do
|
|
|
|
wset <- gets windowset
|
|
|
|
wset' <- f wset
|
2011-09-03 13:00:38 +02:00
|
|
|
windows . const $ wset'
|
|
|
|
|
|
|
|
create :: DynamicWorkspaceConfig -> Int -> X ()
|
|
|
|
create conf i = do
|
|
|
|
sid <- workspaceScreen conf i
|
|
|
|
windows' $ create' conf sid i
|
|
|
|
|
|
|
|
cleanup :: X ()
|
|
|
|
cleanup = windows cleanup'
|
2011-09-03 12:12:07 +02:00
|
|
|
|
2011-09-03 13:43:11 +02:00
|
|
|
focusWindow :: DynamicWorkspaceConfig -> Window -> X ()
|
|
|
|
focusWindow conf w = do
|
|
|
|
wset <- gets windowset
|
|
|
|
let mws = W.findTag w wset
|
|
|
|
whenJust mws $ \ws -> do
|
|
|
|
let i = head $ filter ((== ws) . workspaceTag conf) [0..]
|
|
|
|
sid <- workspaceScreen conf i
|
|
|
|
windows' $ liftM (cleanup' . W.focusWindow w) . viewOn' conf sid i
|
|
|
|
|
2011-09-03 12:12:07 +02:00
|
|
|
view :: DynamicWorkspaceConfig -> Int -> X ()
|
|
|
|
view conf i = do
|
|
|
|
sid <- workspaceScreen conf i
|
2011-09-03 13:00:38 +02:00
|
|
|
windows' $ liftM cleanup' . viewOn' conf sid i
|
2011-09-03 12:12:07 +02:00
|
|
|
|
|
|
|
viewOn :: DynamicWorkspaceConfig -> ScreenId -> Int -> X ()
|
|
|
|
viewOn conf sid i = do
|
|
|
|
updateStoreData $ \(DWSD m) -> DWSD $ M.insert i sid m
|
2011-09-03 13:00:38 +02:00
|
|
|
windows' $ liftM cleanup' . viewOn' conf sid i
|
2011-09-03 12:12:07 +02:00
|
|
|
|
|
|
|
viewOnCurrent :: DynamicWorkspaceConfig -> Int -> X ()
|
|
|
|
viewOnCurrent conf i = do
|
|
|
|
sid <- gets (W.screen . W.current . windowset)
|
|
|
|
viewOn conf sid i
|