------------------------------------------------------------------------------
-- |
-- Module : Dzen
-- Copyright : (c) Mads N Noe 2010
-- Maintainer : mail (@) madsnoe.dk
-- License : as-is
--
-- Functions for spawning dzen instances.
--
------------------------------------------------------------------------------
module Panel
( spawnPanels
, killPanels
, getScreenCount
) where
-- Haskell modules
import Control.Monad
import Data.List
import Foreign.C.Types (CInt)
import GHC.IOBase (Handle)
import System.Cmd
import System.Environment (getEnv)
import System.Posix.Files(fileExist)
-- XMonad modules
import Control.Monad
import Graphics.X11.Xlib
import Graphics.X11.Xinerama
import XMonad
import XMonad.Util.Run(spawnPipe)
-- Custom modules
import Config
import Utils
-- | Run before each restart of xmonad to ensure that there
-- will only be the expected panel instances running.
killPanels :: X ()
killPanels = do
spawn' "killall conky-cli"
spawn' "killall hbar"
spawn' "killall trayer"
return ()
-- | Spawn the applications that make the upper panel.
spawnPanels :: IO ([Handle])
spawnPanels = do
count <- getScreenCount'
pipes <- mapM (spawnDzenOnScreen count) [0..count-1]
spawnTrayer
return pipes
spawnTrayer = spawn' $ intercalate " "
[ "trayer"
, "--edge" , "top"
, "--align" , "right"
, "--widthtype" , "pixel"
, "--width" , show wTrayer
, "--heighttype" , "pixel"
, "--height" , height
, "--margin" , show $ wHbar + wConky
, "--transparent" , "true"
, "--alpha" , "0"
, "--tint" , convert $ defaultBG
, "--SetDockType" , "true"
, "--SetPartialStrut" , "true"
, "--expand" , "true"
]
where
convert ('#':xs) = '0':'x':xs
convert xs = xs
-- | spawn' two dzen instances at the top of the screen, reading input
-- from xmonad and hbar respectively.
spawnDzenOnScreen count screen = do
-- Unfortunately, only one instance of trayer is allowed.
let wTrayerMaybe = if screen == count - 1 then wTrayer else 0
(sx, sy, sw, sh) <- getScreenDim screen
pipes <- spawnPipe $ dzen
sy -- vertical position
sx -- horizontal position
(sw - wHbar - wTrayerMaybe - wConky) -- horizontal width
'l' -- text align
"" -- no actions
spawnDzenWithConky $ dzen
sy -- vertical position
(sx + sw - wHbar - wConky) -- horizontal position
wConky -- horizontal width
'r' -- text align
"" -- no actions
spawn' $ hbar ++ dzen
sy -- vertical position
(sx + sw - wHbar) -- horizontal position
wHbar -- horizontal width
'r' -- text align
"" -- no actions
return pipes
where
spawnDzenWithConky dest =
fileExist conkyrc >>=
(flip when $ do_ $ spawn' $ dzenWithConky conkyrc dest)
dzenWithConky conkyrc dest = intercalate " " ["conky-cli -c", conkyrc, "|", dest]
-- | Return a string that launches dzen with the given configuration.
dzen :: Num a => a -- ^ vertical position
-> a -- ^ horizontal position
-> a -- ^ horizontal width
-> Char -- ^ text align
-> String -- ^ actions
-> String
dzen y x w ta e =
intercalate " "
[ "dzen2"
, "-x" , show x
, "-w" , show w
, "-y" , show y
, "-h" , height
, "-fn" , quote font
, "-bg" , quote defaultBG
, "-fg" , quote defaultFG
, "-ta" , [ta]
, "-e" , quote e
]
-- | Get the number of available screens.
getScreenCount :: Num a => X a
getScreenCount = io getScreenCount'
getScreenCount' :: Num a => IO a
getScreenCount' = do
d <- openDisplay ""
screens <- getScreenInfo d
return $ fromInteger $ toInteger $ length screens
-- | Return the dimensions (x, y, width, height) of screen n.
getScreenDim :: Num a => Int -> IO (a, a, a, a)
getScreenDim n = do
d <- openDisplay ""
screens <- getScreenInfo d
closeDisplay d
let rn = screens!!(min (abs n) (length screens - 1))
case screens of
[] -> return $ (0, 0, 1024, 768) -- fallback
[r] -> return $ (fromIntegral $ rect_x r , fromIntegral $ rect_y r , fromIntegral $ rect_width r , fromIntegral $ rect_height r )
otherwise -> return $ (fromIntegral $ rect_x rn, fromIntegral $ rect_y rn, fromIntegral $ rect_width rn, fromIntegral $ rect_height rn)
-- | Run the command in the background, ensuring that the
-- value returned is always 0. This is to avoid making
-- spawn break a sequence of commands due to a return
-- value indicating that an error has occured.
spawn' x = spawn $ x ++ "&"