Add a backbuffer for the created window.
authorMatthijs Kooijman <matthijs@stdin.nl>
Mon, 24 Aug 2009 18:24:33 +0000 (20:24 +0200)
committerMatthijs Kooijman <matthijs@stdin.nl>
Mon, 24 Aug 2009 18:39:54 +0000 (20:39 +0200)
This backbuffer is copied to the window on every expose event, but
nothing is draw on it yet.

FPPrac.hs

index 47b3cad30e0c80c06efa2445adeebc50b9ab7e62..79a6a0ac9405b167d0c76b931c9292bdc49462c4 100644 (file)
--- a/FPPrac.hs
+++ b/FPPrac.hs
@@ -99,6 +99,7 @@ testProg = Main
 
 data IState = forall s. IS
        { window    :: Gtk.Window
 
 data IState = forall s. IS
        { window    :: Gtk.Window
+       , buffer    :: IORef Cairo.Surface
        , postponed :: IORef [Request]
        , usrState  :: IORef s
        , usrProg   :: TinaStep s
        , postponed :: IORef [Request]
        , usrState  :: IORef s
        , usrProg   :: TinaStep s
@@ -132,11 +133,11 @@ runTina :: TinaProgram -> IO ()
 runTina Main {..} = do
        usrState  <- newIORef initialState
        postponed <- newIORef (GfxText (rgb 0 0 0) (pt 50 50) "foo" : GfxClear :initialRequests)
 runTina Main {..} = do
        usrState  <- newIORef initialState
        postponed <- newIORef (GfxText (rgb 0 0 0) (pt 50 50) "foo" : GfxClear :initialRequests)
-       let state = IS { window = undefined, usrProg = eventHandler, .. }
+       let state = IS { window = undefined, buffer = undefined, usrProg = eventHandler, .. }
        runGUI windowWidth windowHeight state
 
 runGUI :: Int -> Int -> IState -> IO ()
        runGUI windowWidth windowHeight state
 
 runGUI :: Int -> Int -> IState -> IO ()
-runGUI w h s = do
+runGUI w h (IS { .. }) = do
        -- Init GTK.
        Gtk.initGUI
        
        -- Init GTK.
        Gtk.initGUI
        
@@ -150,14 +151,36 @@ runGUI w h s = do
                       , Gtk.windowDefaultHeight := h
                       ]
        Gtk.onDestroy window Gtk.mainQuit
                       , Gtk.windowDefaultHeight := h
                       ]
        Gtk.onDestroy window Gtk.mainQuit
-
-       -- Add the window to the state
-       let state = s { window = window }
        
        
+       -- Create a buffer to draw on (name the actual buffer buffer', so we
+       -- can use IS { .. } syntax below to pack the state. Using a record update
+       -- wouldn't work, probably because Cairo.Surface contains an existential
+       -- type...
+       -- We put the buffer in an IORef, so we can change it for a new one
+       -- later on (on window resizes).
+       buffer' <- Cairo.createImageSurface Cairo.FormatARGB32 w h
+       buffer <- newIORef buffer'
+
+       -- Register the expose event
+       Gtk.on window Gtk.exposeEvent $ onExpose buffer
+
+       -- Repack state
+       let state = IS { .. }
+               
        -- Show the window and start the Gtk mainloop.
        Gtk.widgetShowAll window
        Gtk.mainGUI
 
        -- Show the window and start the Gtk mainloop.
        Gtk.widgetShowAll window
        Gtk.mainGUI
 
+-- | Copy the given surface to the exposed window on an expose event.
+onExpose :: IORef Cairo.Surface -> EventM.EventM EventM.EExpose Bool
+onExpose buffer = do
+       current_buffer <- liftIO $ readIORef buffer
+       dw <- EventM.eventWindow
+       -- Copy the buffer to the window
+       liftIO $ Gtk.renderWithDrawable dw $ do
+               Cairo.setSourceSurface current_buffer 0 0
+               Cairo.paint
+       return True -- No clue what this means
 
 {-
 runGUI s IS {..} = do
 
 {-
 runGUI s IS {..} = do