----------------------------------------------------------------------------- -- | -- Module : XMonad.Util.Timer -- Copyright : (c) Andrea Rossato and David Roundy 2007 -- License : BSD-style (see xmonad/LICENSE) -- -- Maintainer : andrea.rossato@unibz.it -- Stability : unstable -- Portability : unportable -- -- A module for setting up timers ----------------------------------------------------------------------------- module XMonad.Util.Timer ( -- * Usage -- $usage startTimer , handleTimer , TimerId ) where import XMonad import Control.Applicative import Control.Concurrent import Data.Unique -- $usage -- This module can be used to setup a timer to handle deferred events. -- See 'XMonad.Layout.ShowWName' for an usage example. type TimerId = Int -- | Start a timer, which will send a ClientMessageEvent after some -- time (in seconds). startTimer :: Rational -> X TimerId startTimer s = io $ do u <- hashUnique <$> newUnique doubleFork $ do d <- openDisplay "" rw <- rootWindow d $ defaultScreen d threadDelay (fromEnum $ s * 1000000) a <- internAtom d "XMONAD_TIMER" False allocaXEvent $ \e -> do setEventType e clientMessage setClientMessageEvent e rw a 32 (fromIntegral u) currentTime sendEvent d rw False structureNotifyMask e sync d False return u -- | Given a 'TimerId' and an 'Event', run an action when the 'Event' -- has been sent by the timer specified by the 'TimerId' handleTimer :: TimerId -> Event -> X (Maybe a) -> X (Maybe a) handleTimer ti (ClientMessageEvent {ev_message_type = mt, ev_data = dt}) action = do d <- asks display a <- io $ internAtom d "XMONAD_TIMER" False if mt == a && dt /= [] && fromIntegral (head dt) == ti then action else return Nothing handleTimer _ _ _ = return Nothing