ghcjs-base-0.2.0.0: JavaScript/Web/AnimationFrame.hs
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE JavaScriptFFI #-}
{-# LANGUAGE InterruptibleFFI #-}
{-# LANGUAGE DeriveDataTypeable #-}
{- |
Animation frames are the browser's mechanism for smooth animation.
An animation frame callback is run just before the browser repaints.
When the content window is inactive, for example when the user is looking
at another tab, it can take a long time for an animation frame callback
to happen. Be careful structuring evaluation around this! Typically this
means carefully forcing the data before the animation frame is requested,
so the callback can run quickly and predictably.
-}
module JavaScript.Web.AnimationFrame
( waitForAnimationFrame
, inAnimationFrame
, cancelAnimationFrame
, AnimationFrameHandle
) where
import GHCJS.Foreign.Callback
import GHCJS.Marshal.Pure
import GHCJS.Types
import Control.Exception (onException)
import Data.Typeable
newtype AnimationFrameHandle = AnimationFrameHandle JSVal
deriving (Typeable)
{- |
Wait for an animation frame callback to continue running the current
thread. Use 'GHCJS.Concurrent.synchronously' if the thread should
not be preempted. This will return the high-performance clock time
stamp once an animation frame is reached.
-}
waitForAnimationFrame :: IO Double
waitForAnimationFrame = do
h <- js_makeAnimationFrameHandle
js_waitForAnimationFrame h `onException` js_cancelAnimationFrame h
{- |
Run the action in an animationframe callback. The action runs in a
synchronous thread, and is passed the high-performance clock time
stamp for that frame.
-}
inAnimationFrame :: OnBlocked -- ^ what to do when encountering a blocking call
-> (Double -> IO ()) -- ^ the action to run
-> IO AnimationFrameHandle
inAnimationFrame onBlocked x = do
cb <- syncCallback1 onBlocked (x . pFromJSVal)
h <- js_makeAnimationFrameHandleCallback (jsval cb)
js_requestAnimationFrame h
return h
cancelAnimationFrame :: AnimationFrameHandle -> IO ()
cancelAnimationFrame h = js_cancelAnimationFrame h
{-# INLINE cancelAnimationFrame #-}
-- -----------------------------------------------------------------------------
foreign import javascript unsafe "{ handle: null, callback: null }"
js_makeAnimationFrameHandle :: IO AnimationFrameHandle
foreign import javascript unsafe "{ handle: null, callback: $1 }"
js_makeAnimationFrameHandleCallback :: JSVal -> IO AnimationFrameHandle
foreign import javascript unsafe "h$animationFrameCancel"
js_cancelAnimationFrame :: AnimationFrameHandle -> IO ()
foreign import javascript interruptible
"$1.handle = window.requestAnimationFrame($c);"
js_waitForAnimationFrame :: AnimationFrameHandle -> IO Double
foreign import javascript unsafe "h$animationFrameRequest"
js_requestAnimationFrame :: AnimationFrameHandle -> IO ()