diff options
-rw-r--r-- | Main.hs | 65 | ||||
-rw-r--r-- | W.hs | 31 |
2 files changed, 55 insertions, 41 deletions
@@ -67,7 +67,9 @@ keys = [ (mod1Mask .|. shiftMask, xK_Return, spawn "xterm") , (mod1Mask, xK_p, spawn "exe=`dmenu_path | dmenu` && exec $exe") , (controlMask, xK_space, spawn "gmrun") - , (mod1Mask, xK_Tab, switch) + , (mod1Mask, xK_Tab, focus 1) + , (mod1Mask, xK_j, focus 1) + , (mod1Mask, xK_k, focus (-1)) , (mod1Mask .|. shiftMask, xK_q, io $ exitWith ExitSuccess) ] @@ -112,63 +114,50 @@ handle _ = return () -- --------------------------------------------------------------------- -- Managing windows --- | Modify the current window list with a pure funtion, and refresh -withWindows :: (Windows -> Windows) -> W () -withWindows f = do - modifyWindows f - refresh - --- | Run an action on the currently focused window -withCurrent :: (Window -> W ()) -> W () -withCurrent f = do - ws <- gets windows - case ws of - [] -> return () - (w:_) -> f w - -- -- | refresh. Refresh the currently focused window. Resizes to full -- screen and raises the window. -- refresh :: W () -refresh = withCurrent $ \w -> do - d <- gets display - sw <- gets screenWidth - sh <- gets screenHeight - io $ do moveResizeWindow d w 0 0 (fromIntegral sw) (fromIntegral sh) - raiseWindow d w +refresh = do + ws <- gets windows + case ws of + [] -> return () + (w:_) -> do + d <- gets display + sw <- liftM fromIntegral (gets screenWidth) + sh <- liftM fromIntegral (gets screenHeight) + io $ do moveResizeWindow d w 0 0 sw sh + raiseWindow d w + +-- | Modify the current window list with a pure funtion, and refresh +withWindows :: (Windows -> Windows) -> W () +withWindows f = do + modifyWindows f + refresh --- -- | manage. Add a new window to be managed --- manage :: Window -> W () manage w = do trace "manage" d <- gets display - withWindows $ \ws -> if w `elem` ws then ws else w:ws -- a set + withWindows (nub . (w :)) io $ mapWindow d w --- -- | unmanage, a window no longer exists, remove it from the stack --- unmanage :: Window -> W () unmanage w = do dpy <- gets display - io $ grabServer dpy - modifyWindows (filter (/= w)) - io $ sync dpy False - io $ ungrabServer dpy - refresh + io $ do grabServer dpy + sync dpy False + ungrabServer dpy + withWindows $ filter (/= w) --- --- | switch. switch focus to next window in list. +-- | focus. focus to window at offset 'n' in list. -- The currently focused window is always the head of the list --- -switch :: W () -switch = withWindows rotate +focus :: Int -> W () +focus n = withWindows (rotate n) --- -- | spawn. Launch an external application --- spawn :: String -> W () spawn = io_ . runCommand @@ -29,6 +29,14 @@ data WState = WState , windows :: !Windows } +-- +-- Multithreaded issues: +-- +-- We'll want a status bar, it will probably read from stdin +-- but will thus need to run in its own thread, and modify its status +-- bar window +-- + type Windows = [Window] -- | The W monad, a StateT transformer over IO encapuslating the window @@ -74,6 +82,23 @@ forever a = a >> forever a snoc :: [a] -> a -> [a] snoc xs x = xs ++ [x] --- | Rotate a list one element -rotate [] = [] -rotate (x:xs) = xs `snoc` x +-- | Rotate a list by 'n' elements. +-- +-- for xs = [5..8] ++ [1..4] +-- +-- rotate 0 +-- [5,6,7,8,1,2,3,4] +-- +-- rotate 1 +-- [6,7,8,1,2,3,4,5] +-- +-- rotate (-1) +-- [4,5,6,7,8,1,2,3] +-- +rotate n xs = take l . drop offset . cycle $ xs + where + l = length xs + offset | n < 0 = l + n + | otherwise = n + + |