packages feed

GLFW-b 3.2.1.0 → 3.2.1.1

raw patch · 6 files changed

+3470/−3464 lines, 6 filesdep ~basedep ~bindings-GLFW

Dependency ranges changed: base, bindings-GLFW

Files

GLFW-b.cabal view
@@ -1,86 +1,86 @@-name:         GLFW-b-version:      3.2.1.0-category:     Graphics--author:       Brian Lewis <brian@lorf.org>-maintainer:   Brian Lewis <brian@lorf.org>-            , Schell Scivally <schell.scivally@synapsegroup.com>-            , Pavel Krajcevski <krajcevski@gmail.com>--license:      BSD3-license-file: LICENSE--synopsis:     Bindings to GLFW OpenGL library-description:-  Bindings to GLFW (<http://www.glfw.org/>), an open source, multi-platform-  library for creating windows with OpenGL contexts and managing input and-  events.-  .-  GLFW-b depends on bindings-GLFW-  (<http://hackage.haskell.org/package/bindings-GLFW>), which, as of the time-  of this writing, binds to GLFW 3.2.1, released 2016-08-18-  (<http://www.glfw.org/Version-3.2.1-released.html>-  <http://www.glfw.org/changelog.html>).-  .-  If you've used GLFW < 3 before, you should read the transition guide-  (<http://www.glfw.org/docs/3.0/moving.html>).--cabal-version: >= 1.10-build-type:    Simple------------------------------------------------------------------------------------extra-source-files:-  README.md-  TODO------------------------------------------------------------------------------------library-  default-language: Haskell2010--  ghc-options: -Wall-  if impl(ghc >= 6.8)-    ghc-options: -fwarn-tabs--  exposed-modules:-    Graphics.UI.GLFW--  other-modules:-    Graphics.UI.GLFW.C-    Graphics.UI.GLFW.Types--  build-depends:-      base          <  5-    , deepseq       >= 1.1.0.0-    , bindings-GLFW >= 3.2.1.1------------------------------------------------------------------------------------test-suite main-  default-language: Haskell2010--  ghc-options: -Wall-  if impl(ghc >= 6.8)-    ghc-options: -fwarn-tabs--  type: exitcode-stdio-1.0--  main-is: Test.hs-  other-modules:-    Graphics.UI.GLFW-    Graphics.UI.GLFW.C-    Graphics.UI.GLFW.Types-  build-depends:-      base                 <  5-    , HUnit                >= 1.3 && < 1.7-    , bindings-GLFW        >= 3.2.1.0-    , deepseq              >= 1.1.0.0-    , test-framework       == 0.8.*-    , test-framework-hunit == 0.3.*------------------------------------------------------------------------------------source-repository head-  type:     git-  location: git://github.com/bsl/GLFW-b.git+name:         GLFW-b
+version:      3.2.1.1
+category:     Graphics
+
+author:       Brian Lewis <brian@lorf.org>
+maintainer:   Brian Lewis <brian@lorf.org>
+            , Schell Scivally <schell.scivally@synapsegroup.com>
+            , Pavel Krajcevski <krajcevski@gmail.com>
+
+license:      BSD3
+license-file: LICENSE
+
+synopsis:     Bindings to GLFW OpenGL library
+description:
+  Bindings to GLFW (<http://www.glfw.org/>), an open source, multi-platform
+  library for creating windows with OpenGL contexts and managing input and
+  events.
+  .
+  GLFW-b depends on bindings-GLFW
+  (<http://hackage.haskell.org/package/bindings-GLFW>), which, as of the time
+  of this writing, binds to GLFW 3.2.1, released 2016-08-18
+  (<http://www.glfw.org/Version-3.2.1-released.html>
+  <http://www.glfw.org/changelog.html>).
+  .
+  If you've used GLFW < 3 before, you should read the transition guide
+  (<http://www.glfw.org/docs/3.0/moving.html>).
+
+cabal-version: >= 1.10
+build-type:    Simple
+
+--------------------------------------------------------------------------------
+
+extra-source-files:
+  README.md
+  TODO
+
+--------------------------------------------------------------------------------
+
+library
+  default-language: Haskell2010
+
+  ghc-options: -Wall
+  if impl(ghc >= 6.8)
+    ghc-options: -fwarn-tabs
+
+  exposed-modules:
+    Graphics.UI.GLFW
+
+  other-modules:
+    Graphics.UI.GLFW.C
+    Graphics.UI.GLFW.Types
+
+  build-depends:
+      base          <  5
+    , deepseq       >= 1.1.0.0
+    , bindings-GLFW >= 3.2.1.1 && < 3.3
+
+--------------------------------------------------------------------------------
+
+test-suite main
+  default-language: Haskell2010
+
+  ghc-options: -Wall
+  if impl(ghc >= 6.8)
+    ghc-options: -fwarn-tabs
+
+  type: exitcode-stdio-1.0
+
+  main-is: Test.hs
+  other-modules:
+    Graphics.UI.GLFW
+    Graphics.UI.GLFW.C
+    Graphics.UI.GLFW.Types
+  build-depends:
+      base                 <  5
+    , HUnit                >= 1.3 && < 1.7
+    , bindings-GLFW        >= 3.2.1.0 && < 3.3
+    , deepseq              >= 1.1.0.0
+    , test-framework       == 0.8.*
+    , test-framework-hunit == 0.3.*
+
+--------------------------------------------------------------------------------
+
+source-repository head
+  type:     git
+  location: git://github.com/bsl/GLFW-b.git
Graphics/UI/GLFW.hs view
@@ -1,1665 +1,1671 @@-{-|--Threading restrictions which apply to the C version of GLFW still apply when-writing @GLFW-b@ programs. See-<http://www.glfw.org/docs/3.2/intro.html#thread_safety GLFW thread safety documentation>-(applies here).--Current context restructions which apply to the C version of GLFW still apply.-See <http://www.glfw.org/docs/3.2/context.html#context_current  GLFW current context documentation>-(applies here).--@GLFW-b@ wraps callbacks and schedules them to be run after 'pollEvents' and-'waitEvents' in the normal GHC runtime where they aren't subject to the usual-GLFW reentrancy restrictions. See-<http://www.glfw.org/docs/3.2/intro.html#reentrancy GLFW reentrancy documentation>-(does not apply here).---}-module Graphics.UI.GLFW-  ( -- * Error handling-    Error (..)-    ---  , setErrorCallback, ErrorCallback--    -- * Initialization and version information-  , Version (..)-    ---  , init-  , terminate-  , getVersion-  , getVersionString--    -- * Monitor handling-  , Monitor-  , MonitorState (..)-  , VideoMode    (..)-  , GammaRamp    (gammaRampRed, gammaRampGreen, gammaRampBlue)-  , makeGammaRamp-    ---  , getMonitors-  , getPrimaryMonitor-  , getMonitorPos-  , getMonitorPhysicalSize-  , getMonitorName-  , setMonitorCallback, MonitorCallback-  , getVideoModes-  , getVideoMode-  , setGamma-  , getGammaRamp-  , setGammaRamp--    -- * Window handling-  , Window-  , WindowHint             (..)-  , ContextRobustness      (..)-  , OpenGLProfile          (..)-  , ClientAPI              (..)-  , ContextCreationAPI     (..)-  , ContextReleaseBehavior (..)-    ---  , defaultWindowHints-  , windowHint-  , createWindow-  , destroyWindow-  , windowShouldClose-  , setWindowShouldClose-  , setWindowTitle-  , getWindowPos-  , setWindowPos-  , getWindowSize-  , setWindowSize-  , setWindowSizeLimits-  , setWindowAspectRatio-  , getWindowFrameSize-  , getFramebufferSize-  , setWindowIcon-  , iconifyWindow-  , restoreWindow-  , focusWindow-  , maximizeWindow-  , showWindow-  , hideWindow-  , getWindowMonitor-  , setCursorPos-  , setFullscreen-  , setWindowed-    -- related to c'glfwGetWindowAttrib --.-  , getWindowFocused                   -- |-  , getWindowMaximized                 -- |-  , getWindowFloating                  -- |-  , getWindowIconified                 -- |-  , getWindowResizable                 -- |-  , getWindowDecorated                 -- |-  , getWindowVisible                   -- |-  , getWindowClientAPI                 -- |-  , getWindowContextCreationAPI        -- |-  , getWindowContextVersionMajor       -- |-  , getWindowContextVersionMinor       -- |-  , getWindowContextVersionRevision    -- |-  , getWindowContextRobustness         -- |-  , getWindowContextReleaseBehavior    -- |-  , getWindowContextNoError            -- |-  , getWindowOpenGLForwardCompat       -- |-  , getWindowOpenGLDebugContext        -- |-  , getWindowOpenGLProfile  --------------'-  , setWindowPosCallback,       WindowPosCallback-  , setWindowSizeCallback,      WindowSizeCallback-  , setWindowCloseCallback,     WindowCloseCallback-  , setWindowRefreshCallback,   WindowRefreshCallback-  , setWindowFocusCallback,     WindowFocusCallback-  , setWindowIconifyCallback,   WindowIconifyCallback-  , setFramebufferSizeCallback, FramebufferSizeCallback-  , pollEvents-  , waitEvents-  , waitEventsTimeout-  , postEmptyEvent--    -- * Input handling-  , Key                         (..)-  , KeyState                    (..)-  , Joystick                    (..)-  , JoystickState               (..)-  , JoystickButtonState         (..)-  , MouseButton                 (..)-  , MouseButtonState            (..)-  , CursorState                 (..)-  , CursorInputMode             (..)-  , StickyKeysInputMode         (..)-  , StickyMouseButtonsInputMode (..)-  , ModifierKeys                (..)-  , Image-  , mkImage-  , Cursor                      (..)-  , StandardCursorShape         (..)-    ---    -- related to c'glfwSetInputMode ----.-  , getCursorInputMode                -- |-  , setCursorInputMode                -- |-  , getStickyKeysInputMode            -- |-  , setStickyKeysInputMode            -- |-  , getStickyMouseButtonsInputMode    -- |-  , setStickyMouseButtonsInputMode  -----'-  , getKey-  , getKeyName-  , getMouseButton-  , getCursorPos-  , setKeyCallback,         KeyCallback-  , setCharCallback,        CharCallback-  , setCharModsCallback,    CharModsCallback-  , setMouseButtonCallback, MouseButtonCallback-  , setCursorPosCallback,   CursorPosCallback-  , setCursorEnterCallback, CursorEnterCallback-  , createCursor-  , createStandardCursor-  , setCursor-  , destroyCursor-  , setScrollCallback,      ScrollCallback-  , setDropCallback,        DropCallback-  , joystickPresent-  , getJoystickAxes-  , getJoystickButtons-  , getJoystickName-  , setJoystickCallback,    JoystickCallback--    -- * Time-  , getTime-  , setTime-  , getTimerValue-  , getTimerFrequency--    -- * Context-  , makeContextCurrent-  , getCurrentContext-  , swapBuffers-  , swapInterval-  , extensionSupported--    -- * Clipboard-  , getClipboardString-  , setClipboardString--    -- * Vulkan-related functions-  , vulkanSupported-  , getRequiredInstanceExtensions-  , getInstanceProcAddress-  , getPhysicalDevicePresentationSupport-  , createWindowSurface--    -- * Native access functions-    -- $nativeaccess-  , getWin32Adapter-  , getWin32Monitor-  , getWin32Window-  , getWGLContext-  , getCocoaMonitor-  , getCocoaWindow-  , getNSGLContext-  , getX11Display-  , getX11Adapter-  , getX11Monitor-  , getX11Window-  , getGLXContext-  , getGLXWindow-  , getWaylandDisplay-  , getWaylandMonitor-  , getWaylandWindow-  , getMirDisplay-  , getMirMonitor-  , getMirWindow-  , getEGLDisplay-  , getEGLContext-  , getEGLSurface--  ) where------------------------------------------------------------------------------------import Prelude hiding (init)--import Control.Monad         (when, liftM)-import Data.IORef            (IORef, atomicModifyIORef, newIORef, readIORef)-import Data.Word             (Word32, Word64)-import Foreign.C.String      (peekCString, withCString, CString)-import Foreign.C.Types       (CUInt, CUShort)-import Foreign.Marshal.Alloc (alloca, allocaBytes)-import Foreign.Marshal.Array (advancePtr, allocaArray, peekArray, withArray)-import Foreign.Ptr           (FunPtr, freeHaskellFunPtr, nullFunPtr, nullPtr-                             ,Ptr)-import Foreign.StablePtr-import Foreign.Storable      (Storable (..))-import System.IO.Unsafe      (unsafePerformIO)--import Graphics.UI.GLFW.C-import Graphics.UI.GLFW.Types--import Bindings.GLFW-------------------------------------------------------------------------------------- We store FunPtrs from mk'GLFW*fun in these stored*Fun IORefs. Initialized--- with unsafePerformIO, they are basically mutable global variables.--storedErrorFun           :: IORef C'GLFWerrorfun-storedMonitorFun         :: IORef C'GLFWmonitorfun-storedJoystickFun        :: IORef C'GLFWjoystickfun--storedErrorFun           = unsafePerformIO $ newIORef nullFunPtr-storedMonitorFun         = unsafePerformIO $ newIORef nullFunPtr-storedJoystickFun        = unsafePerformIO $ newIORef nullFunPtr---- These NOINLINE pragmas are due to use of unsafePerformIO.--- See http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO-Unsafe.html#v:unsafePerformIO .--{-# NOINLINE storedErrorFun           #-}-{-# NOINLINE storedMonitorFun         #-}-{-# NOINLINE storedJoystickFun         #-}--setWindowCallback-  :: (c -> IO (FunPtr c))                    -- wf   wrapper function-  -> (h -> c)                                -- af   adapter function-  -> (FunPtr c -> IO (FunPtr c))             -- gf   c'glfwSet*Callback function-  -> (WindowCallbacks -> IORef (FunPtr c))   -- ior  accessor for storage location-  -> Window                                  -- win  window-  -> Maybe h                                 -- mcb  Haskell callback-  -> IO ()-setWindowCallback wr af gf ior win mcb = do-    pcallbacks <- castPtrToStablePtr `liftM` c'glfwGetWindowUserPointer (unWindow win)-    callbacks <- deRefStablePtr pcallbacks-    setCallback wr af gf (ior callbacks) mcb--setCallback-  :: (c -> IO (FunPtr c))          -- wf   wrapper function-  -> (h -> c)                      -- af   adapter function-  -> (FunPtr c -> IO (FunPtr c))   -- gf   c'glfwSet*Callback function-  -> IORef (FunPtr c)              -- ior  storage location-  -> Maybe h                       -- mcb  Haskell callback-  -> IO ()-setCallback wf af gf ior mcb = do-    -- If mcb is Just, make ccb the FunPtr of the adapted callback. Otherwise a-    -- null FunPtr.-    ccb <- maybe (return nullFunPtr) (wf . af) mcb-    -- Call the GLFW callback-setting function.-    _ <- gf ccb-    -- Store it.-    storeCallback ior ccb--storeCallback :: IORef (FunPtr a) -> FunPtr a -> IO ()-storeCallback ior new = do-    -- Store the new FunPtr, retrieve the previous one.-    prev <- atomicModifyIORef ior (\cur -> (new, cur))-    -- Free the old FunPtr if necessary.-    when (prev /= nullFunPtr) $ freeHaskellFunPtr prev-------------------------------------------------------------------------------------- | The error code and also a human-readable error message.-type ErrorCallback           = Error -> String                                           -> IO ()--- | Fires when the window position changes.-type WindowPosCallback       = Window -> Int -> Int                                      -> IO ()--- | Fires when the window is resized (in Screen Coordinates, which might not map 1:1 with pixels).-type WindowSizeCallback      = Window -> Int -> Int                                      -> IO ()--- | Fires when the user is attempting to close the window-type WindowCloseCallback     = Window                                                    -> IO ()--- | Fires when the contents of the window are damaged and they must be refreshed.-type WindowRefreshCallback   = Window                                                    -> IO ()--- | Fires when the window gains or loses input focus.-type WindowFocusCallback     = Window -> Bool                                            -> IO ()--- | Fires when the window is iconified (minimized) or not.-type WindowIconifyCallback   = Window -> Bool                                            -> IO ()--- | Fires when the size of the framebuffer for the window changes (in Pixels).-type FramebufferSizeCallback = Window -> Int -> Int                                      -> IO ()--- | Fires whenever a mouse button is clicked.-type MouseButtonCallback     = Window -> MouseButton -> MouseButtonState -> ModifierKeys -> IO ()--- | Fires every time the cursor position changes. Sub-pixel accuracy is used, when available.-type CursorPosCallback       = Window -> Double -> Double                                -> IO ()--- | Fires when the cursor enters or exits the client area of the window.-type CursorEnterCallback     = Window -> CursorState                                     -> IO ()--- | Fires when the user scrolls the mouse wheel or via touch gesture.-type ScrollCallback          = Window -> Double -> Double                                -> IO ()--- | Fires for each press or repeat of keyboard keys (regardless of if it has textual meaning or not, eg Shift)-type KeyCallback             = Window -> Key -> Int -> KeyState -> ModifierKeys          -> IO ()--- | Fires when a complete character codepoint is typed by the user, Shift then 'b' generates "B".-type CharCallback            = Window -> Char                                            -> IO ()--- | Similar to 'CharCallback', fires when a complete unicode codepoint is typed by the user.-type CharModsCallback        = Window -> Char -> ModifierKeys                            -> IO ()--- | Fires when a monitor is connected or disconnected.-type MonitorCallback         = Monitor -> MonitorState                                   -> IO ()--- | Fires when a joystick is connected or disconnected.-type JoystickCallback        = Joystick -> JoystickState                                 -> IO ()---- 3.1 additions------------------------------------------------------------------------------------- CB scheduling--data ScheduledCallbacks = ScheduledCallbacks-  { _forward :: [IO ()] -- Execution iterates this list-  , _backward :: [IO ()] -- New schedules prepend here-  }--storedScheduledCallbacks :: IORef ScheduledCallbacks-storedScheduledCallbacks = unsafePerformIO . newIORef $ ScheduledCallbacks [] []---- This NOINLINE pragma is due to use of unsafePerformIO.--- See http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO-Unsafe.html#v:unsafePerformIO .--{-# NOINLINE storedScheduledCallbacks #-}---- This is provided in newer "base" versions. To avoid depending on--- it, it's reimplemented here. Should remove if/when compatibility--- with older base is not an issue:-atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b-atomicModifyIORef' ref f = do-    b <- atomicModifyIORef ref-            (\x -> let (a, b) = f x-                    in (a, a `seq` b))-    b `seq` return b--schedule :: IO () -> IO ()-schedule act =-  atomicModifyIORef' storedScheduledCallbacks $-  \(ScheduledCallbacks oldForward oldBackward) ->-  (ScheduledCallbacks oldForward (act : oldBackward), ())--splitFirst :: [a] -> (Maybe a, [a])-splitFirst [] = (Nothing, [])-splitFirst (x:xs) = (Just x, xs)--getNextScheduled :: IO (Maybe (IO ()))-getNextScheduled =-  atomicModifyIORef storedScheduledCallbacks $-  \(ScheduledCallbacks oldForward oldBackward) ->-  case oldForward of-    [] ->-      let (mCb, newForward) = splitFirst (reverse oldBackward)-      in (ScheduledCallbacks newForward [], mCb)-    (cb:rest) ->                -- Eat forward first-      (ScheduledCallbacks rest oldBackward, Just cb)--executeScheduled :: IO ()-executeScheduled = do-  mcb <- getNextScheduled-  case mcb of-    Nothing -> return ()-    Just cb -> cb >> executeScheduled------------------------------------------------------------------------------------- Error handling---- | Can (and probably should) be used before GLFW initialization.--- See <http://www.glfw.org/docs/3.2/group__init.html#gaa5d796c3cf7c1a7f02f845486333fb5f glfwSetErrorCallback>-setErrorCallback :: Maybe ErrorCallback -> IO ()-setErrorCallback = setCallback-    mk'GLFWerrorfun-    (\cb a0 a1 -> do-        s <- peekCString a1-        schedule $ cb (fromC a0) s)-    c'glfwSetErrorCallback-    storedErrorFun------------------------------------------------------------------------------------- Image utility functions--withGLFWImage :: Image -> (Ptr C'GLFWimage -> IO a) -> IO a-withGLFWImage (Image w h pxs) f =-  alloca        $ \p'img ->-  withArray pxs $ \p'pxs -> do-    poke p'img $ C'GLFWimage (toC w) (toC h) p'pxs-    f p'img------------------------------------------------------------------------------------- Initialization and version information---- | Attempts to initialize the GLFW library. When the library is not initialized, the only--- allowed functions to call are 'getVersion', 'getVersionString', 'setErrorCallback',--- 'init', and 'terminate'. Returns if the initialization was successful or not.--- See <http://www.glfw.org/docs/3.2/group__init.html#ga317aac130a235ab08c6db0834907d85e glfwInit>--- and <http://www.glfw.org/docs/3.2/intro.html#intro_init Initialization and Termination>-init :: IO Bool-init =-    fromC `fmap` c'glfwInit---- | Cleans up GLFW and puts the library into an uninitialized state.--- Once you call this, you must initilize the library again.--- Warning: No window's context may be current in another thread when this is called.--- See <http://www.glfw.org/docs/3.2/group__init.html#gaaae48c0a18607ea4a4ba951d939f0901 glfwTerminate>--- and <http://www.glfw.org/docs/3.2/intro.html#intro_init Initialization and Termination>-terminate :: IO ()-terminate = do-    c'glfwTerminate-    -- Free all stored FunPtrs.-    storeCallback storedErrorFun           nullFunPtr-    storeCallback storedMonitorFun         nullFunPtr-    storeCallback storedJoystickFun         nullFunPtr---- | Gets the version of the GLFW library that's being used with the current program.--- See <http://www.glfw.org/docs/3.2/group__init.html#ga9f8ffaacf3c269cc48eafbf8b9b71197 glfwGetVersion>-getVersion :: IO Version-getVersion =-    allocaArray 3 $ \p -> do-        let p0 = p-            p1 = p `advancePtr` 1-            p2 = p `advancePtr` 2-        c'glfwGetVersion p0 p1 p2-        v0 <- fromC `fmap` peek p0-        v1 <- fromC `fmap` peek p1-        v2 <- fromC `fmap` peek p2-        return $ Version v0 v1 v2---- | Gets the compile-time version string of the GLFW library binary.--- Gives extra info like platform and compile time options used, but you should not--- attempt to parse this to get the GLFW version number. Use 'getVersion' instead.--- See <http://www.glfw.org/docs/3.2/group__init.html#ga23d47dc013fce2bf58036da66079a657 glfwGetVersionString>-getVersionString :: IO (Maybe String)-getVersionString = do-    p'vs <- c'glfwGetVersionString-    if p'vs /= nullPtr-      then Just `fmap` peekCString p'vs-      else return Nothing------------------------------------------------------------------------------------- Monitor handling---- | Gets the list of available monitors, if possible.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga3fba51c8bd36491d4712aa5bd074a537 glfwGetMonitors>-getMonitors :: IO (Maybe [Monitor])-getMonitors =-    alloca $ \p'n -> do-        p'mon <- c'glfwGetMonitors p'n-        n <- fromC `fmap` peek p'n-        if p'mon == nullPtr || n <= 0-          then return Nothing-          else (Just . map fromC) `fmap` peekArray n p'mon---- | Gets the primary monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga721867d84c6d18d6790d64d2847ca0b1 glfwGetPrimaryMonitor>-getPrimaryMonitor :: IO (Maybe Monitor)-getPrimaryMonitor = do-    p'mon <- c'glfwGetPrimaryMonitor-    return $-      if p'mon == nullPtr-        then Nothing-        else Just $ fromC p'mon---- | Gets the position of the specified monitor within the coordinate space.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga102f54e7acc9149edbcf0997152df8c9 glfwGetMonitorPos>-getMonitorPos :: Monitor -> IO (Int, Int)-getMonitorPos mon =-    allocaArray 2 $ \p -> do-        let p'x = p-            p'y = p `advancePtr` 1-        c'glfwGetMonitorPos (toC mon) p'x p'y-        x <- fromC `fmap` peek p'x-        y <- fromC `fmap` peek p'y-        return (x, y)---- | The physical width and height of the monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga7d8bffc6c55539286a6bd20d32a8d7ea glfwGetMonitorPhysicalSize>-getMonitorPhysicalSize :: Monitor -> IO (Int, Int)-getMonitorPhysicalSize mon =-    allocaArray 2 $ \p -> do-        let p'w = p-            p'h = p `advancePtr` 1-        c'glfwGetMonitorPhysicalSize (toC mon) p'w p'h-        w <- fromC `fmap` peek p'w-        h <- fromC `fmap` peek p'h-        return (w, h)---- | A human-readable name for the monitor specified.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga79a34ee22ff080ca954a9663e4679daf getMonitorName>-getMonitorName :: Monitor -> IO (Maybe String)-getMonitorName mon = do-    p'name <- c'glfwGetMonitorName (toC mon)-    if p'name == nullPtr-      then return Nothing-      else Just `fmap` peekCString p'name---- | Sets a callback for when a monitor is connected or disconnected.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#gac3fe0f647f68b731f99756cd81897378 glfwSetMonitorCallback>-setMonitorCallback :: Maybe MonitorCallback -> IO ()-setMonitorCallback = setCallback-    mk'GLFWmonitorfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    c'glfwSetMonitorCallback-    storedMonitorFun---- | Obtains the possible video modes of the monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga820b0ce9a5237d645ea7cbb4bd383458 glfwGetVideoModes>-getVideoModes :: Monitor -> IO (Maybe [VideoMode])-getVideoModes mon =-    alloca $ \p'n -> do-        p'vms <- c'glfwGetVideoModes (toC mon) p'n-        n <- fromC `fmap` peek p'n-        if p'vms == nullPtr || n <= 0-          then return Nothing-          else (Just . map fromC) `fmap` peekArray n p'vms---- | Gets the active video mode of the monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#gafc1bb972a921ad5b3bd5d63a95fc2d52 glfwGetVideoMode>-getVideoMode :: Monitor -> IO (Maybe VideoMode)-getVideoMode mon = do-    p'vm <- c'glfwGetVideoMode (toC mon)-    if p'vm == nullPtr-      then return Nothing-      else (Just . fromC) `fmap` peek p'vm---- | Sets the gamma of a monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga6ac582625c990220785ddd34efa3169a glfwSetGamma>-setGamma :: Monitor -> Double -> IO ()-setGamma mon e =-    c'glfwSetGamma (toC mon) (toC e)---- | Gets the gamma ramp in use with the monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#gab7c41deb2219bde3e1eb756ddaa9ec80 glfwGetGammaRamp>-getGammaRamp :: Monitor -> IO (Maybe GammaRamp)-getGammaRamp m = do-    p'ggr <- c'glfwGetGammaRamp (toC m)-    if p'ggr == nullPtr-      then return Nothing-      else do-          ggr <- peek p'ggr-          let p'rs = c'GLFWgammaramp'red   ggr-              p'gs = c'GLFWgammaramp'green ggr-              p'bs = c'GLFWgammaramp'blue  ggr-              cn   = c'GLFWgammaramp'size  ggr-              n    = fromC cn-          if n == 0 || nullPtr `elem` [p'rs, p'gs, p'bs]-            then return Nothing-            else do-                rs <- map fromC `fmap` peekArray n p'rs-                gs <- map fromC `fmap` peekArray n p'gs-                bs <- map fromC `fmap` peekArray n p'bs-                return $ Just GammaRamp-                  { gammaRampRed   = rs-                  , gammaRampGreen = gs-                  , gammaRampBlue  = bs-                  }---- | Assigns a gamma ramp to use with the given monitor.--- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga583f0ffd0d29613d8cd172b996bbf0dd glfwSetGammaRamp>-setGammaRamp :: Monitor -> GammaRamp -> IO ()-setGammaRamp mon gr =-    let rs = map toC $ gammaRampRed   gr :: [CUShort]-        gs = map toC $ gammaRampGreen gr :: [CUShort]-        bs = map toC $ gammaRampBlue  gr :: [CUShort]-        -- GammaRamp's smart constructor ensures that the RGB lists all have-        -- equal length, so just use the number of reds.-        cn = toC $ length rs :: CUInt-    in alloca       $ \p'ggr ->-       withArray rs $ \p'rs  ->-       withArray gs $ \p'gs  ->-       withArray bs $ \p'bs  -> do-          let ggr = C'GLFWgammaramp-                      { c'GLFWgammaramp'red   = p'rs-                      , c'GLFWgammaramp'green = p'gs-                      , c'GLFWgammaramp'blue  = p'bs-                      , c'GLFWgammaramp'size  = cn-                      }-          poke p'ggr ggr-          c'glfwSetGammaRamp (toC mon) p'ggr------------------------------------------------------------------------------------- Window handling---- | Sets all the window hints to default.--- See <http://www.glfw.org/docs/3.2/group__window.html#gaa77c4898dfb83344a6b4f76aa16b9a4a glfwDefaultWindowHints>-defaultWindowHints :: IO ()-defaultWindowHints =-    c'glfwDefaultWindowHints---- | Hints something to the GLFW windowing system.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033 glfwWindowHint>-windowHint :: WindowHint -> IO ()-windowHint wh =-    let (t, v) = unpack-    in c'glfwWindowHint t v-  where-    unpack = case wh of-      (WindowHint'Resizable              x) -> (c'GLFW_RESIZABLE,                toC x)-      (WindowHint'Visible                x) -> (c'GLFW_VISIBLE,                  toC x)-      (WindowHint'Decorated              x) -> (c'GLFW_DECORATED,                toC x)-      (WindowHint'RedBits                x) -> (c'GLFW_RED_BITS,                 toC x)-      (WindowHint'GreenBits              x) -> (c'GLFW_GREEN_BITS,               toC x)-      (WindowHint'BlueBits               x) -> (c'GLFW_BLUE_BITS,                toC x)-      (WindowHint'AlphaBits              x) -> (c'GLFW_ALPHA_BITS,               toC x)-      (WindowHint'DepthBits              x) -> (c'GLFW_DEPTH_BITS,               toC x)-      (WindowHint'StencilBits            x) -> (c'GLFW_STENCIL_BITS,             toC x)-      (WindowHint'AccumRedBits           x) -> (c'GLFW_ACCUM_RED_BITS,           toC x)-      (WindowHint'AccumGreenBits         x) -> (c'GLFW_ACCUM_GREEN_BITS,         toC x)-      (WindowHint'AccumBlueBits          x) -> (c'GLFW_ACCUM_BLUE_BITS,          toC x)-      (WindowHint'AccumAlphaBits         x) -> (c'GLFW_ACCUM_ALPHA_BITS,         toC x)-      (WindowHint'AuxBuffers             x) -> (c'GLFW_AUX_BUFFERS,              toC x)-      (WindowHint'Samples                x) -> (c'GLFW_SAMPLES,                  toC x)-      (WindowHint'RefreshRate            x) -> (c'GLFW_REFRESH_RATE,             toC x)-      (WindowHint'DoubleBuffer           x) -> (c'GLFW_DOUBLEBUFFER,             toC x)-      (WindowHint'Stereo                 x) -> (c'GLFW_STEREO,                   toC x)-      (WindowHint'sRGBCapable            x) -> (c'GLFW_SRGB_CAPABLE,             toC x)-      (WindowHint'Floating               x) -> (c'GLFW_FLOATING,                 toC x)-      (WindowHint'Focused                x) -> (c'GLFW_FOCUSED,                  toC x)-      (WindowHint'Maximized              x) -> (c'GLFW_MAXIMIZED,                toC x)-      (WindowHint'AutoIconify            x) -> (c'GLFW_AUTO_ICONIFY,             toC x)-      (WindowHint'ClientAPI              x) -> (c'GLFW_CLIENT_API,               toC x)-      (WindowHint'ContextCreationAPI     x) -> (c'GLFW_CONTEXT_CREATION_API,     toC x)-      (WindowHint'ContextVersionMajor    x) -> (c'GLFW_CONTEXT_VERSION_MAJOR,    toC x)-      (WindowHint'ContextVersionMinor    x) -> (c'GLFW_CONTEXT_VERSION_MINOR,    toC x)-      (WindowHint'ContextRobustness      x) -> (c'GLFW_CONTEXT_ROBUSTNESS,       toC x)-      (WindowHint'ContextReleaseBehavior x) -> (c'GLFW_CONTEXT_RELEASE_BEHAVIOR, toC x)-      (WindowHint'ContextNoError         x) -> (c'GLFW_CONTEXT_NO_ERROR,         toC x)-      (WindowHint'OpenGLForwardCompat    x) -> (c'GLFW_OPENGL_FORWARD_COMPAT,    toC x)-      (WindowHint'OpenGLDebugContext     x) -> (c'GLFW_OPENGL_DEBUG_CONTEXT,     toC x)-      (WindowHint'OpenGLProfile          x) -> (c'GLFW_OPENGL_PROFILE,           toC x)---- | Creates a new window.--- Note: If running in GHCI don't forget to `:set -fno-ghci-sandbox` or you--- may run into an assertion failure, segfault or other nasty crash.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344 glfwCreateWindow>-createWindow :: Int -- ^ Desired width for the window.-             -> Int -- ^ Desired height for the window.-             -> String -- ^ Desired title for the window.-             -> Maybe Monitor -- ^ Monitor to use in fullscreen mode.-             -> Maybe Window  -- ^ Window for context object sharing, see-                              -- <http://www.glfw.org/docs/3.2/context.html#context_sharing here>.-             -> IO (Maybe Window)-createWindow w h title mmon mwin =-    withCString title $ \ptitle -> do-        charFun             <- newIORef nullFunPtr-        charModsFun         <- newIORef nullFunPtr-        cursorEnterFun      <- newIORef nullFunPtr-        cursorPosFun        <- newIORef nullFunPtr-        framebufferSizeFun  <- newIORef nullFunPtr-        keyFun              <- newIORef nullFunPtr-        mouseButtonFun      <- newIORef nullFunPtr-        scrollFun           <- newIORef nullFunPtr-        windowCloseFun      <- newIORef nullFunPtr-        windowFocusFun      <- newIORef nullFunPtr-        windowIconifyFun    <- newIORef nullFunPtr-        windowPosFun        <- newIORef nullFunPtr-        windowRefreshFun    <- newIORef nullFunPtr-        windowSizeFun       <- newIORef nullFunPtr-        dropFun             <- newIORef nullFunPtr-        let callbacks = WindowCallbacks-              { storedCharFun             = charFun-              , storedCharModsFun         = charModsFun-              , storedCursorEnterFun      = cursorEnterFun-              , storedCursorPosFun        = cursorPosFun-              , storedFramebufferSizeFun  = framebufferSizeFun-              , storedKeyFun              = keyFun-              , storedMouseButtonFun      = mouseButtonFun-              , storedScrollFun           = scrollFun-              , storedWindowCloseFun      = windowCloseFun-              , storedWindowFocusFun      = windowFocusFun-              , storedWindowIconifyFun    = windowIconifyFun-              , storedWindowPosFun        = windowPosFun-              , storedWindowRefreshFun    = windowRefreshFun-              , storedWindowSizeFun       = windowSizeFun-              , storedDropFun             = dropFun-              }-        p'win <- c'glfwCreateWindow-          (toC w)-          (toC h)-          ptitle-          (maybe nullPtr toC mmon)-          (maybe nullPtr toC mwin)-        if p'win == nullPtr-          then return Nothing-          else do callbackPtr <- newStablePtr callbacks-                  c'glfwSetWindowUserPointer p'win (castStablePtrToPtr callbackPtr)-                  return $ Just $ fromC p'win---- | Cleans up a window and all associated resources--- See <http://www.glfw.org/docs/3.2/group__window.html#gacdf43e51376051d2c091662e9fe3d7b2 glfwDestroyWindow>-destroyWindow :: Window -> IO ()-destroyWindow win = do-    pcb <- castPtrToStablePtr `liftM` c'glfwGetWindowUserPointer (toC win)-    cbs <- deRefStablePtr pcb-    c'glfwDestroyWindow (toC win)--    let free callback = do funptr <- readIORef (callback cbs)-                           when (funptr /= nullFunPtr) $ freeHaskellFunPtr funptr-    free storedCharFun-    free storedCharModsFun-    free storedCursorEnterFun-    free storedCursorPosFun-    free storedFramebufferSizeFun-    free storedKeyFun-    free storedMouseButtonFun-    free storedScrollFun-    free storedWindowCloseFun-    free storedWindowFocusFun-    free storedWindowIconifyFun-    free storedWindowPosFun-    free storedWindowRefreshFun-    free storedWindowSizeFun-    freeStablePtr pcb---- | If the window should close or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga24e02fbfefbb81fc45320989f8140ab5 glfwWindowShouldClose>-windowShouldClose :: Window -> IO Bool-windowShouldClose win =-    fromC `fmap` c'glfwWindowShouldClose (toC win)---- | Sets if the window should close or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga49c449dde2a6f87d996f4daaa09d6708 glfwSetWindowShouldClose>-setWindowShouldClose :: Window -> Bool -> IO ()-setWindowShouldClose win b =-    c'glfwSetWindowShouldClose (toC win) (toC b)---- | Sets the Title string of the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga5d877f09e968cef7a360b513306f17ff glfwSetWindowTitle>-setWindowTitle :: Window -> String -> IO ()-setWindowTitle win title =-    withCString title $ c'glfwSetWindowTitle (toC win)---- | Gets the window's position (in Screen Coordinates).--- See <http://www.glfw.org/docs/3.2/group__window.html#ga73cb526c000876fd8ddf571570fdb634 glfwGetWindowPos>-getWindowPos :: Window -> IO (Int, Int)-getWindowPos win =-    allocaArray 2 $ \p -> do-        let p'x = p-            p'y = p `advancePtr` 1-        c'glfwGetWindowPos (toC win) p'x p'y-        x <- fromC `fmap` peek p'x-        y <- fromC `fmap` peek p'y-        return (x, y)---- | Sets the window's position (in Screen Coordinates).--- See <http://www.glfw.org/docs/3.2/group__window.html#ga1abb6d690e8c88e0c8cd1751356dbca8 glfwSetWindowPos>-setWindowPos :: Window -> Int -> Int -> IO ()-setWindowPos win x y =-    c'glfwSetWindowPos (toC win) (toC x) (toC y)---- | Gets the size of the window (in Screen Coordinates).--- See <http://www.glfw.org/docs/3.2/group__window.html#gaeea7cbc03373a41fb51cfbf9f2a5d4c6 glfwGetWindowSize>-getWindowSize :: Window -> IO (Int, Int)-getWindowSize win =-    allocaArray 2 $ \p -> do-        let p'w = p-            p'h = p `advancePtr` 1-        c'glfwGetWindowSize (toC win) p'w p'h-        w <- fromC `fmap` peek p'w-        h <- fromC `fmap` peek p'h-        return (w, h)---- | Gets the size of the frame around the window (in Screen Coordinates). This--- size includes the title bar, if the window has one. Not to be confused with--- 'getFramebufferSize', which gets the size of the rendering area.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga1a9fd382058c53101b21cf211898f1f1 glfwGetWindowFrameSize>-getWindowFrameSize :: Window -> IO (Int, Int, Int, Int)-getWindowFrameSize win =-    allocaArray 4 $ \p -> do-        let p'l = p-            p't = p `advancePtr` 1-            p'r = p `advancePtr` 2-            p'b = p `advancePtr` 3-        c'glfwGetWindowFrameSize (toC win) p'l p't p'r p'b-        l <- fromC `fmap` peek p'l-        t <- fromC `fmap` peek p't-        r <- fromC `fmap` peek p'r-        b <- fromC `fmap` peek p'b-        return (l, t, r, b)---- | Sets the size of the client area for the window (in Screen Coordinates).--- See <http://www.glfw.org/docs/3.2/group__window.html#ga371911f12c74c504dd8d47d832d095cb glfwSetWindowSize>-setWindowSize :: Window -> Int -> Int -> IO ()-setWindowSize win w h =-    c'glfwSetWindowSize (toC win) (toC w) (toC h)---- | Sets the size limits of the client area of the specified window. If the--- window is full screen, the size limits only take effect once it is made--- windowed. If the window is not resizable this function does nothing. Pass--- 'Nothing' in any argument to disable the limit.--- See <http://www.glfw.org/docs/3.2/group__window.html#gac314fa6cec7d2d307be9963e2709cc90 glfwSetWindowSizeLimits>-setWindowSizeLimits :: Window-                    -> Maybe Int-                    -- ^ The minimum width, in screen coordinates, of the client-                    --   area.-                    -> Maybe Int-                    -- ^ The minimum height, in screen coordinates, of the-                    --   client area.-                    -> Maybe Int-                    -- ^ The maximum width, in screen coordinates, of the client-                    --   area.-                    -> Maybe Int-                    -- ^ The maximum height, in screen coordinates, of the-                    --   client area.-                    -> IO ()-setWindowSizeLimits win min'w min'h max'w max'h =-  c'glfwSetWindowSizeLimits (toC win) (toC min'w) (toC min'h)-                                      (toC max'w) (toC max'h)---- | Sets the required aspect ratio of the client area of the specified window.--- Pass Nothing to disable the limit.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga72ac8cb1ee2e312a878b55153d81b937 glfwSetWindowAspectRatio>-setWindowAspectRatio :: Window -> Maybe (Int, Int) -> IO ()-setWindowAspectRatio win Nothing =-  c'glfwSetWindowAspectRatio (toC win) c'GLFW_DONT_CARE c'GLFW_DONT_CARE-setWindowAspectRatio win (Just (w, h)) =-  c'glfwSetWindowAspectRatio (toC win) (toC w) (toC h)---- | The size of the framebuffer (in Pixels)--- See <http://www.glfw.org/docs/3.2/group__window.html#ga0e2637a4161afb283f5300c7f94785c9 glfwGetFramebufferSize>-getFramebufferSize :: Window -> IO (Int, Int)-getFramebufferSize win =-    allocaArray 2 $ \p -> do-        let p'w = p-            p'h = p `advancePtr` 1-        c'glfwGetFramebufferSize (toC win) p'w p'h-        w <- fromC `fmap` peek p'w-        h <- fromC `fmap` peek p'h-        return (w, h)---- | Sets the icon of the specified window. The system will try to find the--- image with the dimensions closest to the ones required by the platform. This--- image is then scaled and used as the icon for that size. Good sizes are--- 16x16, 32x32, and 48x48. Pass the empty list to reset to the default icon.--- Has no effect on OS X (See the <https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html Bundle Programming Guide>)-setWindowIcon :: Window -> [Image] -> IO ()-setWindowIcon win [] = c'glfwSetWindowIcon (toC win) 0 nullPtr-setWindowIcon win imgs =-  let arrSizeBytes = length imgs * sizeOf (undefined :: C'GLFWimage)--      addNextImage :: [Image] -> Int -> Ptr C'GLFWimage -> IO ()-      addNextImage [] numImages ptr =-        c'glfwSetWindowIcon (toC win) (toC numImages) ptr--      addNextImage (img:rest) idx ptr =-        withGLFWImage img $ \p'img -> do-          c'img <- peek p'img-          pokeElemOff ptr idx c'img-          addNextImage rest (idx + 1) ptr-  in allocaBytes arrSizeBytes $ addNextImage imgs 0---- | Iconifies (minimizes) the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga1bb559c0ebaad63c5c05ad2a066779c4 glfwIconifyWindow>-iconifyWindow :: Window -> IO ()-iconifyWindow =-    c'glfwIconifyWindow . toC---- | Restores the window from an iconified/minimized state.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga52527a5904b47d802b6b4bb519cdebc7 glfwRestoreWindow>-restoreWindow :: Window -> IO ()-restoreWindow =-    c'glfwRestoreWindow . toC---- | Brings the specified window to front and sets input focus. The window--- should already be visible and not iconified.--- See <http://www.glfw.org/docs/latest/group__window.html#ga873780357abd3f3a081d71a40aae45a1 glfwFocusWindow>-focusWindow :: Window -> IO ()-focusWindow = c'glfwFocusWindow . toC---- | Maximizes the specified window if it was not already maximized.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga3f541387449d911274324ae7f17ec56b glfwMaximizeWindow>-maximizeWindow :: Window -> IO ()-maximizeWindow = c'glfwMaximizeWindow . toC---- | Shows the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga61be47917b72536a148300f46494fc66 glfwShowWindow>-showWindow :: Window -> IO ()-showWindow =-    c'glfwShowWindow . toC---- | Hides the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga49401f82a1ba5f15db5590728314d47c glfwHideWindow>-hideWindow :: Window -> IO ()-hideWindow =-    c'glfwHideWindow . toC---- | Gets the monitor that this window is running on, provided the window is--- fullscreen.--- See <http://www.glfw.org/docs/3.2/group__window.html#gaeac25e64789974ccbe0811766bd91a16 glfwGetWindowMonitor>-getWindowMonitor :: Window -> IO (Maybe Monitor)-getWindowMonitor win = do-    p'mon <- c'glfwGetWindowMonitor (toC win)-    return $ if p'mon == nullPtr-      then Nothing-      else Just $ fromC p'mon---- | Sets the position of the cursor within the window.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga04b03af936d906ca123c8f4ee08b39e7 glfwSetCursorPos>-setCursorPos :: Window -> Double -> Double -> IO ()-setCursorPos win x y =-    c'glfwSetCursorPos (toC win) (toC x) (toC y)---- | Makes a window fullscreen on the given monitor. The number of red, green,--- and blue bits is ignored. Note, this shouldn't be used to update the--- resolution of a fullscreen window. Use 'setWindowSize' instead.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga81c76c418af80a1cce7055bccb0ae0a7 glfwSetWindowMonitor>-setFullscreen :: Window -> Monitor -> VideoMode -> IO ()-setFullscreen win mon (VideoMode width height _ _ _ refresh) =-  c'glfwSetWindowMonitor (toC win) (toC mon) 0 0 (toC width) (toC height) (toC refresh)---- | Updates a window to be windowed instead of fullscreen. Note, this shouldn't--- be used to update the position or size of a window. Use 'setWindowPos' and--- 'setWindowSize' instead.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga81c76c418af80a1cce7055bccb0ae0a7 glfwSetWindowMonitor>-setWindowed :: Window-            -> Int  -- ^ The width of the client area-            -> Int  -- ^ The height of the client area-            -> Int  -- ^ The x position of the window-            -> Int  -- ^ The y position of the window-            -> IO ()-setWindowed win width height x y =-  c'glfwSetWindowMonitor (toC win) nullPtr (toC x) (toC y) (toC width) (toC height) 0---- start of functions related to c'glfwGetWindowAttrib---- | If the window has focus or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowFocused :: Window -> IO Bool-getWindowFocused win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_FOCUSED---- | If the window is maximized or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowMaximized :: Window -> IO Bool-getWindowMaximized win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_MAXIMIZED---- | If the window has been set to be 'always on top' or not.--- See <http://www.glfw.org/docs/latest/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowFloating :: Window -> IO Bool-getWindowFloating win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_FLOATING---- | If the window is iconified (minimized) or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowIconified :: Window -> IO Bool-getWindowIconified win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_ICONIFIED---- | If the window is resizable or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowResizable :: Window -> IO Bool-getWindowResizable win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_RESIZABLE---- | If the window is decorated or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowDecorated :: Window -> IO Bool-getWindowDecorated win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_DECORATED---- | If the window is visible or not.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowVisible :: Window -> IO Bool-getWindowVisible win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_VISIBLE---- | The client api for this window.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowClientAPI :: Window -> IO ClientAPI-getWindowClientAPI win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CLIENT_API---- | Returns the context creation API used to create the specified window.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextCreationAPI :: Window -> IO ContextCreationAPI-getWindowContextCreationAPI win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_CREATION_API---- | The context's "major" version, x.0.0--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextVersionMajor :: Window -> IO Int-getWindowContextVersionMajor win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_VERSION_MAJOR---- | The context's "minor" version, 0.y.0--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextVersionMinor :: Window -> IO Int-getWindowContextVersionMinor win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_VERSION_MINOR---- | The context's "revision" version, 0.0.z--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextVersionRevision :: Window -> IO Int-getWindowContextVersionRevision win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_REVISION---- | The context robustness of this window.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextRobustness :: Window -> IO ContextRobustness-getWindowContextRobustness win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_ROBUSTNESS---- | Returns the context release behavior.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowContextReleaseBehavior :: Window -> IO ContextReleaseBehavior-getWindowContextReleaseBehavior win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_RELEASE_BEHAVIOR---- | Returns true if the window is set to NO_ERROR (see the--- <https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_no_error.txt KHR_no_error>--- extension.-getWindowContextNoError :: Window -> IO Bool-getWindowContextNoError win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_NO_ERROR---- | If this window is set for opengl to be forward compatible.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowOpenGLForwardCompat :: Window -> IO Bool-getWindowOpenGLForwardCompat win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_FORWARD_COMPAT---- | If the window has an opengl debug context--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowOpenGLDebugContext :: Window -> IO Bool-getWindowOpenGLDebugContext win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_DEBUG_CONTEXT---- | Obtains the current opengl profile.--- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>-getWindowOpenGLProfile :: Window -> IO OpenGLProfile-getWindowOpenGLProfile win =-    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_PROFILE---- end of functions related to c'glfwGetWindowAttrib---- | Sets the callback to use when the window position changes.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga2837d4d240659feb4268fcb6530a6ba1 glfwSetWindowPosCallback>-setWindowPosCallback :: Window -> Maybe WindowPosCallback -> IO ()-setWindowPosCallback win = setWindowCallback-    mk'GLFWwindowposfun-    (\cb a0 a1 a2 ->-      schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetWindowPosCallback (toC win))-    storedWindowPosFun-    win---- | Sets the callback to use when the window's size changes.--- See <http://www.glfw.org/docs/3.2/group__window.html#gaa40cd24840daa8c62f36cafc847c72b6 glfwSetWindowSizeCallback>-setWindowSizeCallback :: Window -> Maybe WindowSizeCallback -> IO ()-setWindowSizeCallback win = setWindowCallback-    mk'GLFWwindowsizefun-    (\cb a0 a1 a2 ->-      schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetWindowSizeCallback (toC win))-    storedWindowSizeFun-    win---- | Sets the callback to use when the user attempts to close the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#gaade9264e79fae52bdb78e2df11ee8d6a glfwSetWindowCloseCallback>-setWindowCloseCallback :: Window -> Maybe WindowCloseCallback -> IO ()-setWindowCloseCallback win = setWindowCallback-    mk'GLFWwindowclosefun-    (. fromC)-    (c'glfwSetWindowCloseCallback (toC win))-    storedWindowCloseFun-    win---- | Sets the callback to use when the window's data is partly dead and it should refresh.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga4569b76e8ac87c55b53199e6becd97eb glfwSetWindowRefreshCallback>-setWindowRefreshCallback :: Window -> Maybe WindowRefreshCallback -> IO ()-setWindowRefreshCallback win = setWindowCallback-    mk'GLFWwindowrefreshfun-    (. fromC)-    (c'glfwSetWindowRefreshCallback (toC win))-    storedWindowRefreshFun-    win---- | Sets the callback to use when the window gains or loses focus.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga25d1c584edb375d7711c5c3548ba711f glfwSetWindowFocusCallback>-setWindowFocusCallback :: Window -> Maybe WindowFocusCallback -> IO ()-setWindowFocusCallback win = setWindowCallback-    mk'GLFWwindowfocusfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    (c'glfwSetWindowFocusCallback (toC win))-    storedWindowFocusFun-    win---- | Sets the callback to use when the window is iconified or not (aka, minimized or not).--- See <http://www.glfw.org/docs/3.2/group__window.html#gab1ea7263081c0e073b8d5b91d6ffd367 glfwSetWindowIconifyCallback>-setWindowIconifyCallback :: Window -> Maybe WindowIconifyCallback -> IO ()-setWindowIconifyCallback win = setWindowCallback-    mk'GLFWwindowiconifyfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    (c'glfwSetWindowIconifyCallback (toC win))-    storedWindowIconifyFun-    win---- | Sets the callback to use when the framebuffer's size changes.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga3203461a5303bf289f2e05f854b2f7cf glfwSetFramebufferSizeCallback>-setFramebufferSizeCallback :: Window -> Maybe FramebufferSizeCallback -> IO ()-setFramebufferSizeCallback win = setWindowCallback-    mk'GLFWframebuffersizefun-    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetFramebufferSizeCallback (toC win))-    storedFramebufferSizeFun-    win---- | Checks for any pending events, processes them, and then immediately returns.--- This is most useful for continual rendering, such as games.--- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>-pollEvents :: IO ()-pollEvents = c'glfwPollEvents >> executeScheduled---- | Waits until at least one event is in the queue then processes the queue and returns.--- Requires at least one window to be active for it to sleep. This saves a lot of CPU, and--- is better if you're doing only periodic rendering, such as with an editor program.--- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>-waitEvents :: IO ()-waitEvents = c'glfwWaitEvents >> executeScheduled---- | Same as 'waitEvents', with a timeout after which the function returns.--- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>-waitEventsTimeout :: Double -> IO ()-waitEventsTimeout seconds =-  c'glfwWaitEventsTimeout (toC seconds) >> executeScheduled---- | Creates an empty event within the event queue. Can be called from any--- thread, so you can use this to wake up the main thread that's using--- 'waitEvents' from a secondary thread.--- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>-postEmptyEvent :: IO ()-postEmptyEvent = c'glfwPostEmptyEvent------------------------------------------------------------------------------------- Input handling---- start of glfw{GS}etInputMode-related functions---- | Gets the current cursor input mode.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-getCursorInputMode :: Window -> IO CursorInputMode-getCursorInputMode win =-    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_CURSOR---- | Set the cursor input mode.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-setCursorInputMode :: Window -> CursorInputMode -> IO ()-setCursorInputMode win c =-    c'glfwSetInputMode (toC win) c'GLFW_CURSOR (toC c)---- | Gets the current sticky keys mode.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-getStickyKeysInputMode :: Window -> IO StickyKeysInputMode-getStickyKeysInputMode win =-    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_STICKY_KEYS---- | Sets if sticky keys should be used or not.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-setStickyKeysInputMode :: Window -> StickyKeysInputMode -> IO ()-setStickyKeysInputMode win sk =-    c'glfwSetInputMode (toC win) c'GLFW_STICKY_KEYS (toC sk)---- | Gets if sticky mouse buttons are on or not.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-getStickyMouseButtonsInputMode :: Window -> IO StickyMouseButtonsInputMode-getStickyMouseButtonsInputMode win =-    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_STICKY_MOUSE_BUTTONS---- | Sets if sticky mouse buttons should be used or not.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>-setStickyMouseButtonsInputMode :: Window -> StickyMouseButtonsInputMode -> IO ()-setStickyMouseButtonsInputMode win smb =-    c'glfwSetInputMode (toC win) c'GLFW_STICKY_MOUSE_BUTTONS (toC smb)---- end of glfw{GS}etInputMode-related functions---- | Gets the state of the specified key. If Stickey Keys isn't enabled then it's possible for--- keyboard polling to miss individual key presses. Use the callback to avoid this.--- See <http://www.glfw.org/docs/3.2/group__input.html#gadd341da06bc8d418b4dc3a3518af9ad2 glfwGetKey>-getKey :: Window -> Key -> IO KeyState-getKey win k =-    fromC `fmap` c'glfwGetKey (toC win) (toC k)---- | Returns the localized name of the specified printable key. This is intended--- for displaying key bindings to the user. The scancode is used if the provided--- 'Key' isn't printable. If the scancode maps to a non-printable key as well,--- then 'Nothing' is returned.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga237a182e5ec0b21ce64543f3b5e7e2be glfwGetKeyName>-getKeyName :: Key -> Int -> IO (Maybe String)-getKeyName k scancode = do-  cstr <- c'glfwGetKeyName (toC k) (toC scancode)-  if cstr == nullPtr-    then return Nothing-    else Just `fmap` peekCString cstr---- | Gets the state of a single specified mouse button. If sticky mouse button--- mode isn't enabled it's possible for mouse polling to miss individual mouse events. Use--- the call back to avoid this.--- See <http://www.glfw.org/docs/3.2/group__input.html#gac1473feacb5996c01a7a5a33b5066704 glfwGetMouseButton>-getMouseButton :: Window -> MouseButton -> IO MouseButtonState-getMouseButton win b =-    fromC `fmap` c'glfwGetMouseButton (toC win) (toC b)---- | Returns the position, in screen coodinates, relative to the upper left.--- If the 'CursorInputMode' is "disabled", then results are unbounded by the window size.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga01d37b6c40133676b9cea60ca1d7c0cc glfwGetCursorPos>-getCursorPos :: Window -> IO (Double, Double)-getCursorPos win =-    allocaArray 2 $ \p -> do-        let p'x = p-            p'y = p `advancePtr` 1-        c'glfwGetCursorPos (toC win) p'x p'y-        x <- fromC `fmap` peek p'x-        y <- fromC `fmap` peek p'y-        return (x, y)---- | Assigns the given callback to use for all keyboard presses and repeats.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga7e496507126f35ea72f01b2e6ef6d155 glfwSetKeyCallback>-setKeyCallback :: Window -> Maybe KeyCallback -> IO ()-setKeyCallback win = setWindowCallback-    mk'GLFWkeyfun-    (\cb a0 a1 a2 a3 a4 ->-      schedule $ cb (fromC a0) (fromC a1) (fromC a2) (fromC a3) (fromC a4))-    (c'glfwSetKeyCallback (toC win))-    storedKeyFun-    win---- | Sets the callback to use when the user types a character--- See <http://www.glfw.org/docs/3.2/group__input.html#ga556239421c6a5a243c66fca28da9f742 glfwSetCharCallback>-setCharCallback :: Window -> Maybe CharCallback -> IO ()-setCharCallback win = setWindowCallback-    mk'GLFWcharfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    (c'glfwSetCharCallback (toC win))-    storedCharFun-    win---- | Sets the callback to use with Unicode characters regardless of what--- modifier keys are used.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga3f55ef5dc03a374e567f068b13c94afc glfwSetCharModsCallback>-setCharModsCallback :: Window -> Maybe CharModsCallback -> IO ()-setCharModsCallback win = setWindowCallback-    mk'GLFWcharmodsfun-    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetCharModsCallback (toC win))-    storedCharModsFun-    win---- | Assigns the callback to run whenver a mouse button is clicked.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaef49b72d84d615bca0a6ed65485e035d glfwSetMouseButtonCallback>-setMouseButtonCallback :: Window -> Maybe MouseButtonCallback -> IO ()-setMouseButtonCallback win = setWindowCallback-    mk'GLFWmousebuttonfun-    (\cb a0 a1 a2 a3 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2) (fromC a3))-    (c'glfwSetMouseButtonCallback (toC win))-    storedMouseButtonFun-    win---- | Assigns the callback to run whenver the cursor position changes.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga7dad39486f2c7591af7fb25134a2501d glfwSetCursorPosCallback>-setCursorPosCallback :: Window -> Maybe CursorPosCallback -> IO ()-setCursorPosCallback win = setWindowCallback-    mk'GLFWcursorposfun-    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetCursorPosCallback (toC win))-    storedCursorPosFun-    win---- | Sets the callback for when the cursor enters or leaves the client area.--- See <http://www.glfw.org/docs/3.2/input.html#cursor_enter Cursor Enter/Leave Events>-setCursorEnterCallback :: Window -> Maybe CursorEnterCallback -> IO ()-setCursorEnterCallback win = setWindowCallback-    mk'GLFWcursorenterfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    (c'glfwSetCursorEnterCallback (toC win))-    storedCursorEnterFun-    win---- | Sets the callback to run when the user scrolls with the mouse wheel or a touch gesture.--- See <http://www.glfw.org/docs/3.2/input.html#scrolling Scroll Input>-setScrollCallback :: Window -> Maybe ScrollCallback -> IO ()-setScrollCallback win = setWindowCallback-    mk'GLFWscrollfun-    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))-    (c'glfwSetScrollCallback (toC win))-    storedScrollFun-    win---- | Tests if the joystick is present at all--- See <http://www.glfw.org/docs/3.2/group__input.html#gaffcbd9ac8ee737fcdd25475123a3c790 glfwJoystickPresent>-joystickPresent :: Joystick -> IO Bool-joystickPresent js =-    fromC `fmap` c'glfwJoystickPresent (toC js)---- | Returns the values of all axes of the specified joystick, normalized to between -1.0 and 1.0--- See <http://www.glfw.org/docs/3.2/group__input.html#ga6271d46a5901ec2c99601ccf4dd14731 glfwGetJoystickAxes>-getJoystickAxes :: Joystick -> IO (Maybe [Double])-getJoystickAxes js =-    alloca $ \p'n -> do-        p'axes <- c'glfwGetJoystickAxes (toC js) p'n-        n <- fromC `fmap` peek p'n-        if p'axes == nullPtr || n <= 0-          then return Nothing-          else (Just . map fromC) `fmap` peekArray n p'axes---- | Returns a list of all joystick button states for the specified joystick.--- See <http://www.glfw.org/docs/3.2/group__input.html#gace54cd930dcd502e118fe4021384ce1b glfwGetJoystickButtons>-getJoystickButtons :: Joystick -> IO (Maybe [JoystickButtonState])-getJoystickButtons js =-    alloca $ \p'n -> do-        p'buttons <- c'glfwGetJoystickButtons (toC js) p'n-        n <- fromC `fmap` peek p'n-        if p'buttons == nullPtr || n <= 0-          then return Nothing-          else (Just . map fromC) `fmap` peekArray n p'buttons---- | A human-readable name for a Joystick. Not guranteed to be unique.--- See <http://www.glfw.org/docs/3.2/group__input.html#gac8d7f6107e05cfd106cfba973ab51e19 glfwGetJoystickName>-getJoystickName :: Joystick -> IO (Maybe String)-getJoystickName js = do-    p'name <- c'glfwGetJoystickName (toC js)-    if p'name == nullPtr-      then return Nothing-      else Just `fmap` peekCString p'name---- | Sets a callback for when a joystick is connected or disconnected.--- See <http://www.glfw.org/docs/3.2/group__input.html#gab1dc8379f1b82bb660a6b9c9fa06ca07 glfwSetJoystickCallback>-setJoystickCallback :: Maybe JoystickCallback -> IO ()-setJoystickCallback = setCallback-    mk'GLFWjoystickfun-    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))-    c'glfwSetJoystickCallback-    storedJoystickFun------------------------------------------------------------------------------------- Time---- | Returns the time (in seconds) of the GLFW timer.--- This is the amount of time since GLFW was initialized, unless 'setTime' was used.--- The exact resolution is system dependent.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaa6cf4e7a77158a3b8fd00328b1720a4a glfwGetTime>-getTime :: IO (Maybe Double)-getTime = do-    t <- fromC `fmap` c'glfwGetTime-    return $ if t == 0-      then Nothing-      else Just t---- | Sets the GLFW timer to the specified value, which is measured in seconds, and must be positive.--- The value must also be less than ~584 years in seconds (18446744073.0).--- After this the timer begins to count upward at the normal rate.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaf59589ef6e8b8c8b5ad184b25afd4dc0 glfwSetTime>-setTime :: Double -> IO ()-setTime = c'glfwSetTime . toC---- | Returns the current value of the raw timer, measured in 1 / frequency--- seconds. The frequency can be queried using getTimerFrequency.--- See <http://www.glfw.org/docs/3.2/input_guide.html#time Timer input>-getTimerValue :: IO Word64-getTimerValue = c'glfwGetTimerValue---- | Returns the frequency, in Hz, of the raw timer.--- See <http://www.glfw.org/docs/3.2/input_guide.html#time Timer input>-getTimerFrequency :: IO Word64-getTimerFrequency = c'glfwGetTimerFrequency------------------------------------------------------------------------------------- Context---- | Makes the context of the specified window the current one for the calling thread.--- A context can only be made current on a single thread at a time,--- and each thread can have only a single current context at a time.--- See <http://www.glfw.org/docs/3.2/group__context.html#ga1c04dc242268f827290fe40aa1c91157 glfwMakeContextCurrent>-makeContextCurrent :: Maybe Window -> IO ()-makeContextCurrent =-    c'glfwMakeContextCurrent . maybe nullPtr toC---- | Obtains which window owns the current context of the calling thread.--- See <http://www.glfw.org/docs/3.2/group__context.html#gac84759b1f6c2d271a4fea8ae89ec980d glfwGetCurrentContext>-getCurrentContext :: IO (Maybe Window)-getCurrentContext = do-    p'win <- c'glfwGetCurrentContext-    return $ if p'win == nullPtr-      then Nothing-      else Just $ fromC p'win---- | Swaps the front and back buffers of the window.--- See <http://www.glfw.org/docs/3.2/group__window.html#ga15a5a1ee5b3c2ca6b15ca209a12efd14 glfwSwapBuffers>-swapBuffers :: Window -> IO ()-swapBuffers =-    c'glfwSwapBuffers . toC---- | Sets the number of screen updates that the GPU should wait after 'swapBuffers' before actually swapping the buffers.--- Generates 'Error'NoCurrentContext' if no context is current.--- See <http://www.glfw.org/docs/3.2/group__context.html#ga6d4e0cdf151b5e579bd67f13202994ed glfwSwapInterval>-swapInterval :: Int -> IO ()-swapInterval =-    c'glfwSwapInterval . toC---- | If the current OpenGL or OpenGL ES context supports the extension specified.--- Generates 'Error'NoCurrentContext' if no context is current.--- See <http://www.glfw.org/docs/3.2/group__context.html#ga87425065c011cef1ebd6aac75e059dfa glfwExtensionSupported>-extensionSupported :: String -> IO Bool-extensionSupported ext =-    withCString ext $ \p'ext ->-      fromC `fmap` c'glfwExtensionSupported p'ext------------------------------------------------------------------------------------- Clipboard--- http://www.glfw.org/docs/3.2/input.html#clipboard---- | The window that will own the clipboard contents, and also the clipboard string.--- See <http://www.glfw.org/docs/3.2/group__input.html#gaba1f022c5eb07dfac421df34cdcd31dd glfwSetClipboardString>-setClipboardString :: Window -> String -> IO ()-setClipboardString win s =-    withCString s (c'glfwSetClipboardString (toC win))---- | Obtains the contents of the system keyboard, if possible.--- Generates 'Error'FormatUnavailable' if the system clipboard is empty or if it's not a UTF-8 string.--- See <http://www.glfw.org/docs/3.2/group__input.html#ga5aba1d704d9ab539282b1fbe9f18bb94 glfwGetClipboardString>-getClipboardString :: Window -> IO (Maybe String)-getClipboardString win = do-    p's <- c'glfwGetClipboardString (toC win)-    if p's == nullPtr-      then return Nothing-      else Just `fmap` peekCString p's------------------------------------------------------------------------------------- 3.1 additions (http://www.glfw.org/docs/3.1/news.html#news_31)------------------------------------------------------------------------------------- Cursor Objects--- http://www.glfw.org/docs/3.2/input.html#cursor_object---- | Creates a new cursor.-createCursor :: Image -- ^ The desired cursor image.-             -> Int   -- ^ The desired x-coordinate, in pixels, of the cursor-                      --   hotspot.-             -> Int   -- ^ The desired y-coordinate, in pixels, of the cursor-                      --   hotspot.-             -> IO Cursor-createCursor img x y =-  withGLFWImage img $ \p'img ->-    Cursor `fmap` c'glfwCreateCursor p'img (toC x) (toC y)---- | Creates a cursor with a standard shape that can be set for a window with--- setCursor.-createStandardCursor :: StandardCursorShape -> IO Cursor-createStandardCursor = (fmap Cursor) . c'glfwCreateStandardCursor . toC---- | Sets the cursor image to be used when the cursor is over the client area--- of the specified window. The set cursor will only be visible when the cursor--- mode of the window is GLFW_CURSOR_NORMAL.---- On some platforms, the set cursor may not be visible unless the window also--- has input focus.-setCursor :: Window -> Cursor -> IO ()-setCursor (Window wptr) (Cursor cptr) = c'glfwSetCursor wptr cptr---- | Destroys a cursor previously created with `createCursor`. Any remaining--- cursors will be destroyed by `terminate`.-destroyCursor :: Cursor -> IO ()-destroyCursor = c'glfwDestroyCursor . unCursor---- | A callback that allows for drag and drop support.-type DropCallback = Window    -- ^ The window that received the event.-                  -> [String] -- ^ The file and/or directory path names-                  -> IO ()---- | Sets the file drop callback of the specified window, which is called when--- one or more dragged files are dropped on the window.-setDropCallback :: Window -> Maybe DropCallback -> IO ()-setDropCallback win = setWindowCallback-    mk'GLFWdropfun-    (\cb w c fs -> do-        let count = fromC c-        fps <- flip mapM [0..count-1] $ \i -> do-            let p = advancePtr fs i-            p' <- peek p-            peekCString p'-        schedule $ cb (fromC w) fps)-    (c'glfwSetDropCallback (toC win))-    storedDropFun-    win------------------------------------------------------------------------------------- Vulkan-related functions------------------------------------------------------------------------------------- | This function returns whether the Vulkan loader has been found.---   This check is performed by `init`.-vulkanSupported :: IO Bool-vulkanSupported = (c'GLFW_TRUE ==) <$> c'glfwVulkanSupported---- | Get required vulkan extensions;---   Pointer memory is managed by GLFW, destroyed by `terminate` call.------   The returned extension names are kept in `CString` type, because---   they are expected to be consumed by vulkan device initialization functions.-getRequiredInstanceExtensions :: IO [CString]-getRequiredInstanceExtensions = alloca $ \countPtr -> do-    extsPtrPtr <- c'glfwGetRequiredInstanceExtensions countPtr-    count <- fromIntegral <$> peek countPtr-    peekArray count extsPtrPtr---- | Returns the address of the specified Vulkan instance function.-getInstanceProcAddress :: Ptr vkInstance-                          -- ^ VkInstance.-                          --   Note, the returned function must be used-                          --   with the same instance or its child.-                       -> String-                          -- ^ Function name-                       -> IO (FunPtr vkProc)-getInstanceProcAddress i procName-  = withCString procName (c'glfwGetInstanceProcAddress i)---- | Returns whether the specified queue family can present images.-getPhysicalDevicePresentationSupport ::-       Ptr vkInstance-       -- ^ VkInstance-    -> Ptr vkPhysicalDevice-       -- ^ VkPhysicalDevice-    -> Word32-       -- ^ Index of a queue family to query.-       --   This is an index in the array returned by-       --   @vkGetPhysicalDeviceQueueFamilyProperties@ function.-    -> IO Bool-getPhysicalDevicePresentationSupport inst dev i-  = (c'GLFW_TRUE ==) <$> c'glfwGetPhysicalDevicePresentationSupport inst dev i---- | Creates a Vulkan surface for the specified window-createWindowSurface :: Enum vkResult-                    => Ptr vkInstance-                       -- ^ VkInstance-                    -> Window-                       -- ^ GLFWwindow *window-                    -> Ptr vkAllocationCallbacks-                       -- ^ const VkAllocationCallbacks *allocator-                    -> Ptr vkSurfaceKHR-                       -- ^ VkSurfaceKHR *surface-                    -> IO vkResult-createWindowSurface i win acs s-  = toEnum . fromIntegral-  <$> c'glfwCreateWindowSurface i (toC win) acs s------------------------------------------------------------------------------------- Native APIs------------------------------------------------------------------------------------- $nativeaccess--- The low level native-access bindings are exposed here via bindings-GLFW.--- These must be enabled with the 'ExposeNative' flag passed to bindings-GLFW.--- The return values of these functions are used as a best-guess and are not--- coupled with any other implementation. They should be used with caution--- and at your own risk.---- | See <http://www.glfw.org/docs/3.2/group__native.html#gac84f63a3f9db145b9435e5e0dbc4183d glfwGetWin32Adapter>-getWin32Adapter :: Window -> IO CString-getWin32Adapter = c'glfwGetWin32Adapter . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gac408b09a330749402d5d1fa1f5894dd9 glfwGetWin32Monitor>-getWin32Monitor :: Window -> IO CString-getWin32Monitor = c'glfwGetWin32Monitor . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gafe5079aa79038b0079fc09d5f0a8e667 glfwGetWin32Window>-getWin32Window  :: Window -> IO (Ptr ())-getWin32Window = c'glfwGetWin32Window . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gadc4010d91d9cc1134d040eeb1202a143 glfwGetWGLContext>-getWGLContext :: Window -> IO (Ptr ())-getWGLContext = c'glfwGetWGLContext . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gaf22f429aec4b1aab316142d66d9be3e6 glfwGetCocoaMonitor>-getCocoaMonitor :: Window -> IO (Ptr Word32)-getCocoaMonitor = c'glfwGetCocoaMonitor . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gac3ed9d495d0c2bb9652de5a50c648715 glfwGetCocoaWindow>-getCocoaWindow :: Window -> IO (Ptr ())-getCocoaWindow = c'glfwGetCocoaWindow . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga559e002e3cd63c979881770cd4dc63bc glfwGetNSGLContext>-getNSGLContext :: Window -> IO (Ptr ())-getNSGLContext = c'glfwGetNSGLContext . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga8519b66594ea3ef6eeafaa2e3ee37406 glfwGetX11Display>-getX11Display :: Window -> IO (Ptr display)-getX11Display = c'glfwGetX11Display . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga088fbfa80f50569402b41be71ad66e40 glfwGetX11Adapter>-getX11Adapter :: Window -> IO Word64-getX11Adapter = c'glfwGetX11Adapter . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gab2f8cc043905e9fa9b12bfdbbcfe874c glfwGetX11Monitor>-getX11Monitor :: Window -> IO Word64-getX11Monitor = c'glfwGetX11Monitor . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga90ca676322740842db446999a1b1f21d glfwGetX11Window>-getX11Window  :: Window -> IO Word64-getX11Window = c'glfwGetX11Window . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga62d884114b0abfcdc2930e89f20867e2 glfwGetGLXContext>-getGLXContext :: Window -> IO (Ptr ())-getGLXContext = c'glfwGetGLXContext . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga1ed27b8766e859a21381e8f8ce18d049 glfwGetGLXWindow>-getGLXWindow  :: Window -> IO Word64-getGLXWindow = c'glfwGetGLXWindow . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#gaaf8118a3c877f3a6bc8e7a649519de5e glfwGetWaylandDisplay>-getWaylandDisplay :: IO (Ptr wl_display)-getWaylandDisplay = c'glfwGetWaylandDisplay---- | See <http://www.glfw.org/docs/3.2/group__native.html#gab10427a667b6cd91eec7709f7a906bd3 glfwGetWaylandMonitor>-getWaylandMonitor :: Window -> IO (Ptr wl_output)-getWaylandMonitor = c'glfwGetWaylandMonitor . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga4738d7aca4191363519a9a641c3ab64c glfwGetWaylandWindow>-getWaylandWindow :: Window -> IO (Ptr wl_surface)-getWaylandWindow = c'glfwGetWaylandWindow . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga40dd05325d9813fa67d61328c51d2930 glfwGetMirDisplay>-getMirDisplay :: IO (Ptr mir_connection)-getMirDisplay = c'glfwGetMirDisplay---- | See <http://www.glfw.org/docs/3.2/group__native.html#gae0941c11dc8f01aeb7cbb563f5cd930b glfwGetMirMonitor>-getMirMonitor :: Window -> IO Int-getMirMonitor = (fmap fromC) . c'glfwGetMirMonitor . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga964d52bb7932216c379762eef1ea9b05 glfwGetMirWindow>-getMirWindow :: Window -> IO (Ptr mir_surface)-getMirWindow = c'glfwGetMirWindow . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga1cd8d973f47aacb5532d368147cc3138 glfwGetEGLDisplay>-getEGLDisplay :: IO (Ptr ())-getEGLDisplay = c'glfwGetEGLDisplay---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga671c5072becd085f4ab5771a9c8efcf1 glfwGetEGLContext>-getEGLContext :: Window -> IO (Ptr ())-getEGLContext = c'glfwGetEGLContext . toC---- | See <http://www.glfw.org/docs/3.2/group__native.html#ga2199b36117a6a695fec8441d8052eee6 glfwGetEGLSurface>-getEGLSurface :: Window -> IO (Ptr ())-getEGLSurface = c'glfwGetEGLSurface . toC+{-|
+
+Threading restrictions which apply to the C version of GLFW still apply when
+writing @GLFW-b@ programs. See
+<http://www.glfw.org/docs/3.2/intro.html#thread_safety GLFW thread safety documentation>
+(applies here).
+
+Current context restructions which apply to the C version of GLFW still apply.
+See <http://www.glfw.org/docs/3.2/context.html#context_current  GLFW current context documentation>
+(applies here).
+
+@GLFW-b@ wraps callbacks and schedules them to be run after 'pollEvents' and
+'waitEvents' in the normal GHC runtime where they aren't subject to the usual
+GLFW reentrancy restrictions. See
+<http://www.glfw.org/docs/3.2/intro.html#reentrancy GLFW reentrancy documentation>
+(does not apply here).
+
+-}
+module Graphics.UI.GLFW
+  ( -- * Error handling
+    Error (..)
+    --
+  , setErrorCallback, ErrorCallback
+
+    -- * Initialization and version information
+  , Version (..)
+    --
+  , init
+  , terminate
+  , getVersion
+  , getVersionString
+
+    -- * Monitor handling
+  , Monitor
+  , MonitorState (..)
+  , VideoMode    (..)
+  , GammaRamp    (gammaRampRed, gammaRampGreen, gammaRampBlue)
+  , makeGammaRamp
+    --
+  , getMonitors
+  , getPrimaryMonitor
+  , getMonitorPos
+  , getMonitorPhysicalSize
+  , getMonitorName
+  , setMonitorCallback, MonitorCallback
+  , getVideoModes
+  , getVideoMode
+  , setGamma
+  , getGammaRamp
+  , setGammaRamp
+
+    -- * Window handling
+  , Window
+  , WindowHint             (..)
+  , ContextRobustness      (..)
+  , OpenGLProfile          (..)
+  , ClientAPI              (..)
+  , ContextCreationAPI     (..)
+  , ContextReleaseBehavior (..)
+    --
+  , defaultWindowHints
+  , windowHint
+  , createWindow
+  , destroyWindow
+  , windowShouldClose
+  , setWindowShouldClose
+  , setWindowTitle
+  , getWindowPos
+  , setWindowPos
+  , getWindowSize
+  , setWindowSize
+  , setWindowSizeLimits
+  , setWindowAspectRatio
+  , getWindowFrameSize
+  , getFramebufferSize
+  , setWindowIcon
+  , iconifyWindow
+  , restoreWindow
+  , focusWindow
+  , maximizeWindow
+  , showWindow
+  , hideWindow
+  , getWindowMonitor
+  , setCursorPos
+  , setFullscreen
+  , setWindowed
+    -- related to c'glfwGetWindowAttrib --.
+  , getWindowFocused                   -- |
+  , getWindowMaximized                 -- |
+  , getWindowFloating                  -- |
+  , getWindowIconified                 -- |
+  , getWindowResizable                 -- |
+  , getWindowDecorated                 -- |
+  , getWindowVisible                   -- |
+  , getWindowClientAPI                 -- |
+  , getWindowContextCreationAPI        -- |
+  , getWindowContextVersionMajor       -- |
+  , getWindowContextVersionMinor       -- |
+  , getWindowContextVersionRevision    -- |
+  , getWindowContextRobustness         -- |
+  , getWindowContextReleaseBehavior    -- |
+  , getWindowContextNoError            -- |
+  , getWindowOpenGLForwardCompat       -- |
+  , getWindowOpenGLDebugContext        -- |
+  , getWindowOpenGLProfile  --------------'
+  , setWindowPosCallback,       WindowPosCallback
+  , setWindowSizeCallback,      WindowSizeCallback
+  , setWindowCloseCallback,     WindowCloseCallback
+  , setWindowRefreshCallback,   WindowRefreshCallback
+  , setWindowFocusCallback,     WindowFocusCallback
+  , setWindowIconifyCallback,   WindowIconifyCallback
+  , setFramebufferSizeCallback, FramebufferSizeCallback
+  , pollEvents
+  , waitEvents
+  , waitEventsTimeout
+  , postEmptyEvent
+
+    -- * Input handling
+  , Key                         (..)
+  , KeyState                    (..)
+  , Joystick                    (..)
+  , JoystickState               (..)
+  , JoystickButtonState         (..)
+  , MouseButton                 (..)
+  , MouseButtonState            (..)
+  , CursorState                 (..)
+  , CursorInputMode             (..)
+  , StickyKeysInputMode         (..)
+  , StickyMouseButtonsInputMode (..)
+  , ModifierKeys                (..)
+  , Image
+  , mkImage
+  , Cursor                      (..)
+  , StandardCursorShape         (..)
+    --
+    -- related to c'glfwSetInputMode ----.
+  , getCursorInputMode                -- |
+  , setCursorInputMode                -- |
+  , getStickyKeysInputMode            -- |
+  , setStickyKeysInputMode            -- |
+  , getStickyMouseButtonsInputMode    -- |
+  , setStickyMouseButtonsInputMode  -----'
+  , getKey
+  , getKeyName
+  , getMouseButton
+  , getCursorPos
+  , setKeyCallback,         KeyCallback
+  , setCharCallback,        CharCallback
+  , setCharModsCallback,    CharModsCallback
+  , setMouseButtonCallback, MouseButtonCallback
+  , setCursorPosCallback,   CursorPosCallback
+  , setCursorEnterCallback, CursorEnterCallback
+  , createCursor
+  , createStandardCursor
+  , setCursor
+  , destroyCursor
+  , setScrollCallback,      ScrollCallback
+  , setDropCallback,        DropCallback
+  , joystickPresent
+  , getJoystickAxes
+  , getJoystickButtons
+  , getJoystickName
+  , setJoystickCallback,    JoystickCallback
+
+    -- * Time
+  , getTime
+  , setTime
+  , getTimerValue
+  , getTimerFrequency
+
+    -- * Context
+  , makeContextCurrent
+  , getCurrentContext
+  , swapBuffers
+  , swapInterval
+  , extensionSupported
+
+    -- * Clipboard
+  , getClipboardString
+  , setClipboardString
+
+    -- * Vulkan-related functions
+  , vulkanSupported
+  , getRequiredInstanceExtensions
+  , getInstanceProcAddress
+  , getPhysicalDevicePresentationSupport
+  , createWindowSurface
+
+    -- * Native access functions
+    -- $nativeaccess
+  , getWin32Adapter
+  , getWin32Monitor
+  , getWin32Window
+  , getWGLContext
+  , getCocoaMonitor
+  , getCocoaWindow
+  , getNSGLContext
+  , getX11Display
+  , getX11Adapter
+  , getX11Monitor
+  , getX11Window
+  , getGLXContext
+  , getGLXWindow
+  , getWaylandDisplay
+  , getWaylandMonitor
+  , getWaylandWindow
+  , getMirDisplay
+  , getMirMonitor
+  , getMirWindow
+  , getEGLDisplay
+  , getEGLContext
+  , getEGLSurface
+
+  ) where
+
+--------------------------------------------------------------------------------
+
+import Prelude hiding (init)
+
+import Control.Monad         (when, liftM)
+import Data.IORef            (IORef, atomicModifyIORef, newIORef, readIORef)
+import Data.Word             (Word32, Word64)
+import Foreign.C.String      (peekCString, withCString, CString)
+import Foreign.C.Types       (CUInt, CUShort)
+import Foreign.Marshal.Alloc (alloca, allocaBytes)
+import Foreign.Marshal.Array (advancePtr, allocaArray, peekArray, withArray)
+import Foreign.Ptr           (FunPtr, freeHaskellFunPtr, nullFunPtr, nullPtr
+                             ,Ptr)
+import Foreign.StablePtr
+import Foreign.Storable      (Storable (..))
+import System.IO.Unsafe      (unsafePerformIO)
+
+import Graphics.UI.GLFW.C
+import Graphics.UI.GLFW.Types
+
+import Bindings.GLFW
+
+--------------------------------------------------------------------------------
+
+-- We store FunPtrs from mk'GLFW*fun in these stored*Fun IORefs. Initialized
+-- with unsafePerformIO, they are basically mutable global variables.
+
+storedErrorFun           :: IORef C'GLFWerrorfun
+storedMonitorFun         :: IORef C'GLFWmonitorfun
+storedJoystickFun        :: IORef C'GLFWjoystickfun
+
+storedErrorFun           = unsafePerformIO $ newIORef nullFunPtr
+storedMonitorFun         = unsafePerformIO $ newIORef nullFunPtr
+storedJoystickFun        = unsafePerformIO $ newIORef nullFunPtr
+
+-- These NOINLINE pragmas are due to use of unsafePerformIO.
+-- See http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO-Unsafe.html#v:unsafePerformIO .
+
+{-# NOINLINE storedErrorFun           #-}
+{-# NOINLINE storedMonitorFun         #-}
+{-# NOINLINE storedJoystickFun         #-}
+
+setWindowCallback
+  :: (c -> IO (FunPtr c))                    -- wf   wrapper function
+  -> (h -> c)                                -- af   adapter function
+  -> (FunPtr c -> IO (FunPtr c))             -- gf   c'glfwSet*Callback function
+  -> (WindowCallbacks -> IORef (FunPtr c))   -- ior  accessor for storage location
+  -> Window                                  -- win  window
+  -> Maybe h                                 -- mcb  Haskell callback
+  -> IO ()
+setWindowCallback wr af gf ior win mcb = do
+    pcallbacks <- castPtrToStablePtr `liftM` c'glfwGetWindowUserPointer (unWindow win)
+    callbacks <- deRefStablePtr pcallbacks
+    setCallback wr af gf (ior callbacks) mcb
+
+setCallback
+  :: (c -> IO (FunPtr c))          -- wf   wrapper function
+  -> (h -> c)                      -- af   adapter function
+  -> (FunPtr c -> IO (FunPtr c))   -- gf   c'glfwSet*Callback function
+  -> IORef (FunPtr c)              -- ior  storage location
+  -> Maybe h                       -- mcb  Haskell callback
+  -> IO ()
+setCallback wf af gf ior mcb = do
+    -- If mcb is Just, make ccb the FunPtr of the adapted callback. Otherwise a
+    -- null FunPtr.
+    ccb <- maybe (return nullFunPtr) (wf . af) mcb
+    -- Call the GLFW callback-setting function.
+    _ <- gf ccb
+    -- Store it.
+    storeCallback ior ccb
+
+storeCallback :: IORef (FunPtr a) -> FunPtr a -> IO ()
+storeCallback ior new = do
+    -- Store the new FunPtr, retrieve the previous one.
+    prev <- atomicModifyIORef ior (\cur -> (new, cur))
+    -- Free the old FunPtr if necessary.
+    when (prev /= nullFunPtr) $ freeHaskellFunPtr prev
+
+--------------------------------------------------------------------------------
+
+-- | The error code and also a human-readable error message.
+type ErrorCallback           = Error -> String                                           -> IO ()
+-- | Fires when the window position changes.
+type WindowPosCallback       = Window -> Int -> Int                                      -> IO ()
+-- | Fires when the window is resized (in Screen Coordinates, which might not map 1:1 with pixels).
+type WindowSizeCallback      = Window -> Int -> Int                                      -> IO ()
+-- | Fires when the user is attempting to close the window
+type WindowCloseCallback     = Window                                                    -> IO ()
+-- | Fires when the contents of the window are damaged and they must be refreshed.
+type WindowRefreshCallback   = Window                                                    -> IO ()
+-- | Fires when the window gains or loses input focus.
+type WindowFocusCallback     = Window -> Bool                                            -> IO ()
+-- | Fires when the window is iconified (minimized) or not.
+type WindowIconifyCallback   = Window -> Bool                                            -> IO ()
+-- | Fires when the size of the framebuffer for the window changes (in Pixels).
+type FramebufferSizeCallback = Window -> Int -> Int                                      -> IO ()
+-- | Fires whenever a mouse button is clicked.
+type MouseButtonCallback     = Window -> MouseButton -> MouseButtonState -> ModifierKeys -> IO ()
+-- | Fires every time the cursor position changes. Sub-pixel accuracy is used, when available.
+type CursorPosCallback       = Window -> Double -> Double                                -> IO ()
+-- | Fires when the cursor enters or exits the client area of the window.
+type CursorEnterCallback     = Window -> CursorState                                     -> IO ()
+-- | Fires when the user scrolls the mouse wheel or via touch gesture.
+type ScrollCallback          = Window -> Double -> Double                                -> IO ()
+-- | Fires for each press or repeat of keyboard keys (regardless of if it has textual meaning or not, eg Shift)
+type KeyCallback             = Window -> Key -> Int -> KeyState -> ModifierKeys          -> IO ()
+-- | Fires when a complete character codepoint is typed by the user, Shift then 'b' generates "B".
+type CharCallback            = Window -> Char                                            -> IO ()
+-- | Similar to 'CharCallback', fires when a complete unicode codepoint is typed by the user.
+type CharModsCallback        = Window -> Char -> ModifierKeys                            -> IO ()
+-- | Fires when a monitor is connected or disconnected.
+type MonitorCallback         = Monitor -> MonitorState                                   -> IO ()
+-- | Fires when a joystick is connected or disconnected.
+type JoystickCallback        = Joystick -> JoystickState                                 -> IO ()
+
+-- 3.1 additions
+
+--------------------------------------------------------------------------------
+-- CB scheduling
+
+data ScheduledCallbacks = ScheduledCallbacks
+  { _forward :: [IO ()] -- Execution iterates this list
+  , _backward :: [IO ()] -- New schedules prepend here
+  }
+
+storedScheduledCallbacks :: IORef ScheduledCallbacks
+storedScheduledCallbacks = unsafePerformIO . newIORef $ ScheduledCallbacks [] []
+
+-- This NOINLINE pragma is due to use of unsafePerformIO.
+-- See http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-IO-Unsafe.html#v:unsafePerformIO .
+
+{-# NOINLINE storedScheduledCallbacks #-}
+
+-- This is provided in newer "base" versions. To avoid depending on
+-- it, it's reimplemented here. Should remove if/when compatibility
+-- with older base is not an issue:
+atomicModifyIORef' :: IORef a -> (a -> (a,b)) -> IO b
+atomicModifyIORef' ref f = do
+    b <- atomicModifyIORef ref
+            (\x -> let (a, b) = f x
+                    in (a, a `seq` b))
+    b `seq` return b
+
+schedule :: IO () -> IO ()
+schedule act =
+  atomicModifyIORef' storedScheduledCallbacks $
+  \(ScheduledCallbacks oldForward oldBackward) ->
+  (ScheduledCallbacks oldForward (act : oldBackward), ())
+
+splitFirst :: [a] -> (Maybe a, [a])
+splitFirst [] = (Nothing, [])
+splitFirst (x:xs) = (Just x, xs)
+
+getNextScheduled :: IO (Maybe (IO ()))
+getNextScheduled =
+  atomicModifyIORef storedScheduledCallbacks $
+  \(ScheduledCallbacks oldForward oldBackward) ->
+  case oldForward of
+    [] ->
+      let (mCb, newForward) = splitFirst (reverse oldBackward)
+      in (ScheduledCallbacks newForward [], mCb)
+    (cb:rest) ->                -- Eat forward first
+      (ScheduledCallbacks rest oldBackward, Just cb)
+
+executeScheduled :: IO ()
+executeScheduled = do
+  mcb <- getNextScheduled
+  case mcb of
+    Nothing -> return ()
+    Just cb -> cb >> executeScheduled
+
+--------------------------------------------------------------------------------
+-- Error handling
+
+-- | Can (and probably should) be used before GLFW initialization.
+-- See <http://www.glfw.org/docs/3.2/group__init.html#gaa5d796c3cf7c1a7f02f845486333fb5f glfwSetErrorCallback>
+setErrorCallback :: Maybe ErrorCallback -> IO ()
+setErrorCallback = setCallback
+    mk'GLFWerrorfun
+    (\cb a0 a1 -> do
+        s <- peekCString a1
+        schedule $ cb (fromC a0) s)
+    c'glfwSetErrorCallback
+    storedErrorFun
+
+--------------------------------------------------------------------------------
+-- Image utility functions
+
+withGLFWImage :: Image -> (Ptr C'GLFWimage -> IO a) -> IO a
+withGLFWImage (Image w h pxs) f =
+  alloca        $ \p'img ->
+  withArray pxs $ \p'pxs -> do
+    poke p'img $ C'GLFWimage (toC w) (toC h) p'pxs
+    f p'img
+
+--------------------------------------------------------------------------------
+-- Initialization and version information
+
+-- | Attempts to initialize the GLFW library. When the library is not initialized, the only
+-- allowed functions to call are 'getVersion', 'getVersionString', 'setErrorCallback',
+-- 'init', and 'terminate'. Returns if the initialization was successful or not.
+-- See <http://www.glfw.org/docs/3.2/group__init.html#ga317aac130a235ab08c6db0834907d85e glfwInit>
+-- and <http://www.glfw.org/docs/3.2/intro.html#intro_init Initialization and Termination>
+init :: IO Bool
+init =
+    fromC `fmap` c'glfwInit
+
+-- | Cleans up GLFW and puts the library into an uninitialized state.
+-- Once you call this, you must initilize the library again.
+-- Warning: No window's context may be current in another thread when this is called.
+-- See <http://www.glfw.org/docs/3.2/group__init.html#gaaae48c0a18607ea4a4ba951d939f0901 glfwTerminate>
+-- and <http://www.glfw.org/docs/3.2/intro.html#intro_init Initialization and Termination>. This
+-- function is not <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+terminate :: IO ()
+terminate = do
+    c'glfwTerminate
+    -- Free all stored FunPtrs.
+    storeCallback storedErrorFun           nullFunPtr
+    storeCallback storedMonitorFun         nullFunPtr
+    storeCallback storedJoystickFun         nullFunPtr
+
+-- | Gets the version of the GLFW library that's being used with the current program.
+-- See <http://www.glfw.org/docs/3.2/group__init.html#ga9f8ffaacf3c269cc48eafbf8b9b71197 glfwGetVersion>
+getVersion :: IO Version
+getVersion =
+    allocaArray 3 $ \p -> do
+        let p0 = p
+            p1 = p `advancePtr` 1
+            p2 = p `advancePtr` 2
+        c'glfwGetVersion p0 p1 p2
+        v0 <- fromC `fmap` peek p0
+        v1 <- fromC `fmap` peek p1
+        v2 <- fromC `fmap` peek p2
+        return $ Version v0 v1 v2
+
+-- | Gets the compile-time version string of the GLFW library binary.
+-- Gives extra info like platform and compile time options used, but you should not
+-- attempt to parse this to get the GLFW version number. Use 'getVersion' instead.
+-- See <http://www.glfw.org/docs/3.2/group__init.html#ga23d47dc013fce2bf58036da66079a657 glfwGetVersionString>
+getVersionString :: IO (Maybe String)
+getVersionString = do
+    p'vs <- c'glfwGetVersionString
+    if p'vs /= nullPtr
+      then Just `fmap` peekCString p'vs
+      else return Nothing
+
+--------------------------------------------------------------------------------
+-- Monitor handling
+
+-- | Gets the list of available monitors, if possible.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga3fba51c8bd36491d4712aa5bd074a537 glfwGetMonitors>
+getMonitors :: IO (Maybe [Monitor])
+getMonitors =
+    alloca $ \p'n -> do
+        p'mon <- c'glfwGetMonitors p'n
+        n <- fromC `fmap` peek p'n
+        if p'mon == nullPtr || n <= 0
+          then return Nothing
+          else (Just . map fromC) `fmap` peekArray n p'mon
+
+-- | Gets the primary monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga721867d84c6d18d6790d64d2847ca0b1 glfwGetPrimaryMonitor>
+getPrimaryMonitor :: IO (Maybe Monitor)
+getPrimaryMonitor = do
+    p'mon <- c'glfwGetPrimaryMonitor
+    return $
+      if p'mon == nullPtr
+        then Nothing
+        else Just $ fromC p'mon
+
+-- | Gets the position of the specified monitor within the coordinate space.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga102f54e7acc9149edbcf0997152df8c9 glfwGetMonitorPos>
+getMonitorPos :: Monitor -> IO (Int, Int)
+getMonitorPos mon =
+    allocaArray 2 $ \p -> do
+        let p'x = p
+            p'y = p `advancePtr` 1
+        c'glfwGetMonitorPos (toC mon) p'x p'y
+        x <- fromC `fmap` peek p'x
+        y <- fromC `fmap` peek p'y
+        return (x, y)
+
+-- | The physical width and height of the monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga7d8bffc6c55539286a6bd20d32a8d7ea glfwGetMonitorPhysicalSize>
+getMonitorPhysicalSize :: Monitor -> IO (Int, Int)
+getMonitorPhysicalSize mon =
+    allocaArray 2 $ \p -> do
+        let p'w = p
+            p'h = p `advancePtr` 1
+        c'glfwGetMonitorPhysicalSize (toC mon) p'w p'h
+        w <- fromC `fmap` peek p'w
+        h <- fromC `fmap` peek p'h
+        return (w, h)
+
+-- | A human-readable name for the monitor specified.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga79a34ee22ff080ca954a9663e4679daf getMonitorName>
+getMonitorName :: Monitor -> IO (Maybe String)
+getMonitorName mon = do
+    p'name <- c'glfwGetMonitorName (toC mon)
+    if p'name == nullPtr
+      then return Nothing
+      else Just `fmap` peekCString p'name
+
+-- | Sets a callback for when a monitor is connected or disconnected.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#gac3fe0f647f68b731f99756cd81897378 glfwSetMonitorCallback>
+setMonitorCallback :: Maybe MonitorCallback -> IO ()
+setMonitorCallback = setCallback
+    mk'GLFWmonitorfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    c'glfwSetMonitorCallback
+    storedMonitorFun
+
+-- | Obtains the possible video modes of the monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga820b0ce9a5237d645ea7cbb4bd383458 glfwGetVideoModes>
+getVideoModes :: Monitor -> IO (Maybe [VideoMode])
+getVideoModes mon =
+    alloca $ \p'n -> do
+        p'vms <- c'glfwGetVideoModes (toC mon) p'n
+        n <- fromC `fmap` peek p'n
+        if p'vms == nullPtr || n <= 0
+          then return Nothing
+          else (Just . map fromC) `fmap` peekArray n p'vms
+
+-- | Gets the active video mode of the monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#gafc1bb972a921ad5b3bd5d63a95fc2d52 glfwGetVideoMode>
+getVideoMode :: Monitor -> IO (Maybe VideoMode)
+getVideoMode mon = do
+    p'vm <- c'glfwGetVideoMode (toC mon)
+    if p'vm == nullPtr
+      then return Nothing
+      else (Just . fromC) `fmap` peek p'vm
+
+-- | Sets the gamma of a monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga6ac582625c990220785ddd34efa3169a glfwSetGamma>
+setGamma :: Monitor -> Double -> IO ()
+setGamma mon e =
+    c'glfwSetGamma (toC mon) (toC e)
+
+-- | Gets the gamma ramp in use with the monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#gab7c41deb2219bde3e1eb756ddaa9ec80 glfwGetGammaRamp>
+getGammaRamp :: Monitor -> IO (Maybe GammaRamp)
+getGammaRamp m = do
+    p'ggr <- c'glfwGetGammaRamp (toC m)
+    if p'ggr == nullPtr
+      then return Nothing
+      else do
+          ggr <- peek p'ggr
+          let p'rs = c'GLFWgammaramp'red   ggr
+              p'gs = c'GLFWgammaramp'green ggr
+              p'bs = c'GLFWgammaramp'blue  ggr
+              cn   = c'GLFWgammaramp'size  ggr
+              n    = fromC cn
+          if n == 0 || nullPtr `elem` [p'rs, p'gs, p'bs]
+            then return Nothing
+            else do
+                rs <- map fromC `fmap` peekArray n p'rs
+                gs <- map fromC `fmap` peekArray n p'gs
+                bs <- map fromC `fmap` peekArray n p'bs
+                return $ Just GammaRamp
+                  { gammaRampRed   = rs
+                  , gammaRampGreen = gs
+                  , gammaRampBlue  = bs
+                  }
+
+-- | Assigns a gamma ramp to use with the given monitor.
+-- See <http://www.glfw.org/docs/3.2/group__monitor.html#ga583f0ffd0d29613d8cd172b996bbf0dd glfwSetGammaRamp>
+setGammaRamp :: Monitor -> GammaRamp -> IO ()
+setGammaRamp mon gr =
+    let rs = map toC $ gammaRampRed   gr :: [CUShort]
+        gs = map toC $ gammaRampGreen gr :: [CUShort]
+        bs = map toC $ gammaRampBlue  gr :: [CUShort]
+        -- GammaRamp's smart constructor ensures that the RGB lists all have
+        -- equal length, so just use the number of reds.
+        cn = toC $ length rs :: CUInt
+    in alloca       $ \p'ggr ->
+       withArray rs $ \p'rs  ->
+       withArray gs $ \p'gs  ->
+       withArray bs $ \p'bs  -> do
+          let ggr = C'GLFWgammaramp
+                      { c'GLFWgammaramp'red   = p'rs
+                      , c'GLFWgammaramp'green = p'gs
+                      , c'GLFWgammaramp'blue  = p'bs
+                      , c'GLFWgammaramp'size  = cn
+                      }
+          poke p'ggr ggr
+          c'glfwSetGammaRamp (toC mon) p'ggr
+
+--------------------------------------------------------------------------------
+-- Window handling
+
+-- | Sets all the window hints to default.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gaa77c4898dfb83344a6b4f76aa16b9a4a glfwDefaultWindowHints>
+defaultWindowHints :: IO ()
+defaultWindowHints =
+    c'glfwDefaultWindowHints
+
+-- | Hints something to the GLFW windowing system.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga7d9c8c62384b1e2821c4dc48952d2033 glfwWindowHint>
+windowHint :: WindowHint -> IO ()
+windowHint wh =
+    let (t, v) = unpack
+    in c'glfwWindowHint t v
+  where
+    unpack = case wh of
+      (WindowHint'Resizable              x) -> (c'GLFW_RESIZABLE,                toC x)
+      (WindowHint'Visible                x) -> (c'GLFW_VISIBLE,                  toC x)
+      (WindowHint'Decorated              x) -> (c'GLFW_DECORATED,                toC x)
+      (WindowHint'RedBits                x) -> (c'GLFW_RED_BITS,                 toC x)
+      (WindowHint'GreenBits              x) -> (c'GLFW_GREEN_BITS,               toC x)
+      (WindowHint'BlueBits               x) -> (c'GLFW_BLUE_BITS,                toC x)
+      (WindowHint'AlphaBits              x) -> (c'GLFW_ALPHA_BITS,               toC x)
+      (WindowHint'DepthBits              x) -> (c'GLFW_DEPTH_BITS,               toC x)
+      (WindowHint'StencilBits            x) -> (c'GLFW_STENCIL_BITS,             toC x)
+      (WindowHint'AccumRedBits           x) -> (c'GLFW_ACCUM_RED_BITS,           toC x)
+      (WindowHint'AccumGreenBits         x) -> (c'GLFW_ACCUM_GREEN_BITS,         toC x)
+      (WindowHint'AccumBlueBits          x) -> (c'GLFW_ACCUM_BLUE_BITS,          toC x)
+      (WindowHint'AccumAlphaBits         x) -> (c'GLFW_ACCUM_ALPHA_BITS,         toC x)
+      (WindowHint'AuxBuffers             x) -> (c'GLFW_AUX_BUFFERS,              toC x)
+      (WindowHint'Samples                x) -> (c'GLFW_SAMPLES,                  toC x)
+      (WindowHint'RefreshRate            x) -> (c'GLFW_REFRESH_RATE,             toC x)
+      (WindowHint'DoubleBuffer           x) -> (c'GLFW_DOUBLEBUFFER,             toC x)
+      (WindowHint'Stereo                 x) -> (c'GLFW_STEREO,                   toC x)
+      (WindowHint'sRGBCapable            x) -> (c'GLFW_SRGB_CAPABLE,             toC x)
+      (WindowHint'Floating               x) -> (c'GLFW_FLOATING,                 toC x)
+      (WindowHint'Focused                x) -> (c'GLFW_FOCUSED,                  toC x)
+      (WindowHint'Maximized              x) -> (c'GLFW_MAXIMIZED,                toC x)
+      (WindowHint'AutoIconify            x) -> (c'GLFW_AUTO_ICONIFY,             toC x)
+      (WindowHint'ClientAPI              x) -> (c'GLFW_CLIENT_API,               toC x)
+      (WindowHint'ContextCreationAPI     x) -> (c'GLFW_CONTEXT_CREATION_API,     toC x)
+      (WindowHint'ContextVersionMajor    x) -> (c'GLFW_CONTEXT_VERSION_MAJOR,    toC x)
+      (WindowHint'ContextVersionMinor    x) -> (c'GLFW_CONTEXT_VERSION_MINOR,    toC x)
+      (WindowHint'ContextRobustness      x) -> (c'GLFW_CONTEXT_ROBUSTNESS,       toC x)
+      (WindowHint'ContextReleaseBehavior x) -> (c'GLFW_CONTEXT_RELEASE_BEHAVIOR, toC x)
+      (WindowHint'ContextNoError         x) -> (c'GLFW_CONTEXT_NO_ERROR,         toC x)
+      (WindowHint'OpenGLForwardCompat    x) -> (c'GLFW_OPENGL_FORWARD_COMPAT,    toC x)
+      (WindowHint'OpenGLDebugContext     x) -> (c'GLFW_OPENGL_DEBUG_CONTEXT,     toC x)
+      (WindowHint'OpenGLProfile          x) -> (c'GLFW_OPENGL_PROFILE,           toC x)
+
+-- | Creates a new window.
+-- Note: If running in GHCI don't forget to `:set -fno-ghci-sandbox` or you
+-- may run into an assertion failure, segfault or other nasty crash.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga5c336fddf2cbb5b92f65f10fb6043344 glfwCreateWindow>
+createWindow :: Int -- ^ Desired width for the window.
+             -> Int -- ^ Desired height for the window.
+             -> String -- ^ Desired title for the window.
+             -> Maybe Monitor -- ^ Monitor to use in fullscreen mode.
+             -> Maybe Window  -- ^ Window for context object sharing, see
+                              -- <http://www.glfw.org/docs/3.2/context.html#context_sharing here>.
+             -> IO (Maybe Window)
+createWindow w h title mmon mwin =
+    withCString title $ \ptitle -> do
+        charFun             <- newIORef nullFunPtr
+        charModsFun         <- newIORef nullFunPtr
+        cursorEnterFun      <- newIORef nullFunPtr
+        cursorPosFun        <- newIORef nullFunPtr
+        framebufferSizeFun  <- newIORef nullFunPtr
+        keyFun              <- newIORef nullFunPtr
+        mouseButtonFun      <- newIORef nullFunPtr
+        scrollFun           <- newIORef nullFunPtr
+        windowCloseFun      <- newIORef nullFunPtr
+        windowFocusFun      <- newIORef nullFunPtr
+        windowIconifyFun    <- newIORef nullFunPtr
+        windowPosFun        <- newIORef nullFunPtr
+        windowRefreshFun    <- newIORef nullFunPtr
+        windowSizeFun       <- newIORef nullFunPtr
+        dropFun             <- newIORef nullFunPtr
+        let callbacks = WindowCallbacks
+              { storedCharFun             = charFun
+              , storedCharModsFun         = charModsFun
+              , storedCursorEnterFun      = cursorEnterFun
+              , storedCursorPosFun        = cursorPosFun
+              , storedFramebufferSizeFun  = framebufferSizeFun
+              , storedKeyFun              = keyFun
+              , storedMouseButtonFun      = mouseButtonFun
+              , storedScrollFun           = scrollFun
+              , storedWindowCloseFun      = windowCloseFun
+              , storedWindowFocusFun      = windowFocusFun
+              , storedWindowIconifyFun    = windowIconifyFun
+              , storedWindowPosFun        = windowPosFun
+              , storedWindowRefreshFun    = windowRefreshFun
+              , storedWindowSizeFun       = windowSizeFun
+              , storedDropFun             = dropFun
+              }
+        p'win <- c'glfwCreateWindow
+          (toC w)
+          (toC h)
+          ptitle
+          (maybe nullPtr toC mmon)
+          (maybe nullPtr toC mwin)
+        if p'win == nullPtr
+          then return Nothing
+          else do callbackPtr <- newStablePtr callbacks
+                  c'glfwSetWindowUserPointer p'win (castStablePtrToPtr callbackPtr)
+                  return $ Just $ fromC p'win
+
+-- | Cleans up a window and all associated resources
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacdf43e51376051d2c091662e9fe3d7b2 glfwDestroyWindow>.
+-- This function is not <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+destroyWindow :: Window -> IO ()
+destroyWindow win = do
+    pcb <- castPtrToStablePtr `liftM` c'glfwGetWindowUserPointer (toC win)
+    cbs <- deRefStablePtr pcb
+    c'glfwDestroyWindow (toC win)
+
+    let free callback = do funptr <- readIORef (callback cbs)
+                           when (funptr /= nullFunPtr) $ freeHaskellFunPtr funptr
+    free storedCharFun
+    free storedCharModsFun
+    free storedCursorEnterFun
+    free storedCursorPosFun
+    free storedFramebufferSizeFun
+    free storedKeyFun
+    free storedMouseButtonFun
+    free storedScrollFun
+    free storedWindowCloseFun
+    free storedWindowFocusFun
+    free storedWindowIconifyFun
+    free storedWindowPosFun
+    free storedWindowRefreshFun
+    free storedWindowSizeFun
+    freeStablePtr pcb
+
+-- | If the window should close or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga24e02fbfefbb81fc45320989f8140ab5 glfwWindowShouldClose>
+windowShouldClose :: Window -> IO Bool
+windowShouldClose win =
+    fromC `fmap` c'glfwWindowShouldClose (toC win)
+
+-- | Sets if the window should close or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga49c449dde2a6f87d996f4daaa09d6708 glfwSetWindowShouldClose>
+setWindowShouldClose :: Window -> Bool -> IO ()
+setWindowShouldClose win b =
+    c'glfwSetWindowShouldClose (toC win) (toC b)
+
+-- | Sets the Title string of the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga5d877f09e968cef7a360b513306f17ff glfwSetWindowTitle>
+setWindowTitle :: Window -> String -> IO ()
+setWindowTitle win title =
+    withCString title $ c'glfwSetWindowTitle (toC win)
+
+-- | Gets the window's position (in Screen Coordinates).
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga73cb526c000876fd8ddf571570fdb634 glfwGetWindowPos>
+getWindowPos :: Window -> IO (Int, Int)
+getWindowPos win =
+    allocaArray 2 $ \p -> do
+        let p'x = p
+            p'y = p `advancePtr` 1
+        c'glfwGetWindowPos (toC win) p'x p'y
+        x <- fromC `fmap` peek p'x
+        y <- fromC `fmap` peek p'y
+        return (x, y)
+
+-- | Sets the window's position (in Screen Coordinates).
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga1abb6d690e8c88e0c8cd1751356dbca8 glfwSetWindowPos>
+setWindowPos :: Window -> Int -> Int -> IO ()
+setWindowPos win x y =
+    c'glfwSetWindowPos (toC win) (toC x) (toC y)
+
+-- | Gets the size of the window (in Screen Coordinates).
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gaeea7cbc03373a41fb51cfbf9f2a5d4c6 glfwGetWindowSize>
+getWindowSize :: Window -> IO (Int, Int)
+getWindowSize win =
+    allocaArray 2 $ \p -> do
+        let p'w = p
+            p'h = p `advancePtr` 1
+        c'glfwGetWindowSize (toC win) p'w p'h
+        w <- fromC `fmap` peek p'w
+        h <- fromC `fmap` peek p'h
+        return (w, h)
+
+-- | Gets the size of the frame around the window (in Screen Coordinates). This
+-- size includes the title bar, if the window has one. Not to be confused with
+-- 'getFramebufferSize', which gets the size of the rendering area.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga1a9fd382058c53101b21cf211898f1f1 glfwGetWindowFrameSize>
+getWindowFrameSize :: Window -> IO (Int, Int, Int, Int)
+getWindowFrameSize win =
+    allocaArray 4 $ \p -> do
+        let p'l = p
+            p't = p `advancePtr` 1
+            p'r = p `advancePtr` 2
+            p'b = p `advancePtr` 3
+        c'glfwGetWindowFrameSize (toC win) p'l p't p'r p'b
+        l <- fromC `fmap` peek p'l
+        t <- fromC `fmap` peek p't
+        r <- fromC `fmap` peek p'r
+        b <- fromC `fmap` peek p'b
+        return (l, t, r, b)
+
+-- | Sets the size of the client area for the window (in Screen Coordinates).
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga371911f12c74c504dd8d47d832d095cb glfwSetWindowSize>
+setWindowSize :: Window -> Int -> Int -> IO ()
+setWindowSize win w h =
+    c'glfwSetWindowSize (toC win) (toC w) (toC h)
+
+-- | Sets the size limits of the client area of the specified window. If the
+-- window is full screen, the size limits only take effect once it is made
+-- windowed. If the window is not resizable this function does nothing. Pass
+-- 'Nothing' in any argument to disable the limit.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gac314fa6cec7d2d307be9963e2709cc90 glfwSetWindowSizeLimits>
+setWindowSizeLimits :: Window
+                    -> Maybe Int
+                    -- ^ The minimum width, in screen coordinates, of the client
+                    --   area.
+                    -> Maybe Int
+                    -- ^ The minimum height, in screen coordinates, of the
+                    --   client area.
+                    -> Maybe Int
+                    -- ^ The maximum width, in screen coordinates, of the client
+                    --   area.
+                    -> Maybe Int
+                    -- ^ The maximum height, in screen coordinates, of the
+                    --   client area.
+                    -> IO ()
+setWindowSizeLimits win min'w min'h max'w max'h =
+  c'glfwSetWindowSizeLimits (toC win) (toC min'w) (toC min'h)
+                                      (toC max'w) (toC max'h)
+
+-- | Sets the required aspect ratio of the client area of the specified window.
+-- Pass Nothing to disable the limit.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga72ac8cb1ee2e312a878b55153d81b937 glfwSetWindowAspectRatio>
+setWindowAspectRatio :: Window -> Maybe (Int, Int) -> IO ()
+setWindowAspectRatio win Nothing =
+  c'glfwSetWindowAspectRatio (toC win) c'GLFW_DONT_CARE c'GLFW_DONT_CARE
+setWindowAspectRatio win (Just (w, h)) =
+  c'glfwSetWindowAspectRatio (toC win) (toC w) (toC h)
+
+-- | The size of the framebuffer (in Pixels)
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga0e2637a4161afb283f5300c7f94785c9 glfwGetFramebufferSize>
+getFramebufferSize :: Window -> IO (Int, Int)
+getFramebufferSize win =
+    allocaArray 2 $ \p -> do
+        let p'w = p
+            p'h = p `advancePtr` 1
+        c'glfwGetFramebufferSize (toC win) p'w p'h
+        w <- fromC `fmap` peek p'w
+        h <- fromC `fmap` peek p'h
+        return (w, h)
+
+-- | Sets the icon of the specified window. The system will try to find the
+-- image with the dimensions closest to the ones required by the platform. This
+-- image is then scaled and used as the icon for that size. Good sizes are
+-- 16x16, 32x32, and 48x48. Pass the empty list to reset to the default icon.
+-- Has no effect on OS X (See the <https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/Introduction/Introduction.html Bundle Programming Guide>)
+setWindowIcon :: Window -> [Image] -> IO ()
+setWindowIcon win [] = c'glfwSetWindowIcon (toC win) 0 nullPtr
+setWindowIcon win imgs =
+  let arrSizeBytes = length imgs * sizeOf (undefined :: C'GLFWimage)
+
+      addNextImage :: [Image] -> Int -> Ptr C'GLFWimage -> IO ()
+      addNextImage [] numImages ptr =
+        c'glfwSetWindowIcon (toC win) (toC numImages) ptr
+
+      addNextImage (img:rest) idx ptr =
+        withGLFWImage img $ \p'img -> do
+          c'img <- peek p'img
+          pokeElemOff ptr idx c'img
+          addNextImage rest (idx + 1) ptr
+  in allocaBytes arrSizeBytes $ addNextImage imgs 0
+
+-- | Iconifies (minimizes) the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga1bb559c0ebaad63c5c05ad2a066779c4 glfwIconifyWindow>
+iconifyWindow :: Window -> IO ()
+iconifyWindow =
+    c'glfwIconifyWindow . toC
+
+-- | Restores the window from an iconified/minimized state.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga52527a5904b47d802b6b4bb519cdebc7 glfwRestoreWindow>
+restoreWindow :: Window -> IO ()
+restoreWindow =
+    c'glfwRestoreWindow . toC
+
+-- | Brings the specified window to front and sets input focus. The window
+-- should already be visible and not iconified.
+-- See <http://www.glfw.org/docs/latest/group__window.html#ga873780357abd3f3a081d71a40aae45a1 glfwFocusWindow>
+focusWindow :: Window -> IO ()
+focusWindow = c'glfwFocusWindow . toC
+
+-- | Maximizes the specified window if it was not already maximized.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga3f541387449d911274324ae7f17ec56b glfwMaximizeWindow>
+maximizeWindow :: Window -> IO ()
+maximizeWindow = c'glfwMaximizeWindow . toC
+
+-- | Shows the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga61be47917b72536a148300f46494fc66 glfwShowWindow>
+showWindow :: Window -> IO ()
+showWindow =
+    c'glfwShowWindow . toC
+
+-- | Hides the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga49401f82a1ba5f15db5590728314d47c glfwHideWindow>
+hideWindow :: Window -> IO ()
+hideWindow =
+    c'glfwHideWindow . toC
+
+-- | Gets the monitor that this window is running on, provided the window is
+-- fullscreen.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gaeac25e64789974ccbe0811766bd91a16 glfwGetWindowMonitor>
+getWindowMonitor :: Window -> IO (Maybe Monitor)
+getWindowMonitor win = do
+    p'mon <- c'glfwGetWindowMonitor (toC win)
+    return $ if p'mon == nullPtr
+      then Nothing
+      else Just $ fromC p'mon
+
+-- | Sets the position of the cursor within the window.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga04b03af936d906ca123c8f4ee08b39e7 glfwSetCursorPos>
+setCursorPos :: Window -> Double -> Double -> IO ()
+setCursorPos win x y =
+    c'glfwSetCursorPos (toC win) (toC x) (toC y)
+
+-- | Makes a window fullscreen on the given monitor. The number of red, green,
+-- and blue bits is ignored. Note, this shouldn't be used to update the
+-- resolution of a fullscreen window. Use 'setWindowSize' instead.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga81c76c418af80a1cce7055bccb0ae0a7 glfwSetWindowMonitor>
+setFullscreen :: Window -> Monitor -> VideoMode -> IO ()
+setFullscreen win mon (VideoMode width height _ _ _ refresh) =
+  c'glfwSetWindowMonitor (toC win) (toC mon) 0 0 (toC width) (toC height) (toC refresh)
+
+-- | Updates a window to be windowed instead of fullscreen. Note, this shouldn't
+-- be used to update the position or size of a window. Use 'setWindowPos' and
+-- 'setWindowSize' instead.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga81c76c418af80a1cce7055bccb0ae0a7 glfwSetWindowMonitor>
+setWindowed :: Window
+            -> Int  -- ^ The width of the client area
+            -> Int  -- ^ The height of the client area
+            -> Int  -- ^ The x position of the window
+            -> Int  -- ^ The y position of the window
+            -> IO ()
+setWindowed win width height x y =
+  c'glfwSetWindowMonitor (toC win) nullPtr (toC x) (toC y) (toC width) (toC height) 0
+
+-- start of functions related to c'glfwGetWindowAttrib
+
+-- | If the window has focus or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowFocused :: Window -> IO Bool
+getWindowFocused win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_FOCUSED
+
+-- | If the window is maximized or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowMaximized :: Window -> IO Bool
+getWindowMaximized win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_MAXIMIZED
+
+-- | If the window has been set to be 'always on top' or not.
+-- See <http://www.glfw.org/docs/latest/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowFloating :: Window -> IO Bool
+getWindowFloating win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_FLOATING
+
+-- | If the window is iconified (minimized) or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowIconified :: Window -> IO Bool
+getWindowIconified win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_ICONIFIED
+
+-- | If the window is resizable or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowResizable :: Window -> IO Bool
+getWindowResizable win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_RESIZABLE
+
+-- | If the window is decorated or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowDecorated :: Window -> IO Bool
+getWindowDecorated win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_DECORATED
+
+-- | If the window is visible or not.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowVisible :: Window -> IO Bool
+getWindowVisible win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_VISIBLE
+
+-- | The client api for this window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowClientAPI :: Window -> IO ClientAPI
+getWindowClientAPI win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CLIENT_API
+
+-- | Returns the context creation API used to create the specified window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextCreationAPI :: Window -> IO ContextCreationAPI
+getWindowContextCreationAPI win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_CREATION_API
+
+-- | The context's "major" version, x.0.0
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextVersionMajor :: Window -> IO Int
+getWindowContextVersionMajor win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_VERSION_MAJOR
+
+-- | The context's "minor" version, 0.y.0
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextVersionMinor :: Window -> IO Int
+getWindowContextVersionMinor win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_VERSION_MINOR
+
+-- | The context's "revision" version, 0.0.z
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextVersionRevision :: Window -> IO Int
+getWindowContextVersionRevision win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_REVISION
+
+-- | The context robustness of this window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextRobustness :: Window -> IO ContextRobustness
+getWindowContextRobustness win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_ROBUSTNESS
+
+-- | Returns the context release behavior.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowContextReleaseBehavior :: Window -> IO ContextReleaseBehavior
+getWindowContextReleaseBehavior win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_RELEASE_BEHAVIOR
+
+-- | Returns true if the window is set to NO_ERROR (see the
+-- <https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_no_error.txt KHR_no_error>
+-- extension.
+getWindowContextNoError :: Window -> IO Bool
+getWindowContextNoError win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_CONTEXT_NO_ERROR
+
+-- | If this window is set for opengl to be forward compatible.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowOpenGLForwardCompat :: Window -> IO Bool
+getWindowOpenGLForwardCompat win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_FORWARD_COMPAT
+
+-- | If the window has an opengl debug context
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowOpenGLDebugContext :: Window -> IO Bool
+getWindowOpenGLDebugContext win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_DEBUG_CONTEXT
+
+-- | Obtains the current opengl profile.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gacccb29947ea4b16860ebef42c2cb9337 glfwGetWindowAttrib>
+getWindowOpenGLProfile :: Window -> IO OpenGLProfile
+getWindowOpenGLProfile win =
+    fromC `fmap` c'glfwGetWindowAttrib (toC win) c'GLFW_OPENGL_PROFILE
+
+-- end of functions related to c'glfwGetWindowAttrib
+
+-- | Sets the callback to use when the window position changes.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga2837d4d240659feb4268fcb6530a6ba1 glfwSetWindowPosCallback>
+setWindowPosCallback :: Window -> Maybe WindowPosCallback -> IO ()
+setWindowPosCallback win = setWindowCallback
+    mk'GLFWwindowposfun
+    (\cb a0 a1 a2 ->
+      schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetWindowPosCallback (toC win))
+    storedWindowPosFun
+    win
+
+-- | Sets the callback to use when the window's size changes.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gaa40cd24840daa8c62f36cafc847c72b6 glfwSetWindowSizeCallback>
+setWindowSizeCallback :: Window -> Maybe WindowSizeCallback -> IO ()
+setWindowSizeCallback win = setWindowCallback
+    mk'GLFWwindowsizefun
+    (\cb a0 a1 a2 ->
+      schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetWindowSizeCallback (toC win))
+    storedWindowSizeFun
+    win
+
+-- | Sets the callback to use when the user attempts to close the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gaade9264e79fae52bdb78e2df11ee8d6a glfwSetWindowCloseCallback>
+setWindowCloseCallback :: Window -> Maybe WindowCloseCallback -> IO ()
+setWindowCloseCallback win = setWindowCallback
+    mk'GLFWwindowclosefun
+    (. fromC)
+    (c'glfwSetWindowCloseCallback (toC win))
+    storedWindowCloseFun
+    win
+
+-- | Sets the callback to use when the window's data is partly dead and it should refresh.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga4569b76e8ac87c55b53199e6becd97eb glfwSetWindowRefreshCallback>
+setWindowRefreshCallback :: Window -> Maybe WindowRefreshCallback -> IO ()
+setWindowRefreshCallback win = setWindowCallback
+    mk'GLFWwindowrefreshfun
+    (. fromC)
+    (c'glfwSetWindowRefreshCallback (toC win))
+    storedWindowRefreshFun
+    win
+
+-- | Sets the callback to use when the window gains or loses focus.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga25d1c584edb375d7711c5c3548ba711f glfwSetWindowFocusCallback>
+setWindowFocusCallback :: Window -> Maybe WindowFocusCallback -> IO ()
+setWindowFocusCallback win = setWindowCallback
+    mk'GLFWwindowfocusfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    (c'glfwSetWindowFocusCallback (toC win))
+    storedWindowFocusFun
+    win
+
+-- | Sets the callback to use when the window is iconified or not (aka, minimized or not).
+-- See <http://www.glfw.org/docs/3.2/group__window.html#gab1ea7263081c0e073b8d5b91d6ffd367 glfwSetWindowIconifyCallback>
+setWindowIconifyCallback :: Window -> Maybe WindowIconifyCallback -> IO ()
+setWindowIconifyCallback win = setWindowCallback
+    mk'GLFWwindowiconifyfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    (c'glfwSetWindowIconifyCallback (toC win))
+    storedWindowIconifyFun
+    win
+
+-- | Sets the callback to use when the framebuffer's size changes.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga3203461a5303bf289f2e05f854b2f7cf glfwSetFramebufferSizeCallback>
+setFramebufferSizeCallback :: Window -> Maybe FramebufferSizeCallback -> IO ()
+setFramebufferSizeCallback win = setWindowCallback
+    mk'GLFWframebuffersizefun
+    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetFramebufferSizeCallback (toC win))
+    storedFramebufferSizeFun
+    win
+
+-- | Checks for any pending events, processes them, and then immediately returns.
+-- This is most useful for continual rendering, such as games.
+-- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>. This
+-- function is not <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+pollEvents :: IO ()
+pollEvents = c'glfwPollEvents >> executeScheduled
+
+-- | Waits until at least one event is in the queue then processes the queue and returns.
+-- Requires at least one window to be active for it to sleep. This saves a lot of CPU, and
+-- is better if you're doing only periodic rendering, such as with an editor program.
+-- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>. This
+-- function is not <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+waitEvents :: IO ()
+waitEvents = c'glfwWaitEvents >> executeScheduled
+
+-- | Same as 'waitEvents', with a timeout after which the function returns.
+-- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>. This
+-- function is not <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+waitEventsTimeout :: Double -> IO ()
+waitEventsTimeout seconds =
+  c'glfwWaitEventsTimeout (toC seconds) >> executeScheduled
+
+-- | Creates an empty event within the event queue. Can be called from any
+-- thread, so you can use this to wake up the main thread that's using
+-- 'waitEvents' from a secondary thread.
+-- See the <http://www.glfw.org/docs/3.2/input.html#events Event Processing Guide>
+postEmptyEvent :: IO ()
+postEmptyEvent = c'glfwPostEmptyEvent
+
+--------------------------------------------------------------------------------
+-- Input handling
+
+-- start of glfw{GS}etInputMode-related functions
+
+-- | Gets the current cursor input mode.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+getCursorInputMode :: Window -> IO CursorInputMode
+getCursorInputMode win =
+    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_CURSOR
+
+-- | Set the cursor input mode.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+setCursorInputMode :: Window -> CursorInputMode -> IO ()
+setCursorInputMode win c =
+    c'glfwSetInputMode (toC win) c'GLFW_CURSOR (toC c)
+
+-- | Gets the current sticky keys mode.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+getStickyKeysInputMode :: Window -> IO StickyKeysInputMode
+getStickyKeysInputMode win =
+    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_STICKY_KEYS
+
+-- | Sets if sticky keys should be used or not.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+setStickyKeysInputMode :: Window -> StickyKeysInputMode -> IO ()
+setStickyKeysInputMode win sk =
+    c'glfwSetInputMode (toC win) c'GLFW_STICKY_KEYS (toC sk)
+
+-- | Gets if sticky mouse buttons are on or not.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+getStickyMouseButtonsInputMode :: Window -> IO StickyMouseButtonsInputMode
+getStickyMouseButtonsInputMode win =
+    fromC `fmap` c'glfwGetInputMode (toC win) c'GLFW_STICKY_MOUSE_BUTTONS
+
+-- | Sets if sticky mouse buttons should be used or not.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa92336e173da9c8834558b54ee80563b glfwSetInputMode>
+setStickyMouseButtonsInputMode :: Window -> StickyMouseButtonsInputMode -> IO ()
+setStickyMouseButtonsInputMode win smb =
+    c'glfwSetInputMode (toC win) c'GLFW_STICKY_MOUSE_BUTTONS (toC smb)
+
+-- end of glfw{GS}etInputMode-related functions
+
+-- | Gets the state of the specified key. If Stickey Keys isn't enabled then it's possible for
+-- keyboard polling to miss individual key presses. Use the callback to avoid this.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gadd341da06bc8d418b4dc3a3518af9ad2 glfwGetKey>
+getKey :: Window -> Key -> IO KeyState
+getKey win k =
+    fromC `fmap` c'glfwGetKey (toC win) (toC k)
+
+-- | Returns the localized name of the specified printable key. This is intended
+-- for displaying key bindings to the user. The scancode is used if the provided
+-- 'Key' isn't printable. If the scancode maps to a non-printable key as well,
+-- then 'Nothing' is returned.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga237a182e5ec0b21ce64543f3b5e7e2be glfwGetKeyName>
+getKeyName :: Key -> Int -> IO (Maybe String)
+getKeyName k scancode = do
+  cstr <- c'glfwGetKeyName (toC k) (toC scancode)
+  if cstr == nullPtr
+    then return Nothing
+    else Just `fmap` peekCString cstr
+
+-- | Gets the state of a single specified mouse button. If sticky mouse button
+-- mode isn't enabled it's possible for mouse polling to miss individual mouse events. Use
+-- the call back to avoid this.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gac1473feacb5996c01a7a5a33b5066704 glfwGetMouseButton>
+getMouseButton :: Window -> MouseButton -> IO MouseButtonState
+getMouseButton win b =
+    fromC `fmap` c'glfwGetMouseButton (toC win) (toC b)
+
+-- | Returns the position, in screen coodinates, relative to the upper left.
+-- If the 'CursorInputMode' is "disabled", then results are unbounded by the window size.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga01d37b6c40133676b9cea60ca1d7c0cc glfwGetCursorPos>
+getCursorPos :: Window -> IO (Double, Double)
+getCursorPos win =
+    allocaArray 2 $ \p -> do
+        let p'x = p
+            p'y = p `advancePtr` 1
+        c'glfwGetCursorPos (toC win) p'x p'y
+        x <- fromC `fmap` peek p'x
+        y <- fromC `fmap` peek p'y
+        return (x, y)
+
+-- | Assigns the given callback to use for all keyboard presses and repeats.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga7e496507126f35ea72f01b2e6ef6d155 glfwSetKeyCallback>
+setKeyCallback :: Window -> Maybe KeyCallback -> IO ()
+setKeyCallback win = setWindowCallback
+    mk'GLFWkeyfun
+    (\cb a0 a1 a2 a3 a4 ->
+      schedule $ cb (fromC a0) (fromC a1) (fromC a2) (fromC a3) (fromC a4))
+    (c'glfwSetKeyCallback (toC win))
+    storedKeyFun
+    win
+
+-- | Sets the callback to use when the user types a character
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga556239421c6a5a243c66fca28da9f742 glfwSetCharCallback>
+setCharCallback :: Window -> Maybe CharCallback -> IO ()
+setCharCallback win = setWindowCallback
+    mk'GLFWcharfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    (c'glfwSetCharCallback (toC win))
+    storedCharFun
+    win
+
+-- | Sets the callback to use with Unicode characters regardless of what
+-- modifier keys are used.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga3f55ef5dc03a374e567f068b13c94afc glfwSetCharModsCallback>
+setCharModsCallback :: Window -> Maybe CharModsCallback -> IO ()
+setCharModsCallback win = setWindowCallback
+    mk'GLFWcharmodsfun
+    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetCharModsCallback (toC win))
+    storedCharModsFun
+    win
+
+-- | Assigns the callback to run whenver a mouse button is clicked.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaef49b72d84d615bca0a6ed65485e035d glfwSetMouseButtonCallback>
+setMouseButtonCallback :: Window -> Maybe MouseButtonCallback -> IO ()
+setMouseButtonCallback win = setWindowCallback
+    mk'GLFWmousebuttonfun
+    (\cb a0 a1 a2 a3 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2) (fromC a3))
+    (c'glfwSetMouseButtonCallback (toC win))
+    storedMouseButtonFun
+    win
+
+-- | Assigns the callback to run whenver the cursor position changes.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga7dad39486f2c7591af7fb25134a2501d glfwSetCursorPosCallback>
+setCursorPosCallback :: Window -> Maybe CursorPosCallback -> IO ()
+setCursorPosCallback win = setWindowCallback
+    mk'GLFWcursorposfun
+    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetCursorPosCallback (toC win))
+    storedCursorPosFun
+    win
+
+-- | Sets the callback for when the cursor enters or leaves the client area.
+-- See <http://www.glfw.org/docs/3.2/input.html#cursor_enter Cursor Enter/Leave Events>
+setCursorEnterCallback :: Window -> Maybe CursorEnterCallback -> IO ()
+setCursorEnterCallback win = setWindowCallback
+    mk'GLFWcursorenterfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    (c'glfwSetCursorEnterCallback (toC win))
+    storedCursorEnterFun
+    win
+
+-- | Sets the callback to run when the user scrolls with the mouse wheel or a touch gesture.
+-- See <http://www.glfw.org/docs/3.2/input.html#scrolling Scroll Input>
+setScrollCallback :: Window -> Maybe ScrollCallback -> IO ()
+setScrollCallback win = setWindowCallback
+    mk'GLFWscrollfun
+    (\cb a0 a1 a2 -> schedule $ cb (fromC a0) (fromC a1) (fromC a2))
+    (c'glfwSetScrollCallback (toC win))
+    storedScrollFun
+    win
+
+-- | Tests if the joystick is present at all
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaffcbd9ac8ee737fcdd25475123a3c790 glfwJoystickPresent>
+joystickPresent :: Joystick -> IO Bool
+joystickPresent js =
+    fromC `fmap` c'glfwJoystickPresent (toC js)
+
+-- | Returns the values of all axes of the specified joystick, normalized to between -1.0 and 1.0
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga6271d46a5901ec2c99601ccf4dd14731 glfwGetJoystickAxes>
+getJoystickAxes :: Joystick -> IO (Maybe [Double])
+getJoystickAxes js =
+    alloca $ \p'n -> do
+        p'axes <- c'glfwGetJoystickAxes (toC js) p'n
+        n <- fromC `fmap` peek p'n
+        if p'axes == nullPtr || n <= 0
+          then return Nothing
+          else (Just . map fromC) `fmap` peekArray n p'axes
+
+-- | Returns a list of all joystick button states for the specified joystick.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gace54cd930dcd502e118fe4021384ce1b glfwGetJoystickButtons>
+getJoystickButtons :: Joystick -> IO (Maybe [JoystickButtonState])
+getJoystickButtons js =
+    alloca $ \p'n -> do
+        p'buttons <- c'glfwGetJoystickButtons (toC js) p'n
+        n <- fromC `fmap` peek p'n
+        if p'buttons == nullPtr || n <= 0
+          then return Nothing
+          else (Just . map fromC) `fmap` peekArray n p'buttons
+
+-- | A human-readable name for a Joystick. Not guranteed to be unique.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gac8d7f6107e05cfd106cfba973ab51e19 glfwGetJoystickName>
+getJoystickName :: Joystick -> IO (Maybe String)
+getJoystickName js = do
+    p'name <- c'glfwGetJoystickName (toC js)
+    if p'name == nullPtr
+      then return Nothing
+      else Just `fmap` peekCString p'name
+
+-- | Sets a callback for when a joystick is connected or disconnected.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gab1dc8379f1b82bb660a6b9c9fa06ca07 glfwSetJoystickCallback>
+setJoystickCallback :: Maybe JoystickCallback -> IO ()
+setJoystickCallback = setCallback
+    mk'GLFWjoystickfun
+    (\cb a0 a1 -> schedule $ cb (fromC a0) (fromC a1))
+    c'glfwSetJoystickCallback
+    storedJoystickFun
+
+--------------------------------------------------------------------------------
+-- Time
+
+-- | Returns the time (in seconds) of the GLFW timer.
+-- This is the amount of time since GLFW was initialized, unless 'setTime' was used.
+-- The exact resolution is system dependent.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaa6cf4e7a77158a3b8fd00328b1720a4a glfwGetTime>
+getTime :: IO (Maybe Double)
+getTime = do
+    t <- fromC `fmap` c'glfwGetTime
+    return $ if t == 0
+      then Nothing
+      else Just t
+
+-- | Sets the GLFW timer to the specified value, which is measured in seconds, and must be positive.
+-- The value must also be less than ~584 years in seconds (18446744073.0).
+-- After this the timer begins to count upward at the normal rate.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaf59589ef6e8b8c8b5ad184b25afd4dc0 glfwSetTime>
+setTime :: Double -> IO ()
+setTime = c'glfwSetTime . toC
+
+-- | Returns the current value of the raw timer, measured in 1 / frequency
+-- seconds. The frequency can be queried using getTimerFrequency.
+-- See <http://www.glfw.org/docs/3.2/input_guide.html#time Timer input>
+getTimerValue :: IO Word64
+getTimerValue = c'glfwGetTimerValue
+
+-- | Returns the frequency, in Hz, of the raw timer.
+-- See <http://www.glfw.org/docs/3.2/input_guide.html#time Timer input>
+getTimerFrequency :: IO Word64
+getTimerFrequency = c'glfwGetTimerFrequency
+
+--------------------------------------------------------------------------------
+-- Context
+
+-- | Makes the context of the specified window the current one for the calling thread.
+-- A context can only be made current on a single thread at a time,
+-- and each thread can have only a single current context at a time.
+-- See <http://www.glfw.org/docs/3.2/group__context.html#ga1c04dc242268f827290fe40aa1c91157 glfwMakeContextCurrent>
+makeContextCurrent :: Maybe Window -> IO ()
+makeContextCurrent =
+    c'glfwMakeContextCurrent . maybe nullPtr toC
+
+-- | Obtains which window owns the current context of the calling thread.
+-- See <http://www.glfw.org/docs/3.2/group__context.html#gac84759b1f6c2d271a4fea8ae89ec980d glfwGetCurrentContext>
+getCurrentContext :: IO (Maybe Window)
+getCurrentContext = do
+    p'win <- c'glfwGetCurrentContext
+    return $ if p'win == nullPtr
+      then Nothing
+      else Just $ fromC p'win
+
+-- | Swaps the front and back buffers of the window.
+-- See <http://www.glfw.org/docs/3.2/group__window.html#ga15a5a1ee5b3c2ca6b15ca209a12efd14 glfwSwapBuffers>
+swapBuffers :: Window -> IO ()
+swapBuffers =
+    c'glfwSwapBuffers . toC
+
+-- | Sets the number of screen updates that the GPU should wait after 'swapBuffers' before actually swapping the buffers.
+-- Generates 'Error'NoCurrentContext' if no context is current.
+-- See <http://www.glfw.org/docs/3.2/group__context.html#ga6d4e0cdf151b5e579bd67f13202994ed glfwSwapInterval>
+swapInterval :: Int -> IO ()
+swapInterval =
+    c'glfwSwapInterval . toC
+
+-- | If the current OpenGL or OpenGL ES context supports the extension specified.
+-- Generates 'Error'NoCurrentContext' if no context is current.
+-- See <http://www.glfw.org/docs/3.2/group__context.html#ga87425065c011cef1ebd6aac75e059dfa glfwExtensionSupported>
+extensionSupported :: String -> IO Bool
+extensionSupported ext =
+    withCString ext $ \p'ext ->
+      fromC `fmap` c'glfwExtensionSupported p'ext
+
+--------------------------------------------------------------------------------
+-- Clipboard
+-- http://www.glfw.org/docs/3.2/input.html#clipboard
+
+-- | The window that will own the clipboard contents, and also the clipboard string.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#gaba1f022c5eb07dfac421df34cdcd31dd glfwSetClipboardString>
+setClipboardString :: Window -> String -> IO ()
+setClipboardString win s =
+    withCString s (c'glfwSetClipboardString (toC win))
+
+-- | Obtains the contents of the system keyboard, if possible.
+-- Generates 'Error'FormatUnavailable' if the system clipboard is empty or if it's not a UTF-8 string.
+-- See <http://www.glfw.org/docs/3.2/group__input.html#ga5aba1d704d9ab539282b1fbe9f18bb94 glfwGetClipboardString>
+getClipboardString :: Window -> IO (Maybe String)
+getClipboardString win = do
+    p's <- c'glfwGetClipboardString (toC win)
+    if p's == nullPtr
+      then return Nothing
+      else Just `fmap` peekCString p's
+
+--------------------------------------------------------------------------------
+-- 3.1 additions (http://www.glfw.org/docs/3.1/news.html#news_31)
+--------------------------------------------------------------------------------
+
+-- Cursor Objects
+-- http://www.glfw.org/docs/3.2/input.html#cursor_object
+
+-- | Creates a new cursor.
+createCursor :: Image -- ^ The desired cursor image.
+             -> Int   -- ^ The desired x-coordinate, in pixels, of the cursor
+                      --   hotspot.
+             -> Int   -- ^ The desired y-coordinate, in pixels, of the cursor
+                      --   hotspot.
+             -> IO Cursor
+createCursor img x y =
+  withGLFWImage img $ \p'img ->
+    Cursor `fmap` c'glfwCreateCursor p'img (toC x) (toC y)
+
+-- | Creates a cursor with a standard shape that can be set for a window with
+-- setCursor.
+createStandardCursor :: StandardCursorShape -> IO Cursor
+createStandardCursor = (fmap Cursor) . c'glfwCreateStandardCursor . toC
+
+-- | Sets the cursor image to be used when the cursor is over the client area
+-- of the specified window. The set cursor will only be visible when the cursor
+-- mode of the window is GLFW_CURSOR_NORMAL.
+
+-- On some platforms, the set cursor may not be visible unless the window also
+-- has input focus.
+setCursor :: Window -> Cursor -> IO ()
+setCursor (Window wptr) (Cursor cptr) = c'glfwSetCursor wptr cptr
+
+-- | Destroys a cursor previously created with `createCursor`. Any remaining
+-- cursors will be destroyed by `terminate`. This function is not
+-- <https://www.glfw.org/docs/latest/intro.html#reentrancy reentrant>.
+destroyCursor :: Cursor -> IO ()
+destroyCursor = c'glfwDestroyCursor . unCursor
+
+-- | A callback that allows for drag and drop support.
+type DropCallback = Window    -- ^ The window that received the event.
+                  -> [String] -- ^ The file and/or directory path names
+                  -> IO ()
+
+-- | Sets the file drop callback of the specified window, which is called when
+-- one or more dragged files are dropped on the window.
+setDropCallback :: Window -> Maybe DropCallback -> IO ()
+setDropCallback win = setWindowCallback
+    mk'GLFWdropfun
+    (\cb w c fs -> do
+        let count = fromC c
+        fps <- flip mapM [0..count-1] $ \i -> do
+            let p = advancePtr fs i
+            p' <- peek p
+            peekCString p'
+        schedule $ cb (fromC w) fps)
+    (c'glfwSetDropCallback (toC win))
+    storedDropFun
+    win
+
+--------------------------------------------------------------------------------
+-- Vulkan-related functions
+--------------------------------------------------------------------------------
+
+-- | This function returns whether the Vulkan loader has been found.
+--   This check is performed by `init`.
+vulkanSupported :: IO Bool
+vulkanSupported = (c'GLFW_TRUE ==) <$> c'glfwVulkanSupported
+
+-- | Get required vulkan extensions;
+--   Pointer memory is managed by GLFW, destroyed by `terminate` call.
+--
+--   The returned extension names are kept in `CString` type, because
+--   they are expected to be consumed by vulkan device initialization functions.
+getRequiredInstanceExtensions :: IO [CString]
+getRequiredInstanceExtensions = alloca $ \countPtr -> do
+    extsPtrPtr <- c'glfwGetRequiredInstanceExtensions countPtr
+    count <- fromIntegral <$> peek countPtr
+    peekArray count extsPtrPtr
+
+-- | Returns the address of the specified Vulkan instance function.
+getInstanceProcAddress :: Ptr vkInstance
+                          -- ^ VkInstance.
+                          --   Note, the returned function must be used
+                          --   with the same instance or its child.
+                       -> String
+                          -- ^ Function name
+                       -> IO (FunPtr vkProc)
+getInstanceProcAddress i procName
+  = withCString procName (c'glfwGetInstanceProcAddress i)
+
+-- | Returns whether the specified queue family can present images.
+getPhysicalDevicePresentationSupport ::
+       Ptr vkInstance
+       -- ^ VkInstance
+    -> Ptr vkPhysicalDevice
+       -- ^ VkPhysicalDevice
+    -> Word32
+       -- ^ Index of a queue family to query.
+       --   This is an index in the array returned by
+       --   @vkGetPhysicalDeviceQueueFamilyProperties@ function.
+    -> IO Bool
+getPhysicalDevicePresentationSupport inst dev i
+  = (c'GLFW_TRUE ==) <$> c'glfwGetPhysicalDevicePresentationSupport inst dev i
+
+-- | Creates a Vulkan surface for the specified window
+createWindowSurface :: Enum vkResult
+                    => Ptr vkInstance
+                       -- ^ VkInstance
+                    -> Window
+                       -- ^ GLFWwindow *window
+                    -> Ptr vkAllocationCallbacks
+                       -- ^ const VkAllocationCallbacks *allocator
+                    -> Ptr vkSurfaceKHR
+                       -- ^ VkSurfaceKHR *surface
+                    -> IO vkResult
+createWindowSurface i win acs s
+  = toEnum . fromIntegral
+  <$> c'glfwCreateWindowSurface i (toC win) acs s
+
+--------------------------------------------------------------------------------
+-- Native APIs
+--------------------------------------------------------------------------------
+
+-- $nativeaccess
+-- The low level native-access bindings are exposed here via bindings-GLFW.
+-- These must be enabled with the 'ExposeNative' flag passed to bindings-GLFW.
+-- The return values of these functions are used as a best-guess and are not
+-- coupled with any other implementation. They should be used with caution
+-- and at your own risk.
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gac84f63a3f9db145b9435e5e0dbc4183d glfwGetWin32Adapter>
+getWin32Adapter :: Window -> IO CString
+getWin32Adapter = c'glfwGetWin32Adapter . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gac408b09a330749402d5d1fa1f5894dd9 glfwGetWin32Monitor>
+getWin32Monitor :: Window -> IO CString
+getWin32Monitor = c'glfwGetWin32Monitor . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gafe5079aa79038b0079fc09d5f0a8e667 glfwGetWin32Window>
+getWin32Window  :: Window -> IO (Ptr ())
+getWin32Window = c'glfwGetWin32Window . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gadc4010d91d9cc1134d040eeb1202a143 glfwGetWGLContext>
+getWGLContext :: Window -> IO (Ptr ())
+getWGLContext = c'glfwGetWGLContext . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gaf22f429aec4b1aab316142d66d9be3e6 glfwGetCocoaMonitor>
+getCocoaMonitor :: Window -> IO (Ptr Word32)
+getCocoaMonitor = c'glfwGetCocoaMonitor . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gac3ed9d495d0c2bb9652de5a50c648715 glfwGetCocoaWindow>
+getCocoaWindow :: Window -> IO (Ptr ())
+getCocoaWindow = c'glfwGetCocoaWindow . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga559e002e3cd63c979881770cd4dc63bc glfwGetNSGLContext>
+getNSGLContext :: Window -> IO (Ptr ())
+getNSGLContext = c'glfwGetNSGLContext . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga8519b66594ea3ef6eeafaa2e3ee37406 glfwGetX11Display>
+getX11Display :: Window -> IO (Ptr display)
+getX11Display = c'glfwGetX11Display . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga088fbfa80f50569402b41be71ad66e40 glfwGetX11Adapter>
+getX11Adapter :: Window -> IO Word64
+getX11Adapter = c'glfwGetX11Adapter . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gab2f8cc043905e9fa9b12bfdbbcfe874c glfwGetX11Monitor>
+getX11Monitor :: Window -> IO Word64
+getX11Monitor = c'glfwGetX11Monitor . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga90ca676322740842db446999a1b1f21d glfwGetX11Window>
+getX11Window  :: Window -> IO Word64
+getX11Window = c'glfwGetX11Window . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga62d884114b0abfcdc2930e89f20867e2 glfwGetGLXContext>
+getGLXContext :: Window -> IO (Ptr ())
+getGLXContext = c'glfwGetGLXContext . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga1ed27b8766e859a21381e8f8ce18d049 glfwGetGLXWindow>
+getGLXWindow  :: Window -> IO Word64
+getGLXWindow = c'glfwGetGLXWindow . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gaaf8118a3c877f3a6bc8e7a649519de5e glfwGetWaylandDisplay>
+getWaylandDisplay :: IO (Ptr wl_display)
+getWaylandDisplay = c'glfwGetWaylandDisplay
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gab10427a667b6cd91eec7709f7a906bd3 glfwGetWaylandMonitor>
+getWaylandMonitor :: Window -> IO (Ptr wl_output)
+getWaylandMonitor = c'glfwGetWaylandMonitor . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga4738d7aca4191363519a9a641c3ab64c glfwGetWaylandWindow>
+getWaylandWindow :: Window -> IO (Ptr wl_surface)
+getWaylandWindow = c'glfwGetWaylandWindow . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga40dd05325d9813fa67d61328c51d2930 glfwGetMirDisplay>
+getMirDisplay :: IO (Ptr mir_connection)
+getMirDisplay = c'glfwGetMirDisplay
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#gae0941c11dc8f01aeb7cbb563f5cd930b glfwGetMirMonitor>
+getMirMonitor :: Window -> IO Int
+getMirMonitor = (fmap fromC) . c'glfwGetMirMonitor . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga964d52bb7932216c379762eef1ea9b05 glfwGetMirWindow>
+getMirWindow :: Window -> IO (Ptr mir_surface)
+getMirWindow = c'glfwGetMirWindow . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga1cd8d973f47aacb5532d368147cc3138 glfwGetEGLDisplay>
+getEGLDisplay :: IO (Ptr ())
+getEGLDisplay = c'glfwGetEGLDisplay
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga671c5072becd085f4ab5771a9c8efcf1 glfwGetEGLContext>
+getEGLContext :: Window -> IO (Ptr ())
+getEGLContext = c'glfwGetEGLContext . toC
+
+-- | See <http://www.glfw.org/docs/3.2/group__native.html#ga2199b36117a6a695fec8441d8052eee6 glfwGetEGLSurface>
+getEGLSurface :: Window -> IO (Ptr ())
+getEGLSurface = c'glfwGetEGLSurface . toC
Graphics/UI/GLFW/C.hs view
@@ -1,568 +1,568 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts #-}-------------------------------------------------------------------------------------- This code is generated by util/genC.hs.------------------------------------------------------------------------------------module Graphics.UI.GLFW.C where------------------------------------------------------------------------------------import Data.Bits       ((.&.))-import Data.Char       (chr, ord)-import Foreign.C.Types (CDouble, CFloat, CInt, CUChar, CUInt, CUShort)-import Foreign.Ptr     (Ptr)--import Bindings.GLFW-import Graphics.UI.GLFW.Types------------------------------------------------------------------------------------class C c h where-  fromC :: c -> h-  toC   :: h -> c------------------------------------------------------------------------------------instance (C CInt b) => C CInt (Maybe b) where-  fromC i | i == c'GLFW_DONT_CARE = Nothing-          | otherwise = Just $ fromC i-  toC = maybe c'GLFW_DONT_CARE toC------------------------------------------------------------------------------------instance C CInt Char where-  fromC = chr . fromIntegral-  toC = fromIntegral . ord--instance C CUInt Char where-  fromC = chr . fromIntegral-  toC = fromIntegral . ord--instance C CDouble Double where-  fromC = realToFrac-  toC = realToFrac--instance C CInt Int where-  fromC = fromIntegral-  toC = fromIntegral--instance C CUInt Int where-  fromC = fromIntegral-  toC = fromIntegral--instance C CUShort Int where-  fromC = fromIntegral-  toC = fromIntegral--instance C CFloat Double where-  fromC = realToFrac-  toC = realToFrac--instance C (Ptr C'GLFWmonitor) Monitor where-  fromC = Monitor-  toC = unMonitor--instance C (Ptr C'GLFWwindow) Window where-  fromC = Window-  toC = unWindow--instance C CInt ModifierKeys where-  fromC v = ModifierKeys-    { modifierKeysShift   = (v .&. c'GLFW_MOD_SHIFT)   /= 0-    , modifierKeysControl = (v .&. c'GLFW_MOD_CONTROL) /= 0-    , modifierKeysAlt     = (v .&. c'GLFW_MOD_ALT)     /= 0-    , modifierKeysSuper   = (v .&. c'GLFW_MOD_SUPER)   /= 0-    }-  toC = undefined--instance C C'GLFWvidmode VideoMode where-  fromC gvm = VideoMode-    { videoModeWidth       = fromIntegral $ c'GLFWvidmode'width       gvm-    , videoModeHeight      = fromIntegral $ c'GLFWvidmode'height      gvm-    , videoModeRedBits     = fromIntegral $ c'GLFWvidmode'redBits     gvm-    , videoModeGreenBits   = fromIntegral $ c'GLFWvidmode'greenBits   gvm-    , videoModeBlueBits    = fromIntegral $ c'GLFWvidmode'blueBits    gvm-    , videoModeRefreshRate = fromIntegral $ c'GLFWvidmode'refreshRate gvm-    }-  toC = undefined--instance C CInt StandardCursorShape where-  fromC v-    | v == c'GLFW_ARROW_CURSOR     = StandardCursorShape'Arrow-    | v == c'GLFW_IBEAM_CURSOR     = StandardCursorShape'IBeam-    | v == c'GLFW_CROSSHAIR_CURSOR = StandardCursorShape'Crosshair-    | v == c'GLFW_HAND_CURSOR      = StandardCursorShape'Hand-    | v == c'GLFW_HRESIZE_CURSOR   = StandardCursorShape'HResize-    | v == c'GLFW_VRESIZE_CURSOR   = StandardCursorShape'VResize-    | otherwise = error $ "C CInt StandardCursorShape fromC: " ++ show v-  toC  StandardCursorShape'Arrow     = c'GLFW_ARROW_CURSOR-  toC  StandardCursorShape'IBeam     = c'GLFW_IBEAM_CURSOR-  toC  StandardCursorShape'Crosshair = c'GLFW_CROSSHAIR_CURSOR-  toC  StandardCursorShape'Hand      = c'GLFW_HAND_CURSOR-  toC  StandardCursorShape'HResize   = c'GLFW_HRESIZE_CURSOR-  toC  StandardCursorShape'VResize   = c'GLFW_VRESIZE_CURSOR------------------------------------------------------------------------------------instance C CInt Bool where-  fromC v-    | v == c'GLFW_FALSE = False-    | v == c'GLFW_TRUE = True-    | otherwise = error $ "C CInt Bool fromC: " ++ show v-  toC False = c'GLFW_FALSE-  toC True = c'GLFW_TRUE--instance C CInt Error where-  fromC v-    | v == c'GLFW_NOT_INITIALIZED = Error'NotInitialized-    | v == c'GLFW_NO_CURRENT_CONTEXT = Error'NoCurrentContext-    | v == c'GLFW_INVALID_ENUM = Error'InvalidEnum-    | v == c'GLFW_INVALID_VALUE = Error'InvalidValue-    | v == c'GLFW_OUT_OF_MEMORY = Error'OutOfMemory-    | v == c'GLFW_API_UNAVAILABLE = Error'ApiUnavailable-    | v == c'GLFW_VERSION_UNAVAILABLE = Error'VersionUnavailable-    | v == c'GLFW_PLATFORM_ERROR = Error'PlatformError-    | v == c'GLFW_FORMAT_UNAVAILABLE = Error'FormatUnavailable-    | otherwise = error $ "C CInt Error fromC: " ++ show v-  toC Error'NotInitialized = c'GLFW_NOT_INITIALIZED-  toC Error'NoCurrentContext = c'GLFW_NO_CURRENT_CONTEXT-  toC Error'InvalidEnum = c'GLFW_INVALID_ENUM-  toC Error'InvalidValue = c'GLFW_INVALID_VALUE-  toC Error'OutOfMemory = c'GLFW_OUT_OF_MEMORY-  toC Error'ApiUnavailable = c'GLFW_API_UNAVAILABLE-  toC Error'VersionUnavailable = c'GLFW_VERSION_UNAVAILABLE-  toC Error'PlatformError = c'GLFW_PLATFORM_ERROR-  toC Error'FormatUnavailable = c'GLFW_FORMAT_UNAVAILABLE--instance C CInt MonitorState where-  fromC v-    | v == c'GLFW_CONNECTED = MonitorState'Connected-    | v == c'GLFW_DISCONNECTED = MonitorState'Disconnected-    | otherwise = error $ "C CInt MonitorState fromC: " ++ show v-  toC MonitorState'Connected = c'GLFW_CONNECTED-  toC MonitorState'Disconnected = c'GLFW_DISCONNECTED--instance C CInt ContextRobustness where-  fromC v-    | v == c'GLFW_NO_ROBUSTNESS = ContextRobustness'NoRobustness-    | v == c'GLFW_NO_RESET_NOTIFICATION = ContextRobustness'NoResetNotification-    | v == c'GLFW_LOSE_CONTEXT_ON_RESET = ContextRobustness'LoseContextOnReset-    | otherwise = error $ "C CInt ContextRobustness fromC: " ++ show v-  toC ContextRobustness'NoRobustness = c'GLFW_NO_ROBUSTNESS-  toC ContextRobustness'NoResetNotification = c'GLFW_NO_RESET_NOTIFICATION-  toC ContextRobustness'LoseContextOnReset = c'GLFW_LOSE_CONTEXT_ON_RESET--instance C CInt ContextReleaseBehavior where-  fromC v-    | v == c'GLFW_ANY_RELEASE_BEHAVIOR = ContextReleaseBehavior'Any-    | v == c'GLFW_RELEASE_BEHAVIOR_NONE = ContextReleaseBehavior'None-    | v == c'GLFW_RELEASE_BEHAVIOR_FLUSH = ContextReleaseBehavior'Flush-    | otherwise = error $ "C CInt ContextReleaseBehavior fromC: " ++ show v-  toC ContextReleaseBehavior'Any = c'GLFW_ANY_RELEASE_BEHAVIOR-  toC ContextReleaseBehavior'None = c'GLFW_RELEASE_BEHAVIOR_NONE-  toC ContextReleaseBehavior'Flush = c'GLFW_RELEASE_BEHAVIOR_FLUSH--instance C CInt OpenGLProfile where-  fromC v-    | v == c'GLFW_OPENGL_ANY_PROFILE = OpenGLProfile'Any-    | v == c'GLFW_OPENGL_COMPAT_PROFILE = OpenGLProfile'Compat-    | v == c'GLFW_OPENGL_CORE_PROFILE = OpenGLProfile'Core-    | otherwise = error $ "C CInt OpenGLProfile fromC: " ++ show v-  toC OpenGLProfile'Any = c'GLFW_OPENGL_ANY_PROFILE-  toC OpenGLProfile'Compat = c'GLFW_OPENGL_COMPAT_PROFILE-  toC OpenGLProfile'Core = c'GLFW_OPENGL_CORE_PROFILE--instance C CInt ClientAPI where-  fromC v-    | v == c'GLFW_NO_API = ClientAPI'NoAPI-    | v == c'GLFW_OPENGL_API = ClientAPI'OpenGL-    | v == c'GLFW_OPENGL_ES_API = ClientAPI'OpenGLES-    | otherwise = error $ "C CInt ClientAPI fromC: " ++ show v-  toC ClientAPI'NoAPI = c'GLFW_NO_API-  toC ClientAPI'OpenGL = c'GLFW_OPENGL_API-  toC ClientAPI'OpenGLES = c'GLFW_OPENGL_ES_API--instance C CInt ContextCreationAPI where-  fromC v-    | v == c'GLFW_NATIVE_CONTEXT_API = ContextCreationAPI'Native-    | v == c'GLFW_EGL_CONTEXT_API = ContextCreationAPI'EGL-    | otherwise = error $ "C CInt ContextCreationAPI fromC: " ++ show v-  toC ContextCreationAPI'Native = c'GLFW_NATIVE_CONTEXT_API-  toC ContextCreationAPI'EGL = c'GLFW_EGL_CONTEXT_API--instance C CInt Key where-  fromC v-    | v == c'GLFW_KEY_UNKNOWN = Key'Unknown-    | v == c'GLFW_KEY_SPACE = Key'Space-    | v == c'GLFW_KEY_APOSTROPHE = Key'Apostrophe-    | v == c'GLFW_KEY_COMMA = Key'Comma-    | v == c'GLFW_KEY_MINUS = Key'Minus-    | v == c'GLFW_KEY_PERIOD = Key'Period-    | v == c'GLFW_KEY_SLASH = Key'Slash-    | v == c'GLFW_KEY_0 = Key'0-    | v == c'GLFW_KEY_1 = Key'1-    | v == c'GLFW_KEY_2 = Key'2-    | v == c'GLFW_KEY_3 = Key'3-    | v == c'GLFW_KEY_4 = Key'4-    | v == c'GLFW_KEY_5 = Key'5-    | v == c'GLFW_KEY_6 = Key'6-    | v == c'GLFW_KEY_7 = Key'7-    | v == c'GLFW_KEY_8 = Key'8-    | v == c'GLFW_KEY_9 = Key'9-    | v == c'GLFW_KEY_SEMICOLON = Key'Semicolon-    | v == c'GLFW_KEY_EQUAL = Key'Equal-    | v == c'GLFW_KEY_A = Key'A-    | v == c'GLFW_KEY_B = Key'B-    | v == c'GLFW_KEY_C = Key'C-    | v == c'GLFW_KEY_D = Key'D-    | v == c'GLFW_KEY_E = Key'E-    | v == c'GLFW_KEY_F = Key'F-    | v == c'GLFW_KEY_G = Key'G-    | v == c'GLFW_KEY_H = Key'H-    | v == c'GLFW_KEY_I = Key'I-    | v == c'GLFW_KEY_J = Key'J-    | v == c'GLFW_KEY_K = Key'K-    | v == c'GLFW_KEY_L = Key'L-    | v == c'GLFW_KEY_M = Key'M-    | v == c'GLFW_KEY_N = Key'N-    | v == c'GLFW_KEY_O = Key'O-    | v == c'GLFW_KEY_P = Key'P-    | v == c'GLFW_KEY_Q = Key'Q-    | v == c'GLFW_KEY_R = Key'R-    | v == c'GLFW_KEY_S = Key'S-    | v == c'GLFW_KEY_T = Key'T-    | v == c'GLFW_KEY_U = Key'U-    | v == c'GLFW_KEY_V = Key'V-    | v == c'GLFW_KEY_W = Key'W-    | v == c'GLFW_KEY_X = Key'X-    | v == c'GLFW_KEY_Y = Key'Y-    | v == c'GLFW_KEY_Z = Key'Z-    | v == c'GLFW_KEY_LEFT_BRACKET = Key'LeftBracket-    | v == c'GLFW_KEY_BACKSLASH = Key'Backslash-    | v == c'GLFW_KEY_RIGHT_BRACKET = Key'RightBracket-    | v == c'GLFW_KEY_GRAVE_ACCENT = Key'GraveAccent-    | v == c'GLFW_KEY_WORLD_1 = Key'World1-    | v == c'GLFW_KEY_WORLD_2 = Key'World2-    | v == c'GLFW_KEY_ESCAPE = Key'Escape-    | v == c'GLFW_KEY_ENTER = Key'Enter-    | v == c'GLFW_KEY_TAB = Key'Tab-    | v == c'GLFW_KEY_BACKSPACE = Key'Backspace-    | v == c'GLFW_KEY_INSERT = Key'Insert-    | v == c'GLFW_KEY_DELETE = Key'Delete-    | v == c'GLFW_KEY_RIGHT = Key'Right-    | v == c'GLFW_KEY_LEFT = Key'Left-    | v == c'GLFW_KEY_DOWN = Key'Down-    | v == c'GLFW_KEY_UP = Key'Up-    | v == c'GLFW_KEY_PAGE_UP = Key'PageUp-    | v == c'GLFW_KEY_PAGE_DOWN = Key'PageDown-    | v == c'GLFW_KEY_HOME = Key'Home-    | v == c'GLFW_KEY_END = Key'End-    | v == c'GLFW_KEY_CAPS_LOCK = Key'CapsLock-    | v == c'GLFW_KEY_SCROLL_LOCK = Key'ScrollLock-    | v == c'GLFW_KEY_NUM_LOCK = Key'NumLock-    | v == c'GLFW_KEY_PRINT_SCREEN = Key'PrintScreen-    | v == c'GLFW_KEY_PAUSE = Key'Pause-    | v == c'GLFW_KEY_F1 = Key'F1-    | v == c'GLFW_KEY_F2 = Key'F2-    | v == c'GLFW_KEY_F3 = Key'F3-    | v == c'GLFW_KEY_F4 = Key'F4-    | v == c'GLFW_KEY_F5 = Key'F5-    | v == c'GLFW_KEY_F6 = Key'F6-    | v == c'GLFW_KEY_F7 = Key'F7-    | v == c'GLFW_KEY_F8 = Key'F8-    | v == c'GLFW_KEY_F9 = Key'F9-    | v == c'GLFW_KEY_F10 = Key'F10-    | v == c'GLFW_KEY_F11 = Key'F11-    | v == c'GLFW_KEY_F12 = Key'F12-    | v == c'GLFW_KEY_F13 = Key'F13-    | v == c'GLFW_KEY_F14 = Key'F14-    | v == c'GLFW_KEY_F15 = Key'F15-    | v == c'GLFW_KEY_F16 = Key'F16-    | v == c'GLFW_KEY_F17 = Key'F17-    | v == c'GLFW_KEY_F18 = Key'F18-    | v == c'GLFW_KEY_F19 = Key'F19-    | v == c'GLFW_KEY_F20 = Key'F20-    | v == c'GLFW_KEY_F21 = Key'F21-    | v == c'GLFW_KEY_F22 = Key'F22-    | v == c'GLFW_KEY_F23 = Key'F23-    | v == c'GLFW_KEY_F24 = Key'F24-    | v == c'GLFW_KEY_F25 = Key'F25-    | v == c'GLFW_KEY_KP_0 = Key'Pad0-    | v == c'GLFW_KEY_KP_1 = Key'Pad1-    | v == c'GLFW_KEY_KP_2 = Key'Pad2-    | v == c'GLFW_KEY_KP_3 = Key'Pad3-    | v == c'GLFW_KEY_KP_4 = Key'Pad4-    | v == c'GLFW_KEY_KP_5 = Key'Pad5-    | v == c'GLFW_KEY_KP_6 = Key'Pad6-    | v == c'GLFW_KEY_KP_7 = Key'Pad7-    | v == c'GLFW_KEY_KP_8 = Key'Pad8-    | v == c'GLFW_KEY_KP_9 = Key'Pad9-    | v == c'GLFW_KEY_KP_DECIMAL = Key'PadDecimal-    | v == c'GLFW_KEY_KP_DIVIDE = Key'PadDivide-    | v == c'GLFW_KEY_KP_MULTIPLY = Key'PadMultiply-    | v == c'GLFW_KEY_KP_SUBTRACT = Key'PadSubtract-    | v == c'GLFW_KEY_KP_ADD = Key'PadAdd-    | v == c'GLFW_KEY_KP_ENTER = Key'PadEnter-    | v == c'GLFW_KEY_KP_EQUAL = Key'PadEqual-    | v == c'GLFW_KEY_LEFT_SHIFT = Key'LeftShift-    | v == c'GLFW_KEY_LEFT_CONTROL = Key'LeftControl-    | v == c'GLFW_KEY_LEFT_ALT = Key'LeftAlt-    | v == c'GLFW_KEY_LEFT_SUPER = Key'LeftSuper-    | v == c'GLFW_KEY_RIGHT_SHIFT = Key'RightShift-    | v == c'GLFW_KEY_RIGHT_CONTROL = Key'RightControl-    | v == c'GLFW_KEY_RIGHT_ALT = Key'RightAlt-    | v == c'GLFW_KEY_RIGHT_SUPER = Key'RightSuper-    | v == c'GLFW_KEY_MENU = Key'Menu-    | otherwise = error $ "C CInt Key fromC: " ++ show v-  toC Key'Unknown = c'GLFW_KEY_UNKNOWN-  toC Key'Space = c'GLFW_KEY_SPACE-  toC Key'Apostrophe = c'GLFW_KEY_APOSTROPHE-  toC Key'Comma = c'GLFW_KEY_COMMA-  toC Key'Minus = c'GLFW_KEY_MINUS-  toC Key'Period = c'GLFW_KEY_PERIOD-  toC Key'Slash = c'GLFW_KEY_SLASH-  toC Key'0 = c'GLFW_KEY_0-  toC Key'1 = c'GLFW_KEY_1-  toC Key'2 = c'GLFW_KEY_2-  toC Key'3 = c'GLFW_KEY_3-  toC Key'4 = c'GLFW_KEY_4-  toC Key'5 = c'GLFW_KEY_5-  toC Key'6 = c'GLFW_KEY_6-  toC Key'7 = c'GLFW_KEY_7-  toC Key'8 = c'GLFW_KEY_8-  toC Key'9 = c'GLFW_KEY_9-  toC Key'Semicolon = c'GLFW_KEY_SEMICOLON-  toC Key'Equal = c'GLFW_KEY_EQUAL-  toC Key'A = c'GLFW_KEY_A-  toC Key'B = c'GLFW_KEY_B-  toC Key'C = c'GLFW_KEY_C-  toC Key'D = c'GLFW_KEY_D-  toC Key'E = c'GLFW_KEY_E-  toC Key'F = c'GLFW_KEY_F-  toC Key'G = c'GLFW_KEY_G-  toC Key'H = c'GLFW_KEY_H-  toC Key'I = c'GLFW_KEY_I-  toC Key'J = c'GLFW_KEY_J-  toC Key'K = c'GLFW_KEY_K-  toC Key'L = c'GLFW_KEY_L-  toC Key'M = c'GLFW_KEY_M-  toC Key'N = c'GLFW_KEY_N-  toC Key'O = c'GLFW_KEY_O-  toC Key'P = c'GLFW_KEY_P-  toC Key'Q = c'GLFW_KEY_Q-  toC Key'R = c'GLFW_KEY_R-  toC Key'S = c'GLFW_KEY_S-  toC Key'T = c'GLFW_KEY_T-  toC Key'U = c'GLFW_KEY_U-  toC Key'V = c'GLFW_KEY_V-  toC Key'W = c'GLFW_KEY_W-  toC Key'X = c'GLFW_KEY_X-  toC Key'Y = c'GLFW_KEY_Y-  toC Key'Z = c'GLFW_KEY_Z-  toC Key'LeftBracket = c'GLFW_KEY_LEFT_BRACKET-  toC Key'Backslash = c'GLFW_KEY_BACKSLASH-  toC Key'RightBracket = c'GLFW_KEY_RIGHT_BRACKET-  toC Key'GraveAccent = c'GLFW_KEY_GRAVE_ACCENT-  toC Key'World1 = c'GLFW_KEY_WORLD_1-  toC Key'World2 = c'GLFW_KEY_WORLD_2-  toC Key'Escape = c'GLFW_KEY_ESCAPE-  toC Key'Enter = c'GLFW_KEY_ENTER-  toC Key'Tab = c'GLFW_KEY_TAB-  toC Key'Backspace = c'GLFW_KEY_BACKSPACE-  toC Key'Insert = c'GLFW_KEY_INSERT-  toC Key'Delete = c'GLFW_KEY_DELETE-  toC Key'Right = c'GLFW_KEY_RIGHT-  toC Key'Left = c'GLFW_KEY_LEFT-  toC Key'Down = c'GLFW_KEY_DOWN-  toC Key'Up = c'GLFW_KEY_UP-  toC Key'PageUp = c'GLFW_KEY_PAGE_UP-  toC Key'PageDown = c'GLFW_KEY_PAGE_DOWN-  toC Key'Home = c'GLFW_KEY_HOME-  toC Key'End = c'GLFW_KEY_END-  toC Key'CapsLock = c'GLFW_KEY_CAPS_LOCK-  toC Key'ScrollLock = c'GLFW_KEY_SCROLL_LOCK-  toC Key'NumLock = c'GLFW_KEY_NUM_LOCK-  toC Key'PrintScreen = c'GLFW_KEY_PRINT_SCREEN-  toC Key'Pause = c'GLFW_KEY_PAUSE-  toC Key'F1 = c'GLFW_KEY_F1-  toC Key'F2 = c'GLFW_KEY_F2-  toC Key'F3 = c'GLFW_KEY_F3-  toC Key'F4 = c'GLFW_KEY_F4-  toC Key'F5 = c'GLFW_KEY_F5-  toC Key'F6 = c'GLFW_KEY_F6-  toC Key'F7 = c'GLFW_KEY_F7-  toC Key'F8 = c'GLFW_KEY_F8-  toC Key'F9 = c'GLFW_KEY_F9-  toC Key'F10 = c'GLFW_KEY_F10-  toC Key'F11 = c'GLFW_KEY_F11-  toC Key'F12 = c'GLFW_KEY_F12-  toC Key'F13 = c'GLFW_KEY_F13-  toC Key'F14 = c'GLFW_KEY_F14-  toC Key'F15 = c'GLFW_KEY_F15-  toC Key'F16 = c'GLFW_KEY_F16-  toC Key'F17 = c'GLFW_KEY_F17-  toC Key'F18 = c'GLFW_KEY_F18-  toC Key'F19 = c'GLFW_KEY_F19-  toC Key'F20 = c'GLFW_KEY_F20-  toC Key'F21 = c'GLFW_KEY_F21-  toC Key'F22 = c'GLFW_KEY_F22-  toC Key'F23 = c'GLFW_KEY_F23-  toC Key'F24 = c'GLFW_KEY_F24-  toC Key'F25 = c'GLFW_KEY_F25-  toC Key'Pad0 = c'GLFW_KEY_KP_0-  toC Key'Pad1 = c'GLFW_KEY_KP_1-  toC Key'Pad2 = c'GLFW_KEY_KP_2-  toC Key'Pad3 = c'GLFW_KEY_KP_3-  toC Key'Pad4 = c'GLFW_KEY_KP_4-  toC Key'Pad5 = c'GLFW_KEY_KP_5-  toC Key'Pad6 = c'GLFW_KEY_KP_6-  toC Key'Pad7 = c'GLFW_KEY_KP_7-  toC Key'Pad8 = c'GLFW_KEY_KP_8-  toC Key'Pad9 = c'GLFW_KEY_KP_9-  toC Key'PadDecimal = c'GLFW_KEY_KP_DECIMAL-  toC Key'PadDivide = c'GLFW_KEY_KP_DIVIDE-  toC Key'PadMultiply = c'GLFW_KEY_KP_MULTIPLY-  toC Key'PadSubtract = c'GLFW_KEY_KP_SUBTRACT-  toC Key'PadAdd = c'GLFW_KEY_KP_ADD-  toC Key'PadEnter = c'GLFW_KEY_KP_ENTER-  toC Key'PadEqual = c'GLFW_KEY_KP_EQUAL-  toC Key'LeftShift = c'GLFW_KEY_LEFT_SHIFT-  toC Key'LeftControl = c'GLFW_KEY_LEFT_CONTROL-  toC Key'LeftAlt = c'GLFW_KEY_LEFT_ALT-  toC Key'LeftSuper = c'GLFW_KEY_LEFT_SUPER-  toC Key'RightShift = c'GLFW_KEY_RIGHT_SHIFT-  toC Key'RightControl = c'GLFW_KEY_RIGHT_CONTROL-  toC Key'RightAlt = c'GLFW_KEY_RIGHT_ALT-  toC Key'RightSuper = c'GLFW_KEY_RIGHT_SUPER-  toC Key'Menu = c'GLFW_KEY_MENU--instance C CInt KeyState where-  fromC v-    | v == c'GLFW_PRESS = KeyState'Pressed-    | v == c'GLFW_RELEASE = KeyState'Released-    | v == c'GLFW_REPEAT = KeyState'Repeating-    | otherwise = error $ "C CInt KeyState fromC: " ++ show v-  toC KeyState'Pressed = c'GLFW_PRESS-  toC KeyState'Released = c'GLFW_RELEASE-  toC KeyState'Repeating = c'GLFW_REPEAT--instance C CInt Joystick where-  fromC v-    | v == c'GLFW_JOYSTICK_1 = Joystick'1-    | v == c'GLFW_JOYSTICK_2 = Joystick'2-    | v == c'GLFW_JOYSTICK_3 = Joystick'3-    | v == c'GLFW_JOYSTICK_4 = Joystick'4-    | v == c'GLFW_JOYSTICK_5 = Joystick'5-    | v == c'GLFW_JOYSTICK_6 = Joystick'6-    | v == c'GLFW_JOYSTICK_7 = Joystick'7-    | v == c'GLFW_JOYSTICK_8 = Joystick'8-    | v == c'GLFW_JOYSTICK_9 = Joystick'9-    | v == c'GLFW_JOYSTICK_10 = Joystick'10-    | v == c'GLFW_JOYSTICK_11 = Joystick'11-    | v == c'GLFW_JOYSTICK_12 = Joystick'12-    | v == c'GLFW_JOYSTICK_13 = Joystick'13-    | v == c'GLFW_JOYSTICK_14 = Joystick'14-    | v == c'GLFW_JOYSTICK_15 = Joystick'15-    | v == c'GLFW_JOYSTICK_16 = Joystick'16-    | otherwise = error $ "C CInt Joystick fromC: " ++ show v-  toC Joystick'1 = c'GLFW_JOYSTICK_1-  toC Joystick'2 = c'GLFW_JOYSTICK_2-  toC Joystick'3 = c'GLFW_JOYSTICK_3-  toC Joystick'4 = c'GLFW_JOYSTICK_4-  toC Joystick'5 = c'GLFW_JOYSTICK_5-  toC Joystick'6 = c'GLFW_JOYSTICK_6-  toC Joystick'7 = c'GLFW_JOYSTICK_7-  toC Joystick'8 = c'GLFW_JOYSTICK_8-  toC Joystick'9 = c'GLFW_JOYSTICK_9-  toC Joystick'10 = c'GLFW_JOYSTICK_10-  toC Joystick'11 = c'GLFW_JOYSTICK_11-  toC Joystick'12 = c'GLFW_JOYSTICK_12-  toC Joystick'13 = c'GLFW_JOYSTICK_13-  toC Joystick'14 = c'GLFW_JOYSTICK_14-  toC Joystick'15 = c'GLFW_JOYSTICK_15-  toC Joystick'16 = c'GLFW_JOYSTICK_16--instance C CUChar JoystickButtonState where-  fromC v-    | v == c'GLFW_PRESS = JoystickButtonState'Pressed-    | v == c'GLFW_RELEASE = JoystickButtonState'Released-    | otherwise = error $ "C CUChar JoystickButtonState fromC: " ++ show v-  toC JoystickButtonState'Pressed = c'GLFW_PRESS-  toC JoystickButtonState'Released = c'GLFW_RELEASE--instance C CInt JoystickState where-  fromC v-    | v == c'GLFW_CONNECTED = JoystickState'Connected-    | v == c'GLFW_DISCONNECTED = JoystickState'Disconnected-    | otherwise = error $ "C CInt JoystickState fromC: " ++ show v-  toC JoystickState'Connected = c'GLFW_CONNECTED-  toC JoystickState'Disconnected = c'GLFW_DISCONNECTED--instance C CInt MouseButton where-  fromC v-    | v == c'GLFW_MOUSE_BUTTON_1 = MouseButton'1-    | v == c'GLFW_MOUSE_BUTTON_2 = MouseButton'2-    | v == c'GLFW_MOUSE_BUTTON_3 = MouseButton'3-    | v == c'GLFW_MOUSE_BUTTON_4 = MouseButton'4-    | v == c'GLFW_MOUSE_BUTTON_5 = MouseButton'5-    | v == c'GLFW_MOUSE_BUTTON_6 = MouseButton'6-    | v == c'GLFW_MOUSE_BUTTON_7 = MouseButton'7-    | v == c'GLFW_MOUSE_BUTTON_8 = MouseButton'8-    | otherwise = error $ "C CInt MouseButton fromC: " ++ show v-  toC MouseButton'1 = c'GLFW_MOUSE_BUTTON_1-  toC MouseButton'2 = c'GLFW_MOUSE_BUTTON_2-  toC MouseButton'3 = c'GLFW_MOUSE_BUTTON_3-  toC MouseButton'4 = c'GLFW_MOUSE_BUTTON_4-  toC MouseButton'5 = c'GLFW_MOUSE_BUTTON_5-  toC MouseButton'6 = c'GLFW_MOUSE_BUTTON_6-  toC MouseButton'7 = c'GLFW_MOUSE_BUTTON_7-  toC MouseButton'8 = c'GLFW_MOUSE_BUTTON_8--instance C CInt MouseButtonState where-  fromC v-    | v == c'GLFW_PRESS = MouseButtonState'Pressed-    | v == c'GLFW_RELEASE = MouseButtonState'Released-    | otherwise = error $ "C CInt MouseButtonState fromC: " ++ show v-  toC MouseButtonState'Pressed = c'GLFW_PRESS-  toC MouseButtonState'Released = c'GLFW_RELEASE--instance C CInt CursorState where-  fromC v-    | v == c'GLFW_TRUE = CursorState'InWindow-    | v == c'GLFW_FALSE = CursorState'NotInWindow-    | otherwise = error $ "C CInt CursorState fromC: " ++ show v-  toC CursorState'InWindow = c'GLFW_TRUE-  toC CursorState'NotInWindow = c'GLFW_FALSE--instance C CInt CursorInputMode where-  fromC v-    | v == c'GLFW_CURSOR_NORMAL = CursorInputMode'Normal-    | v == c'GLFW_CURSOR_HIDDEN = CursorInputMode'Hidden-    | v == c'GLFW_CURSOR_DISABLED = CursorInputMode'Disabled-    | otherwise = error $ "C CInt CursorInputMode fromC: " ++ show v-  toC CursorInputMode'Normal = c'GLFW_CURSOR_NORMAL-  toC CursorInputMode'Hidden = c'GLFW_CURSOR_HIDDEN-  toC CursorInputMode'Disabled = c'GLFW_CURSOR_DISABLED--instance C CInt StickyKeysInputMode where-  fromC v-    | v == c'GLFW_TRUE = StickyKeysInputMode'Enabled-    | v == c'GLFW_FALSE = StickyKeysInputMode'Disabled-    | otherwise = error $ "C CInt StickyKeysInputMode fromC: " ++ show v-  toC StickyKeysInputMode'Enabled = c'GLFW_TRUE-  toC StickyKeysInputMode'Disabled = c'GLFW_FALSE--instance C CInt StickyMouseButtonsInputMode where-  fromC v-    | v == c'GLFW_TRUE = StickyMouseButtonsInputMode'Enabled-    | v == c'GLFW_FALSE = StickyMouseButtonsInputMode'Disabled-    | otherwise = error $ "C CInt StickyMouseButtonsInputMode fromC: " ++ show v-  toC StickyMouseButtonsInputMode'Enabled = c'GLFW_TRUE-  toC StickyMouseButtonsInputMode'Disabled = c'GLFW_FALSE-----------------------------------------------------------------------------------+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FlexibleContexts #-}
+
+--------------------------------------------------------------------------------
+
+-- This code is generated by util/genC.hs.
+
+--------------------------------------------------------------------------------
+
+module Graphics.UI.GLFW.C where
+
+--------------------------------------------------------------------------------
+
+import Data.Bits       ((.&.))
+import Data.Char       (chr, ord)
+import Foreign.C.Types (CDouble, CFloat, CInt, CUChar, CUInt, CUShort)
+import Foreign.Ptr     (Ptr)
+
+import Bindings.GLFW
+import Graphics.UI.GLFW.Types
+
+--------------------------------------------------------------------------------
+
+class C c h where
+  fromC :: c -> h
+  toC   :: h -> c
+
+--------------------------------------------------------------------------------
+
+instance (C CInt b) => C CInt (Maybe b) where
+  fromC i | i == c'GLFW_DONT_CARE = Nothing
+          | otherwise = Just $ fromC i
+  toC = maybe c'GLFW_DONT_CARE toC
+
+--------------------------------------------------------------------------------
+
+instance C CInt Char where
+  fromC = chr . fromIntegral
+  toC = fromIntegral . ord
+
+instance C CUInt Char where
+  fromC = chr . fromIntegral
+  toC = fromIntegral . ord
+
+instance C CDouble Double where
+  fromC = realToFrac
+  toC = realToFrac
+
+instance C CInt Int where
+  fromC = fromIntegral
+  toC = fromIntegral
+
+instance C CUInt Int where
+  fromC = fromIntegral
+  toC = fromIntegral
+
+instance C CUShort Int where
+  fromC = fromIntegral
+  toC = fromIntegral
+
+instance C CFloat Double where
+  fromC = realToFrac
+  toC = realToFrac
+
+instance C (Ptr C'GLFWmonitor) Monitor where
+  fromC = Monitor
+  toC = unMonitor
+
+instance C (Ptr C'GLFWwindow) Window where
+  fromC = Window
+  toC = unWindow
+
+instance C CInt ModifierKeys where
+  fromC v = ModifierKeys
+    { modifierKeysShift   = (v .&. c'GLFW_MOD_SHIFT)   /= 0
+    , modifierKeysControl = (v .&. c'GLFW_MOD_CONTROL) /= 0
+    , modifierKeysAlt     = (v .&. c'GLFW_MOD_ALT)     /= 0
+    , modifierKeysSuper   = (v .&. c'GLFW_MOD_SUPER)   /= 0
+    }
+  toC = undefined
+
+instance C C'GLFWvidmode VideoMode where
+  fromC gvm = VideoMode
+    { videoModeWidth       = fromIntegral $ c'GLFWvidmode'width       gvm
+    , videoModeHeight      = fromIntegral $ c'GLFWvidmode'height      gvm
+    , videoModeRedBits     = fromIntegral $ c'GLFWvidmode'redBits     gvm
+    , videoModeGreenBits   = fromIntegral $ c'GLFWvidmode'greenBits   gvm
+    , videoModeBlueBits    = fromIntegral $ c'GLFWvidmode'blueBits    gvm
+    , videoModeRefreshRate = fromIntegral $ c'GLFWvidmode'refreshRate gvm
+    }
+  toC = undefined
+
+instance C CInt StandardCursorShape where
+  fromC v
+    | v == c'GLFW_ARROW_CURSOR     = StandardCursorShape'Arrow
+    | v == c'GLFW_IBEAM_CURSOR     = StandardCursorShape'IBeam
+    | v == c'GLFW_CROSSHAIR_CURSOR = StandardCursorShape'Crosshair
+    | v == c'GLFW_HAND_CURSOR      = StandardCursorShape'Hand
+    | v == c'GLFW_HRESIZE_CURSOR   = StandardCursorShape'HResize
+    | v == c'GLFW_VRESIZE_CURSOR   = StandardCursorShape'VResize
+    | otherwise = error $ "C CInt StandardCursorShape fromC: " ++ show v
+  toC  StandardCursorShape'Arrow     = c'GLFW_ARROW_CURSOR
+  toC  StandardCursorShape'IBeam     = c'GLFW_IBEAM_CURSOR
+  toC  StandardCursorShape'Crosshair = c'GLFW_CROSSHAIR_CURSOR
+  toC  StandardCursorShape'Hand      = c'GLFW_HAND_CURSOR
+  toC  StandardCursorShape'HResize   = c'GLFW_HRESIZE_CURSOR
+  toC  StandardCursorShape'VResize   = c'GLFW_VRESIZE_CURSOR
+
+--------------------------------------------------------------------------------
+
+instance C CInt Bool where
+  fromC v
+    | v == c'GLFW_FALSE = False
+    | v == c'GLFW_TRUE = True
+    | otherwise = error $ "C CInt Bool fromC: " ++ show v
+  toC False = c'GLFW_FALSE
+  toC True = c'GLFW_TRUE
+
+instance C CInt Error where
+  fromC v
+    | v == c'GLFW_NOT_INITIALIZED = Error'NotInitialized
+    | v == c'GLFW_NO_CURRENT_CONTEXT = Error'NoCurrentContext
+    | v == c'GLFW_INVALID_ENUM = Error'InvalidEnum
+    | v == c'GLFW_INVALID_VALUE = Error'InvalidValue
+    | v == c'GLFW_OUT_OF_MEMORY = Error'OutOfMemory
+    | v == c'GLFW_API_UNAVAILABLE = Error'ApiUnavailable
+    | v == c'GLFW_VERSION_UNAVAILABLE = Error'VersionUnavailable
+    | v == c'GLFW_PLATFORM_ERROR = Error'PlatformError
+    | v == c'GLFW_FORMAT_UNAVAILABLE = Error'FormatUnavailable
+    | otherwise = error $ "C CInt Error fromC: " ++ show v
+  toC Error'NotInitialized = c'GLFW_NOT_INITIALIZED
+  toC Error'NoCurrentContext = c'GLFW_NO_CURRENT_CONTEXT
+  toC Error'InvalidEnum = c'GLFW_INVALID_ENUM
+  toC Error'InvalidValue = c'GLFW_INVALID_VALUE
+  toC Error'OutOfMemory = c'GLFW_OUT_OF_MEMORY
+  toC Error'ApiUnavailable = c'GLFW_API_UNAVAILABLE
+  toC Error'VersionUnavailable = c'GLFW_VERSION_UNAVAILABLE
+  toC Error'PlatformError = c'GLFW_PLATFORM_ERROR
+  toC Error'FormatUnavailable = c'GLFW_FORMAT_UNAVAILABLE
+
+instance C CInt MonitorState where
+  fromC v
+    | v == c'GLFW_CONNECTED = MonitorState'Connected
+    | v == c'GLFW_DISCONNECTED = MonitorState'Disconnected
+    | otherwise = error $ "C CInt MonitorState fromC: " ++ show v
+  toC MonitorState'Connected = c'GLFW_CONNECTED
+  toC MonitorState'Disconnected = c'GLFW_DISCONNECTED
+
+instance C CInt ContextRobustness where
+  fromC v
+    | v == c'GLFW_NO_ROBUSTNESS = ContextRobustness'NoRobustness
+    | v == c'GLFW_NO_RESET_NOTIFICATION = ContextRobustness'NoResetNotification
+    | v == c'GLFW_LOSE_CONTEXT_ON_RESET = ContextRobustness'LoseContextOnReset
+    | otherwise = error $ "C CInt ContextRobustness fromC: " ++ show v
+  toC ContextRobustness'NoRobustness = c'GLFW_NO_ROBUSTNESS
+  toC ContextRobustness'NoResetNotification = c'GLFW_NO_RESET_NOTIFICATION
+  toC ContextRobustness'LoseContextOnReset = c'GLFW_LOSE_CONTEXT_ON_RESET
+
+instance C CInt ContextReleaseBehavior where
+  fromC v
+    | v == c'GLFW_ANY_RELEASE_BEHAVIOR = ContextReleaseBehavior'Any
+    | v == c'GLFW_RELEASE_BEHAVIOR_NONE = ContextReleaseBehavior'None
+    | v == c'GLFW_RELEASE_BEHAVIOR_FLUSH = ContextReleaseBehavior'Flush
+    | otherwise = error $ "C CInt ContextReleaseBehavior fromC: " ++ show v
+  toC ContextReleaseBehavior'Any = c'GLFW_ANY_RELEASE_BEHAVIOR
+  toC ContextReleaseBehavior'None = c'GLFW_RELEASE_BEHAVIOR_NONE
+  toC ContextReleaseBehavior'Flush = c'GLFW_RELEASE_BEHAVIOR_FLUSH
+
+instance C CInt OpenGLProfile where
+  fromC v
+    | v == c'GLFW_OPENGL_ANY_PROFILE = OpenGLProfile'Any
+    | v == c'GLFW_OPENGL_COMPAT_PROFILE = OpenGLProfile'Compat
+    | v == c'GLFW_OPENGL_CORE_PROFILE = OpenGLProfile'Core
+    | otherwise = error $ "C CInt OpenGLProfile fromC: " ++ show v
+  toC OpenGLProfile'Any = c'GLFW_OPENGL_ANY_PROFILE
+  toC OpenGLProfile'Compat = c'GLFW_OPENGL_COMPAT_PROFILE
+  toC OpenGLProfile'Core = c'GLFW_OPENGL_CORE_PROFILE
+
+instance C CInt ClientAPI where
+  fromC v
+    | v == c'GLFW_NO_API = ClientAPI'NoAPI
+    | v == c'GLFW_OPENGL_API = ClientAPI'OpenGL
+    | v == c'GLFW_OPENGL_ES_API = ClientAPI'OpenGLES
+    | otherwise = error $ "C CInt ClientAPI fromC: " ++ show v
+  toC ClientAPI'NoAPI = c'GLFW_NO_API
+  toC ClientAPI'OpenGL = c'GLFW_OPENGL_API
+  toC ClientAPI'OpenGLES = c'GLFW_OPENGL_ES_API
+
+instance C CInt ContextCreationAPI where
+  fromC v
+    | v == c'GLFW_NATIVE_CONTEXT_API = ContextCreationAPI'Native
+    | v == c'GLFW_EGL_CONTEXT_API = ContextCreationAPI'EGL
+    | otherwise = error $ "C CInt ContextCreationAPI fromC: " ++ show v
+  toC ContextCreationAPI'Native = c'GLFW_NATIVE_CONTEXT_API
+  toC ContextCreationAPI'EGL = c'GLFW_EGL_CONTEXT_API
+
+instance C CInt Key where
+  fromC v
+    | v == c'GLFW_KEY_UNKNOWN = Key'Unknown
+    | v == c'GLFW_KEY_SPACE = Key'Space
+    | v == c'GLFW_KEY_APOSTROPHE = Key'Apostrophe
+    | v == c'GLFW_KEY_COMMA = Key'Comma
+    | v == c'GLFW_KEY_MINUS = Key'Minus
+    | v == c'GLFW_KEY_PERIOD = Key'Period
+    | v == c'GLFW_KEY_SLASH = Key'Slash
+    | v == c'GLFW_KEY_0 = Key'0
+    | v == c'GLFW_KEY_1 = Key'1
+    | v == c'GLFW_KEY_2 = Key'2
+    | v == c'GLFW_KEY_3 = Key'3
+    | v == c'GLFW_KEY_4 = Key'4
+    | v == c'GLFW_KEY_5 = Key'5
+    | v == c'GLFW_KEY_6 = Key'6
+    | v == c'GLFW_KEY_7 = Key'7
+    | v == c'GLFW_KEY_8 = Key'8
+    | v == c'GLFW_KEY_9 = Key'9
+    | v == c'GLFW_KEY_SEMICOLON = Key'Semicolon
+    | v == c'GLFW_KEY_EQUAL = Key'Equal
+    | v == c'GLFW_KEY_A = Key'A
+    | v == c'GLFW_KEY_B = Key'B
+    | v == c'GLFW_KEY_C = Key'C
+    | v == c'GLFW_KEY_D = Key'D
+    | v == c'GLFW_KEY_E = Key'E
+    | v == c'GLFW_KEY_F = Key'F
+    | v == c'GLFW_KEY_G = Key'G
+    | v == c'GLFW_KEY_H = Key'H
+    | v == c'GLFW_KEY_I = Key'I
+    | v == c'GLFW_KEY_J = Key'J
+    | v == c'GLFW_KEY_K = Key'K
+    | v == c'GLFW_KEY_L = Key'L
+    | v == c'GLFW_KEY_M = Key'M
+    | v == c'GLFW_KEY_N = Key'N
+    | v == c'GLFW_KEY_O = Key'O
+    | v == c'GLFW_KEY_P = Key'P
+    | v == c'GLFW_KEY_Q = Key'Q
+    | v == c'GLFW_KEY_R = Key'R
+    | v == c'GLFW_KEY_S = Key'S
+    | v == c'GLFW_KEY_T = Key'T
+    | v == c'GLFW_KEY_U = Key'U
+    | v == c'GLFW_KEY_V = Key'V
+    | v == c'GLFW_KEY_W = Key'W
+    | v == c'GLFW_KEY_X = Key'X
+    | v == c'GLFW_KEY_Y = Key'Y
+    | v == c'GLFW_KEY_Z = Key'Z
+    | v == c'GLFW_KEY_LEFT_BRACKET = Key'LeftBracket
+    | v == c'GLFW_KEY_BACKSLASH = Key'Backslash
+    | v == c'GLFW_KEY_RIGHT_BRACKET = Key'RightBracket
+    | v == c'GLFW_KEY_GRAVE_ACCENT = Key'GraveAccent
+    | v == c'GLFW_KEY_WORLD_1 = Key'World1
+    | v == c'GLFW_KEY_WORLD_2 = Key'World2
+    | v == c'GLFW_KEY_ESCAPE = Key'Escape
+    | v == c'GLFW_KEY_ENTER = Key'Enter
+    | v == c'GLFW_KEY_TAB = Key'Tab
+    | v == c'GLFW_KEY_BACKSPACE = Key'Backspace
+    | v == c'GLFW_KEY_INSERT = Key'Insert
+    | v == c'GLFW_KEY_DELETE = Key'Delete
+    | v == c'GLFW_KEY_RIGHT = Key'Right
+    | v == c'GLFW_KEY_LEFT = Key'Left
+    | v == c'GLFW_KEY_DOWN = Key'Down
+    | v == c'GLFW_KEY_UP = Key'Up
+    | v == c'GLFW_KEY_PAGE_UP = Key'PageUp
+    | v == c'GLFW_KEY_PAGE_DOWN = Key'PageDown
+    | v == c'GLFW_KEY_HOME = Key'Home
+    | v == c'GLFW_KEY_END = Key'End
+    | v == c'GLFW_KEY_CAPS_LOCK = Key'CapsLock
+    | v == c'GLFW_KEY_SCROLL_LOCK = Key'ScrollLock
+    | v == c'GLFW_KEY_NUM_LOCK = Key'NumLock
+    | v == c'GLFW_KEY_PRINT_SCREEN = Key'PrintScreen
+    | v == c'GLFW_KEY_PAUSE = Key'Pause
+    | v == c'GLFW_KEY_F1 = Key'F1
+    | v == c'GLFW_KEY_F2 = Key'F2
+    | v == c'GLFW_KEY_F3 = Key'F3
+    | v == c'GLFW_KEY_F4 = Key'F4
+    | v == c'GLFW_KEY_F5 = Key'F5
+    | v == c'GLFW_KEY_F6 = Key'F6
+    | v == c'GLFW_KEY_F7 = Key'F7
+    | v == c'GLFW_KEY_F8 = Key'F8
+    | v == c'GLFW_KEY_F9 = Key'F9
+    | v == c'GLFW_KEY_F10 = Key'F10
+    | v == c'GLFW_KEY_F11 = Key'F11
+    | v == c'GLFW_KEY_F12 = Key'F12
+    | v == c'GLFW_KEY_F13 = Key'F13
+    | v == c'GLFW_KEY_F14 = Key'F14
+    | v == c'GLFW_KEY_F15 = Key'F15
+    | v == c'GLFW_KEY_F16 = Key'F16
+    | v == c'GLFW_KEY_F17 = Key'F17
+    | v == c'GLFW_KEY_F18 = Key'F18
+    | v == c'GLFW_KEY_F19 = Key'F19
+    | v == c'GLFW_KEY_F20 = Key'F20
+    | v == c'GLFW_KEY_F21 = Key'F21
+    | v == c'GLFW_KEY_F22 = Key'F22
+    | v == c'GLFW_KEY_F23 = Key'F23
+    | v == c'GLFW_KEY_F24 = Key'F24
+    | v == c'GLFW_KEY_F25 = Key'F25
+    | v == c'GLFW_KEY_KP_0 = Key'Pad0
+    | v == c'GLFW_KEY_KP_1 = Key'Pad1
+    | v == c'GLFW_KEY_KP_2 = Key'Pad2
+    | v == c'GLFW_KEY_KP_3 = Key'Pad3
+    | v == c'GLFW_KEY_KP_4 = Key'Pad4
+    | v == c'GLFW_KEY_KP_5 = Key'Pad5
+    | v == c'GLFW_KEY_KP_6 = Key'Pad6
+    | v == c'GLFW_KEY_KP_7 = Key'Pad7
+    | v == c'GLFW_KEY_KP_8 = Key'Pad8
+    | v == c'GLFW_KEY_KP_9 = Key'Pad9
+    | v == c'GLFW_KEY_KP_DECIMAL = Key'PadDecimal
+    | v == c'GLFW_KEY_KP_DIVIDE = Key'PadDivide
+    | v == c'GLFW_KEY_KP_MULTIPLY = Key'PadMultiply
+    | v == c'GLFW_KEY_KP_SUBTRACT = Key'PadSubtract
+    | v == c'GLFW_KEY_KP_ADD = Key'PadAdd
+    | v == c'GLFW_KEY_KP_ENTER = Key'PadEnter
+    | v == c'GLFW_KEY_KP_EQUAL = Key'PadEqual
+    | v == c'GLFW_KEY_LEFT_SHIFT = Key'LeftShift
+    | v == c'GLFW_KEY_LEFT_CONTROL = Key'LeftControl
+    | v == c'GLFW_KEY_LEFT_ALT = Key'LeftAlt
+    | v == c'GLFW_KEY_LEFT_SUPER = Key'LeftSuper
+    | v == c'GLFW_KEY_RIGHT_SHIFT = Key'RightShift
+    | v == c'GLFW_KEY_RIGHT_CONTROL = Key'RightControl
+    | v == c'GLFW_KEY_RIGHT_ALT = Key'RightAlt
+    | v == c'GLFW_KEY_RIGHT_SUPER = Key'RightSuper
+    | v == c'GLFW_KEY_MENU = Key'Menu
+    | otherwise = error $ "C CInt Key fromC: " ++ show v
+  toC Key'Unknown = c'GLFW_KEY_UNKNOWN
+  toC Key'Space = c'GLFW_KEY_SPACE
+  toC Key'Apostrophe = c'GLFW_KEY_APOSTROPHE
+  toC Key'Comma = c'GLFW_KEY_COMMA
+  toC Key'Minus = c'GLFW_KEY_MINUS
+  toC Key'Period = c'GLFW_KEY_PERIOD
+  toC Key'Slash = c'GLFW_KEY_SLASH
+  toC Key'0 = c'GLFW_KEY_0
+  toC Key'1 = c'GLFW_KEY_1
+  toC Key'2 = c'GLFW_KEY_2
+  toC Key'3 = c'GLFW_KEY_3
+  toC Key'4 = c'GLFW_KEY_4
+  toC Key'5 = c'GLFW_KEY_5
+  toC Key'6 = c'GLFW_KEY_6
+  toC Key'7 = c'GLFW_KEY_7
+  toC Key'8 = c'GLFW_KEY_8
+  toC Key'9 = c'GLFW_KEY_9
+  toC Key'Semicolon = c'GLFW_KEY_SEMICOLON
+  toC Key'Equal = c'GLFW_KEY_EQUAL
+  toC Key'A = c'GLFW_KEY_A
+  toC Key'B = c'GLFW_KEY_B
+  toC Key'C = c'GLFW_KEY_C
+  toC Key'D = c'GLFW_KEY_D
+  toC Key'E = c'GLFW_KEY_E
+  toC Key'F = c'GLFW_KEY_F
+  toC Key'G = c'GLFW_KEY_G
+  toC Key'H = c'GLFW_KEY_H
+  toC Key'I = c'GLFW_KEY_I
+  toC Key'J = c'GLFW_KEY_J
+  toC Key'K = c'GLFW_KEY_K
+  toC Key'L = c'GLFW_KEY_L
+  toC Key'M = c'GLFW_KEY_M
+  toC Key'N = c'GLFW_KEY_N
+  toC Key'O = c'GLFW_KEY_O
+  toC Key'P = c'GLFW_KEY_P
+  toC Key'Q = c'GLFW_KEY_Q
+  toC Key'R = c'GLFW_KEY_R
+  toC Key'S = c'GLFW_KEY_S
+  toC Key'T = c'GLFW_KEY_T
+  toC Key'U = c'GLFW_KEY_U
+  toC Key'V = c'GLFW_KEY_V
+  toC Key'W = c'GLFW_KEY_W
+  toC Key'X = c'GLFW_KEY_X
+  toC Key'Y = c'GLFW_KEY_Y
+  toC Key'Z = c'GLFW_KEY_Z
+  toC Key'LeftBracket = c'GLFW_KEY_LEFT_BRACKET
+  toC Key'Backslash = c'GLFW_KEY_BACKSLASH
+  toC Key'RightBracket = c'GLFW_KEY_RIGHT_BRACKET
+  toC Key'GraveAccent = c'GLFW_KEY_GRAVE_ACCENT
+  toC Key'World1 = c'GLFW_KEY_WORLD_1
+  toC Key'World2 = c'GLFW_KEY_WORLD_2
+  toC Key'Escape = c'GLFW_KEY_ESCAPE
+  toC Key'Enter = c'GLFW_KEY_ENTER
+  toC Key'Tab = c'GLFW_KEY_TAB
+  toC Key'Backspace = c'GLFW_KEY_BACKSPACE
+  toC Key'Insert = c'GLFW_KEY_INSERT
+  toC Key'Delete = c'GLFW_KEY_DELETE
+  toC Key'Right = c'GLFW_KEY_RIGHT
+  toC Key'Left = c'GLFW_KEY_LEFT
+  toC Key'Down = c'GLFW_KEY_DOWN
+  toC Key'Up = c'GLFW_KEY_UP
+  toC Key'PageUp = c'GLFW_KEY_PAGE_UP
+  toC Key'PageDown = c'GLFW_KEY_PAGE_DOWN
+  toC Key'Home = c'GLFW_KEY_HOME
+  toC Key'End = c'GLFW_KEY_END
+  toC Key'CapsLock = c'GLFW_KEY_CAPS_LOCK
+  toC Key'ScrollLock = c'GLFW_KEY_SCROLL_LOCK
+  toC Key'NumLock = c'GLFW_KEY_NUM_LOCK
+  toC Key'PrintScreen = c'GLFW_KEY_PRINT_SCREEN
+  toC Key'Pause = c'GLFW_KEY_PAUSE
+  toC Key'F1 = c'GLFW_KEY_F1
+  toC Key'F2 = c'GLFW_KEY_F2
+  toC Key'F3 = c'GLFW_KEY_F3
+  toC Key'F4 = c'GLFW_KEY_F4
+  toC Key'F5 = c'GLFW_KEY_F5
+  toC Key'F6 = c'GLFW_KEY_F6
+  toC Key'F7 = c'GLFW_KEY_F7
+  toC Key'F8 = c'GLFW_KEY_F8
+  toC Key'F9 = c'GLFW_KEY_F9
+  toC Key'F10 = c'GLFW_KEY_F10
+  toC Key'F11 = c'GLFW_KEY_F11
+  toC Key'F12 = c'GLFW_KEY_F12
+  toC Key'F13 = c'GLFW_KEY_F13
+  toC Key'F14 = c'GLFW_KEY_F14
+  toC Key'F15 = c'GLFW_KEY_F15
+  toC Key'F16 = c'GLFW_KEY_F16
+  toC Key'F17 = c'GLFW_KEY_F17
+  toC Key'F18 = c'GLFW_KEY_F18
+  toC Key'F19 = c'GLFW_KEY_F19
+  toC Key'F20 = c'GLFW_KEY_F20
+  toC Key'F21 = c'GLFW_KEY_F21
+  toC Key'F22 = c'GLFW_KEY_F22
+  toC Key'F23 = c'GLFW_KEY_F23
+  toC Key'F24 = c'GLFW_KEY_F24
+  toC Key'F25 = c'GLFW_KEY_F25
+  toC Key'Pad0 = c'GLFW_KEY_KP_0
+  toC Key'Pad1 = c'GLFW_KEY_KP_1
+  toC Key'Pad2 = c'GLFW_KEY_KP_2
+  toC Key'Pad3 = c'GLFW_KEY_KP_3
+  toC Key'Pad4 = c'GLFW_KEY_KP_4
+  toC Key'Pad5 = c'GLFW_KEY_KP_5
+  toC Key'Pad6 = c'GLFW_KEY_KP_6
+  toC Key'Pad7 = c'GLFW_KEY_KP_7
+  toC Key'Pad8 = c'GLFW_KEY_KP_8
+  toC Key'Pad9 = c'GLFW_KEY_KP_9
+  toC Key'PadDecimal = c'GLFW_KEY_KP_DECIMAL
+  toC Key'PadDivide = c'GLFW_KEY_KP_DIVIDE
+  toC Key'PadMultiply = c'GLFW_KEY_KP_MULTIPLY
+  toC Key'PadSubtract = c'GLFW_KEY_KP_SUBTRACT
+  toC Key'PadAdd = c'GLFW_KEY_KP_ADD
+  toC Key'PadEnter = c'GLFW_KEY_KP_ENTER
+  toC Key'PadEqual = c'GLFW_KEY_KP_EQUAL
+  toC Key'LeftShift = c'GLFW_KEY_LEFT_SHIFT
+  toC Key'LeftControl = c'GLFW_KEY_LEFT_CONTROL
+  toC Key'LeftAlt = c'GLFW_KEY_LEFT_ALT
+  toC Key'LeftSuper = c'GLFW_KEY_LEFT_SUPER
+  toC Key'RightShift = c'GLFW_KEY_RIGHT_SHIFT
+  toC Key'RightControl = c'GLFW_KEY_RIGHT_CONTROL
+  toC Key'RightAlt = c'GLFW_KEY_RIGHT_ALT
+  toC Key'RightSuper = c'GLFW_KEY_RIGHT_SUPER
+  toC Key'Menu = c'GLFW_KEY_MENU
+
+instance C CInt KeyState where
+  fromC v
+    | v == c'GLFW_PRESS = KeyState'Pressed
+    | v == c'GLFW_RELEASE = KeyState'Released
+    | v == c'GLFW_REPEAT = KeyState'Repeating
+    | otherwise = error $ "C CInt KeyState fromC: " ++ show v
+  toC KeyState'Pressed = c'GLFW_PRESS
+  toC KeyState'Released = c'GLFW_RELEASE
+  toC KeyState'Repeating = c'GLFW_REPEAT
+
+instance C CInt Joystick where
+  fromC v
+    | v == c'GLFW_JOYSTICK_1 = Joystick'1
+    | v == c'GLFW_JOYSTICK_2 = Joystick'2
+    | v == c'GLFW_JOYSTICK_3 = Joystick'3
+    | v == c'GLFW_JOYSTICK_4 = Joystick'4
+    | v == c'GLFW_JOYSTICK_5 = Joystick'5
+    | v == c'GLFW_JOYSTICK_6 = Joystick'6
+    | v == c'GLFW_JOYSTICK_7 = Joystick'7
+    | v == c'GLFW_JOYSTICK_8 = Joystick'8
+    | v == c'GLFW_JOYSTICK_9 = Joystick'9
+    | v == c'GLFW_JOYSTICK_10 = Joystick'10
+    | v == c'GLFW_JOYSTICK_11 = Joystick'11
+    | v == c'GLFW_JOYSTICK_12 = Joystick'12
+    | v == c'GLFW_JOYSTICK_13 = Joystick'13
+    | v == c'GLFW_JOYSTICK_14 = Joystick'14
+    | v == c'GLFW_JOYSTICK_15 = Joystick'15
+    | v == c'GLFW_JOYSTICK_16 = Joystick'16
+    | otherwise = error $ "C CInt Joystick fromC: " ++ show v
+  toC Joystick'1 = c'GLFW_JOYSTICK_1
+  toC Joystick'2 = c'GLFW_JOYSTICK_2
+  toC Joystick'3 = c'GLFW_JOYSTICK_3
+  toC Joystick'4 = c'GLFW_JOYSTICK_4
+  toC Joystick'5 = c'GLFW_JOYSTICK_5
+  toC Joystick'6 = c'GLFW_JOYSTICK_6
+  toC Joystick'7 = c'GLFW_JOYSTICK_7
+  toC Joystick'8 = c'GLFW_JOYSTICK_8
+  toC Joystick'9 = c'GLFW_JOYSTICK_9
+  toC Joystick'10 = c'GLFW_JOYSTICK_10
+  toC Joystick'11 = c'GLFW_JOYSTICK_11
+  toC Joystick'12 = c'GLFW_JOYSTICK_12
+  toC Joystick'13 = c'GLFW_JOYSTICK_13
+  toC Joystick'14 = c'GLFW_JOYSTICK_14
+  toC Joystick'15 = c'GLFW_JOYSTICK_15
+  toC Joystick'16 = c'GLFW_JOYSTICK_16
+
+instance C CUChar JoystickButtonState where
+  fromC v
+    | v == c'GLFW_PRESS = JoystickButtonState'Pressed
+    | v == c'GLFW_RELEASE = JoystickButtonState'Released
+    | otherwise = error $ "C CUChar JoystickButtonState fromC: " ++ show v
+  toC JoystickButtonState'Pressed = c'GLFW_PRESS
+  toC JoystickButtonState'Released = c'GLFW_RELEASE
+
+instance C CInt JoystickState where
+  fromC v
+    | v == c'GLFW_CONNECTED = JoystickState'Connected
+    | v == c'GLFW_DISCONNECTED = JoystickState'Disconnected
+    | otherwise = error $ "C CInt JoystickState fromC: " ++ show v
+  toC JoystickState'Connected = c'GLFW_CONNECTED
+  toC JoystickState'Disconnected = c'GLFW_DISCONNECTED
+
+instance C CInt MouseButton where
+  fromC v
+    | v == c'GLFW_MOUSE_BUTTON_1 = MouseButton'1
+    | v == c'GLFW_MOUSE_BUTTON_2 = MouseButton'2
+    | v == c'GLFW_MOUSE_BUTTON_3 = MouseButton'3
+    | v == c'GLFW_MOUSE_BUTTON_4 = MouseButton'4
+    | v == c'GLFW_MOUSE_BUTTON_5 = MouseButton'5
+    | v == c'GLFW_MOUSE_BUTTON_6 = MouseButton'6
+    | v == c'GLFW_MOUSE_BUTTON_7 = MouseButton'7
+    | v == c'GLFW_MOUSE_BUTTON_8 = MouseButton'8
+    | otherwise = error $ "C CInt MouseButton fromC: " ++ show v
+  toC MouseButton'1 = c'GLFW_MOUSE_BUTTON_1
+  toC MouseButton'2 = c'GLFW_MOUSE_BUTTON_2
+  toC MouseButton'3 = c'GLFW_MOUSE_BUTTON_3
+  toC MouseButton'4 = c'GLFW_MOUSE_BUTTON_4
+  toC MouseButton'5 = c'GLFW_MOUSE_BUTTON_5
+  toC MouseButton'6 = c'GLFW_MOUSE_BUTTON_6
+  toC MouseButton'7 = c'GLFW_MOUSE_BUTTON_7
+  toC MouseButton'8 = c'GLFW_MOUSE_BUTTON_8
+
+instance C CInt MouseButtonState where
+  fromC v
+    | v == c'GLFW_PRESS = MouseButtonState'Pressed
+    | v == c'GLFW_RELEASE = MouseButtonState'Released
+    | otherwise = error $ "C CInt MouseButtonState fromC: " ++ show v
+  toC MouseButtonState'Pressed = c'GLFW_PRESS
+  toC MouseButtonState'Released = c'GLFW_RELEASE
+
+instance C CInt CursorState where
+  fromC v
+    | v == c'GLFW_TRUE = CursorState'InWindow
+    | v == c'GLFW_FALSE = CursorState'NotInWindow
+    | otherwise = error $ "C CInt CursorState fromC: " ++ show v
+  toC CursorState'InWindow = c'GLFW_TRUE
+  toC CursorState'NotInWindow = c'GLFW_FALSE
+
+instance C CInt CursorInputMode where
+  fromC v
+    | v == c'GLFW_CURSOR_NORMAL = CursorInputMode'Normal
+    | v == c'GLFW_CURSOR_HIDDEN = CursorInputMode'Hidden
+    | v == c'GLFW_CURSOR_DISABLED = CursorInputMode'Disabled
+    | otherwise = error $ "C CInt CursorInputMode fromC: " ++ show v
+  toC CursorInputMode'Normal = c'GLFW_CURSOR_NORMAL
+  toC CursorInputMode'Hidden = c'GLFW_CURSOR_HIDDEN
+  toC CursorInputMode'Disabled = c'GLFW_CURSOR_DISABLED
+
+instance C CInt StickyKeysInputMode where
+  fromC v
+    | v == c'GLFW_TRUE = StickyKeysInputMode'Enabled
+    | v == c'GLFW_FALSE = StickyKeysInputMode'Disabled
+    | otherwise = error $ "C CInt StickyKeysInputMode fromC: " ++ show v
+  toC StickyKeysInputMode'Enabled = c'GLFW_TRUE
+  toC StickyKeysInputMode'Disabled = c'GLFW_FALSE
+
+instance C CInt StickyMouseButtonsInputMode where
+  fromC v
+    | v == c'GLFW_TRUE = StickyMouseButtonsInputMode'Enabled
+    | v == c'GLFW_FALSE = StickyMouseButtonsInputMode'Disabled
+    | otherwise = error $ "C CInt StickyMouseButtonsInputMode fromC: " ++ show v
+  toC StickyMouseButtonsInputMode'Enabled = c'GLFW_TRUE
+  toC StickyMouseButtonsInputMode'Disabled = c'GLFW_FALSE
+
+--------------------------------------------------------------------------------
+
 {-# ANN module "HLint: ignore Use camelCase" #-}
Graphics/UI/GLFW/Types.hs view
@@ -1,530 +1,530 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE StandaloneDeriving #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}---- | The types of the package. This module is considered "internal", and the--- types are re-exported from Graphics.UI.GLFW as necessary.-module Graphics.UI.GLFW.Types where------------------------------------------------------------------------------------import Control.DeepSeq  (NFData)-import Data.Data        (Data)-import Data.IORef       (IORef)-import Data.Typeable    (Typeable)-import Data.Word        (Word8)-import Foreign.Ptr      (Ptr)-import Foreign.C.Types  (CUChar(..))-import GHC.Generics--import Bindings.GLFW------------------------------------------------------------------------------------- Error handling---- | An enum for one of the <http://www.glfw.org/docs/3.2/group__errors.html#ga196e125ef261d94184e2b55c05762f14 GLFW error codes>.-data Error =-    Error'NotInitialized -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga2374ee02c177f12e1fa76ff3ed15e14a doc>-  | Error'NoCurrentContext -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gaa8290386e9528ccb9e42a3a4e16fc0d0 doc>-  | Error'InvalidEnum -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga76f6bb9c4eea73db675f096b404593ce doc>-  | Error'InvalidValue -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gaaf2ef9aa8202c2b82ac2d921e554c687 doc>-  | Error'OutOfMemory -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga9023953a2bcb98c2906afd071d21ee7f doc>-  | Error'ApiUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga56882b290db23261cc6c053c40c2d08e doc>-  | Error'VersionUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gad16c5565b4a69f9c2a9ac2c0dbc89462 doc>-  | Error'PlatformError -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gad44162d78100ea5e87cdd38426b8c7a1 doc>-  | Error'FormatUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga196e125ef261d94184e2b55c05762f14 doc>-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData Error------------------------------------------------------------------------------------- Initialization and version information---- | The library version of the GLFW implementation in use.--- See <http://www.glfw.org/docs/3.2/intro.html#intro_version Version Management>-data Version = Version-  { versionMajor    :: Int-  , versionMinor    :: Int-  , versionRevision :: Int-  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData Version------------------------------------------------------------------------------------- Monitor handling---- | Represents a physical monitor that's currently connected.--- See the <http://www.glfw.org/docs/3.2/monitor.html Monitor Guide>-newtype Monitor = Monitor-  { unMonitor :: Ptr C'GLFWmonitor-  } deriving (Data, Eq, Ord, Show, Typeable, Generic)---- | Part of the 'MonitorCallback', for when a monitor gets connected or disconnected.-data MonitorState =-    MonitorState'Connected-  | MonitorState'Disconnected-  deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData MonitorState---- | See <http://www.glfw.org/docs/3.2/monitor.html#monitor_modes Video Modes>-data VideoMode = VideoMode-  { videoModeWidth       :: Int-  , videoModeHeight      :: Int-  , videoModeRedBits     :: Int-  , videoModeGreenBits   :: Int-  , videoModeBlueBits    :: Int-  , videoModeRefreshRate :: Int-  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData VideoMode---- | Lets you adjust the gamma of a monitor. To ensure that only valid values are created, use 'makeGammaRamp'.--- See <http://www.glfw.org/docs/3.2/monitor.html#monitor_gamma Gamma Ramp>.-data GammaRamp = GammaRamp-  -- NOTE: It would be bad to give clients a way to construct invalid gamma ramps-  -- with lists of unequal length, so this constructor should not be exported.-  { gammaRampRed   :: [Int]-  , gammaRampGreen :: [Int]-  , gammaRampBlue  :: [Int]-  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData GammaRamp---- | Smart constructor for a 'GammaRamp'.-makeGammaRamp :: [Int] -> [Int] -> [Int] -> Maybe GammaRamp-makeGammaRamp rs gs bs-    | lengthsEqual = Just $ GammaRamp rs gs bs-    | otherwise    = Nothing-  where-    lengthsEqual =-      let rsl = length rs-          gsl = length gs-          bsl = length bs-      in rsl == gsl && gsl == bsl------------------------------------------------------------------------------------- Window handling---- | Collects all the callbacks that can be associated with a Window into a single place.-data WindowCallbacks = WindowCallbacks-  { storedCharFun             :: IORef C'GLFWcharfun-  , storedCharModsFun         :: IORef C'GLFWcharmodsfun-  , storedCursorEnterFun      :: IORef C'GLFWcursorenterfun-  , storedCursorPosFun        :: IORef C'GLFWcursorposfun-  , storedFramebufferSizeFun  :: IORef C'GLFWframebuffersizefun-  , storedKeyFun              :: IORef C'GLFWkeyfun-  , storedMouseButtonFun      :: IORef C'GLFWmousebuttonfun-  , storedScrollFun           :: IORef C'GLFWscrollfun-  , storedWindowCloseFun      :: IORef C'GLFWwindowclosefun-  , storedWindowFocusFun      :: IORef C'GLFWwindowfocusfun-  , storedWindowIconifyFun    :: IORef C'GLFWwindowiconifyfun-  , storedWindowPosFun        :: IORef C'GLFWwindowposfun-  , storedWindowRefreshFun    :: IORef C'GLFWwindowrefreshfun-  , storedWindowSizeFun       :: IORef C'GLFWwindowsizefun-  , storedDropFun             :: IORef C'GLFWdropfun-  }---- | Reprisents a GLFW window value.--- See the <http://www.glfw.org/docs/3.2/window.html Window Guide>-newtype Window = Window-  { unWindow :: Ptr C'GLFWwindow-  } deriving (Data, Eq, Ord, Show, Typeable, Generic)---- | Lets you set various window hints before creating a 'Window'.--- See <http://www.glfw.org/docs/3.2/window.html#window_hints Window Hints>,--- particularly <http://www.glfw.org/docs/3.2/window.html#window_hints_values Supported and Default Values>.-data WindowHint =-    WindowHint'Resizable              Bool-  | WindowHint'Visible                Bool-  | WindowHint'Decorated              Bool-  | WindowHint'RedBits                (Maybe Int)-  | WindowHint'GreenBits              (Maybe Int)-  | WindowHint'BlueBits               (Maybe Int)-  | WindowHint'AlphaBits              (Maybe Int)-  | WindowHint'DepthBits              (Maybe Int)-  | WindowHint'StencilBits            (Maybe Int)-  | WindowHint'AccumRedBits           (Maybe Int)-  | WindowHint'AccumGreenBits         (Maybe Int)-  | WindowHint'AccumBlueBits          (Maybe Int)-  | WindowHint'AccumAlphaBits         (Maybe Int)-  | WindowHint'AuxBuffers             (Maybe Int)-  | WindowHint'Samples                (Maybe Int)-  | WindowHint'RefreshRate            (Maybe Int)-  | WindowHint'DoubleBuffer           Bool-  | WindowHint'Stereo                 Bool-  | WindowHint'sRGBCapable            Bool-  | WindowHint'Floating               Bool-  | WindowHint'Focused                Bool-  | WindowHint'Maximized              Bool-  | WindowHint'AutoIconify            Bool-  | WindowHint'ClientAPI              ClientAPI-  | WindowHint'ContextCreationAPI     ContextCreationAPI-  | WindowHint'ContextVersionMajor    Int-  | WindowHint'ContextVersionMinor    Int-  | WindowHint'ContextRobustness      ContextRobustness-  | WindowHint'ContextReleaseBehavior ContextReleaseBehavior-  | WindowHint'ContextNoError         Bool-  | WindowHint'OpenGLForwardCompat    Bool-  | WindowHint'OpenGLDebugContext     Bool-  | WindowHint'OpenGLProfile          OpenGLProfile-  deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData WindowHint---- | The OpenGL robustness strategy.-data ContextRobustness =-    ContextRobustness'NoRobustness-  | ContextRobustness'NoResetNotification-  | ContextRobustness'LoseContextOnReset-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData ContextRobustness---- | The OpenGL profile.-data OpenGLProfile =-    OpenGLProfile'Any-  | OpenGLProfile'Compat-  | OpenGLProfile'Core-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData OpenGLProfile---- | The type of OpenGL to create a context for.-data ClientAPI =-    ClientAPI'NoAPI-  | ClientAPI'OpenGL-  | ClientAPI'OpenGLES-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData ClientAPI---- | The type of API to use for context creation.--- See the <http://www.glfw.org/docs/latest/window_guide.html Window Guide> for--- more information.------ This is a hard constraint. If no client API is requested, this hint is--- ignored. Best practice is to stick to one API or the other, otherwise may--- segfault on Linux. OS X does not support the EGL API and will fail if this--- hint is used.-data ContextCreationAPI-  = ContextCreationAPI'Native-  | ContextCreationAPI'EGL-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData ContextCreationAPI---- | The context release behavior.--- See the <http://www.glfw.org/docs/latest/window_guide.html Window Guide> for--- more information.------ Context release behaviors are described in detail by the--- <https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_context_flush_control.txt KHR_context_flush_control>--- extension.-data ContextReleaseBehavior-  = ContextReleaseBehavior'Any-  | ContextReleaseBehavior'None-  | ContextReleaseBehavior'Flush-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData ContextReleaseBehavior------------------------------------------------------------------------------------- Input handling---- | Part of the <http://www.glfw.org/docs/3.2/input.html#input_keyboard Keyboard Input> system.-data Key =-    Key'Unknown-  | Key'Space-  | Key'Apostrophe-  | Key'Comma-  | Key'Minus-  | Key'Period-  | Key'Slash-  | Key'0-  | Key'1-  | Key'2-  | Key'3-  | Key'4-  | Key'5-  | Key'6-  | Key'7-  | Key'8-  | Key'9-  | Key'Semicolon-  | Key'Equal-  | Key'A-  | Key'B-  | Key'C-  | Key'D-  | Key'E-  | Key'F-  | Key'G-  | Key'H-  | Key'I-  | Key'J-  | Key'K-  | Key'L-  | Key'M-  | Key'N-  | Key'O-  | Key'P-  | Key'Q-  | Key'R-  | Key'S-  | Key'T-  | Key'U-  | Key'V-  | Key'W-  | Key'X-  | Key'Y-  | Key'Z-  | Key'LeftBracket-  | Key'Backslash-  | Key'RightBracket-  | Key'GraveAccent-  | Key'World1-  | Key'World2-  | Key'Escape-  | Key'Enter-  | Key'Tab-  | Key'Backspace-  | Key'Insert-  | Key'Delete-  | Key'Right-  | Key'Left-  | Key'Down-  | Key'Up-  | Key'PageUp-  | Key'PageDown-  | Key'Home-  | Key'End-  | Key'CapsLock-  | Key'ScrollLock-  | Key'NumLock-  | Key'PrintScreen-  | Key'Pause-  | Key'F1-  | Key'F2-  | Key'F3-  | Key'F4-  | Key'F5-  | Key'F6-  | Key'F7-  | Key'F8-  | Key'F9-  | Key'F10-  | Key'F11-  | Key'F12-  | Key'F13-  | Key'F14-  | Key'F15-  | Key'F16-  | Key'F17-  | Key'F18-  | Key'F19-  | Key'F20-  | Key'F21-  | Key'F22-  | Key'F23-  | Key'F24-  | Key'F25-  | Key'Pad0-  | Key'Pad1-  | Key'Pad2-  | Key'Pad3-  | Key'Pad4-  | Key'Pad5-  | Key'Pad6-  | Key'Pad7-  | Key'Pad8-  | Key'Pad9-  | Key'PadDecimal-  | Key'PadDivide-  | Key'PadMultiply-  | Key'PadSubtract-  | Key'PadAdd-  | Key'PadEnter-  | Key'PadEqual-  | Key'LeftShift-  | Key'LeftControl-  | Key'LeftAlt-  | Key'LeftSuper-  | Key'RightShift-  | Key'RightControl-  | Key'RightAlt-  | Key'RightSuper-  | Key'Menu-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData Key---- | The state of an individual key when 'getKey' is called.-data KeyState =-    KeyState'Pressed-  | KeyState'Released-  | KeyState'Repeating-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData KeyState---- | For use with the <http://www.glfw.org/docs/3.2/input.html#joystick Joystick Input> system.-data Joystick =-    Joystick'1-  | Joystick'2-  | Joystick'3-  | Joystick'4-  | Joystick'5-  | Joystick'6-  | Joystick'7-  | Joystick'8-  | Joystick'9-  | Joystick'10-  | Joystick'11-  | Joystick'12-  | Joystick'13-  | Joystick'14-  | Joystick'15-  | Joystick'16-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData Joystick---- | If a given joystick button is pressed or not when 'getJoystickButtons' is called.-data JoystickButtonState =-    JoystickButtonState'Pressed-  | JoystickButtonState'Released-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData JoystickButtonState---- | Part of the 'JoystickCallback', for when a monitor gets connected or disconnected.-data JoystickState-  = JoystickState'Connected-  | JoystickState'Disconnected-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData JoystickState---- | Part of the <http://www.glfw.org/docs/3.2/input.html#input_mouse Mouse Input> system.-data MouseButton =-    MouseButton'1-  | MouseButton'2-  | MouseButton'3-  | MouseButton'4-  | MouseButton'5-  | MouseButton'6-  | MouseButton'7-  | MouseButton'8-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData MouseButton---- | If the mouse button is pressed or not when 'getMouseButton' is called.-data MouseButtonState =-    MouseButtonState'Pressed-  | MouseButtonState'Released-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData MouseButtonState---- | If the mouse's cursor is in the window or not.-data CursorState =-    CursorState'InWindow-  | CursorState'NotInWindow-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData CursorState---- | Allows for special forms of mouse input.--- See <http://www.glfw.org/docs/3.2/input.html#cursor_mode Cursor Modes>-data CursorInputMode =-    CursorInputMode'Normal-  | CursorInputMode'Hidden-  | CursorInputMode'Disabled-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData CursorInputMode---- | When sticky keys is enabled, once a key is pressed it will remain pressed--- at least until the state is polled with 'getKey'. After that, if the key has--- been released it will switch back to released. This helps prevent problems--- with low-resolution polling missing key pressed. Note that use of the--- callbacks to avoid this problem the the recommended route, and this is just--- for a fallback.-data StickyKeysInputMode =-    StickyKeysInputMode'Enabled-  | StickyKeysInputMode'Disabled-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData StickyKeysInputMode---- | This is the mouse version of "StickyKeysInputMode".-data StickyMouseButtonsInputMode =-    StickyMouseButtonsInputMode'Enabled-  | StickyMouseButtonsInputMode'Disabled-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData StickyMouseButtonsInputMode---- | Modifier keys that were pressed as part of another keypress event.-data ModifierKeys = ModifierKeys-  { modifierKeysShift   :: Bool-  , modifierKeysControl :: Bool-  , modifierKeysAlt     :: Bool-  , modifierKeysSuper   :: Bool-  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData ModifierKeys------------------------------------------------------------------------------------- 3.1 Additions-----------------------------------------------------------------------------------deriving instance Data CUChar---- | GLFW image data, for setting up custom mouse cursor appearnaces.-data Image = Image-  { imageWidth  :: Int-  , imageHeight :: Int-  , imagePixels :: [CUChar]-  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)---- | Create an image given the function to generate 8-bit RGBA values based on--- the pixel location.-mkImage :: Int -> Int -> (Int -> Int -> (Word8, Word8, Word8, Word8)) -> Image-mkImage width height gen = Image-  { imageWidth = width-  , imageHeight = height-  , imagePixels = [ CUChar channel | y <- [0..(height - 1)]-                                   , x <- [0..(width - 1)]-                                   , (r, g, b, a) <- [gen x y]-                                   , channel <- [r, g, b, a]-                  ]-  }--instance NFData Image---- | Reprisents a GLFW cursor.-newtype Cursor = Cursor-  { unCursor :: Ptr C'GLFWcursor-  } deriving (Data, Eq, Ord, Show, Typeable, Generic)---- | Lets you use one of the standard cursor appearnaces that the local--- system theme provides for.--- See <http://www.glfw.org/docs/3.2/input.html#cursor_standard Standard Cursor Creation>.-data StandardCursorShape =-    StandardCursorShape'Arrow-  | StandardCursorShape'IBeam-  | StandardCursorShape'Crosshair-  | StandardCursorShape'Hand-  | StandardCursorShape'HResize-  | StandardCursorShape'VResize-  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)--instance NFData StandardCursorShape------------------------------------------------------------------------------------{-# ANN module "HLint: ignore Use camelCase" #-}+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE DeriveGeneric #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+
+-- | The types of the package. This module is considered "internal", and the
+-- types are re-exported from Graphics.UI.GLFW as necessary.
+module Graphics.UI.GLFW.Types where
+
+--------------------------------------------------------------------------------
+
+import Control.DeepSeq  (NFData)
+import Data.Data        (Data)
+import Data.IORef       (IORef)
+import Data.Typeable    (Typeable)
+import Data.Word        (Word8)
+import Foreign.Ptr      (Ptr)
+import Foreign.C.Types  (CUChar(..))
+import GHC.Generics
+
+import Bindings.GLFW
+
+--------------------------------------------------------------------------------
+-- Error handling
+
+-- | An enum for one of the <http://www.glfw.org/docs/3.2/group__errors.html#ga196e125ef261d94184e2b55c05762f14 GLFW error codes>.
+data Error =
+    Error'NotInitialized -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga2374ee02c177f12e1fa76ff3ed15e14a doc>
+  | Error'NoCurrentContext -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gaa8290386e9528ccb9e42a3a4e16fc0d0 doc>
+  | Error'InvalidEnum -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga76f6bb9c4eea73db675f096b404593ce doc>
+  | Error'InvalidValue -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gaaf2ef9aa8202c2b82ac2d921e554c687 doc>
+  | Error'OutOfMemory -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga9023953a2bcb98c2906afd071d21ee7f doc>
+  | Error'ApiUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga56882b290db23261cc6c053c40c2d08e doc>
+  | Error'VersionUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gad16c5565b4a69f9c2a9ac2c0dbc89462 doc>
+  | Error'PlatformError -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#gad44162d78100ea5e87cdd38426b8c7a1 doc>
+  | Error'FormatUnavailable -- ^ <http://www.glfw.org/docs/3.2/group__errors.html#ga196e125ef261d94184e2b55c05762f14 doc>
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData Error
+
+--------------------------------------------------------------------------------
+-- Initialization and version information
+
+-- | The library version of the GLFW implementation in use.
+-- See <http://www.glfw.org/docs/3.2/intro.html#intro_version Version Management>
+data Version = Version
+  { versionMajor    :: {-# UNPACK #-} !Int
+  , versionMinor    :: {-# UNPACK #-} !Int
+  , versionRevision :: {-# UNPACK #-} !Int
+  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData Version
+
+--------------------------------------------------------------------------------
+-- Monitor handling
+
+-- | Represents a physical monitor that's currently connected.
+-- See the <http://www.glfw.org/docs/3.2/monitor.html Monitor Guide>
+newtype Monitor = Monitor
+  { unMonitor :: Ptr C'GLFWmonitor
+  } deriving (Data, Eq, Ord, Show, Typeable, Generic)
+
+-- | Part of the 'MonitorCallback', for when a monitor gets connected or disconnected.
+data MonitorState =
+    MonitorState'Connected
+  | MonitorState'Disconnected
+  deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData MonitorState
+
+-- | See <http://www.glfw.org/docs/3.2/monitor.html#monitor_modes Video Modes>
+data VideoMode = VideoMode
+  { videoModeWidth       :: {-# UNPACK #-} !Int
+  , videoModeHeight      :: {-# UNPACK #-} !Int
+  , videoModeRedBits     :: {-# UNPACK #-} !Int
+  , videoModeGreenBits   :: {-# UNPACK #-} !Int
+  , videoModeBlueBits    :: {-# UNPACK #-} !Int
+  , videoModeRefreshRate :: {-# UNPACK #-} !Int
+  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData VideoMode
+
+-- | Lets you adjust the gamma of a monitor. To ensure that only valid values are created, use 'makeGammaRamp'.
+-- See <http://www.glfw.org/docs/3.2/monitor.html#monitor_gamma Gamma Ramp>.
+data GammaRamp = GammaRamp
+  -- NOTE: It would be bad to give clients a way to construct invalid gamma ramps
+  -- with lists of unequal length, so this constructor should not be exported.
+  { gammaRampRed   :: [Int]
+  , gammaRampGreen :: [Int]
+  , gammaRampBlue  :: [Int]
+  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData GammaRamp
+
+-- | Smart constructor for a 'GammaRamp'.
+makeGammaRamp :: [Int] -> [Int] -> [Int] -> Maybe GammaRamp
+makeGammaRamp rs gs bs
+    | lengthsEqual = Just $ GammaRamp rs gs bs
+    | otherwise    = Nothing
+  where
+    lengthsEqual =
+      let rsl = length rs
+          gsl = length gs
+          bsl = length bs
+      in rsl == gsl && gsl == bsl
+
+--------------------------------------------------------------------------------
+-- Window handling
+
+-- | Collects all the callbacks that can be associated with a Window into a single place.
+data WindowCallbacks = WindowCallbacks
+  { storedCharFun             :: !(IORef C'GLFWcharfun)
+  , storedCharModsFun         :: !(IORef C'GLFWcharmodsfun)
+  , storedCursorEnterFun      :: !(IORef C'GLFWcursorenterfun)
+  , storedCursorPosFun        :: !(IORef C'GLFWcursorposfun)
+  , storedFramebufferSizeFun  :: !(IORef C'GLFWframebuffersizefun)
+  , storedKeyFun              :: !(IORef C'GLFWkeyfun)
+  , storedMouseButtonFun      :: !(IORef C'GLFWmousebuttonfun)
+  , storedScrollFun           :: !(IORef C'GLFWscrollfun)
+  , storedWindowCloseFun      :: !(IORef C'GLFWwindowclosefun)
+  , storedWindowFocusFun      :: !(IORef C'GLFWwindowfocusfun)
+  , storedWindowIconifyFun    :: !(IORef C'GLFWwindowiconifyfun)
+  , storedWindowPosFun        :: !(IORef C'GLFWwindowposfun)
+  , storedWindowRefreshFun    :: !(IORef C'GLFWwindowrefreshfun)
+  , storedWindowSizeFun       :: !(IORef C'GLFWwindowsizefun)
+  , storedDropFun             :: !(IORef C'GLFWdropfun)
+  }
+
+-- | Reprisents a GLFW window value.
+-- See the <http://www.glfw.org/docs/3.2/window.html Window Guide>
+newtype Window = Window
+  { unWindow :: Ptr C'GLFWwindow
+  } deriving (Data, Eq, Ord, Show, Typeable, Generic)
+
+-- | Lets you set various window hints before creating a 'Window'.
+-- See <http://www.glfw.org/docs/3.2/window.html#window_hints Window Hints>,
+-- particularly <http://www.glfw.org/docs/3.2/window.html#window_hints_values Supported and Default Values>.
+data WindowHint =
+    WindowHint'Resizable              !Bool
+  | WindowHint'Visible                !Bool
+  | WindowHint'Decorated              !Bool
+  | WindowHint'RedBits                !(Maybe Int)
+  | WindowHint'GreenBits              !(Maybe Int)
+  | WindowHint'BlueBits               !(Maybe Int)
+  | WindowHint'AlphaBits              !(Maybe Int)
+  | WindowHint'DepthBits              !(Maybe Int)
+  | WindowHint'StencilBits            !(Maybe Int)
+  | WindowHint'AccumRedBits           !(Maybe Int)
+  | WindowHint'AccumGreenBits         !(Maybe Int)
+  | WindowHint'AccumBlueBits          !(Maybe Int)
+  | WindowHint'AccumAlphaBits         !(Maybe Int)
+  | WindowHint'AuxBuffers             !(Maybe Int)
+  | WindowHint'Samples                !(Maybe Int)
+  | WindowHint'RefreshRate            !(Maybe Int)
+  | WindowHint'DoubleBuffer           !Bool
+  | WindowHint'Stereo                 !Bool
+  | WindowHint'sRGBCapable            !Bool
+  | WindowHint'Floating               !Bool
+  | WindowHint'Focused                !Bool
+  | WindowHint'Maximized              !Bool
+  | WindowHint'AutoIconify            !Bool
+  | WindowHint'ClientAPI              !ClientAPI
+  | WindowHint'ContextCreationAPI     !ContextCreationAPI
+  | WindowHint'ContextVersionMajor    {-# UNPACK #-} !Int
+  | WindowHint'ContextVersionMinor    {-# UNPACK #-} !Int
+  | WindowHint'ContextRobustness      !ContextRobustness
+  | WindowHint'ContextReleaseBehavior !ContextReleaseBehavior
+  | WindowHint'ContextNoError         !Bool
+  | WindowHint'OpenGLForwardCompat    !Bool
+  | WindowHint'OpenGLDebugContext     !Bool
+  | WindowHint'OpenGLProfile          !OpenGLProfile
+  deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData WindowHint
+
+-- | The OpenGL robustness strategy.
+data ContextRobustness =
+    ContextRobustness'NoRobustness
+  | ContextRobustness'NoResetNotification
+  | ContextRobustness'LoseContextOnReset
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData ContextRobustness
+
+-- | The OpenGL profile.
+data OpenGLProfile =
+    OpenGLProfile'Any
+  | OpenGLProfile'Compat
+  | OpenGLProfile'Core
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData OpenGLProfile
+
+-- | The type of OpenGL to create a context for.
+data ClientAPI =
+    ClientAPI'NoAPI
+  | ClientAPI'OpenGL
+  | ClientAPI'OpenGLES
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData ClientAPI
+
+-- | The type of API to use for context creation.
+-- See the <http://www.glfw.org/docs/latest/window_guide.html Window Guide> for
+-- more information.
+--
+-- This is a hard constraint. If no client API is requested, this hint is
+-- ignored. Best practice is to stick to one API or the other, otherwise may
+-- segfault on Linux. OS X does not support the EGL API and will fail if this
+-- hint is used.
+data ContextCreationAPI
+  = ContextCreationAPI'Native
+  | ContextCreationAPI'EGL
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData ContextCreationAPI
+
+-- | The context release behavior.
+-- See the <http://www.glfw.org/docs/latest/window_guide.html Window Guide> for
+-- more information.
+--
+-- Context release behaviors are described in detail by the
+-- <https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_context_flush_control.txt KHR_context_flush_control>
+-- extension.
+data ContextReleaseBehavior
+  = ContextReleaseBehavior'Any
+  | ContextReleaseBehavior'None
+  | ContextReleaseBehavior'Flush
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData ContextReleaseBehavior
+
+--------------------------------------------------------------------------------
+-- Input handling
+
+-- | Part of the <http://www.glfw.org/docs/3.2/input.html#input_keyboard Keyboard Input> system.
+data Key =
+    Key'Unknown
+  | Key'Space
+  | Key'Apostrophe
+  | Key'Comma
+  | Key'Minus
+  | Key'Period
+  | Key'Slash
+  | Key'0
+  | Key'1
+  | Key'2
+  | Key'3
+  | Key'4
+  | Key'5
+  | Key'6
+  | Key'7
+  | Key'8
+  | Key'9
+  | Key'Semicolon
+  | Key'Equal
+  | Key'A
+  | Key'B
+  | Key'C
+  | Key'D
+  | Key'E
+  | Key'F
+  | Key'G
+  | Key'H
+  | Key'I
+  | Key'J
+  | Key'K
+  | Key'L
+  | Key'M
+  | Key'N
+  | Key'O
+  | Key'P
+  | Key'Q
+  | Key'R
+  | Key'S
+  | Key'T
+  | Key'U
+  | Key'V
+  | Key'W
+  | Key'X
+  | Key'Y
+  | Key'Z
+  | Key'LeftBracket
+  | Key'Backslash
+  | Key'RightBracket
+  | Key'GraveAccent
+  | Key'World1
+  | Key'World2
+  | Key'Escape
+  | Key'Enter
+  | Key'Tab
+  | Key'Backspace
+  | Key'Insert
+  | Key'Delete
+  | Key'Right
+  | Key'Left
+  | Key'Down
+  | Key'Up
+  | Key'PageUp
+  | Key'PageDown
+  | Key'Home
+  | Key'End
+  | Key'CapsLock
+  | Key'ScrollLock
+  | Key'NumLock
+  | Key'PrintScreen
+  | Key'Pause
+  | Key'F1
+  | Key'F2
+  | Key'F3
+  | Key'F4
+  | Key'F5
+  | Key'F6
+  | Key'F7
+  | Key'F8
+  | Key'F9
+  | Key'F10
+  | Key'F11
+  | Key'F12
+  | Key'F13
+  | Key'F14
+  | Key'F15
+  | Key'F16
+  | Key'F17
+  | Key'F18
+  | Key'F19
+  | Key'F20
+  | Key'F21
+  | Key'F22
+  | Key'F23
+  | Key'F24
+  | Key'F25
+  | Key'Pad0
+  | Key'Pad1
+  | Key'Pad2
+  | Key'Pad3
+  | Key'Pad4
+  | Key'Pad5
+  | Key'Pad6
+  | Key'Pad7
+  | Key'Pad8
+  | Key'Pad9
+  | Key'PadDecimal
+  | Key'PadDivide
+  | Key'PadMultiply
+  | Key'PadSubtract
+  | Key'PadAdd
+  | Key'PadEnter
+  | Key'PadEqual
+  | Key'LeftShift
+  | Key'LeftControl
+  | Key'LeftAlt
+  | Key'LeftSuper
+  | Key'RightShift
+  | Key'RightControl
+  | Key'RightAlt
+  | Key'RightSuper
+  | Key'Menu
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData Key
+
+-- | The state of an individual key when 'getKey' is called.
+data KeyState =
+    KeyState'Pressed
+  | KeyState'Released
+  | KeyState'Repeating
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData KeyState
+
+-- | For use with the <http://www.glfw.org/docs/3.2/input.html#joystick Joystick Input> system.
+data Joystick =
+    Joystick'1
+  | Joystick'2
+  | Joystick'3
+  | Joystick'4
+  | Joystick'5
+  | Joystick'6
+  | Joystick'7
+  | Joystick'8
+  | Joystick'9
+  | Joystick'10
+  | Joystick'11
+  | Joystick'12
+  | Joystick'13
+  | Joystick'14
+  | Joystick'15
+  | Joystick'16
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData Joystick
+
+-- | If a given joystick button is pressed or not when 'getJoystickButtons' is called.
+data JoystickButtonState =
+    JoystickButtonState'Pressed
+  | JoystickButtonState'Released
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData JoystickButtonState
+
+-- | Part of the 'JoystickCallback', for when a monitor gets connected or disconnected.
+data JoystickState
+  = JoystickState'Connected
+  | JoystickState'Disconnected
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData JoystickState
+
+-- | Part of the <http://www.glfw.org/docs/3.2/input.html#input_mouse Mouse Input> system.
+data MouseButton =
+    MouseButton'1
+  | MouseButton'2
+  | MouseButton'3
+  | MouseButton'4
+  | MouseButton'5
+  | MouseButton'6
+  | MouseButton'7
+  | MouseButton'8
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData MouseButton
+
+-- | If the mouse button is pressed or not when 'getMouseButton' is called.
+data MouseButtonState =
+    MouseButtonState'Pressed
+  | MouseButtonState'Released
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData MouseButtonState
+
+-- | If the mouse's cursor is in the window or not.
+data CursorState =
+    CursorState'InWindow
+  | CursorState'NotInWindow
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData CursorState
+
+-- | Allows for special forms of mouse input.
+-- See <http://www.glfw.org/docs/3.2/input.html#cursor_mode Cursor Modes>
+data CursorInputMode =
+    CursorInputMode'Normal
+  | CursorInputMode'Hidden
+  | CursorInputMode'Disabled
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData CursorInputMode
+
+-- | When sticky keys is enabled, once a key is pressed it will remain pressed
+-- at least until the state is polled with 'getKey'. After that, if the key has
+-- been released it will switch back to released. This helps prevent problems
+-- with low-resolution polling missing key pressed. Note that use of the
+-- callbacks to avoid this problem the the recommended route, and this is just
+-- for a fallback.
+data StickyKeysInputMode =
+    StickyKeysInputMode'Enabled
+  | StickyKeysInputMode'Disabled
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData StickyKeysInputMode
+
+-- | This is the mouse version of "StickyKeysInputMode".
+data StickyMouseButtonsInputMode =
+    StickyMouseButtonsInputMode'Enabled
+  | StickyMouseButtonsInputMode'Disabled
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData StickyMouseButtonsInputMode
+
+-- | Modifier keys that were pressed as part of another keypress event.
+data ModifierKeys = ModifierKeys
+  { modifierKeysShift   :: !Bool
+  , modifierKeysControl :: !Bool
+  , modifierKeysAlt     :: !Bool
+  , modifierKeysSuper   :: !Bool
+  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData ModifierKeys
+
+--------------------------------------------------------------------------------
+-- 3.1 Additions
+--------------------------------------------------------------------------------
+
+deriving instance Data CUChar
+
+-- | GLFW image data, for setting up custom mouse cursor appearnaces.
+data Image = Image
+  { imageWidth  :: {-# UNPACK #-} !Int
+  , imageHeight :: {-# UNPACK #-} !Int
+  , imagePixels :: [CUChar]
+  } deriving (Data, Eq, Ord, Read, Show, Typeable, Generic)
+
+-- | Create an image given the function to generate 8-bit RGBA values based on
+-- the pixel location.
+mkImage :: Int -> Int -> (Int -> Int -> (Word8, Word8, Word8, Word8)) -> Image
+mkImage width height gen = Image
+  { imageWidth = width
+  , imageHeight = height
+  , imagePixels = [ CUChar channel | y <- [0..(height - 1)]
+                                   , x <- [0..(width - 1)]
+                                   , (r, g, b, a) <- [gen x y]
+                                   , channel <- [r, g, b, a]
+                  ]
+  }
+
+instance NFData Image
+
+-- | Reprisents a GLFW cursor.
+newtype Cursor = Cursor
+  { unCursor :: Ptr C'GLFWcursor
+  } deriving (Data, Eq, Ord, Show, Typeable, Generic)
+
+-- | Lets you use one of the standard cursor appearnaces that the local
+-- system theme provides for.
+-- See <http://www.glfw.org/docs/3.2/input.html#cursor_standard Standard Cursor Creation>.
+data StandardCursorShape =
+    StandardCursorShape'Arrow
+  | StandardCursorShape'IBeam
+  | StandardCursorShape'Crosshair
+  | StandardCursorShape'Hand
+  | StandardCursorShape'HResize
+  | StandardCursorShape'VResize
+  deriving (Bounded, Data, Enum, Eq, Ord, Read, Show, Typeable, Generic)
+
+instance NFData StandardCursorShape
+
+--------------------------------------------------------------------------------
+
+{-# ANN module "HLint: ignore Use camelCase" #-}
README.md view
@@ -8,7 +8,7 @@ creating windows with OpenGL contexts and managing input and events.  GLFW-b depends on [bindings-GLFW][3], which, as of the time of this writing,-binds to GLFW 3.1, [released 2015-01-18][4].+binds to GLFW 3.2.1, [released 2016-08-18][4].  For a demonstration of GLFW-b, see [GLFW-b-demo][5]. @@ -39,6 +39,6 @@ [1]: http://www.haskell.org/ [2]: http://www.glfw.org/ [3]: https://github.com/bsl/bindings-GLFW-[4]: http://www.glfw.org/Version-3.1-released.html+[4]: http://www.glfw.org/Version-3.2.1-released.html [5]: https://github.com/bsl/GLFW-b-demo [6]: http://nvie.com/posts/a-successful-git-branching-model/
Test.hs view
@@ -1,614 +1,614 @@--- base-import Control.Concurrent (threadDelay)-import Control.Monad      (forM_)-import Data.Char          (isAscii)-import Data.Bits          (xor)-import Data.List          (intercalate, isPrefixOf)---- HUnit-import Test.HUnit ((@?=), assertBool, assertFailure)---- test-framework-import Test.Framework (Test, defaultMain, testGroup)---- test-framework-hunit-import Test.Framework.Providers.HUnit (testCase)---- GLFW-b-import qualified Graphics.UI.GLFW as GLFW------------------------------------------------------------------------------------main :: IO ()-main = do-    GLFW.setErrorCallback $ Just $ \e s ->-        putStrLn $ unwords ["###", show e, show s]--    True <- GLFW.init--    Just mon <- GLFW.getPrimaryMonitor--    GLFW.windowHint $ GLFW.WindowHint'Visible False-    mwin@(Just win) <- GLFW.createWindow 100 100 "GLFW-b test" Nothing Nothing-    GLFW.makeContextCurrent mwin--    -- Mostly check for compiling-    GLFW.setJoystickCallback $ Just $ \j c -> putStrLn $ concat-      [ show j, " changed state: ", show c ]--    defaultMain $ tests mon win--    -- TODO because of how defaultMain works, this code is not reached-    GLFW.destroyWindow win-    GLFW.terminate------------------------------------------------------------------------------------versionMajor, versionMinor, versionRevision :: Int-versionMajor = 3-versionMinor = 2-versionRevision = 1--giveItTime :: IO ()-giveItTime = threadDelay 500000--joysticks :: [GLFW.Joystick]-joysticks =-    [ GLFW.Joystick'1-    , GLFW.Joystick'2-    , GLFW.Joystick'3-    , GLFW.Joystick'4-    , GLFW.Joystick'5-    , GLFW.Joystick'6-    , GLFW.Joystick'7-    , GLFW.Joystick'8-    , GLFW.Joystick'9-    , GLFW.Joystick'10-    , GLFW.Joystick'11-    , GLFW.Joystick'12-    , GLFW.Joystick'13-    , GLFW.Joystick'14-    , GLFW.Joystick'15-    , GLFW.Joystick'16-    ]--between :: Ord a => a -> (a,a) -> Bool-between n (l,h) = n >= l && n <= h--videoModeLooksValid :: GLFW.VideoMode -> Bool-videoModeLooksValid vm = and-    [ GLFW.videoModeWidth       vm `between` (0,4000)-    , GLFW.videoModeHeight      vm `between` (0,3000)-    , GLFW.videoModeRedBits     vm `between` (0,  32)-    , GLFW.videoModeGreenBits   vm `between` (0,  32)-    , GLFW.videoModeBlueBits    vm `between` (0,  32)-    , GLFW.videoModeRefreshRate vm `between` (0, 120)-    ]------------------------------------------------------------------------------------tests :: GLFW.Monitor -> GLFW.Window -> [Test]-tests mon win =-    [ testGroup "Initialization and version information"-      [ testCase "getVersion"       test_getVersion-      , testCase "getVersionString" test_getVersionString-      ]-    , testGroup "Monitor handling"-      [ testCase "getMonitors"              test_getMonitors-      , testCase "getPrimaryMonitor"        test_getPrimaryMonitor-      , testCase "getMonitorPos"          $ test_getMonitorPos mon-      , testCase "getMonitorPhysicalSize" $ test_getMonitorPhysicalSize mon-      , testCase "getMonitorName"         $ test_getMonitorName mon-      , testCase "getVideoModes"          $ test_getVideoModes mon-      , testCase "getVideoMode"           $ test_getVideoMode mon-      , testCase "getGamma"               $ test_getGammaRamp mon-      ]-    , testGroup "Window handling"-      [ testCase "defaultWindowHints"             test_defaultWindowHints--      -- Test window attributes-      , testCase "getWindowFocused"             $ test_getWindowFocused win-      , testCase "getWindowResizable"           $ test_getWindowResizable win-      , testCase "getWindowDecorated"           $ test_getWindowDecorated win-      , testCase "getWindowClientAPI"           $ test_getWindowClientAPI win-      , testCase "window context version"       $ test_window_context_version win-      , testCase "getWindowContextRobustness"   $ test_getWindowContextRobustness win-      , testCase "getWindowOpenGLForwardCompat" $ test_getWindowOpenGLForwardCompat win-      , testCase "getWindowOpenGLDebugContext"  $ test_getWindowOpenGLDebugContext win-      , testCase "getWindowOpenGLProfile"       $ test_getWindowOpenGLProfile win-      , testCase "window close flag"            $ test_window_close_flag win-      , testCase "setWindowTitle"               $ test_setWindowTitle win-      , testCase "window pos"                   $ test_window_pos win-      , testCase "window size"                  $ test_window_size win-      , testCase "getWindowFrameSize"           $ test_getWindowFrameSize win-      , testCase "getFramebufferSize"           $ test_getFramebufferSize win-      , testCase "iconification"                $ test_iconification win-      -- , testCase "show/hide"                    $ test_show_hide win-      , testCase "getWindowMonitor"             $ test_getWindowMonitor win mon-      , testCase "setWindowed"                  $ test_setWindowed win-      , testCase "setWindowIcon"                $ test_setWindowIcon win-      , testCase "maximizeWindow"               $ test_maximizeWindow win-      , testCase "setWindowSizeLimits"          $ test_setWindowSizeLimits win-      , testCase "setWindowAspectRatio"         $ test_setWindowAspectRatio win-      , testCase "focusWindow"                  $ test_focusWindow win-      , testCase "cursor pos"                   $ test_cursor_pos win-      , testCase "pollEvents"                     test_pollEvents-      , testCase "waitEvents"                     test_waitEvents-      , testCase "waitEventsTimeout"              test_waitEventsTimeout-      ]-    , testGroup "Input handling"-      [ testCase "cursor input mode"               $ test_cursor_input_mode win-      , testCase "sticky keys input mode"          $ test_sticky_keys_input_mode win-      , testCase "sticky mouse buttons input mode" $ test_sticky_mouse_buttons_input_mode win-      , testCase "joystickPresent"                   test_joystickPresent-      , testCase "getJoystickAxes"                   test_getJoystickAxes-      , testCase "getJoystickButtons"                test_getJoystickButtons-      , testCase "getJoystickName"                   test_getJoystickName-      , testCase "getKeyName"                        test_getKeyName-      ]-    , testGroup "Time"-      [ testCase "getTime"              test_getTime-      , testCase "setTime"              test_setTime-      , testCase "getTimerValue"        test_getTimerValue-      , testCase "getTimerFrequency"    test_getTimerFrequency-      ]-    , testGroup "Context"-      [ testCase "getCurrentContext"  $ test_getCurrentContext win-      , testCase "swapBuffers"        $ test_swapBuffers win-      , testCase "swapInterval"         test_swapInterval-      , testCase "extensionSupported"   test_extensionSupported-      ]-    , testGroup "Clipboard"-      [ testCase "clipboard" $ test_clipboard win-      ]-    ]------------------------------------------------------------------------------------test_getVersion :: IO ()-test_getVersion = do-    v <- GLFW.getVersion-    GLFW.versionMajor v @?= versionMajor-    GLFW.versionMinor v @?= versionMinor-    GLFW.versionRevision v @?= versionRevision--test_getVersionString :: IO ()-test_getVersionString = do-    mvs <- GLFW.getVersionString-    case mvs of-      Just vs -> assertBool "" $ v `isPrefixOf` vs-      Nothing -> assertFailure ""-  where-    v = intercalate "." $ map show [versionMajor, versionMinor]--test_getMonitors :: IO ()-test_getMonitors = do-    r <- GLFW.getMonitors-    case r of-      Just ms -> assertBool "" $ (not . null) ms-      Nothing -> assertFailure ""--test_getPrimaryMonitor :: IO ()-test_getPrimaryMonitor = do-    r <- GLFW.getPrimaryMonitor-    case r of-      Just _  -> return ()-      Nothing -> assertFailure ""--test_getMonitorPos :: GLFW.Monitor -> IO ()-test_getMonitorPos mon = do-    (x, y) <- GLFW.getMonitorPos mon-    assertBool "" $ x >= 0-    assertBool "" $ y >= 0--test_getMonitorPhysicalSize :: GLFW.Monitor -> IO ()-test_getMonitorPhysicalSize mon = do-    (w, h) <- GLFW.getMonitorPhysicalSize mon-    assertBool "" $ w `between` (0, 1000)-    assertBool "" $ h `between` (0,  500)--test_getMonitorName :: GLFW.Monitor -> IO ()-test_getMonitorName mon = do-    mname <- GLFW.getMonitorName mon-    case mname of-      Nothing   -> assertFailure ""-      Just name -> do-          assertBool "" $ length name `between` (0, 20)-          assertBool "" $ all isAscii name--test_getVideoModes :: GLFW.Monitor -> IO ()-test_getVideoModes mon = do-    mvms <- GLFW.getVideoModes mon-    case mvms of-      Nothing  -> assertFailure ""-      Just vms -> assertBool "" $ all videoModeLooksValid vms--test_getVideoMode :: GLFW.Monitor -> IO ()-test_getVideoMode mon = do-    mvm <- GLFW.getVideoMode mon-    case mvm of-      Just vm -> assertBool "" $ videoModeLooksValid vm-      Nothing -> assertFailure ""--test_getGammaRamp :: GLFW.Monitor -> IO ()-test_getGammaRamp mon = do-    mgr <- GLFW.getGammaRamp mon-    case mgr of-      Nothing -> assertFailure ""-      Just gr -> assertBool "" $-        let rsl = length $ GLFW.gammaRampRed   gr-            gsl = length $ GLFW.gammaRampGreen gr-            bsl = length $ GLFW.gammaRampBlue  gr-        in rsl > 0 && rsl == gsl && gsl == bsl------------------------------------------------------------------------------------test_defaultWindowHints :: IO ()-test_defaultWindowHints =-    GLFW.defaultWindowHints--test_window_close_flag :: GLFW.Window -> IO ()-test_window_close_flag win = do-    r0 <- GLFW.windowShouldClose win-    r0 @?= False--    GLFW.setWindowShouldClose win True-    r1 <- GLFW.windowShouldClose win-    r1 @?= True--    GLFW.setWindowShouldClose win False-    r2 <- GLFW.windowShouldClose win-    r2 @?= False--test_setWindowTitle :: GLFW.Window -> IO ()-test_setWindowTitle win =-    GLFW.setWindowTitle win "some new title"---- This is a little strange. Depending on your window manager, etc, after--- setting the window position to (x,y), the actual new window position might--- be (x+5,y+5) due to borders. So we just check for consistency.-test_window_pos :: GLFW.Window -> IO ()-test_window_pos win = do-    let x = 17-        y = 37-        xoff = 53-        yoff = 149-    (x0, y0, dx0, dy0) <- setGet  x        y-    (x1, y1, dx1, dy1) <- setGet (x+xoff) (y+yoff)-    dx0 @?= dx1-    dy0 @?= dy1-    x1 - x0 @?= xoff-    y1 - y0 @?= yoff-  where-    setGet x0 y0 = do-        GLFW.setWindowPos win x0 y0-        giveItTime-        (x1, y1) <- GLFW.getWindowPos win-        let (dx, dy) = (x0-x1, y0-y1)-        return (x1, y1, dx, dy)--test_window_size :: GLFW.Window -> IO ()-test_window_size win = do-    let w = 170-        h = 370-    GLFW.setWindowSize win w h-    giveItTime-    (w', h') <- GLFW.getWindowSize win-    w' @?= w-    h' @?= h--test_getWindowFrameSize :: GLFW.Window -> IO ()-test_getWindowFrameSize win = do-    -- The frame size is pretty dependent on the window manager. We can only-    -- really expect that the window has a title bar, so the top frame won't be-    -- zero...-    (_, t, _, _) <- GLFW.getWindowFrameSize win-    assertBool "Window has no frame width up top!" $ t > 0--test_getFramebufferSize :: GLFW.Window -> IO ()-test_getFramebufferSize win = do-    (w, h) <- GLFW.getWindowSize win-    (fw, fh) <- GLFW.getFramebufferSize win-    -- Window size and framebuffer size are not always equal, an example are-    -- retina screens. But maybe it's safe to assume they'll always be scaled-    -- equally in both dimensions?-    let ww = ( fromIntegral fw / fromIntegral w ) :: Double-        hh = ( fromIntegral fh / fromIntegral h ) :: Double-    ww @?= hh-    assertBool "" $ fw /= 0-    assertBool "" $ fh /= 0--test_iconification :: GLFW.Window -> IO ()-test_iconification win = do-    GLFW.showWindow win-    is0 <- GLFW.getWindowIconified win-    is0 @?= False--    GLFW.iconifyWindow win-    giveItTime-    is1 <- GLFW.getWindowIconified win-    is1 @?= True--    GLFW.restoreWindow win-    GLFW.hideWindow win---- test_show_hide :: GLFW.Window -> IO ()--- test_show_hide win = do---     v0 <- GLFW.getWindowVisible win---     v0 @?= True----     GLFW.hideWindow win---     giveItTime---     v1 <- GLFW.getWindowVisible win---     v1 @?= False----     GLFW.showWindow win---     giveItTime---     v2 <- GLFW.getWindowVisible win---     v2 @?= True--test_getWindowMonitor :: GLFW.Window -> GLFW.Monitor -> IO ()-test_getWindowMonitor win _ = do-    m <- GLFW.getWindowMonitor win-    m @?= Nothing--test_setWindowed :: GLFW.Window -> IO ()-test_setWindowed win = GLFW.setWindowed win 100 100 0 0--test_setWindowIcon :: GLFW.Window -> IO ()-test_setWindowIcon win = let-  icon1 = GLFW.mkImage 32 32 $ \x y ->-    case even ((x `div` 8) `xor` (y `div` 8)) of-      True -> (255, 0, 0, 255)-      False -> (0, 255, 0, 255)--  icon2 = GLFW.mkImage 16 16 $ \x y ->-    case even ((x `div` 8) `xor` (y `div` 8)) of-      True -> (255, 255, 255, 255)-      False -> (0, 0, 0, 255)--  in GLFW.setWindowIcon win [icon1, icon2]--test_maximizeWindow :: GLFW.Window -> IO ()-test_maximizeWindow win = do-  GLFW.showWindow win-  startsMaximized <- GLFW.getWindowMaximized win-  startsMaximized @?= False--  GLFW.maximizeWindow win-  giveItTime--  isMaximized <- GLFW.getWindowMaximized win-  isMaximized @?= True-  GLFW.hideWindow win--test_setWindowSizeLimits :: GLFW.Window -> IO ()-test_setWindowSizeLimits win = do-    GLFW.setWindowSizeLimits win (Just 640) (Just 480) (Just 1024) (Just 768)--test_setWindowAspectRatio :: GLFW.Window -> IO ()-test_setWindowAspectRatio win = do-    GLFW.setWindowAspectRatio win Nothing--test_focusWindow :: GLFW.Window -> IO ()-test_focusWindow = GLFW.focusWindow--test_cursor_pos :: GLFW.Window -> IO ()-test_cursor_pos win = do-  GLFW.showWindow win-  (w, h) <- GLFW.getWindowSize win--  -- Make sure we use integral coordinates here so that we don't run into-  -- platform-dependent differences.-  let cx :: Double-      cy :: Double-      (cx, cy) = (fromIntegral $ w `div` 2, fromIntegral $ h `div` 2)--  -- !HACK! Poll events seems to be necessary on OS X,-  -- before /and/ after glfwSetCursorPos, otherwise, the-  -- windowing system likely never receives the cursor update. This is-  -- reflected in the C version of GLFW as well, we just call it here in-  -- order to have a more robust test.--  GLFW.pollEvents-  GLFW.setCursorPos win cx cy-  GLFW.pollEvents -- !HACK! see comment above--  (cx', cy') <- GLFW.getCursorPos win-  cx' @?= cx-  cy' @?= cy-  GLFW.hideWindow win--test_getWindowFocused :: GLFW.Window -> IO ()-test_getWindowFocused win = do-    fs <- GLFW.getWindowFocused win-    fs @?= False--test_getWindowResizable :: GLFW.Window -> IO ()-test_getWindowResizable win = do-    b <- GLFW.getWindowResizable win-    b @?= True--test_getWindowDecorated :: GLFW.Window -> IO ()-test_getWindowDecorated win = do-    b <- GLFW.getWindowDecorated win-    b @?= True--test_getWindowClientAPI :: GLFW.Window -> IO ()-test_getWindowClientAPI win = do-    a <- GLFW.getWindowClientAPI win-    a @?= GLFW.ClientAPI'OpenGL--test_window_context_version :: GLFW.Window -> IO ()-test_window_context_version win = do-    v0 <- GLFW.getWindowContextVersionMajor    win-    v1 <- GLFW.getWindowContextVersionMinor    win-    assertBool "" $ all (`between` (0, 20)) [v0, v1]--test_getWindowContextRobustness :: GLFW.Window -> IO ()-test_getWindowContextRobustness win = do-    _ <- GLFW.getWindowContextRobustness win-    return ()--test_getWindowOpenGLForwardCompat :: GLFW.Window -> IO ()-test_getWindowOpenGLForwardCompat win = do-    _ <- GLFW.getWindowOpenGLForwardCompat win-    return ()--test_getWindowOpenGLDebugContext :: GLFW.Window -> IO ()-test_getWindowOpenGLDebugContext win = do-    _ <- GLFW.getWindowOpenGLDebugContext win-    return ()--test_getWindowOpenGLProfile :: GLFW.Window -> IO ()-test_getWindowOpenGLProfile win = do-    _ <- GLFW.getWindowOpenGLProfile win-    return ()--test_pollEvents :: IO ()-test_pollEvents =-    GLFW.pollEvents--test_waitEvents :: IO ()-test_waitEvents = GLFW.postEmptyEvent >> GLFW.waitEvents--test_waitEventsTimeout :: IO ()-test_waitEventsTimeout =-    -- to not slow down the test too much we set the timeout to 0.001 second :-    GLFW.waitEventsTimeout 0.001------------------------------------------------------------------------------------test_cursor_input_mode :: GLFW.Window -> IO ()-test_cursor_input_mode win = do-    modes' <- mapM setGet modes-    modes' @?= modes-  where-    modes =-      [ GLFW.CursorInputMode'Disabled-      , GLFW.CursorInputMode'Hidden-      , GLFW.CursorInputMode'Normal-      ]-    setGet m = do-        GLFW.setCursorInputMode win m-        GLFW.getCursorInputMode win--test_sticky_keys_input_mode :: GLFW.Window -> IO ()-test_sticky_keys_input_mode win = do-    modes' <- mapM setGet modes-    modes' @?= modes-  where-    modes =-      [ GLFW.StickyKeysInputMode'Enabled-      , GLFW.StickyKeysInputMode'Disabled-      ]-    setGet m = do-        GLFW.setStickyKeysInputMode win m-        GLFW.getStickyKeysInputMode win--test_sticky_mouse_buttons_input_mode :: GLFW.Window -> IO ()-test_sticky_mouse_buttons_input_mode win = do-    modes' <- mapM setGet modes-    modes' @?= modes-  where-    modes =-      [ GLFW.StickyMouseButtonsInputMode'Enabled-      , GLFW.StickyMouseButtonsInputMode'Disabled-      ]-    setGet m = do-        GLFW.setStickyMouseButtonsInputMode win m-        GLFW.getStickyMouseButtonsInputMode win--test_joystickPresent :: IO ()-test_joystickPresent = do-    _ <- GLFW.joystickPresent GLFW.Joystick'1-    r <- GLFW.joystickPresent GLFW.Joystick'16-    assertBool "" $ not r--test_getJoystickAxes :: IO ()-test_getJoystickAxes =-    mapM_ GLFW.getJoystickAxes joysticks--test_getJoystickButtons :: IO ()-test_getJoystickButtons =-    mapM_ GLFW.getJoystickButtons joysticks--test_getJoystickName :: IO ()-test_getJoystickName =-    mapM_ GLFW.getJoystickName joysticks--test_getKeyName :: IO ()-test_getKeyName =-  forM_ (zip [GLFW.Key'Slash, GLFW.Key'Period] ["/", "."]) $ \(k, n) -> do-    name <- GLFW.getKeyName k 0-    case name of-      Nothing -> return ()-      Just s -> s @?= n------------------------------------------------------------------------------------test_getTime :: IO ()-test_getTime = do-    mt <- GLFW.getTime-    case mt of-      Nothing -> assertFailure ""-      Just t  -> assertBool "" $ t `between` (0, 10)--test_setTime :: IO ()-test_setTime = do-    let t = 37-    GLFW.setTime t-    mt <- GLFW.getTime-    case mt of-      Just t' -> assertBool "" $ t' `between` (t, t+10)-      Nothing -> assertFailure ""--test_getTimerValue :: IO ()-test_getTimerValue = GLFW.getTimerValue >>= assertBool "" . (> 0)--test_getTimerFrequency :: IO ()-test_getTimerFrequency = GLFW.getTimerFrequency >>= assertBool "" . (> 0)------------------------------------------------------------------------------------test_getCurrentContext :: GLFW.Window -> IO ()-test_getCurrentContext win = do-    mwin <- GLFW.getCurrentContext-    case mwin of-      Nothing   -> assertFailure ""-      Just win' -> win' @?= win--test_swapBuffers :: GLFW.Window -> IO ()-test_swapBuffers =-    GLFW.swapBuffers--test_swapInterval :: IO ()-test_swapInterval =-    GLFW.swapInterval 1--test_extensionSupported :: IO ()-test_extensionSupported = do-    b0 <- GLFW.extensionSupported "GL_ARB_multisample"-    b0 @?= True-    b1 <- GLFW.extensionSupported "bogus"-    b1 @?= False------------------------------------------------------------------------------------test_clipboard :: GLFW.Window -> IO ()-test_clipboard win = do-    rs <- mapM setGet ss-    rs @?= map Just ss-  where-    ss =-      [ "abc 123 ???"-      , "xyz 456 !!!"-      ]-    setGet s = do-        GLFW.setClipboardString win s-        giveItTime-        GLFW.getClipboardString win------------------------------------------------------------------------------------{-# ANN module "HLint: ignore Use camelCase" #-}+-- base
+import Control.Concurrent (threadDelay)
+import Control.Monad      (forM_)
+import Data.Char          (isAscii)
+import Data.Bits          (xor)
+import Data.List          (intercalate, isPrefixOf)
+
+-- HUnit
+import Test.HUnit ((@?=), assertBool, assertFailure)
+
+-- test-framework
+import Test.Framework (Test, defaultMain, testGroup)
+
+-- test-framework-hunit
+import Test.Framework.Providers.HUnit (testCase)
+
+-- GLFW-b
+import qualified Graphics.UI.GLFW as GLFW
+
+--------------------------------------------------------------------------------
+
+main :: IO ()
+main = do
+    GLFW.setErrorCallback $ Just $ \e s ->
+        putStrLn $ unwords ["###", show e, show s]
+
+    True <- GLFW.init
+
+    Just mon <- GLFW.getPrimaryMonitor
+
+    GLFW.windowHint $ GLFW.WindowHint'Visible False
+    mwin@(Just win) <- GLFW.createWindow 100 100 "GLFW-b test" Nothing Nothing
+    GLFW.makeContextCurrent mwin
+
+    -- Mostly check for compiling
+    GLFW.setJoystickCallback $ Just $ \j c -> putStrLn $ concat
+      [ show j, " changed state: ", show c ]
+
+    defaultMain $ tests mon win
+
+    -- TODO because of how defaultMain works, this code is not reached
+    GLFW.destroyWindow win
+    GLFW.terminate
+
+--------------------------------------------------------------------------------
+
+versionMajor, versionMinor, versionRevision :: Int
+versionMajor = 3
+versionMinor = 2
+versionRevision = 1
+
+giveItTime :: IO ()
+giveItTime = threadDelay 500000
+
+joysticks :: [GLFW.Joystick]
+joysticks =
+    [ GLFW.Joystick'1
+    , GLFW.Joystick'2
+    , GLFW.Joystick'3
+    , GLFW.Joystick'4
+    , GLFW.Joystick'5
+    , GLFW.Joystick'6
+    , GLFW.Joystick'7
+    , GLFW.Joystick'8
+    , GLFW.Joystick'9
+    , GLFW.Joystick'10
+    , GLFW.Joystick'11
+    , GLFW.Joystick'12
+    , GLFW.Joystick'13
+    , GLFW.Joystick'14
+    , GLFW.Joystick'15
+    , GLFW.Joystick'16
+    ]
+
+between :: Ord a => a -> (a,a) -> Bool
+between n (l,h) = n >= l && n <= h
+
+videoModeLooksValid :: GLFW.VideoMode -> Bool
+videoModeLooksValid vm = and
+    [ GLFW.videoModeWidth       vm `between` (0,4000)
+    , GLFW.videoModeHeight      vm `between` (0,3000)
+    , GLFW.videoModeRedBits     vm `between` (0,  32)
+    , GLFW.videoModeGreenBits   vm `between` (0,  32)
+    , GLFW.videoModeBlueBits    vm `between` (0,  32)
+    , GLFW.videoModeRefreshRate vm `between` (0, 120)
+    ]
+
+--------------------------------------------------------------------------------
+
+tests :: GLFW.Monitor -> GLFW.Window -> [Test]
+tests mon win =
+    [ testGroup "Initialization and version information"
+      [ testCase "getVersion"       test_getVersion
+      , testCase "getVersionString" test_getVersionString
+      ]
+    , testGroup "Monitor handling"
+      [ testCase "getMonitors"              test_getMonitors
+      , testCase "getPrimaryMonitor"        test_getPrimaryMonitor
+      , testCase "getMonitorPos"          $ test_getMonitorPos mon
+      , testCase "getMonitorPhysicalSize" $ test_getMonitorPhysicalSize mon
+      , testCase "getMonitorName"         $ test_getMonitorName mon
+      , testCase "getVideoModes"          $ test_getVideoModes mon
+      , testCase "getVideoMode"           $ test_getVideoMode mon
+      , testCase "getGamma"               $ test_getGammaRamp mon
+      ]
+    , testGroup "Window handling"
+      [ testCase "defaultWindowHints"             test_defaultWindowHints
+
+      -- Test window attributes
+      , testCase "getWindowFocused"             $ test_getWindowFocused win
+      , testCase "getWindowResizable"           $ test_getWindowResizable win
+      , testCase "getWindowDecorated"           $ test_getWindowDecorated win
+      , testCase "getWindowClientAPI"           $ test_getWindowClientAPI win
+      , testCase "window context version"       $ test_window_context_version win
+      , testCase "getWindowContextRobustness"   $ test_getWindowContextRobustness win
+      , testCase "getWindowOpenGLForwardCompat" $ test_getWindowOpenGLForwardCompat win
+      , testCase "getWindowOpenGLDebugContext"  $ test_getWindowOpenGLDebugContext win
+      , testCase "getWindowOpenGLProfile"       $ test_getWindowOpenGLProfile win
+      , testCase "window close flag"            $ test_window_close_flag win
+      , testCase "setWindowTitle"               $ test_setWindowTitle win
+      , testCase "window pos"                   $ test_window_pos win
+      , testCase "window size"                  $ test_window_size win
+      , testCase "getWindowFrameSize"           $ test_getWindowFrameSize win
+      , testCase "getFramebufferSize"           $ test_getFramebufferSize win
+      , testCase "iconification"                $ test_iconification win
+      -- , testCase "show/hide"                    $ test_show_hide win
+      , testCase "getWindowMonitor"             $ test_getWindowMonitor win mon
+      , testCase "setWindowed"                  $ test_setWindowed win
+      , testCase "setWindowIcon"                $ test_setWindowIcon win
+      , testCase "maximizeWindow"               $ test_maximizeWindow win
+      , testCase "setWindowSizeLimits"          $ test_setWindowSizeLimits win
+      , testCase "setWindowAspectRatio"         $ test_setWindowAspectRatio win
+      , testCase "focusWindow"                  $ test_focusWindow win
+      , testCase "cursor pos"                   $ test_cursor_pos win
+      , testCase "pollEvents"                     test_pollEvents
+      , testCase "waitEvents"                     test_waitEvents
+      , testCase "waitEventsTimeout"              test_waitEventsTimeout
+      ]
+    , testGroup "Input handling"
+      [ testCase "cursor input mode"               $ test_cursor_input_mode win
+      , testCase "sticky keys input mode"          $ test_sticky_keys_input_mode win
+      , testCase "sticky mouse buttons input mode" $ test_sticky_mouse_buttons_input_mode win
+      , testCase "joystickPresent"                   test_joystickPresent
+      , testCase "getJoystickAxes"                   test_getJoystickAxes
+      , testCase "getJoystickButtons"                test_getJoystickButtons
+      , testCase "getJoystickName"                   test_getJoystickName
+      , testCase "getKeyName"                        test_getKeyName
+      ]
+    , testGroup "Time"
+      [ testCase "getTime"              test_getTime
+      , testCase "setTime"              test_setTime
+      , testCase "getTimerValue"        test_getTimerValue
+      , testCase "getTimerFrequency"    test_getTimerFrequency
+      ]
+    , testGroup "Context"
+      [ testCase "getCurrentContext"  $ test_getCurrentContext win
+      , testCase "swapBuffers"        $ test_swapBuffers win
+      , testCase "swapInterval"         test_swapInterval
+      , testCase "extensionSupported"   test_extensionSupported
+      ]
+    , testGroup "Clipboard"
+      [ testCase "clipboard" $ test_clipboard win
+      ]
+    ]
+
+--------------------------------------------------------------------------------
+
+test_getVersion :: IO ()
+test_getVersion = do
+    v <- GLFW.getVersion
+    GLFW.versionMajor v @?= versionMajor
+    GLFW.versionMinor v @?= versionMinor
+    GLFW.versionRevision v @?= versionRevision
+
+test_getVersionString :: IO ()
+test_getVersionString = do
+    mvs <- GLFW.getVersionString
+    case mvs of
+      Just vs -> assertBool "" $ v `isPrefixOf` vs
+      Nothing -> assertFailure ""
+  where
+    v = intercalate "." $ map show [versionMajor, versionMinor]
+
+test_getMonitors :: IO ()
+test_getMonitors = do
+    r <- GLFW.getMonitors
+    case r of
+      Just ms -> assertBool "" $ (not . null) ms
+      Nothing -> assertFailure ""
+
+test_getPrimaryMonitor :: IO ()
+test_getPrimaryMonitor = do
+    r <- GLFW.getPrimaryMonitor
+    case r of
+      Just _  -> return ()
+      Nothing -> assertFailure ""
+
+test_getMonitorPos :: GLFW.Monitor -> IO ()
+test_getMonitorPos mon = do
+    (x, y) <- GLFW.getMonitorPos mon
+    assertBool "" $ x >= 0
+    assertBool "" $ y >= 0
+
+test_getMonitorPhysicalSize :: GLFW.Monitor -> IO ()
+test_getMonitorPhysicalSize mon = do
+    (w, h) <- GLFW.getMonitorPhysicalSize mon
+    assertBool "" $ w `between` (0, 1000)
+    assertBool "" $ h `between` (0,  500)
+
+test_getMonitorName :: GLFW.Monitor -> IO ()
+test_getMonitorName mon = do
+    mname <- GLFW.getMonitorName mon
+    case mname of
+      Nothing   -> assertFailure ""
+      Just name -> do
+          assertBool "" $ length name `between` (0, 20)
+          assertBool "" $ all isAscii name
+
+test_getVideoModes :: GLFW.Monitor -> IO ()
+test_getVideoModes mon = do
+    mvms <- GLFW.getVideoModes mon
+    case mvms of
+      Nothing  -> assertFailure ""
+      Just vms -> assertBool "" $ all videoModeLooksValid vms
+
+test_getVideoMode :: GLFW.Monitor -> IO ()
+test_getVideoMode mon = do
+    mvm <- GLFW.getVideoMode mon
+    case mvm of
+      Just vm -> assertBool "" $ videoModeLooksValid vm
+      Nothing -> assertFailure ""
+
+test_getGammaRamp :: GLFW.Monitor -> IO ()
+test_getGammaRamp mon = do
+    mgr <- GLFW.getGammaRamp mon
+    case mgr of
+      Nothing -> assertFailure ""
+      Just gr -> assertBool "" $
+        let rsl = length $ GLFW.gammaRampRed   gr
+            gsl = length $ GLFW.gammaRampGreen gr
+            bsl = length $ GLFW.gammaRampBlue  gr
+        in rsl > 0 && rsl == gsl && gsl == bsl
+
+--------------------------------------------------------------------------------
+
+test_defaultWindowHints :: IO ()
+test_defaultWindowHints =
+    GLFW.defaultWindowHints
+
+test_window_close_flag :: GLFW.Window -> IO ()
+test_window_close_flag win = do
+    r0 <- GLFW.windowShouldClose win
+    r0 @?= False
+
+    GLFW.setWindowShouldClose win True
+    r1 <- GLFW.windowShouldClose win
+    r1 @?= True
+
+    GLFW.setWindowShouldClose win False
+    r2 <- GLFW.windowShouldClose win
+    r2 @?= False
+
+test_setWindowTitle :: GLFW.Window -> IO ()
+test_setWindowTitle win =
+    GLFW.setWindowTitle win "some new title"
+
+-- This is a little strange. Depending on your window manager, etc, after
+-- setting the window position to (x,y), the actual new window position might
+-- be (x+5,y+5) due to borders. So we just check for consistency.
+test_window_pos :: GLFW.Window -> IO ()
+test_window_pos win = do
+    let x = 17
+        y = 37
+        xoff = 53
+        yoff = 149
+    (x0, y0, dx0, dy0) <- setGet  x        y
+    (x1, y1, dx1, dy1) <- setGet (x+xoff) (y+yoff)
+    dx0 @?= dx1
+    dy0 @?= dy1
+    x1 - x0 @?= xoff
+    y1 - y0 @?= yoff
+  where
+    setGet x0 y0 = do
+        GLFW.setWindowPos win x0 y0
+        giveItTime
+        (x1, y1) <- GLFW.getWindowPos win
+        let (dx, dy) = (x0-x1, y0-y1)
+        return (x1, y1, dx, dy)
+
+test_window_size :: GLFW.Window -> IO ()
+test_window_size win = do
+    let w = 170
+        h = 370
+    GLFW.setWindowSize win w h
+    giveItTime
+    (w', h') <- GLFW.getWindowSize win
+    w' @?= w
+    h' @?= h
+
+test_getWindowFrameSize :: GLFW.Window -> IO ()
+test_getWindowFrameSize win = do
+    -- The frame size is pretty dependent on the window manager. We can only
+    -- really expect that the window has a title bar, so the top frame won't be
+    -- zero...
+    (_, t, _, _) <- GLFW.getWindowFrameSize win
+    assertBool "Window has no frame width up top!" $ t > 0
+
+test_getFramebufferSize :: GLFW.Window -> IO ()
+test_getFramebufferSize win = do
+    (w, h) <- GLFW.getWindowSize win
+    (fw, fh) <- GLFW.getFramebufferSize win
+    -- Window size and framebuffer size are not always equal, an example are
+    -- retina screens. But maybe it's safe to assume they'll always be scaled
+    -- equally in both dimensions?
+    let ww = ( fromIntegral fw / fromIntegral w ) :: Double
+        hh = ( fromIntegral fh / fromIntegral h ) :: Double
+    ww @?= hh
+    assertBool "" $ fw /= 0
+    assertBool "" $ fh /= 0
+
+test_iconification :: GLFW.Window -> IO ()
+test_iconification win = do
+    GLFW.showWindow win
+    is0 <- GLFW.getWindowIconified win
+    is0 @?= False
+
+    GLFW.iconifyWindow win
+    giveItTime
+    is1 <- GLFW.getWindowIconified win
+    is1 @?= True
+
+    GLFW.restoreWindow win
+    GLFW.hideWindow win
+
+-- test_show_hide :: GLFW.Window -> IO ()
+-- test_show_hide win = do
+--     v0 <- GLFW.getWindowVisible win
+--     v0 @?= True
+
+--     GLFW.hideWindow win
+--     giveItTime
+--     v1 <- GLFW.getWindowVisible win
+--     v1 @?= False
+
+--     GLFW.showWindow win
+--     giveItTime
+--     v2 <- GLFW.getWindowVisible win
+--     v2 @?= True
+
+test_getWindowMonitor :: GLFW.Window -> GLFW.Monitor -> IO ()
+test_getWindowMonitor win _ = do
+    m <- GLFW.getWindowMonitor win
+    m @?= Nothing
+
+test_setWindowed :: GLFW.Window -> IO ()
+test_setWindowed win = GLFW.setWindowed win 100 100 0 0
+
+test_setWindowIcon :: GLFW.Window -> IO ()
+test_setWindowIcon win = let
+  icon1 = GLFW.mkImage 32 32 $ \x y ->
+    case even ((x `div` 8) `xor` (y `div` 8)) of
+      True -> (255, 0, 0, 255)
+      False -> (0, 255, 0, 255)
+
+  icon2 = GLFW.mkImage 16 16 $ \x y ->
+    case even ((x `div` 8) `xor` (y `div` 8)) of
+      True -> (255, 255, 255, 255)
+      False -> (0, 0, 0, 255)
+
+  in GLFW.setWindowIcon win [icon1, icon2]
+
+test_maximizeWindow :: GLFW.Window -> IO ()
+test_maximizeWindow win = do
+  GLFW.showWindow win
+  startsMaximized <- GLFW.getWindowMaximized win
+  startsMaximized @?= False
+
+  GLFW.maximizeWindow win
+  giveItTime
+
+  isMaximized <- GLFW.getWindowMaximized win
+  isMaximized @?= True
+  GLFW.hideWindow win
+
+test_setWindowSizeLimits :: GLFW.Window -> IO ()
+test_setWindowSizeLimits win = do
+    GLFW.setWindowSizeLimits win (Just 640) (Just 480) (Just 1024) (Just 768)
+
+test_setWindowAspectRatio :: GLFW.Window -> IO ()
+test_setWindowAspectRatio win = do
+    GLFW.setWindowAspectRatio win Nothing
+
+test_focusWindow :: GLFW.Window -> IO ()
+test_focusWindow = GLFW.focusWindow
+
+test_cursor_pos :: GLFW.Window -> IO ()
+test_cursor_pos win = do
+  GLFW.showWindow win
+  (w, h) <- GLFW.getWindowSize win
+
+  -- Make sure we use integral coordinates here so that we don't run into
+  -- platform-dependent differences.
+  let cx :: Double
+      cy :: Double
+      (cx, cy) = (fromIntegral $ w `div` 2, fromIntegral $ h `div` 2)
+
+  -- !HACK! Poll events seems to be necessary on OS X,
+  -- before /and/ after glfwSetCursorPos, otherwise, the
+  -- windowing system likely never receives the cursor update. This is
+  -- reflected in the C version of GLFW as well, we just call it here in
+  -- order to have a more robust test.
+
+  GLFW.pollEvents
+  GLFW.setCursorPos win cx cy
+  GLFW.pollEvents -- !HACK! see comment above
+
+  (cx', cy') <- GLFW.getCursorPos win
+  cx' @?= cx
+  cy' @?= cy
+  GLFW.hideWindow win
+
+test_getWindowFocused :: GLFW.Window -> IO ()
+test_getWindowFocused win = do
+    fs <- GLFW.getWindowFocused win
+    fs @?= False
+
+test_getWindowResizable :: GLFW.Window -> IO ()
+test_getWindowResizable win = do
+    b <- GLFW.getWindowResizable win
+    b @?= True
+
+test_getWindowDecorated :: GLFW.Window -> IO ()
+test_getWindowDecorated win = do
+    b <- GLFW.getWindowDecorated win
+    b @?= True
+
+test_getWindowClientAPI :: GLFW.Window -> IO ()
+test_getWindowClientAPI win = do
+    a <- GLFW.getWindowClientAPI win
+    a @?= GLFW.ClientAPI'OpenGL
+
+test_window_context_version :: GLFW.Window -> IO ()
+test_window_context_version win = do
+    v0 <- GLFW.getWindowContextVersionMajor    win
+    v1 <- GLFW.getWindowContextVersionMinor    win
+    assertBool "" $ all (`between` (0, 20)) [v0, v1]
+
+test_getWindowContextRobustness :: GLFW.Window -> IO ()
+test_getWindowContextRobustness win = do
+    _ <- GLFW.getWindowContextRobustness win
+    return ()
+
+test_getWindowOpenGLForwardCompat :: GLFW.Window -> IO ()
+test_getWindowOpenGLForwardCompat win = do
+    _ <- GLFW.getWindowOpenGLForwardCompat win
+    return ()
+
+test_getWindowOpenGLDebugContext :: GLFW.Window -> IO ()
+test_getWindowOpenGLDebugContext win = do
+    _ <- GLFW.getWindowOpenGLDebugContext win
+    return ()
+
+test_getWindowOpenGLProfile :: GLFW.Window -> IO ()
+test_getWindowOpenGLProfile win = do
+    _ <- GLFW.getWindowOpenGLProfile win
+    return ()
+
+test_pollEvents :: IO ()
+test_pollEvents =
+    GLFW.pollEvents
+
+test_waitEvents :: IO ()
+test_waitEvents = GLFW.postEmptyEvent >> GLFW.waitEvents
+
+test_waitEventsTimeout :: IO ()
+test_waitEventsTimeout =
+    -- to not slow down the test too much we set the timeout to 0.001 second :
+    GLFW.waitEventsTimeout 0.001
+
+--------------------------------------------------------------------------------
+
+test_cursor_input_mode :: GLFW.Window -> IO ()
+test_cursor_input_mode win = do
+    modes' <- mapM setGet modes
+    modes' @?= modes
+  where
+    modes =
+      [ GLFW.CursorInputMode'Disabled
+      , GLFW.CursorInputMode'Hidden
+      , GLFW.CursorInputMode'Normal
+      ]
+    setGet m = do
+        GLFW.setCursorInputMode win m
+        GLFW.getCursorInputMode win
+
+test_sticky_keys_input_mode :: GLFW.Window -> IO ()
+test_sticky_keys_input_mode win = do
+    modes' <- mapM setGet modes
+    modes' @?= modes
+  where
+    modes =
+      [ GLFW.StickyKeysInputMode'Enabled
+      , GLFW.StickyKeysInputMode'Disabled
+      ]
+    setGet m = do
+        GLFW.setStickyKeysInputMode win m
+        GLFW.getStickyKeysInputMode win
+
+test_sticky_mouse_buttons_input_mode :: GLFW.Window -> IO ()
+test_sticky_mouse_buttons_input_mode win = do
+    modes' <- mapM setGet modes
+    modes' @?= modes
+  where
+    modes =
+      [ GLFW.StickyMouseButtonsInputMode'Enabled
+      , GLFW.StickyMouseButtonsInputMode'Disabled
+      ]
+    setGet m = do
+        GLFW.setStickyMouseButtonsInputMode win m
+        GLFW.getStickyMouseButtonsInputMode win
+
+test_joystickPresent :: IO ()
+test_joystickPresent = do
+    _ <- GLFW.joystickPresent GLFW.Joystick'1
+    r <- GLFW.joystickPresent GLFW.Joystick'16
+    assertBool "" $ not r
+
+test_getJoystickAxes :: IO ()
+test_getJoystickAxes =
+    mapM_ GLFW.getJoystickAxes joysticks
+
+test_getJoystickButtons :: IO ()
+test_getJoystickButtons =
+    mapM_ GLFW.getJoystickButtons joysticks
+
+test_getJoystickName :: IO ()
+test_getJoystickName =
+    mapM_ GLFW.getJoystickName joysticks
+
+test_getKeyName :: IO ()
+test_getKeyName =
+  forM_ (zip [GLFW.Key'Slash, GLFW.Key'Period] ["/", "."]) $ \(k, n) -> do
+    name <- GLFW.getKeyName k 0
+    case name of
+      Nothing -> return ()
+      Just s -> s @?= n
+
+--------------------------------------------------------------------------------
+
+test_getTime :: IO ()
+test_getTime = do
+    mt <- GLFW.getTime
+    case mt of
+      Nothing -> assertFailure ""
+      Just t  -> assertBool "" $ t `between` (0, 10)
+
+test_setTime :: IO ()
+test_setTime = do
+    let t = 37
+    GLFW.setTime t
+    mt <- GLFW.getTime
+    case mt of
+      Just t' -> assertBool "" $ t' `between` (t, t+10)
+      Nothing -> assertFailure ""
+
+test_getTimerValue :: IO ()
+test_getTimerValue = GLFW.getTimerValue >>= assertBool "" . (> 0)
+
+test_getTimerFrequency :: IO ()
+test_getTimerFrequency = GLFW.getTimerFrequency >>= assertBool "" . (> 0)
+
+--------------------------------------------------------------------------------
+
+test_getCurrentContext :: GLFW.Window -> IO ()
+test_getCurrentContext win = do
+    mwin <- GLFW.getCurrentContext
+    case mwin of
+      Nothing   -> assertFailure ""
+      Just win' -> win' @?= win
+
+test_swapBuffers :: GLFW.Window -> IO ()
+test_swapBuffers =
+    GLFW.swapBuffers
+
+test_swapInterval :: IO ()
+test_swapInterval =
+    GLFW.swapInterval 1
+
+test_extensionSupported :: IO ()
+test_extensionSupported = do
+    b0 <- GLFW.extensionSupported "GL_ARB_multisample"
+    b0 @?= True
+    b1 <- GLFW.extensionSupported "bogus"
+    b1 @?= False
+
+--------------------------------------------------------------------------------
+
+test_clipboard :: GLFW.Window -> IO ()
+test_clipboard win = do
+    rs <- mapM setGet ss
+    rs @?= map Just ss
+  where
+    ss =
+      [ "abc 123 ???"
+      , "xyz 456 !!!"
+      ]
+    setGet s = do
+        GLFW.setClipboardString win s
+        giveItTime
+        GLFW.getClipboardString win
+
+--------------------------------------------------------------------------------
+
+{-# ANN module "HLint: ignore Use camelCase" #-}