module Graphics.Aosd(
AosdRenderer(..), GeneralRenderer(..),
AosdOptions(..), Transparency(..), Position(..), XClassHint(..), defaultOpts,
aosdFlash,
FlashDurations(..), symDurations,
AosdForeignPtr,aosdNew,aosdDestroy,reconfigure,
aosdRender, aosdShow, aosdHide, aosdLoopOnce, aosdLoopFor,
debugRenderer,
module Graphics.Rendering.Cairo,
Rectangle(..),
CInt, CUInt
) where
import Control.Concurrent.MVar
import Control.Exception
import Control.Monad.Trans.Reader
import Foreign.C
import Foreign.Ptr
import Foreign.StablePtr
import Foreign.Storable
import Graphics.Aosd.AOSD_H
import Graphics.Aosd.Options
import Graphics.Aosd.Renderer
import Graphics.Aosd.Util
import Graphics.Aosd.XUtil
import Graphics.Rendering.Cairo
import Graphics.Rendering.Cairo.Internal(runRender,Cairo)
import Graphics.Rendering.Pango.Enums
import System.IO.Unsafe
c'aosd_new_debug :: String -> IO (Ptr C'Aosd)
c'aosd_new_debug cxt = do
p <- c'aosd_new
putDebugMemory cxt ("c'aosd_new ==> "++show p)
return p
c'aosd_destroy_debug :: String -> Ptr C'Aosd -> IO ()
c'aosd_destroy_debug cxt p = do
putDebugMemory cxt ("c'aosd_destroy "++show p)
c'aosd_destroy p
withAosd :: (Ptr C'Aosd -> IO a) -> IO a
withAosd = bracket (c'aosd_new_debug "withAosd") (c'aosd_destroy_debug "withAosd")
type Render0 = Cairo -> IO ()
withConfiguredAosd :: (AosdRenderer renderer) =>
AosdOptions -> renderer
-> (Ptr C'Aosd -> IO a)
-> IO a
withConfiguredAosd opts x k =
withAosd (\a -> do
z <- reconfigure0 opts x a
k a `finally` freeAosdStructOwnedData "withConfiguredAosd" z
)
reconfigure0 :: (AosdRenderer renderer) => AosdOptions -> renderer -> Ptr C'Aosd -> IO AosdStructOwnedData
reconfigure0 AosdOptions{..} renderer ptr = do
GeneralRenderer{..} <- toGeneralRenderer renderer
ScreenSize{..} <- getScreenSize
let
Rectangle li ti wi hi = grInkExtent
Rectangle lp tp wp hp = grPositioningExtent
calculateOffsetAdjustment pos min_ink min_positioning size_positioning size_screen = fromIntegral $
case pos of
Min -> min_ink min_positioning
Center -> min_ink min_positioning + div (size_screen size_positioning) 2
Max -> min_ink min_positioning + size_screen size_positioning
windowLeft = calculateOffsetAdjustment xPos li lp wp screenWidth + fst offset
windowTop = calculateOffsetAdjustment yPos ti tp hp screenHeight + snd offset
windowWidth = fromIntegral wi
windowHeight = fromIntegral hi
finalRenderer = do
translate (fi . negate $ li) (fi . negate $ ti)
grRender
maybeDo (setClassHint ptr) classHint
maybeDo (setHideUponMouseEvent ptr) hideUponMouseEvent
maybeDo (setMouseEventCB ptr) mouseEventCB
rendererPtr <- newStablePtrDebug "reconfigure0" "renderer" (runReaderT . runRender $ finalRenderer)
maybeDo (c'aosd_set_transparency ptr . toAosdTransparency) transparency
c'aosd_set_geometry ptr windowLeft windowTop windowWidth windowHeight
c'aosd_set_renderer ptr theC'AosdRenderer (castCairoIOStablePtrToPtr rendererPtr)
return (AosdStructOwnedData rendererPtr)
castCairoIOStablePtrToPtr :: StablePtr Render0 -> Ptr ()
castCairoIOStablePtrToPtr = castStablePtrToPtr
theAosdRenderer :: Cairo -> Ptr () -> IO ()
theAosdRenderer cairo p = do
render <- Foreign.StablePtr.deRefStablePtr (Foreign.StablePtr.castPtrToStablePtr p) :: IO Render0
render cairo
theC'AosdRenderer :: C'AosdRenderer
theC'AosdRenderer = unsafePerformIO (mk'AosdRenderer theAosdRenderer)
setClassHint :: Ptr C'Aosd -> XClassHint -> IO ()
setClassHint a XClassHint{ resName, resClass } =
withCString resName (\resName' ->
withCString resClass (\resClass' ->
c'aosd_set_names a resName' resClass'))
setHideUponMouseEvent :: Ptr C'Aosd -> Bool -> IO ()
setHideUponMouseEvent a b = c'aosd_set_hide_upon_mouse_event a (if b then 1 else 0)
setMouseEventCB :: Ptr C'Aosd -> (C'AosdMouseEvent -> IO ()) -> IO ()
setMouseEventCB a f = do
fptr <- mk'AosdMouseEventCb f'
c'aosd_set_mouse_event_cb a fptr Foreign.Ptr.nullPtr
where
f' :: Ptr C'AosdMouseEvent -> Ptr () -> IO ()
f' p _ = do
mouseEvent <- peek p
f mouseEvent
aosdFlash :: (AosdRenderer a) => AosdOptions -> a -> FlashDurations -> IO ()
aosdFlash opts renderer durations = withConfiguredAosd opts renderer (aosdFlash' durations)
aosdFlash' :: FlashDurations -> Ptr C'Aosd -> IO ()
aosdFlash' FlashDurations{..} a = (c'aosd_flash a inMillis fullMillis outMillis)
data AosdForeignPtr = AosdForeignPtr { unAosdPtr :: !(Ptr C'Aosd)
, aosdStructOwnedDataVar :: !(MVar AosdStructOwnedData)
}
aosdNew :: (AosdRenderer renderer) => AosdOptions -> renderer -> IO AosdForeignPtr
aosdNew opts r = do
unAosdPtr <- c'aosd_new_debug "aosdNew"
z <- reconfigure0 opts r unAosdPtr
aosdStructOwnedDataVar <- newMVar z
return AosdForeignPtr {unAosdPtr,aosdStructOwnedDataVar}
reconfigure :: (AosdRenderer renderer) =>
AosdOptions
-> renderer
-> AosdForeignPtr
-> IO ()
reconfigure opts r (AosdForeignPtr fp var) = modifyMVar_ var
(\zOld -> do
zNew <- reconfigure0 opts r fp
freeAosdStructOwnedData "reconfigure" zOld
return zNew)
aosdRender :: AosdForeignPtr -> IO ()
aosdRender = (c'aosd_render) . unAosdPtr
aosdShow :: AosdForeignPtr -> IO ()
aosdShow = (c'aosd_show) . unAosdPtr
aosdHide :: AosdForeignPtr -> IO ()
aosdHide = (c'aosd_hide) . unAosdPtr
aosdLoopOnce :: AosdForeignPtr -> IO ()
aosdLoopOnce = (c'aosd_loop_once) . unAosdPtr
aosdLoopFor ::
AosdForeignPtr
-> CUInt
-> IO ()
aosdLoopFor (AosdForeignPtr fp _) millis = c'aosd_loop_for fp millis
data AosdStructOwnedData = AosdStructOwnedData !(StablePtr (Cairo -> IO ()))
freeAosdStructOwnedData :: String -> AosdStructOwnedData -> IO ()
freeAosdStructOwnedData cxt (AosdStructOwnedData sp_r) = do
freeStablePtrDebug cxt "renderer" sp_r
aosdDestroy :: AosdForeignPtr -> IO ()
aosdDestroy (AosdForeignPtr p var) = do
c'aosd_destroy_debug "aosdDestroy" p
z <- readMVar var
freeAosdStructOwnedData "aosdDestroy" z