module GLUTGtk where import Control.Monad (join) import Control.Monad.Trans (liftIO) import Data.IORef (IORef, newIORef, readIORef) import Graphics.UI.Gtk hiding (Size) import Graphics.UI.Gtk.OpenGL type RealizeCallback = IO () type ReshapeCallback = Size -> IO () type DisplayCallback = IO () type KeyboardMouseCallback = Key -> KeyState -> [Modifier] -> Position -> IO () data Size = Size Int Int deriving (Eq, Ord, Show) data Position = Position Double Double deriving (Eq, Ord, Show) data KeyState = Down | Up deriving (Eq, Ord, Show) data Key = MouseButton MouseButton deriving (Eq, Show) data GLUTGtk = GLUTGtk { realizeCallback :: IORef RealizeCallback , reshapeCallback :: IORef ReshapeCallback , displayCallback :: IORef DisplayCallback , keyboardMouseCallback :: IORef KeyboardMouseCallback , postRedisplay :: IO () , widget :: EventBox } glut :: Size -> IO GLUTGtk glut (Size width height) = do realizeCallback' <- newIORef $ return () displayCallback' <- newIORef $ return () reshapeCallback' <- newIORef $ \_ -> return () keyboardMouseCallback' <- newIORef $ \_ _ _ _ -> return () config <- glConfigNew [ GLModeRGBA, GLModeDouble ] canvas <- glDrawingAreaNew config widgetSetSizeRequest canvas width height eventb <- eventBoxNew set eventb [ containerBorderWidth := 0, containerChild := canvas ] _ <- onRealize canvas $ withGLDrawingArea canvas $ \_ -> join (readIORef realizeCallback') _ <- canvas `on` configureEvent $ tryEvent $ do (w, h) <- eventSize liftIO $ do cb <- readIORef reshapeCallback' cb (Size w h) _ <- canvas `on` exposeEvent $ tryEvent $ liftIO $ withGLDrawingArea canvas $ \gl -> do join (readIORef displayCallback') glDrawableSwapBuffers gl let handleButton s = do b <- eventButton (x, y) <- eventCoordinates ms <- eventModifier liftIO $ do cb <- readIORef keyboardMouseCallback' cb (MouseButton b) s ms (Position x y) _ <- eventb `on` buttonPressEvent $ tryEvent $ handleButton Down _ <- eventb `on` buttonReleaseEvent $ tryEvent $ handleButton Up return $ GLUTGtk { realizeCallback = realizeCallback' , displayCallback = displayCallback' , reshapeCallback = reshapeCallback' , keyboardMouseCallback = keyboardMouseCallback' , postRedisplay = widgetQueueDraw canvas , widget = eventb }