From 6d21a15b2563c8e6f84e1a6fbc6f6b6eb3439cd0 Mon Sep 17 00:00:00 2001 From: Andrea Rossato Date: Sat, 14 Jul 2007 12:39:13 +0200 Subject: README and Cabal edits Added some more credits, corrected typos, updated darcs version to 0.7, changed name to Xmonbar and removed references to XMonad. Xmobar is now just a minimalistic text based status bar for any kind of WM (the XMonad community adopted the more advanced and stable dzen, after all ;-) darcs-hash:20070714103913-d6583-b143dedf4ed5cbcb59b4f630ffce9afe82e32b86.gz --- Commands.hs | 4 +- Config.hs | 6 +- Main.hs | 8 +- Monitors/Batt.hs | 2 +- Monitors/Common.hs | 2 +- Monitors/Cpu.hs | 2 +- Monitors/Mem.hs | 2 +- Monitors/Net.hs | 2 +- Monitors/Swap.hs | 2 +- Monitors/Weather.hs | 2 +- Parsers.hs | 4 +- Plugins/HelloWorld.hs | 2 +- README | 55 +++++------ Runnable.hs | 2 +- XMobar.hs | 254 -------------------------------------------------- Xmobar.hs | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++ xmobar.cabal | 12 ++- 17 files changed, 309 insertions(+), 306 deletions(-) delete mode 100644 XMobar.hs create mode 100644 Xmobar.hs diff --git a/Commands.hs b/Commands.hs index 1a80b80..61fc592 100644 --- a/Commands.hs +++ b/Commands.hs @@ -1,6 +1,6 @@ ----------------------------------------------------------------------------- -- | --- Module : XMobar.Commands +-- Module : Xmobar.Commands -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -14,7 +14,7 @@ -- appear in the 'Config.commands' field of the 'Config.Config' data type. -- -- The 'Command' data type stores the monitors to be run internally by --- XMobar. +-- Xmobar. -- ----------------------------------------------------------------------------- diff --git a/Config.hs b/Config.hs index 9d355ad..e21b7ff 100644 --- a/Config.hs +++ b/Config.hs @@ -1,6 +1,6 @@ ----------------------------------------------------------------------------- -- | --- Module : XMobar.Config +-- Module : Xmobar.Config -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- The configuration module of XMobar, a status bar for the Xmonad Window Manager +-- The configuration module of Xmobar, a text based status bar -- ----------------------------------------------------------------------------- @@ -62,7 +62,7 @@ defaultConfig = -- | This is the list of types that can be hidden inside -- 'Runnable.Runnable', the existential type that stores all commands --- to be executed by XMobar. It is used by 'Runnable.readRunnable' in +-- to be executed by Xmobar. It is used by 'Runnable.readRunnable' in -- the 'Runnable.Runnable' Read instance. To install a plugin just add -- the plugin's type to the list of types appearing in this function's type -- signature. diff --git a/Main.hs b/Main.hs index 5af383f..2f4fc70 100644 --- a/Main.hs +++ b/Main.hs @@ -1,6 +1,6 @@ ----------------------------------------------------------------------------- -- | --- Module : XMobar.Main +-- Module : Xmobar.Main -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- The main module of XMobar, a status bar for the Xmonad Window Manager +-- The main module of Xmobar, a text based status bar -- ----------------------------------------------------------------------------- @@ -19,7 +19,7 @@ module Main ( -- * Main Stuff , readDefaultConfig ) where -import XMobar +import Xmobar import Parsers import Config import System.Environment @@ -37,7 +37,7 @@ main = cl <- parseTemplate config (template config) var <- execCommands config cl (d,w) <- createWin config - runXMobar config var d w eventLoop + runXmobar config var d w eventLoop -- | Reads the configuration files or quits with an error readConfig :: FilePath -> IO Config diff --git a/Monitors/Batt.hs b/Monitors/Batt.hs index 2a81e12..57e9f6f 100644 --- a/Monitors/Batt.hs +++ b/Monitors/Batt.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A battery monitor for XMobar +-- A battery monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Common.hs b/Monitors/Common.hs index 06d5cd2..9928946 100644 --- a/Monitors/Common.hs +++ b/Monitors/Common.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- Utilities for creating monitors for XMobar +-- Utilities for creating monitors for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Cpu.hs b/Monitors/Cpu.hs index b3a125d..14acffb 100644 --- a/Monitors/Cpu.hs +++ b/Monitors/Cpu.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A cpu monitor for XMobar +-- A cpu monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Mem.hs b/Monitors/Mem.hs index dd132a7..04e12f5 100644 --- a/Monitors/Mem.hs +++ b/Monitors/Mem.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A memory monitor for XMobar +-- A memory monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Net.hs b/Monitors/Net.hs index ff1354c..f36c691 100644 --- a/Monitors/Net.hs +++ b/Monitors/Net.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A net device monitor for XMobar +-- A net device monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Swap.hs b/Monitors/Swap.hs index a2091e8..5460a19 100644 --- a/Monitors/Swap.hs +++ b/Monitors/Swap.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A swap usage monitor for XMobar +-- A swap usage monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Monitors/Weather.hs b/Monitors/Weather.hs index fb00d0b..6a9b829 100644 --- a/Monitors/Weather.hs +++ b/Monitors/Weather.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A weather monitor for XMobar +-- A weather monitor for Xmobar -- ----------------------------------------------------------------------------- diff --git a/Parsers.hs b/Parsers.hs index 8c25004..c7b0600 100644 --- a/Parsers.hs +++ b/Parsers.hs @@ -1,6 +1,6 @@ ----------------------------------------------------------------------------- -- | --- Module : XMobar.Parsers +-- Module : Xmobar.Parsers -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- Parsers needed for XMobar, a status bar for the Xmonad Window Manager +-- Parsers needed for Xmobar, a text based status bar -- ----------------------------------------------------------------------------- diff --git a/Plugins/HelloWorld.hs b/Plugins/HelloWorld.hs index 0d72379..c3a6a69 100644 --- a/Plugins/HelloWorld.hs +++ b/Plugins/HelloWorld.hs @@ -8,7 +8,7 @@ -- Stability : unstable -- Portability : unportable -- --- A plugin example for XMobar, a status bar for the Xmonad Window Manager +-- A plugin example for Xmobar, a text based status bar -- ----------------------------------------------------------------------------- diff --git a/README b/README index ef1f7a2..970c964 100644 --- a/README +++ b/README @@ -1,12 +1,14 @@ -XMobar - a status bar for the XMonad Window Manager +Xmobar - A Minimalistic Text Based Status Bar ABOUT ===== -Xmobar is a minimalistic, text based, status bar, designed for the -XMonad Window Manager. +Xmobar is a minimalistic, text based, status bar. + +It was inspired by the Ion3 status bar, and supports similar features, +like dynamic color management, output templates, and extensibility +through plugins. -It was inspired by the Ion3 status bar, and supports similar features. See xmobar.config-sample for a sample configuration. Try it with: @@ -49,9 +51,9 @@ Other configuration options: font: Name of the font to be used bgColor: Backgroud color fgColor: Default font color -xPos: x position (origin in the upper left corner) of the XMobar window +xPos: x position (origin in the upper left corner) of the Xmobar window yPos: y position -width: width of the XMobar window +width: width of the Xmobar window height: height align: text alignment refresh: Refresh rate in tenth of seconds @@ -63,14 +65,14 @@ template: The output template The Output Template ------------------- -The output template must contain at least one command. XMobar will +The output template must contain at least one command. Xmobar will parse the template and will search for the command to be executed in the "commands" configuration option. First an "alias" will be search (internal commands such as Weather or Network have default aliasing, see below). After that the command name will be tried. If a command is found, the arguments specified in the "commands" list will be used. -If no command is found in the "commands" list, XMobar will try to +If no command is found in the "commands" list, Xmobar will try to execute a program with the name found in the template. If the execution is not successful an error will be reported. @@ -78,9 +80,9 @@ The "commands" Configuration Option ----------------------------------- The "commands" configuration option is a list of commands' information -and arguments to be used by XMobar when parsing the output template. +and arguments to be used by Xmobar when parsing the output template. Each member of the list consists in a command prefixed by the "Run" -keyword. Each command has arguments to control the way XMobar is going +keyword. Each command has arguments to control the way Xmobar is going to execute it. Available template commands are: Weather, Network, Memory, Swap, Cpu, @@ -160,7 +162,7 @@ These are the arguments that can be used for internal commands in the Commands' arguments must be set as a list. Es: Run Weather "EGPF" ["-t",": C"] 36000 -In this case XMobar will run the weather monitor, getting information +In this case Xmobar will run the weather monitor, getting information for the weather station ID EGPF (Glasgow Airport, as a homage to GHC) every hour (36000 tenth of seconds), with a template that will output something like: @@ -192,7 +194,7 @@ PLUGINS Writing a Plugin ---------------- -Writing a plugin for XMobar should be very simple. You need to create +Writing a plugin for Xmobar should be very simple. You need to create a data type with at least one constructor. Next you must declare this data type an instance of the Exec class, by @@ -202,9 +204,9 @@ defining the 3 needed methods: rate :: e -> Int alias :: e -> String -"run" must produce the IO String that will be displayed by XMobar. +"run" must produce the IO String that will be displayed by Xmobar. "rate" is the refresh rate for you plugin (the number of tenth of -seconds between two succesive runs); +seconds between two successive runs); "alias" is the name to be used in the output template. That requires importing the plugin API (the Exec class definition), @@ -221,26 +223,26 @@ This requires importing you plugin into Config.hs and adding you type to the type list in the type signature of Config.runnableTypes. For a vary basic example see Plugins/HelloWorld.hs that is distributed -with XMobar. +with Xmobar. Installing a Plugin ------------------- Installing a plugin should require 3 steps. Here we are going to -install the HelloWorld plugin that comes with XMobar: +install the HelloWorld plugin that comes with Xmobar: 1. import the plugin module in Config.hs, by adding: import Plugins.HelloWorld 2. add the plugin data type to the list of data types in the type - signauture of "runnableTypes" in Config.hs. For instance, for the - HelloWorld plugin, chnage "runnableTypes" into: + signature of "runnableTypes" in Config.hs. For instance, for the + HelloWorld plugin, change "runnableTypes" into: runnableTypes :: (Command,(HelloWorld,())) runnableTypes = undefined -3. Rebuild and reinstall XMobar. Now test it with: +3. Rebuild and reinstall Xmobar. Now test it with: xmobar Plugins/helloworld.config @@ -264,19 +266,18 @@ CREDITS ======= Thanks to Robert Manea for his help in understanding how X works. He -gave me suggestions on how to solve many many problems with XMobar. +gave me suggestions on how to solve many problems with Xmobar. + +Thanks to Claus Reinke for make me understand existential types (or at +least for letting me thing I grasp existential types...;-). -XMobar incorporates patches from: -Krzysztof Kosciuszkiewicz +Xmobar incorporates patches from: Krzysztof Kosciuszkiewicz LINKS ===== -The XMobar home page: +The Xmobar home page: http://gorgias.mine.nu/repos/xmobar/ -XMobars darcs repository: +Xmobars darcs repository: http://gorgias.mine.nu/repos/xmobar/ - -The XMonad Window Manager -http://xmonad.org diff --git a/Runnable.hs b/Runnable.hs index 96216d0..c51d173 100644 --- a/Runnable.hs +++ b/Runnable.hs @@ -1,7 +1,7 @@ {-# OPTIONS -fglasgow-exts #-} ----------------------------------------------------------------------------- -- | --- Module : XMobar.Runnable +-- Module : Xmobar.Runnable -- Copyright : (c) Andrea Rossato -- License : BSD-style (see LICENSE) -- diff --git a/XMobar.hs b/XMobar.hs deleted file mode 100644 index 7da3bd3..0000000 --- a/XMobar.hs +++ /dev/null @@ -1,254 +0,0 @@ -{-# OPTIONS -fglasgow-exts #-} ------------------------------------------------------------------------------ --- | --- Module : XMobar --- Copyright : (c) Andrea Rossato --- License : BSD-style (see LICENSE) --- --- Maintainer : Andrea Rossato --- Stability : unstable --- Portability : unportable --- --- A status bar for the Xmonad Window Manager --- ------------------------------------------------------------------------------ - -module XMobar (-- * Main Stuff - -- $main - Xbar - , runXMobar - , eventLoop - , createWin - -- * Printing - -- $print - , drawInWin - , printStrings - -- * Program Execution - -- $commands - , execCommands - , execCommand - , runCommandLoop - , readVariables - -- * Unmamaged Windows - -- $unmanwin - , mkUnmanagedWindow - -- * Useful Utilities - , initColor - , io - ) where - -import Graphics.X11.Xlib -import Graphics.X11.Xlib.Misc - -import Control.Monad.State -import Control.Monad.Reader -import Control.Concurrent - -import Config -import Parsers -import Commands -import Runnable - --- $main --- --- The XMobar data type and basic loops and functions. - --- | This is just esthetics, stolen from XMonad: see 'runXMobar' -newtype Xbar a = X (ReaderT Config (StateT XState IO) a) - deriving (Functor, Monad, MonadIO, MonadState XState, MonadReader Config) - --- | The State component of StateT -data XState = - XState { display :: Display - , window :: Window - , vars :: [(ThreadId, MVar String)] - } - --- | Totally useless: but it is nice to be able to use get to get the --- state and ask to get the configuration: functions requires less --- arguments, after all. -runXMobar :: Config -> [(ThreadId, MVar String)] -> Display -> Window -> Xbar () -> IO () -runXMobar c v d w (X f) = - do runStateT (runReaderT f c) (XState d w v) - return () - --- | The event loop -eventLoop :: Xbar () -eventLoop = - do c <- ask - s <- get - i <- io $ readVariables (vars s) - ps <- io $ parseString c i - drawInWin ps - -- back again: we are never ending - io $ tenthSeconds (refresh c) - eventLoop - --- | The function to create the initial window -createWin :: Config -> IO (Display, Window) -createWin config = - do dpy <- openDisplay "" - let dflt = defaultScreen dpy - rootw <- rootWindow dpy dflt - win <- mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw - (fi $ xPos config) - (fi $ yPos config) - (fi $ width config) - (fi $ height config) - mapWindow dpy win - return (dpy,win) - - --- $print - --- | Draws in and updates the window -drawInWin :: [(String, String)] -> Xbar () -drawInWin str = - do config <- ask - st <- get - let (dpy,win) = (display st, window st) - bgcolor <- io $ initColor dpy $ bgColor config - gc <- io $ createGC dpy win - --let's get the fonts - fontst <- io $ loadQueryFont dpy (font config) - io $ setFont dpy gc (fontFromFontStruct fontst) - -- create a pixmap to write to and fill it with a rectangle - p <- io $ createPixmap dpy win - (fi (width config)) - (fi (height config)) - (defaultDepthOfScreen (defaultScreenOfDisplay dpy)) - -- the fgcolor of the rectangle will be the bgcolor of the window - io $ setForeground dpy gc bgcolor - io $ fillRectangle dpy p gc 0 0 - (fi $ width config) - (fi $ height config) - -- write to the pixmap the new string - let strWithLenth = map (\(s,c) -> (s,c,textWidth fontst s)) str - p' <- printStrings p gc fontst 1 strWithLenth - -- copy the pixmap with the new string to the window - io $ copyArea dpy p' win gc 0 0 (fi (width config)) (fi (height config)) 0 0 - -- free up everything (we do not want to leak memory!) - io $ freeFont dpy fontst - io $ freeGC dpy gc - io $ freePixmap dpy p' - -- resync - io $ sync dpy True - --- | An easy way to print the stuff we need to print -printStrings :: Drawable - -> GC - -> FontStruct - -> Position - -> [(String, String, Position)] - -> Xbar Pixmap -printStrings p _ _ _ [] = return p -printStrings p gc fontst offs sl@((s,c,l):xs) = - do config <- ask - st <- get - let (_,asc,_,_) = textExtents fontst s - totSLen = foldr (\(_,_,len) -> (+) len) 0 sl - valign = (fi (height config) + fi asc) `div` 2 - remWidth = fi (width config) - fi totSLen - offset = case (align config) of - "center" -> (remWidth + offs) `div` 2 - "right" -> remWidth - 1 - "left" -> offs - _ -> offs - fgcolor <- io $ initColor (display st) c - bgcolor <- io $ initColor (display st) (bgColor config) - io $ setForeground (display st) gc fgcolor - io $ setBackground (display st) gc bgcolor - io $ drawImageString (display st) p gc offset valign s - p' <- printStrings p gc fontst (offs + l) xs - return p' - --- $commands - --- | Runs a list of programs as independent threads and returns their thread id --- and the MVar they will be writing to. -execCommands :: Config -> [(Runnable,String,String)] -> IO [(ThreadId, MVar String)] -execCommands _ [] = return [] -execCommands c (x:xs) = - do i <- execCommand c x - is <- execCommands c xs - return $ i : is - -execCommand :: Config -> (Runnable,String,String) -> IO (ThreadId, MVar String) -execCommand c com = - do var <- newMVar "Updating..." - h <- forkIO $ runCommandLoop var c com - return (h,var) - -runCommandLoop :: MVar String -> Config -> (Runnable,String,String) -> IO () -runCommandLoop var conf c@(com,s,ss) - | alias com == "" = - do modifyMVar_ var (\_ -> return $ "Could not parse the template") - tenthSeconds (refresh conf) - runCommandLoop var conf c - | otherwise = - do str <- run com - modifyMVar_ var (\_ -> return $ s ++ str ++ ss) - tenthSeconds (rate com) - runCommandLoop var conf c - --- | Reads MVars set by 'runCommandLoop' -readVariables :: [(ThreadId, MVar String)] -> IO String -readVariables [] = return "" -readVariables ((_,v):xs) = - do f <- readMVar v - fs <- readVariables xs - return $! f ++ fs - -{- $unmanwin - -This is a way to create unmamaged window. It was a mistery in Haskell. -Till I've found out...;-) - --} - --- | Creates a window with the attribute override_redirect set to True. --- Windows Managers should not touch this kind of windows. -mkUnmanagedWindow :: Display - -> Screen - -> Window - -> Position - -> Position - -> Dimension - -> Dimension - -> IO Window -mkUnmanagedWindow dpy scr rw x y w h = do - let visual = defaultVisualOfScreen scr - attrmask = cWOverrideRedirect - win <- allocaSetWindowAttributes $ - \attributes -> do - set_override_redirect attributes True - createWindow dpy rw x y w h 0 (defaultDepthOfScreen scr) - inputOutput visual attrmask attributes - return win - -{- $utility -Utilities, aka stollen without givin' credit stuff. --} - --- | Get the Pixel value for a named color -initColor :: Display -> String -> IO Pixel -initColor dpy c = (color_pixel . fst) `liftM` allocNamedColor dpy colormap c - where colormap = defaultColormap dpy (defaultScreen dpy) - --- | Short-hand for lifting in the IO monad -io :: IO a -> Xbar a -io = liftIO - --- | Work arount to the Int max bound: since threadDelay takes an Int, it --- is not possible to set a thread delay grater than about 45 minutes. --- With a little recursion we solve the problem. -tenthSeconds :: Int -> IO () -tenthSeconds s | s >= x = do threadDelay y - tenthSeconds (x - s) - | otherwise = threadDelay (s * 100000) - where y = (maxBound :: Int) - x = y `div` 100000 - --- | Short-hand for 'fromIntegral' -fi :: (Integral a, Num b) => a -> b -fi = fromIntegral diff --git a/Xmobar.hs b/Xmobar.hs new file mode 100644 index 0000000..dc05d7d --- /dev/null +++ b/Xmobar.hs @@ -0,0 +1,254 @@ +{-# OPTIONS -fglasgow-exts #-} +----------------------------------------------------------------------------- +-- | +-- Module : Xmobar +-- Copyright : (c) Andrea Rossato +-- License : BSD-style (see LICENSE) +-- +-- Maintainer : Andrea Rossato +-- Stability : unstable +-- Portability : unportable +-- +-- A status bar for the Xmonad Window Manager +-- +----------------------------------------------------------------------------- + +module Xmobar (-- * Main Stuff + -- $main + Xbar + , runXmobar + , eventLoop + , createWin + -- * Printing + -- $print + , drawInWin + , printStrings + -- * Program Execution + -- $commands + , execCommands + , execCommand + , runCommandLoop + , readVariables + -- * Unmamaged Windows + -- $unmanwin + , mkUnmanagedWindow + -- * Useful Utilities + , initColor + , io + ) where + +import Graphics.X11.Xlib +import Graphics.X11.Xlib.Misc + +import Control.Monad.State +import Control.Monad.Reader +import Control.Concurrent + +import Config +import Parsers +import Commands +import Runnable + +-- $main +-- +-- The Xmobar data type and basic loops and functions. + +-- | This is just esthetics, stolen from XMonad: see 'runXmobar' +newtype Xbar a = X (ReaderT Config (StateT XState IO) a) + deriving (Functor, Monad, MonadIO, MonadState XState, MonadReader Config) + +-- | The State component of StateT +data XState = + XState { display :: Display + , window :: Window + , vars :: [(ThreadId, MVar String)] + } + +-- | Totally useless: but it is nice to be able to use get to get the +-- state and ask to get the configuration: functions requires less +-- arguments, after all. +runXmobar :: Config -> [(ThreadId, MVar String)] -> Display -> Window -> Xbar () -> IO () +runXmobar c v d w (X f) = + do runStateT (runReaderT f c) (XState d w v) + return () + +-- | The event loop +eventLoop :: Xbar () +eventLoop = + do c <- ask + s <- get + i <- io $ readVariables (vars s) + ps <- io $ parseString c i + drawInWin ps + -- back again: we are never ending + io $ tenthSeconds (refresh c) + eventLoop + +-- | The function to create the initial window +createWin :: Config -> IO (Display, Window) +createWin config = + do dpy <- openDisplay "" + let dflt = defaultScreen dpy + rootw <- rootWindow dpy dflt + win <- mkUnmanagedWindow dpy (defaultScreenOfDisplay dpy) rootw + (fi $ xPos config) + (fi $ yPos config) + (fi $ width config) + (fi $ height config) + mapWindow dpy win + return (dpy,win) + + +-- $print + +-- | Draws in and updates the window +drawInWin :: [(String, String)] -> Xbar () +drawInWin str = + do config <- ask + st <- get + let (dpy,win) = (display st, window st) + bgcolor <- io $ initColor dpy $ bgColor config + gc <- io $ createGC dpy win + --let's get the fonts + fontst <- io $ loadQueryFont dpy (font config) + io $ setFont dpy gc (fontFromFontStruct fontst) + -- create a pixmap to write to and fill it with a rectangle + p <- io $ createPixmap dpy win + (fi (width config)) + (fi (height config)) + (defaultDepthOfScreen (defaultScreenOfDisplay dpy)) + -- the fgcolor of the rectangle will be the bgcolor of the window + io $ setForeground dpy gc bgcolor + io $ fillRectangle dpy p gc 0 0 + (fi $ width config) + (fi $ height config) + -- write to the pixmap the new string + let strWithLenth = map (\(s,c) -> (s,c,textWidth fontst s)) str + p' <- printStrings p gc fontst 1 strWithLenth + -- copy the pixmap with the new string to the window + io $ copyArea dpy p' win gc 0 0 (fi (width config)) (fi (height config)) 0 0 + -- free up everything (we do not want to leak memory!) + io $ freeFont dpy fontst + io $ freeGC dpy gc + io $ freePixmap dpy p' + -- resync + io $ sync dpy True + +-- | An easy way to print the stuff we need to print +printStrings :: Drawable + -> GC + -> FontStruct + -> Position + -> [(String, String, Position)] + -> Xbar Pixmap +printStrings p _ _ _ [] = return p +printStrings p gc fontst offs sl@((s,c,l):xs) = + do config <- ask + st <- get + let (_,asc,_,_) = textExtents fontst s + totSLen = foldr (\(_,_,len) -> (+) len) 0 sl + valign = (fi (height config) + fi asc) `div` 2 + remWidth = fi (width config) - fi totSLen + offset = case (align config) of + "center" -> (remWidth + offs) `div` 2 + "right" -> remWidth - 1 + "left" -> offs + _ -> offs + fgcolor <- io $ initColor (display st) c + bgcolor <- io $ initColor (display st) (bgColor config) + io $ setForeground (display st) gc fgcolor + io $ setBackground (display st) gc bgcolor + io $ drawImageString (display st) p gc offset valign s + p' <- printStrings p gc fontst (offs + l) xs + return p' + +-- $commands + +-- | Runs a list of programs as independent threads and returns their thread id +-- and the MVar they will be writing to. +execCommands :: Config -> [(Runnable,String,String)] -> IO [(ThreadId, MVar String)] +execCommands _ [] = return [] +execCommands c (x:xs) = + do i <- execCommand c x + is <- execCommands c xs + return $ i : is + +execCommand :: Config -> (Runnable,String,String) -> IO (ThreadId, MVar String) +execCommand c com = + do var <- newMVar "Updating..." + h <- forkIO $ runCommandLoop var c com + return (h,var) + +runCommandLoop :: MVar String -> Config -> (Runnable,String,String) -> IO () +runCommandLoop var conf c@(com,s,ss) + | alias com == "" = + do modifyMVar_ var (\_ -> return $ "Could not parse the template") + tenthSeconds (refresh conf) + runCommandLoop var conf c + | otherwise = + do str <- run com + modifyMVar_ var (\_ -> return $ s ++ str ++ ss) + tenthSeconds (rate com) + runCommandLoop var conf c + +-- | Reads MVars set by 'runCommandLoop' +readVariables :: [(ThreadId, MVar String)] -> IO String +readVariables [] = return "" +readVariables ((_,v):xs) = + do f <- readMVar v + fs <- readVariables xs + return $! f ++ fs + +{- $unmanwin + +This is a way to create unmamaged window. It was a mistery in Haskell. +Till I've found out...;-) + +-} + +-- | Creates a window with the attribute override_redirect set to True. +-- Windows Managers should not touch this kind of windows. +mkUnmanagedWindow :: Display + -> Screen + -> Window + -> Position + -> Position + -> Dimension + -> Dimension + -> IO Window +mkUnmanagedWindow dpy scr rw x y w h = do + let visual = defaultVisualOfScreen scr + attrmask = cWOverrideRedirect + win <- allocaSetWindowAttributes $ + \attributes -> do + set_override_redirect attributes True + createWindow dpy rw x y w h 0 (defaultDepthOfScreen scr) + inputOutput visual attrmask attributes + return win + +{- $utility +Utilities, aka stollen without givin' credit stuff. +-} + +-- | Get the Pixel value for a named color +initColor :: Display -> String -> IO Pixel +initColor dpy c = (color_pixel . fst) `liftM` allocNamedColor dpy colormap c + where colormap = defaultColormap dpy (defaultScreen dpy) + +-- | Short-hand for lifting in the IO monad +io :: IO a -> Xbar a +io = liftIO + +-- | Work arount to the Int max bound: since threadDelay takes an Int, it +-- is not possible to set a thread delay grater than about 45 minutes. +-- With a little recursion we solve the problem. +tenthSeconds :: Int -> IO () +tenthSeconds s | s >= x = do threadDelay y + tenthSeconds (x - s) + | otherwise = threadDelay (s * 100000) + where y = (maxBound :: Int) + x = y `div` 100000 + +-- | Short-hand for 'fromIntegral' +fi :: (Integral a, Num b) => a -> b +fi = fromIntegral diff --git a/xmobar.cabal b/xmobar.cabal index 3a633aa..89d79c2 100644 --- a/xmobar.cabal +++ b/xmobar.cabal @@ -1,10 +1,12 @@ name: xmobar -version: 0.6 +version: 0.7 homepage: http://gorgias.mine.nu/repos/xmobar/ -synopsis: A Statusbar for the XMonad Window Manager -description: Xmobar is a minimal status bar for the XMonad Window Manager. +synopsis: A Minimalistic Text Based Status Bar +description: Xmobar is a minimalistic text based status bar. . - It was inspired by the Ion3 status bar, and supports similar features. + Inspired by the Ion3 status bar, it supports similar features, + like dynamic color management, output templates, and extensibility + through plugins. category: System license: BSD3 license-file: LICENSE @@ -15,7 +17,7 @@ build-depends: base>=2.0, X11>=1.2.1, mtl>=1.0, unix>=1.0, parsec>=2.0, fil executable: xmobar main-is: Main.hs Hs-Source-Dirs: ./ -Other-Modules: XMobar, Config, Parsers, Commands, Runnable, Plugins, Monitors.Common, Monitors.Batt +Other-Modules: Xmobar, Config, Parsers, Commands, Runnable, Plugins, Monitors.Common, Monitors.Batt Monitors.Weather, Monitors.Swap, Monitors.Mem, Monitors.Cpu, Monitors.Net ghc-options: -funbox-strict-fields -O2 -fasm -Wall -optl-Wl,-s -threaded ghc-prof-options: -prof -auto-all -- cgit v1.2.3