module XMonad.Stockholm.Pager ( defaultWindowColors , defaultWorkspaceColors , MatchMethod(..) , pager , PagerConfig(..) ) where import qualified XMonad.StackSet as W import Data.List (find) import Data.Maybe (catMaybes) import Graphics.X11 import XMonad import XMonad.Hooks.UrgencyHook import XMonad.Util.Font (fi, stringToPixel) import XMonad.Stockholm.Rhombus data PagerConfig = PagerConfig { pc_font :: String , pc_cellwidth :: Dimension , pc_margin :: Dimension , pc_matchmethod :: MatchMethod , pc_wrap :: Bool , pc_workspaceColors :: Bool -> Bool -> Bool -> (String, String, String) , pc_windowColors :: Bool -> Bool -> Bool -> Bool -> Bool -> (String, String) } instance Default PagerConfig where def = PagerConfig "xft:Sans-8" 100 0 MatchInfix True defaultWorkspaceColors defaultWindowColors pager :: PagerConfig -> (String -> X ()) -> [String] -> X () pager pc = rhombus def { rc_font = pc_font pc , rc_cellwidth = pc_cellwidth pc , rc_margin = pc_margin pc , rc_matchmethod = pc_matchmethod pc , rc_wrap = pc_wrap pc , rc_colors = pc_workspaceColors pc , rc_paint = pagerPaint pc } defaultWorkspaceColors :: Bool -- workspace has focus -> Bool -- workspace name matches incremental search -> Bool -- workspace is the current one -> (String, String, String) -- workspace border, background color, and foreground color defaultWorkspaceColors False False False = ("#101010","#050505","#202020") defaultWorkspaceColors False False True = ("#101010","#050505","#202020") defaultWorkspaceColors False True False = ("#404040","#202020","#b0b0b0") defaultWorkspaceColors False True True = ("#101010","#050505","#505050") defaultWorkspaceColors True _ False = ("#808020","#404010","#f0f0b0") defaultWorkspaceColors True _ True = ("#404010","#202005","#909050") defaultWindowColors :: Bool -- window's workspace has focus -> Bool -- window's workspace name matches incremental search -> Bool -- window's workspace the current one -> Bool -- window is urgent -> Bool -- window has focus -> (String, String) -- window border and background color defaultWindowColors wsf m c u True = ("#802020", snd $ defaultWindowColors wsf m c u False) defaultWindowColors False False False False _ = ("#111111","#060606") defaultWindowColors False False False True _ = ("#802020","#401010") defaultWindowColors False False True False _ = ("#101010","#050505") defaultWindowColors False False True True _ = ("#401010","#200505") defaultWindowColors False True False False _ = ("#202080","#101040") defaultWindowColors False True False True _ = ("#802080","#401040") defaultWindowColors False True True False _ = ("#101040","#100520") defaultWindowColors False True True True _ = ("#401040","#200520") defaultWindowColors True False False False _ = ("#208020","#104010") defaultWindowColors True False False True _ = ("#808020","#404010") defaultWindowColors True False True False _ = ("#104010","#052005") defaultWindowColors True False True True _ = ("#404010","#202005") defaultWindowColors True True False False _ = ("#208080","#104040") defaultWindowColors True True False True _ = ("#808080","#404040") defaultWindowColors True True True False _ = ("#104040","#102020") defaultWindowColors True True True True _ = ("#404040","#202020") pagerPaint :: PagerConfig -> RhombusConfig -> Display -> Drawable -> GC -> WorkspaceId -> Rectangle -> Bool -> Bool -> Bool -> X () pagerPaint pc rc _ p gc t r foc match current = do ss <- gets windowset let x = rect_x r y = rect_y r urgents <- readUrgents let foci = map W.focus $ catMaybes $ map W.stack $ W.workspaces ss let color = pc_windowColors pc foc match current -- :: Bool -> (String, String) (_, _, _fg_color) = pc_workspaceColors pc foc match current let sr = screenRect $ W.screenDetail $ W.current ss let scale = fi (rc_cellwidth rc) / fi (rect_width sr) -- TODO whenNothing print error whenJust (findWorkspace t ss) $ \ ws -> do whenJust (W.stack ws) $ \ s -> withDisplay $ \ d -> io $ do let color' w = color (w `elem` urgents) (w `elem` foci) -- TODO painting of floating windows is broken mapM_ (drawMiniWindow d p gc x y color' scale) (W.down s) drawMiniWindow d p gc x y color' scale (W.focus s) mapM_ (drawMiniWindow d p gc x y color' scale) (W.up s) drawMiniWindow :: Display -> Drawable -> GC -> Position -> Position -> (Window -> (String, String)) -> Double -> Window -> IO () drawMiniWindow d p gc ox oy color s win = do let scale x = round $ fi x * s wa <- getWindowAttributes d win let x = ox + (scale $ wa_x wa) y = oy + (scale $ wa_y wa) w = (scale $ wa_width wa) h = (scale $ wa_height wa) let (fg, bg) = color win fg' <- stringToPixel d fg bg' <- stringToPixel d bg setForeground d gc bg' fillRectangle d p gc (x + 1) (y + 1) (w - 2) (h - 2) setForeground d gc fg' drawLines d p gc [ Point x y , Point (fi w - 1) 0 , Point 0 (fi h - 2) , Point (- fi w + 1) 0 , Point 0 (- fi h + 2) ] coordModePrevious -- TODO externalize findWorkspace findWorkspace :: (Eq i) => i -> W.StackSet i l a sid sd -> Maybe (W.Workspace i l a) findWorkspace t ss = find ((==)t . W.tag) (W.workspaces ss)