    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GI.Cairo.Render.Connector
    -- Copyright   :  (c) Kilian Kilger, Iñaki García Etxebarria 2018
    -- License     :  LGPL-2.1
    --
    -- Maintainer  :  kkilger@gmail.com
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- This library contains glue code to interconnect Haskell GI, i.e. the gi-cairo
    -- library and gi-cairo-render, i.e. the hand written cairo bindings for Haskell.
    -----------------------------------------------------------------------------
    module GI.Cairo.Render.Connector (
       renderWithContext, getContext, toRender
    ) where

    import qualified GI.Cairo(Context(..))
    import Data.GI.Base(ManagedPtr)
    import GI.Cairo.Render(Render)
    import GI.Cairo.Render.Internal(Cairo(..), unCairo, runRender)
    import Control.Monad.Reader(MonadIO, runReaderT, asks)
    import Control.Monad.IO.Class(liftIO)
    import Data.Coerce(coerce)

    -- | This function is used to call a function in the 'GI.Cairo.Render.Render' monad
    -- from the draw function of GTK+. It takes a 'GI.Cairo.Structs.Context' (as it
    -- appears in [gi-cairo](https://hackage.haskell.org/package/gi-cairo)) and a
    -- 'GI.Cairo.Render.Render' action (as it appears in gi-cairo-render)
    -- and renders the `Render` context inside the given context.
    renderWithContext :: MonadIO m =>
                             Render a                   -- ^ Render action
                          -> GI.Cairo.Context           -- ^ Context from gi-cairo
                          -> m a                        -- ^ Result of the action
    renderWithContext :: forall (m :: * -> *) a. MonadIO m => Render a -> Context -> m a
    renderWithContext Render a
    r (GI.Cairo.Context ManagedPtr Context
    ctxt) =
      let cairo :: ManagedPtr Cairo
    cairo = ManagedPtr Context -> ManagedPtr Cairo
    forall a b. Coercible a b => a -> b
    coerce ManagedPtr Context
    ctxt :: ManagedPtr Cairo
      in IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> IO a -> m a
    forall a b. (a -> b) -> a -> b
    $ ReaderT Cairo IO a -> Cairo -> IO a
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT (Render a -> ReaderT Cairo IO a
    forall m. Render m -> ReaderT Cairo IO m
    runRender Render a
    r) (ManagedPtr Cairo -> Cairo
    Cairo ManagedPtr Cairo
    cairo)

    -- | This function is used to call back to functions of GI.Pango or GI.PangoCairo
    -- or other Haskell GI libraries from inside the `Cairo.Render` action.
    -- Example:
    --
    -- > draw :: Cairo.Render ()
    -- > draw = do ...
    -- >           context <- getContext
    -- >           somePangoFunction context
    --
    getContext :: Render GI.Cairo.Context -- ^ Underlying GI.Cairo.Context
    getContext :: Render Context
    getContext = do cairo <- (Cairo -> ManagedPtr Cairo) -> Render (ManagedPtr Cairo)
    forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
    asks Cairo -> ManagedPtr Cairo
    unCairo
                    let ctxt = ManagedPtr Cairo -> ManagedPtr Context
    forall a b. Coercible a b => a -> b
    coerce ManagedPtr Cairo
    cairo :: ManagedPtr GI.Cairo.Context
                    return $ GI.Cairo.Context ctxt

    -- | This function is used to "lift" functions of GI.Pango or GI.PangoCairo
    -- to the Render monad.
    -- Example:
    --
    -- > draw :: Cairo.Render ()
    -- > draw = do ...
    -- >           toRender somePangoFunction

    toRender :: (GI.Cairo.Context -> IO a) -> Render a
    toRender :: forall a. (Context -> IO a) -> Render a
    toRender Context -> IO a
    fun = do context <- Render Context
    getContext
                      liftIO $ fun context