summaryrefslogtreecommitdiffhomepage
path: root/Xmobar.hs
diff options
context:
space:
mode:
authorJose Antonio Ortega Ruiz <jao@gnu.org>2010-12-21 02:36:35 +0100
committerJose Antonio Ortega Ruiz <jao@gnu.org>2010-12-21 02:36:35 +0100
commite3853a9cb2a9a2cffa174d1334e2ca8ba610f151 (patch)
tree13aa04faea320afe85636e23686280386c1c2910 /Xmobar.hs
parent598bfe5deeff079280e8513c55dc7bda3e8cf9a0 (diff)
downloadxmobar-e3853a9cb2a9a2cffa174d1334e2ca8ba610f151.tar.gz
xmobar-e3853a9cb2a9a2cffa174d1334e2ca8ba610f151.tar.bz2
Haskell sources moved to src/ to unclutter toplevel
Diffstat (limited to 'Xmobar.hs')
-rw-r--r--Xmobar.hs306
1 files changed, 0 insertions, 306 deletions
diff --git a/Xmobar.hs b/Xmobar.hs
deleted file mode 100644
index 2f5aa3c..0000000
--- a/Xmobar.hs
+++ /dev/null
@@ -1,306 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable #-}
------------------------------------------------------------------------------
--- |
--- Module : Xmobar
--- Copyright : (c) Andrea Rossato
--- License : BSD-style (see LICENSE)
---
--- Maintainer : Jose A. Ortega Ruiz <jao@gnu.org>
--- Stability : unstable
--- Portability : unportable
---
--- A status bar for the Xmonad Window Manager
---
------------------------------------------------------------------------------
-
-module Xmobar
- ( -- * Main Stuff
- -- $main
- X , XConf (..), runX
- , eventLoop
- -- * Program Execution
- -- $command
- , startCommand
- -- * Window Management
- -- $window
- , createWin, updateWin
- -- * Printing
- -- $print
- , drawInWin, printStrings
- ) where
-
-import Prelude hiding (catch)
-import Graphics.X11.Xlib hiding (textExtents, textWidth)
-import Graphics.X11.Xlib.Extras
-import Graphics.X11.Xinerama
-
-import Control.Arrow ((&&&))
-import Control.Monad.Reader
-import Control.Concurrent
-import Control.Concurrent.STM
-import Control.Exception hiding (handle)
-import Data.Bits
-import Data.Maybe(fromMaybe)
-import Data.Typeable (Typeable)
-
-import Config
-import Parsers
-import Commands
-import Runnable
-import XUtil
-
--- $main
---
--- The Xmobar data type and basic loops and functions.
-
--- | The X type is a ReaderT
-type X = ReaderT XConf IO
-
--- | The ReaderT inner component
-data XConf =
- XConf { display :: Display
- , rect :: Rectangle
- , window :: Window
- , fontS :: XFont
- , config :: Config
- }
-
--- | Runs the ReaderT
-runX :: XConf -> X () -> IO ()
-runX xc f = runReaderT f xc
-
-data WakeUp = WakeUp deriving (Show,Typeable)
-instance Exception WakeUp
-
--- | The event loop
-eventLoop :: XConf -> [(Maybe ThreadId, TVar String)] -> IO ()
-eventLoop xc@(XConf d _ w fs c) v = block $ do
- tv <- atomically $ newTVar []
- t <- myThreadId
- ct <- forkIO (checker t tv "" `catch` \(SomeException _) -> return ())
- go tv ct
- where
- -- interrupt the drawing thread every time a var is updated
- checker t tvar ov = do
- nval <- atomically $ do
- nv <- fmap concat $ mapM readTVar (map snd v)
- guard (nv /= ov)
- writeTVar tvar nv
- return nv
- throwTo t WakeUp
- checker t tvar nval
-
- -- Continuously wait for a timer interrupt or an expose event
- go tv ct = do
- catch (unblock $ allocaXEvent $ \e ->
- handle tv ct =<< (nextEvent' d e >> getEvent e))
- (\WakeUp -> runX xc (updateWin tv) >> return ())
- go tv ct
-
- -- event hanlder
- handle _ ct (ConfigureEvent {ev_window = win}) = do
- rootw <- rootWindow d (defaultScreen d)
- when (win == rootw) $ block $ do
- killThread ct
- destroyWindow d w
- (r',w') <- createWin d fs c
- eventLoop (XConf d r' w' fs c) v
-
- handle tvar _ (ExposeEvent {}) = runX xc (updateWin tvar)
-
- handle _ _ _ = return ()
-
--- $command
-
--- | Runs a command as an independent thread and returns its thread id
--- and the TVar the command will be writing to.
-startCommand :: (Runnable,String,String) -> IO (Maybe ThreadId, TVar String)
-startCommand (com,s,ss)
- | alias com == "" = do var <- atomically $ newTVar is
- atomically $ writeTVar var "Could not parse the template"
- return (Nothing,var)
- | otherwise = do var <- atomically $ newTVar is
- let cb str = atomically $ writeTVar var (s ++ str ++ ss)
- h <- forkIO $ start com cb
- return (Just h,var)
- where is = s ++ "Updating..." ++ ss
-
--- $window
-
--- | The function to create the initial window
-createWin :: Display -> XFont -> Config -> IO (Rectangle,Window)
-createWin d fs c = do
- let dflt = defaultScreen d
- srs <- getScreenInfo d
- rootw <- rootWindow d dflt
- (as,ds) <- textExtents fs "0"
- let ht = as + ds + 4
- (r,o) = setPosition (position c) srs (fi ht)
- win <- newWindow d (defaultScreenOfDisplay d) rootw r o
- selectInput d win (exposureMask .|. structureNotifyMask)
- setProperties r c d win srs
- when (lowerOnStart c) (lowerWindow d win)
- mapWindow d win
- return (r,win)
-
-setPosition :: XPosition -> [Rectangle] -> Dimension -> (Rectangle,Bool)
-setPosition p rs ht =
- case p' of
- Top -> (Rectangle rx ry rw h , True)
- TopW a i -> (Rectangle (ax a i ) ry (nw i ) h , True)
- TopSize a i ch -> (Rectangle (ax a i ) ry (nw i ) (mh ch), True)
- Bottom -> (Rectangle rx ny rw h , True)
- BottomW a i -> (Rectangle (ax a i ) ny (nw i ) h , True)
- BottomSize a i ch -> (Rectangle (ax a i ) ny (nw i ) (mh ch), True)
- Static cx cy cw ch -> (Rectangle (fi cx ) (fi cy) (fi cw) (fi ch), True)
- OnScreen _ p'' -> setPosition p'' [scr] ht
- where
- (scr@(Rectangle rx ry rw rh), p') =
- case p of OnScreen i x -> (fromMaybe (head rs) $ safeIndex i rs, x)
- _ -> (head rs, p)
- ny = ry + fi (rh - ht)
- center i = rx + (fi $ div (remwid i) 2)
- right i = rx + (fi $ remwid i)
- remwid i = rw - pw (fi i)
- ax L = const rx
- ax R = right
- ax C = center
- pw i = rw * (min 100 i) `div` 100
- nw = fi . pw . fi
- h = fi ht
- mh h' = max (fi h') h
-
- safeIndex i = lookup i . zip [0..]
-
-setProperties :: Rectangle -> Config -> Display -> Window -> [Rectangle] -> IO ()
-setProperties r c d w srs = do
- a1 <- internAtom d "_NET_WM_STRUT_PARTIAL" False
- c1 <- internAtom d "CARDINAL" False
- a2 <- internAtom d "_NET_WM_WINDOW_TYPE" False
- c2 <- internAtom d "ATOM" False
- v <- internAtom d "_NET_WM_WINDOW_TYPE_DOCK" False
- changeProperty32 d w a1 c1 propModeReplace $ map fi $
- getStrutValues r (position c) (getRootWindowHeight srs)
- changeProperty32 d w a2 c2 propModeReplace [fromIntegral v]
-
-getRootWindowHeight :: [Rectangle] -> Int
-getRootWindowHeight srs = foldr1 max (map getMaxScreenYCoord srs)
- where
- getMaxScreenYCoord sr = fi (rect_y sr) + fi (rect_height sr)
-
-getStrutValues :: Rectangle -> XPosition -> Int -> [Int]
-getStrutValues r@(Rectangle x y w h) p rwh =
- case p of
- OnScreen _ p' -> getStrutValues r p' rwh
- Top -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- TopW _ _ -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- TopSize {} -> [0, 0, st, 0, 0, 0, 0, 0, nx, nw, 0, 0]
- Bottom -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- BottomW _ _ -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- BottomSize {} -> [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, nx, nw]
- Static _ _ _ _ -> getStaticStrutValues p rwh
- where st = fi y + fi h
- sb = rwh - fi y
- nx = fi x
- nw = fi (x + fi w - 1)
-
--- get some reaonable strut values for static placement.
-getStaticStrutValues :: XPosition -> Int -> [Int]
-getStaticStrutValues (Static cx cy cw ch) rwh
- -- if the yPos is in the top half of the screen, then assume a Top
- -- placement, otherwise, it's a Bottom placement
- | cy < (rwh `div` 2) = [0, 0, st, 0, 0, 0, 0, 0, xs, xe, 0, 0]
- | otherwise = [0, 0, 0, sb, 0, 0, 0, 0, 0, 0, xs, xe]
- where st = cy + ch
- sb = rwh - cy
- xs = cx -- a simple calculation for horizontal (x) placement
- xe = xs + cw
-getStaticStrutValues _ _ = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-
-updateWin :: TVar String -> X ()
-updateWin v = do
- xc <- ask
- let (conf,rec) = (config &&& rect) xc
- [lc,rc] = if length (alignSep conf) == 2
- then alignSep conf
- else alignSep defaultConfig
- i <- io $ atomically $ readTVar v
- let def = [i,[],[]]
- [l,c,r] = case break (==lc) i of
- (le,_:re) -> case break (==rc) re of
- (ce,_:ri) -> [le,ce,ri]
- _ -> def
- _ -> def
- ps <- io $ mapM (parseString conf) [l,c,r]
- drawInWin rec ps
-
--- $print
-
--- | Draws in and updates the window
-drawInWin :: Rectangle -> [[(String, String)]] -> X ()
-drawInWin (Rectangle _ _ wid ht) ~[left,center,right] = do
- r <- ask
- let (c,d ) = (config &&& display) r
- (w,fs) = (window &&& fontS ) r
- strLn = io . mapM (\(s,cl) -> textWidth d fs s >>= \tw -> return (s,cl,fi tw))
- withColors d [bgColor c, borderColor c] $ \[bgcolor, bdcolor] -> do
- gc <- io $ createGC d w
- -- create a pixmap to write to and fill it with a rectangle
- p <- io $ createPixmap d w wid ht
- (defaultDepthOfScreen (defaultScreenOfDisplay d))
- -- the fgcolor of the rectangle will be the bgcolor of the window
- io $ setForeground d gc bgcolor
- io $ fillRectangle d p gc 0 0 wid ht
- -- write to the pixmap the new string
- printStrings p gc fs 1 L =<< strLn left
- printStrings p gc fs 1 R =<< strLn right
- printStrings p gc fs 1 C =<< strLn center
- -- draw 1 pixel border if requested
- io $ drawBorder (border c) d p gc bdcolor wid ht
- -- copy the pixmap with the new string to the window
- io $ copyArea d p w gc 0 0 wid ht 0 0
- -- free up everything (we do not want to leak memory!)
- io $ freeGC d gc
- io $ freePixmap d p
- -- resync
- io $ sync d True
-
-drawBorder :: Border -> Display -> Drawable -> GC -> Pixel -> Dimension
- -> Dimension -> IO ()
-drawBorder b d p gc c wi ht = case b of
- NoBorder -> return ()
- TopB -> drawBorder (TopBM 0) d p gc c w h
- BottomB -> drawBorder (BottomBM 0) d p gc c w h
- FullB -> drawBorder (FullBM 0) d p gc c w h
- TopBM m -> sf >> drawLine d p gc 0 (fi m) (fi w) 0
- BottomBM m -> let rw = (fi h) - (fi m) in
- sf >> drawLine d p gc 0 rw (fi w) rw
- FullBM m -> let rm = fi m; mp = fi m in
- sf >> drawRectangle d p gc mp mp (w - rm) (h - rm)
- where sf = setForeground d gc c
- (w, h) = (wi - 1, ht - 1)
-
--- | An easy way to print the stuff we need to print
-printStrings :: Drawable -> GC -> XFont -> Position
- -> Align -> [(String, String, Position)] -> X ()
-printStrings _ _ _ _ _ [] = return ()
-printStrings dr gc fontst offs a sl@((s,c,l):xs) = do
- r <- ask
- (as,ds) <- io $ textExtents fontst s
- let (conf,d) = (config &&& display) r
- Rectangle _ _ wid ht = rect r
- totSLen = foldr (\(_,_,len) -> (+) len) 0 sl
- valign = fi $ as + ds
- remWidth = fi wid - fi totSLen
- offset = case a of
- C -> (remWidth + offs) `div` 2
- R -> remWidth
- L -> offs
- (fc,bc) = case (break (==',') c) of
- (f,',':b) -> (f, b )
- (f, _) -> (f, bgColor conf)
- withColors d [bc] $ \[bc'] -> do
- io $ setForeground d gc bc'
- io $ fillRectangle d dr gc offset 0 (fi l) ht
- io $ printString d dr fontst gc fc bc offset valign s
- printStrings dr gc fontst (offs + l) a xs