bindings-GLFW 3.1.2.4 → 3.2.1.0
raw patch · 62 files changed
+17238/−11187 lines, 62 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Bindings.GLFW: c'GL_FALSE :: (Num a) => a
- Bindings.GLFW: c'GL_TRUE :: (Num a) => a
+ Bindings.GLFW: c'GLFW_ANY_RELEASE_BEHAVIOR :: (Num a) => a
+ Bindings.GLFW: c'GLFW_AUTO_ICONIFY :: (Num a) => a
+ Bindings.GLFW: c'GLFW_CONTEXT_CREATION_API :: (Num a) => a
+ Bindings.GLFW: c'GLFW_CONTEXT_NO_ERROR :: (Num a) => a
+ Bindings.GLFW: c'GLFW_CONTEXT_RELEASE_BEHAVIOR :: (Num a) => a
+ Bindings.GLFW: c'GLFW_DONT_CARE :: (Num a) => a
+ Bindings.GLFW: c'GLFW_DOUBLEBUFFER :: (Num a) => a
+ Bindings.GLFW: c'GLFW_EGL_CONTEXT_API :: (Num a) => a
+ Bindings.GLFW: c'GLFW_FALSE :: (Num a) => a
+ Bindings.GLFW: c'GLFW_FLOATING :: (Num a) => a
+ Bindings.GLFW: c'GLFW_MAXIMIZED :: (Num a) => a
+ Bindings.GLFW: c'GLFW_NATIVE_CONTEXT_API :: (Num a) => a
+ Bindings.GLFW: c'GLFW_NO_API :: (Num a) => a
+ Bindings.GLFW: c'GLFW_RELEASE_BEHAVIOR_FLUSH :: (Num a) => a
+ Bindings.GLFW: c'GLFW_RELEASE_BEHAVIOR_NONE :: (Num a) => a
+ Bindings.GLFW: c'GLFW_TRUE :: (Num a) => a
+ Bindings.GLFW: c'glfwCreateWindowSurface :: Ptr vkInstance -> Ptr C'GLFWwindow -> Ptr vkAllocationCallbacks -> Ptr vkSurfaceKHR -> IO Int32
+ Bindings.GLFW: c'glfwFocusWindow :: Ptr C'GLFWwindow -> IO ()
+ Bindings.GLFW: c'glfwGetCocoaMonitor :: Ptr C'GLFWwindow -> IO (Ptr Word32)
+ Bindings.GLFW: c'glfwGetCocoaWindow :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetEGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetEGLDisplay :: IO (Ptr ())
+ Bindings.GLFW: c'glfwGetEGLSurface :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetGLXContext :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetGLXWindow :: Ptr C'GLFWwindow -> IO Word64
+ Bindings.GLFW: c'glfwGetInstanceProcAddress :: Ptr vkInstance -> CString -> IO (FunPtr vkProc)
+ Bindings.GLFW: c'glfwGetKeyName :: CInt -> CInt -> IO CString
+ Bindings.GLFW: c'glfwGetMirDisplay :: IO (Ptr mir_connection)
+ Bindings.GLFW: c'glfwGetMirMonitor :: Ptr C'GLFWwindow -> IO CInt
+ Bindings.GLFW: c'glfwGetMirWindow :: Ptr C'GLFWwindow -> IO (Ptr mir_surface)
+ Bindings.GLFW: c'glfwGetNSGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetPhysicalDevicePresentationSupport :: Ptr vkInstance -> Ptr vkPhysicalDevice -> Word32 -> IO CInt
+ Bindings.GLFW: c'glfwGetRequiredInstanceExtensions :: Ptr Word32 -> IO (Ptr CString)
+ Bindings.GLFW: c'glfwGetTimerFrequency :: IO (CULong)
+ Bindings.GLFW: c'glfwGetTimerValue :: IO (CULong)
+ Bindings.GLFW: c'glfwGetWGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetWaylandDisplay :: IO (Ptr wl_display)
+ Bindings.GLFW: c'glfwGetWaylandMonitor :: Ptr C'GLFWwindow -> IO (Ptr wl_output)
+ Bindings.GLFW: c'glfwGetWaylandWindow :: Ptr C'GLFWwindow -> IO (Ptr wl_surface)
+ Bindings.GLFW: c'glfwGetWin32Adapter :: Ptr C'GLFWwindow -> IO CString
+ Bindings.GLFW: c'glfwGetWin32Monitor :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetWin32Window :: Ptr C'GLFWwindow -> IO (Ptr ())
+ Bindings.GLFW: c'glfwGetWindowFrameSize :: Ptr C'GLFWwindow -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ()
+ Bindings.GLFW: c'glfwGetX11Adapter :: Ptr C'GLFWwindow -> IO Word64
+ Bindings.GLFW: c'glfwGetX11Display :: Ptr C'GLFWwindow -> IO (Ptr display)
+ Bindings.GLFW: c'glfwGetX11Monitor :: Ptr C'GLFWwindow -> IO Word64
+ Bindings.GLFW: c'glfwGetX11Window :: Ptr C'GLFWwindow -> IO Word64
+ Bindings.GLFW: c'glfwMaximizeWindow :: Ptr C'GLFWwindow -> IO ()
+ Bindings.GLFW: c'glfwSetCharModsCallback :: Ptr C'GLFWwindow -> C'GLFWcharmodsfun -> IO C'GLFWcharmodsfun
+ Bindings.GLFW: c'glfwSetJoystickCallback :: C'GLFWjoystickfun -> IO C'GLFWjoystickfun
+ Bindings.GLFW: c'glfwSetWindowAspectRatio :: Ptr C'GLFWwindow -> CInt -> CInt -> IO ()
+ Bindings.GLFW: c'glfwSetWindowIcon :: Ptr C'GLFWwindow -> CInt -> Ptr C'GLFWimage -> IO ()
+ Bindings.GLFW: c'glfwSetWindowMonitor :: Ptr C'GLFWwindow -> Ptr C'GLFWmonitor -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()
+ Bindings.GLFW: c'glfwSetWindowSizeLimits :: Ptr C'GLFWwindow -> CInt -> CInt -> CInt -> CInt -> IO ()
+ Bindings.GLFW: c'glfwVulkanSupported :: IO CInt
+ Bindings.GLFW: c'glfwWaitEventsTimeout :: CDouble -> IO ()
+ Bindings.GLFW: mK'GLFWcharmodsfun :: C'GLFWcharmodsfun -> (Ptr C'GLFWwindow -> CUInt -> CInt -> IO ())
+ Bindings.GLFW: mK'GLFWjoystickfun :: C'GLFWjoystickfun -> (CInt -> CInt -> IO ())
+ Bindings.GLFW: mk'GLFWcharmodsfun :: (Ptr C'GLFWwindow -> CUInt -> CInt -> IO ()) -> IO C'GLFWcharmodsfun
+ Bindings.GLFW: mk'GLFWjoystickfun :: (CInt -> CInt -> IO ()) -> IO C'GLFWjoystickfun
+ Bindings.GLFW: p'glfwCreateWindowSurface :: FunPtr (Ptr vkInstance -> Ptr C'GLFWwindow -> Ptr vkAllocationCallbacks -> Ptr vkSurfaceKHR -> IO Int32)
+ Bindings.GLFW: p'glfwFocusWindow :: FunPtr (Ptr C'GLFWwindow -> IO ())
+ Bindings.GLFW: p'glfwGetCocoaMonitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr Word32))
+ Bindings.GLFW: p'glfwGetCocoaWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetEGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetEGLDisplay :: FunPtr (IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetEGLSurface :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetGLXContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetGLXWindow :: FunPtr (Ptr C'GLFWwindow -> IO Word64)
+ Bindings.GLFW: p'glfwGetInstanceProcAddress :: FunPtr (Ptr vkInstance -> CString -> IO (FunPtr vkProc))
+ Bindings.GLFW: p'glfwGetKeyName :: FunPtr (CInt -> CInt -> IO CString)
+ Bindings.GLFW: p'glfwGetMirDisplay :: FunPtr (IO (Ptr mir_connection))
+ Bindings.GLFW: p'glfwGetMirMonitor :: FunPtr (Ptr C'GLFWwindow -> IO CInt)
+ Bindings.GLFW: p'glfwGetMirWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr mir_surface))
+ Bindings.GLFW: p'glfwGetNSGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetPhysicalDevicePresentationSupport :: FunPtr (Ptr vkInstance -> Ptr vkPhysicalDevice -> Word32 -> IO CInt)
+ Bindings.GLFW: p'glfwGetRequiredInstanceExtensions :: FunPtr (Ptr Word32 -> IO (Ptr CString))
+ Bindings.GLFW: p'glfwGetTimerFrequency :: FunPtr (IO (CULong))
+ Bindings.GLFW: p'glfwGetTimerValue :: FunPtr (IO (CULong))
+ Bindings.GLFW: p'glfwGetWGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetWaylandDisplay :: FunPtr (IO (Ptr wl_display))
+ Bindings.GLFW: p'glfwGetWaylandMonitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr wl_output))
+ Bindings.GLFW: p'glfwGetWaylandWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr wl_surface))
+ Bindings.GLFW: p'glfwGetWin32Adapter :: FunPtr (Ptr C'GLFWwindow -> IO CString)
+ Bindings.GLFW: p'glfwGetWin32Monitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetWin32Window :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))
+ Bindings.GLFW: p'glfwGetWindowFrameSize :: FunPtr (Ptr C'GLFWwindow -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ())
+ Bindings.GLFW: p'glfwGetX11Adapter :: FunPtr (Ptr C'GLFWwindow -> IO Word64)
+ Bindings.GLFW: p'glfwGetX11Display :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr display))
+ Bindings.GLFW: p'glfwGetX11Monitor :: FunPtr (Ptr C'GLFWwindow -> IO Word64)
+ Bindings.GLFW: p'glfwGetX11Window :: FunPtr (Ptr C'GLFWwindow -> IO Word64)
+ Bindings.GLFW: p'glfwMaximizeWindow :: FunPtr (Ptr C'GLFWwindow -> IO ())
+ Bindings.GLFW: p'glfwSetCharModsCallback :: FunPtr (Ptr C'GLFWwindow -> C'GLFWcharmodsfun -> IO C'GLFWcharmodsfun)
+ Bindings.GLFW: p'glfwSetJoystickCallback :: FunPtr (C'GLFWjoystickfun -> IO C'GLFWjoystickfun)
+ Bindings.GLFW: p'glfwSetWindowAspectRatio :: FunPtr (Ptr C'GLFWwindow -> CInt -> CInt -> IO ())
+ Bindings.GLFW: p'glfwSetWindowIcon :: FunPtr (Ptr C'GLFWwindow -> CInt -> Ptr C'GLFWimage -> IO ())
+ Bindings.GLFW: p'glfwSetWindowMonitor :: FunPtr (Ptr C'GLFWwindow -> Ptr C'GLFWmonitor -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ())
+ Bindings.GLFW: p'glfwSetWindowSizeLimits :: FunPtr (Ptr C'GLFWwindow -> CInt -> CInt -> CInt -> CInt -> IO ())
+ Bindings.GLFW: p'glfwVulkanSupported :: FunPtr (IO CInt)
+ Bindings.GLFW: p'glfwWaitEventsTimeout :: FunPtr (CDouble -> IO ())
+ Bindings.GLFW: type C'GLFWcharmodsfun = FunPtr (Ptr C'GLFWwindow -> CUInt -> CInt -> IO ())
+ Bindings.GLFW: type C'GLFWjoystickfun = FunPtr (CInt -> CInt -> IO ())
Files
- Bindings/GLFW.hsc +304/−8
- README.md +8/−18
- Test.hs +216/−43
- bindings-GLFW.cabal +11/−8
- glfw/include/GLFW/glfw3.h +4220/−3331
- glfw/include/GLFW/glfw3native.h +172/−72
- glfw/src/cocoa_init.m +144/−18
- glfw/src/cocoa_joystick.h +60/−0
- glfw/src/cocoa_joystick.m +511/−0
- glfw/src/cocoa_monitor.m +38/−64
- glfw/src/cocoa_platform.h +58/−32
- glfw/src/cocoa_time.c +60/−0
- glfw/src/cocoa_window.m +610/−244
- glfw/src/context.c +233/−178
- glfw/src/egl_context.c +453/−240
- glfw/src/egl_context.h +163/−35
- glfw/src/glx_context.c +356/−237
- glfw/src/glx_context.h +128/−66
- glfw/src/init.c +20/−21
- glfw/src/input.c +198/−143
- glfw/src/internal.h +346/−177
- glfw/src/iokit_joystick.h +0/−61
- glfw/src/iokit_joystick.m +0/−506
- glfw/src/linux_joystick.c +112/−95
- glfw/src/linux_joystick.h +26/−21
- glfw/src/mach_time.c +0/−71
- glfw/src/mir_init.c +154/−17
- glfw/src/mir_monitor.c +52/−8
- glfw/src/mir_platform.h +41/−21
- glfw/src/mir_window.c +435/−274
- glfw/src/monitor.c +62/−27
- glfw/src/nsgl_context.h +13/−15
- glfw/src/nsgl_context.m +106/−112
- glfw/src/posix_time.c +24/−36
- glfw/src/posix_time.h +8/−9
- glfw/src/posix_tls.c +14/−12
- glfw/src/posix_tls.h +8/−8
- glfw/src/vulkan.c +302/−0
- glfw/src/wgl_context.c +403/−394
- glfw/src/wgl_context.h +110/−42
- glfw/src/win32_init.c +161/−82
- glfw/src/win32_joystick.c +763/−0
- glfw/src/win32_joystick.h +64/−0
- glfw/src/win32_monitor.c +141/−88
- glfw/src/win32_platform.h +158/−58
- glfw/src/win32_time.c +19/−31
- glfw/src/win32_tls.c +12/−12
- glfw/src/win32_tls.h +0/−48
- glfw/src/win32_window.c +1709/−1297
- glfw/src/window.c +338/−174
- glfw/src/winmm_joystick.c +0/−177
- glfw/src/winmm_joystick.h +0/−47
- glfw/src/wl_init.c +184/−156
- glfw/src/wl_monitor.c +27/−8
- glfw/src/wl_platform.h +60/−21
- glfw/src/wl_window.c +631/−105
- glfw/src/x11_init.c +190/−177
- glfw/src/x11_monitor.c +33/−36
- glfw/src/x11_platform.h +91/−62
- glfw/src/x11_window.c +2454/−1920
- glfw/src/xkb_unicode.c +20/−20
- glfw/src/xkb_unicode.h +4/−4
Bindings/GLFW.hsc view
@@ -7,6 +7,7 @@ #include <bindings.dsl.h> #include <GLFW/glfw3.h>+ #ifdef ExposeNative #warning "You are compiling glfw using the native access functions. BEWARE." @@ -22,8 +23,16 @@ #elif defined(__linux__) - #define GLFW_EXPOSE_NATIVE_X11- #define GLFW_EXPOSE_NATIVE_GLX+ #if defined(BINDINGS_GLFW_USE_X11)+ #define GLFW_EXPOSE_NATIVE_X11+ #define GLFW_EXPOSE_NATIVE_GLX+ #elif defined(BINDINGS_GLFW_USE_WAYLAND)+ #define GLFW_EXPOSE_NATIVE_WAYLAND+ #define GLFW_EXPOSE_NATIVE_EGL+ #elif defined(BINDINGS_GLFW_USE_MIR)+ #define GLFW_EXPOSE_NATIVE_MIR+ #define GLFW_EXPOSE_NATIVE_EGL+ #endif #endif @@ -36,19 +45,19 @@ module Bindings.GLFW where import Prelude (Eq, IO, Num, Show)-import Prelude (($), return)+import Prelude (($), return, error, (++)) import Data.Data (Data)+import Data.Int (Int32)+import Data.Word (Word32, Word64) import Data.Typeable (Typeable) import Foreign.C.Types (CChar, CUChar, CUShort)-import Foreign.C.Types (CDouble(..), CFloat(..), CInt(..), CUInt(..))-import Foreign.Ptr (FunPtr, Ptr, plusPtr)+import Foreign.C.Types (CDouble(..), CFloat(..), CInt(..), CUInt(..), CULong(..))+import Foreign.C.String (CString)+import Foreign.Ptr (FunPtr, nullFunPtr, Ptr, plusPtr) import Foreign.Storable (Storable(..)) -------------------------------------------------------------------------------- -#num GL_FALSE-#num GL_TRUE- #num GLFW_VERSION_MAJOR #num GLFW_VERSION_MINOR #num GLFW_VERSION_REVISION@@ -406,6 +415,14 @@ #num GLFW_HAND_CURSOR #num GLFW_HRESIZE_CURSOR #num GLFW_VRESIZE_CURSOR+#num GLFW_DONT_CARE+#num GLFW_DOUBLEBUFFER+#num GLFW_AUTO_ICONIFY+#num GLFW_FLOATING+#num GLFW_CONTEXT_RELEASE_BEHAVIOR+#num GLFW_ANY_RELEASE_BEHAVIOR+#num GLFW_RELEASE_BEHAVIOR_FLUSH+#num GLFW_RELEASE_BEHAVIOR_NONE #starttype GLFWimage #field width , CInt@@ -418,9 +435,288 @@ deriving instance Data C'GLFWcursor #callback GLFWdropfun , Ptr <GLFWwindow> -> CInt -> Ptr (Ptr CChar) -> IO ()+#callback GLFWcharmodsfun , Ptr <GLFWwindow> -> CUInt -> CInt -> IO () #ccall glfwCreateCursor , Ptr <GLFWimage> -> CInt -> CInt -> IO (Ptr <GLFWcursor>) #ccall glfwCreateStandardCursor , CInt -> IO (Ptr <GLFWcursor>) #ccall glfwSetCursor , Ptr <GLFWwindow> -> Ptr <GLFWcursor> -> IO () #ccall glfwDestroyCursor , Ptr <GLFWcursor> -> IO () #ccall glfwSetDropCallback , Ptr <GLFWwindow> -> <GLFWdropfun> -> IO <GLFWdropfun>+#ccall glfwSetCharModsCallback , Ptr <GLFWwindow> -> <GLFWcharmodsfun> -> IO <GLFWcharmodsfun>+#ccall glfwGetWindowFrameSize , Ptr <GLFWwindow> -> Ptr CInt -> Ptr CInt -> Ptr CInt -> Ptr CInt -> IO ()++--------------------------------------------------------------------------------+-- GLFW 3.2 additions+--------------------------------------------------------------------------------++#num GLFW_NO_API+#num GLFW_CONTEXT_CREATION_API+#num GLFW_NATIVE_CONTEXT_API+#num GLFW_EGL_CONTEXT_API+#num GLFW_CONTEXT_NO_ERROR+#num GLFW_TRUE+#num GLFW_FALSE+#num GLFW_MAXIMIZED++#ccall glfwFocusWindow , Ptr <GLFWwindow> -> IO ()+#ccall glfwMaximizeWindow , Ptr <GLFWwindow> -> IO ()+#ccall glfwSetWindowMonitor , Ptr <GLFWwindow> -> Ptr <GLFWmonitor> -> CInt -> CInt -> CInt -> CInt -> CInt -> IO ()+#ccall glfwSetWindowIcon , Ptr <GLFWwindow> -> CInt -> Ptr <GLFWimage> -> IO ()+#ccall glfwWaitEventsTimeout , CDouble -> IO ()+#ccall glfwSetWindowSizeLimits , Ptr <GLFWwindow> -> CInt -> CInt -> CInt -> CInt -> IO ()+#ccall glfwSetWindowAspectRatio , Ptr <GLFWwindow> -> CInt -> CInt -> IO ()+#ccall glfwGetKeyName , CInt -> CInt -> IO CString+#ccall glfwGetTimerValue , IO (CULong)+#ccall glfwGetTimerFrequency , IO (CULong)++#callback GLFWjoystickfun , CInt -> CInt -> IO ()+#ccall glfwSetJoystickCallback , <GLFWjoystickfun> -> IO <GLFWjoystickfun>++#ccall glfwVulkanSupported , IO CInt+#ccall glfwGetRequiredInstanceExtensions , Ptr Word32 -> IO (Ptr CString)++-- GLFW prevents the declaration of some of the Vulkan functions in its header+-- glfw3.h if it cannot find the required Vulkan headers. As of now (4/2018),+-- these functions are still *defined* in vulkan.c, which is built regardless of+-- whether or not the Vulkan headers were found. Internally, the required types+-- are defined locally in order to make the build work, and h2c will still link+-- against them without a problem. Whether or not you have a valid Vulkan+-- implementation might not be clear though. Nothing is preventing the glfw3+-- authors from hiding the Vulkan functions without valid headers, which could+-- cause some pain in the future, so use the following functions with caution.+-- See commit @521d161af85047 for a way to deal with this more annoyingly.+#ccall glfwGetInstanceProcAddress , Ptr vkInstance -> CString -> IO (FunPtr vkProc)+#ccall glfwGetPhysicalDevicePresentationSupport , Ptr vkInstance -> Ptr vkPhysicalDevice -> Word32 -> IO CInt+#ccall glfwCreateWindowSurface , Ptr vkInstance -> Ptr <GLFWwindow> -> Ptr vkAllocationCallbacks -> Ptr vkSurfaceKHR -> IO Int32+++--------------------------------------------------------------------------------+-- Native APIs+--------------------------------------------------------------------------------++#if defined(GLFW_EXPOSE_NATIVE_WIN32)+#ccall glfwGetWin32Adapter , Ptr <GLFWwindow> -> IO CString+#ccall glfwGetWin32Monitor , Ptr <GLFWwindow> -> IO (Ptr ())+#ccall glfwGetWin32Window , Ptr <GLFWwindow> -> IO (Ptr ())+#else++p'glfwGetWin32Adapter :: FunPtr (Ptr C'GLFWwindow -> IO CString)+p'glfwGetWin32Adapter = nullFunPtr++c'glfwGetWin32Adapter :: Ptr C'GLFWwindow -> IO CString+c'glfwGetWin32Adapter =+ error $ "c'glfwGetWin32Adapter undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetWin32Monitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetWin32Monitor = nullFunPtr++c'glfwGetWin32Monitor :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetWin32Monitor =+ error $ "c'glfwGetWin32Monitor undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetWin32Window :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetWin32Window = nullFunPtr++c'glfwGetWin32Window :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetWin32Window =+ error $ "c'glfwGetWin32Window undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_WGL)+#ccall glfwGetWGLContext , Ptr <GLFWwindow> -> IO (Ptr ())+#else+p'glfwGetWGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetWGLContext = nullFunPtr++c'glfwGetWGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetWGLContext =+ error $ "c'glfwGetWGLContext undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_COCOA)+#ccall glfwGetCocoaMonitor , Ptr <GLFWwindow> -> IO (Ptr Word32)+#ccall glfwGetCocoaWindow , Ptr <GLFWwindow> -> IO (Ptr ())+#else+p'glfwGetCocoaMonitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr Word32))+p'glfwGetCocoaMonitor = nullFunPtr++c'glfwGetCocoaMonitor :: Ptr C'GLFWwindow -> IO (Ptr Word32)+c'glfwGetCocoaMonitor =+ error $ "c'glfwGetCocoaMonitor undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetCocoaWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetCocoaWindow = nullFunPtr++c'glfwGetCocoaWindow :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetCocoaWindow =+ error $ "c'glfwGetCocoaWindow undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_NSGL)+#ccall glfwGetNSGLContext , Ptr <GLFWwindow> -> IO (Ptr ())+#else+p'glfwGetNSGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetNSGLContext = nullFunPtr++c'glfwGetNSGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetNSGLContext =+ error $ "c'glfwGetNSGLContext undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_X11)+#ccall glfwGetX11Display , Ptr <GLFWwindow> -> IO (Ptr display)+#ccall glfwGetX11Adapter , Ptr <GLFWwindow> -> IO Word64+#ccall glfwGetX11Monitor , Ptr <GLFWwindow> -> IO Word64+#ccall glfwGetX11Window , Ptr <GLFWwindow> -> IO Word64+#else+p'glfwGetX11Display :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr display))+p'glfwGetX11Display = nullFunPtr++c'glfwGetX11Display :: Ptr C'GLFWwindow -> IO (Ptr display)+c'glfwGetX11Display =+ error $ "c'glfwGetX11Display undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetX11Adapter :: FunPtr (Ptr C'GLFWwindow -> IO Word64)+p'glfwGetX11Adapter = nullFunPtr++c'glfwGetX11Adapter :: Ptr C'GLFWwindow -> IO Word64+c'glfwGetX11Adapter =+ error $ "c'glfwGetX11Adapter undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetX11Monitor :: FunPtr (Ptr C'GLFWwindow -> IO Word64)+p'glfwGetX11Monitor = nullFunPtr++c'glfwGetX11Monitor :: Ptr C'GLFWwindow -> IO Word64+c'glfwGetX11Monitor =+ error $ "c'glfwGetX11Monitor undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetX11Window :: FunPtr (Ptr C'GLFWwindow -> IO Word64)+p'glfwGetX11Window = nullFunPtr++c'glfwGetX11Window :: Ptr C'GLFWwindow -> IO Word64+c'glfwGetX11Window =+ error $ "c'glfwGetX11Window undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_GLX)+#ccall glfwGetGLXContext , Ptr <GLFWwindow> -> IO (Ptr ())+#ccall glfwGetGLXWindow , Ptr <GLFWwindow> -> IO Word64+#else+p'glfwGetGLXContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetGLXContext = nullFunPtr++c'glfwGetGLXContext :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetGLXContext =+ error $ "c'glfwGetGLXContext undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetGLXWindow :: FunPtr (Ptr C'GLFWwindow -> IO Word64)+p'glfwGetGLXWindow = nullFunPtr++c'glfwGetGLXWindow :: Ptr C'GLFWwindow -> IO Word64+c'glfwGetGLXWindow =+ error $ "c'glfwGetGLXWindow undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)+#ccall glfwGetWaylandDisplay , IO (Ptr wl_display)+#ccall glfwGetWaylandMonitor , Ptr <GLFWwindow> -> IO (Ptr wl_output)+#ccall glfwGetWaylandWindow , Ptr <GLFWwindow> -> IO (Ptr wl_surface)+#else+p'glfwGetWaylandDisplay :: FunPtr (IO (Ptr wl_display))+p'glfwGetWaylandDisplay = nullFunPtr++c'glfwGetWaylandDisplay :: IO (Ptr wl_display)+c'glfwGetWaylandDisplay =+ error $ "c'glfwGetWaylandDisplay undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetWaylandMonitor :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr wl_output))+p'glfwGetWaylandMonitor = nullFunPtr++c'glfwGetWaylandMonitor :: Ptr C'GLFWwindow -> IO (Ptr wl_output)+c'glfwGetWaylandMonitor =+ error $ "c'glfwGetWaylandMonitor undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetWaylandWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr wl_surface))+p'glfwGetWaylandWindow = nullFunPtr++c'glfwGetWaylandWindow :: Ptr C'GLFWwindow -> IO (Ptr wl_surface)+c'glfwGetWaylandWindow =+ error $ "c'glfwGetWaylandWindow undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_MIR)+#ccall glfwGetMirDisplay , IO (Ptr mir_connection)+#ccall glfwGetMirMonitor , Ptr <GLFWwindow> -> IO CInt+#ccall glfwGetMirWindow , Ptr <GLFWwindow> -> IO (Ptr mir_surface)+#else+p'glfwGetMirDisplay :: FunPtr (IO (Ptr mir_connection))+p'glfwGetMirDisplay = nullFunPtr++c'glfwGetMirDisplay :: IO (Ptr mir_connection)+c'glfwGetMirDisplay =+ error $ "c'glfwGetMirDisplay undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetMirMonitor :: FunPtr (Ptr C'GLFWwindow -> IO CInt)+p'glfwGetMirMonitor = nullFunPtr++c'glfwGetMirMonitor :: Ptr C'GLFWwindow -> IO CInt+c'glfwGetMirMonitor =+ error $ "c'glfwGetMirMonitor undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetMirWindow :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr mir_surface))+p'glfwGetMirWindow = nullFunPtr++c'glfwGetMirWindow :: Ptr C'GLFWwindow -> IO (Ptr mir_surface)+c'glfwGetMirWindow =+ error $ "c'glfwGetMirWindow undefined! -- "+ ++ "Did you use the wrong glfw3native API?"+#endif++#if defined(GLFW_EXPOSE_NATIVE_EGL)+#ccall glfwGetEGLDisplay , IO (Ptr ())+#ccall glfwGetEGLContext , Ptr <GLFWwindow> -> IO (Ptr ())+#ccall glfwGetEGLSurface , Ptr <GLFWwindow> -> IO (Ptr ())+#else+p'glfwGetEGLDisplay :: FunPtr (IO (Ptr ()))+p'glfwGetEGLDisplay = nullFunPtr++c'glfwGetEGLDisplay :: IO (Ptr ())+c'glfwGetEGLDisplay =+ error $ "c'glfwGetEGLDisplay undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetEGLContext :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetEGLContext = nullFunPtr++c'glfwGetEGLContext :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetEGLContext =+ error $ "c'glfwGetEGLContext undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++p'glfwGetEGLSurface :: FunPtr (Ptr C'GLFWwindow -> IO (Ptr ()))+p'glfwGetEGLSurface = nullFunPtr++c'glfwGetEGLSurface :: Ptr C'GLFWwindow -> IO (Ptr ())+c'glfwGetEGLSurface =+ error $ "c'glfwGetEGLSurface undefined! -- "+ ++ "Did you use the wrong glfw3native API?"++#endif
README.md view
@@ -9,30 +9,20 @@ library for creating windows with OpenGL contexts and managing input and events. -The binding is to [GLFW 3.1 released 2015-01-18][3].+The binding is to [GLFW 3.2.1 released 2016-08-18][3]. -*These bindings are too low-level for normal use.* For higher-level GLFW-bindings, see [GLFW-b][4].+*These bindings are a lot lower level than intended for normal use.*+For higher-level GLFW bindings, see [GLFW-b][4]. ## Contributing -This package uses git-flow as development model, in short that means that:--1. New features should be added to "develop" branch.-2. "master" branch is reserved for stable releases.-3. Patches for bugs related with previous releases should always be done in- "hotfixes" branch.-4. All merge commits to master from "hotfixes" should be done- using the "--no-ff" flag and from "develop" should avoid merging commits.--Until we have a defined road-map we are going to leave out "release-"branches" and "feature branches". For more information about this development-model please refer to [this site.][5]+1. To add a new feature or fix a bug, please start a new branch with a+ meaningful name (not "feature").+2. "master" branch is reserved as the current up-to-date working tree. -Thanks you, and happy coding.+Thank you, and happy coding. [1]: http://www.haskell.org/ [2]: http://www.glfw.org/-[3]: http://www.glfw.org/Version-3.1-released.html+[3]: http://www.glfw.org/Version-3.2.1-released.html [4]: https://github.com/bsl/GLFW-b-[5]: http://nvie.com/posts/a-successful-git-branching-model/
Test.hs view
@@ -4,13 +4,14 @@ import Data.Char (isAscii) import Data.List (intercalate, isPrefixOf) import Foreign.C.String (peekCString, withCString)+import Foreign.C.Types (CDouble(..)) import Foreign.Marshal.Alloc (alloca) import Foreign.Marshal.Array (peekArray)-import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Ptr (Ptr, nullPtr, nullFunPtr) import Foreign.Storable (Storable(..)) -- HUnit-import Test.HUnit ((@?=), assertBool, assertFailure)+import Test.HUnit ((@?=), (@?), assertBool, assertFailure) -- test-framework import Test.Framework (Test, defaultMain, testGroup)@@ -39,11 +40,19 @@ p'mon <- c'glfwGetPrimaryMonitor - c'glfwWindowHint c'GLFW_VISIBLE c'GL_FALSE+ c'glfwWindowHint c'GLFW_VISIBLE c'GLFW_FALSE p'win <- withCString "bindings-GLFW test" $ \p'title -> c'glfwCreateWindow 100 100 p'title nullPtr nullPtr c'glfwMakeContextCurrent p'win + -- Mostly check for compiling+ cmcb <- mk'GLFWcharmodsfun $ \win x y ->+ putStrLn $ "Got char mods callback! " ++ show (win, x, y)+ _ <- c'glfwSetCharModsCallback p'win cmcb+ jcb <- mk'GLFWjoystickfun $ \x y ->+ putStrLn $ "Got joystick callback! " ++ show (x, y)+ _ <- c'glfwSetJoystickCallback jcb+ defaultMain $ tests p'mon p'win -- TODO because of how defaultMain works, this code is not reached@@ -54,7 +63,7 @@ versionMajor, versionMinor, versionRevision :: Int versionMajor = 3-versionMinor = 1+versionMinor = 2 versionRevision = 1 giveItTime :: IO ()@@ -114,30 +123,43 @@ -- , testCase "gamma ramp" $ test_glfwGamma_ramp p'mon ] , testGroup "Window handling"- [ testCase "glfwDefaultWindowHints" test_glfwDefaultWindowHints- , testCase "window close flag" $ test_window_close_flag p'win- , testCase "glfwSetWindowTitle" $ test_glfwSetWindowTitle p'win- , testCase "window pos" $ test_window_pos p'win- , testCase "window size" $ test_window_size p'win- , testCase "glfwGetFramebufferSize" $ test_glfwGetFramebufferSize p'win- , testCase "iconification" $ test_iconification p'win- -- , testCase "show/hide" $ test_show_hide p'win- , testCase "glfwGetWindowMonitor" $ test_glfwGetWindowMonitor p'win p'mon- , testCase "cursor pos" $ test_cursor_pos p'win- , testCase "glfwGetWindowAttrib" $ test_glfwGetWindowAttrib p'win- , testCase "glfwPollEvents" test_glfwPollEvents- , testCase "glfwWaitEvents" test_glfwWaitEvents+ [ testCase "glfwDefaultWindowHints" test_glfwDefaultWindowHints+ , testCase "glfwGetWindowAttrib" $ test_glfwGetWindowAttrib p'win+ , testCase "window close flag" $ test_window_close_flag p'win+ , testCase "glfwSetWindowTitle" $ test_glfwSetWindowTitle p'win+ , testCase "window pos" $ test_window_pos p'win+ , testCase "window size" $ test_window_size p'win+ , testCase "glfwGetWindowFrameSize" $ test_glfwGetWindowFrameSize p'win+ , testCase "glfwGetFramebufferSize" $ test_glfwGetFramebufferSize p'win+ , testCase "iconification" $ test_iconification p'win+ -- , testCase "show/hide" $ test_show_hide p'win+ , testCase "glfwGetWindowMonitor" $ test_glfwGetWindowMonitor p'win p'mon+ , testCase "glfwSetWindowMonitor" $ test_glfwSetWindowMonitor p'win p'mon+ , testCase "glfwSetWindowIcon" $ test_glfwSetWindowIcon p'win+ , testCase "glfwMaximizeWindow" $ test_glfwMaximizeWindow p'win+ , testCase "glfwSetWindowSizeLimits" $ test_glfwSetWindowSizeLimits p'win+ , testCase "glfwSetWindowAspectRatio" $ test_glfwSetWindowAspectRatio p'win+ , testCase "glfwFocusWindow" $ test_glfwFocusWindow p'win+ , testCase "cursor pos" $ test_cursor_pos p'win+ , testCase "glfwPollEvents" test_glfwPollEvents+ , testCase "glfwWaitEvents" test_glfwWaitEvents+ , testCase "glfwWaitEventsTimeout" test_glfwWaitEventsTimeout ] , testGroup "Input handling" [ testCase "glfwJoystickPresent" test_glfwJoystickPresent , testCase "glfwGetJoystickAxes" test_glfwGetJoystickAxes , testCase "glfwGetJoystickButtons" test_glfwGetJoystickButtons , testCase "glfwGetJoystickName" test_glfwGetJoystickName+ , testCase "glfwGetKeyName" test_glfwGetKeyName ] , testGroup "Time" [ testCase "glfwGetTime" test_glfwGetTime , testCase "glfwSetTime" test_glfwSetTime ]+ , testGroup "Timers"+ [ testCase "glfwGetTimerValue" test_glfwGetTimerValue+ , testCase "glfwSetTimerFrequency" test_glfwGetTimerFrequency+ ] , testGroup "Context" [ testCase "glfwGetCurrentContext" $ test_glfwGetCurrentContext p'win , testCase "glfwSwapBuffers" $ test_glfwSwapBuffers p'win@@ -147,6 +169,13 @@ , testGroup "Clipboard" [ testCase "clipboard" $ test_clipboard p'win ]+ , testGroup "Vulkan"+ [ testCase "glfwVulkanSupported" test_glfwVulkanSupported+ , testCase "glfwGetRequiredInstanceExtensions" test_glfwGetRequiredInstanceExtensions+ , testCase "glfwGetInstanceProcAddress" test_glfwGetInstanceProcAddress+ , testCase "glfwGetPhysicalDevicePresentationSupport" test_glfwGetPhysicalDevicePresentationSupport+ , testCase "glfwCreateWindowSurface" $ test_glfwCreateWindowSurface p'win+ ] ] --------------------------------------------------------------------------------@@ -275,15 +304,15 @@ test_window_close_flag :: Ptr C'GLFWwindow -> IO () test_window_close_flag p'win = do r0 <- c'glfwWindowShouldClose p'win- r0 @?= c'GL_FALSE+ r0 @?= c'GLFW_FALSE - c'glfwSetWindowShouldClose p'win c'GL_TRUE+ c'glfwSetWindowShouldClose p'win c'GLFW_TRUE r1 <- c'glfwWindowShouldClose p'win- r1 @?= c'GL_TRUE+ r1 @?= c'GLFW_TRUE - c'glfwSetWindowShouldClose p'win c'GL_FALSE+ c'glfwSetWindowShouldClose p'win c'GLFW_FALSE r2 <- c'glfwWindowShouldClose p'win- r2 @?= c'GL_FALSE+ r2 @?= c'GLFW_FALSE test_glfwSetWindowTitle :: Ptr C'GLFWwindow -> IO () test_glfwSetWindowTitle p'win =@@ -309,6 +338,7 @@ setGet :: Int -> Int -> IO (Int, Int, Int, Int) setGet x0 y0 = do c'glfwSetWindowPos p'win (fromIntegral x0) (fromIntegral y0)+ c'glfwSwapBuffers p'win giveItTime alloca $ \p'x1 -> alloca $ \p'y1 -> do@@ -320,8 +350,8 @@ test_window_size :: Ptr C'GLFWwindow -> IO () test_window_size p'win = do- let w = 17- h = 37+ let w = 177+ h = 372 c'glfwSetWindowSize p'win w h giveItTime alloca $ \p'w' ->@@ -332,6 +362,15 @@ w' @?= w h' @?= h +-- Really all we can say here is that we likely have a title bar, so just check+-- that the 'frame' around the top edge is > 0.+test_glfwGetWindowFrameSize :: Ptr C'GLFWwindow -> IO ()+test_glfwGetWindowFrameSize p'win =+ alloca $ \p'win_frame_top -> do+ c'glfwGetWindowFrameSize p'win nullPtr p'win_frame_top nullPtr nullPtr+ top <- peek p'win_frame_top+ assertBool "Window has no frame width up top!" $ top > 0+ test_glfwGetFramebufferSize :: Ptr C'GLFWwindow -> IO () test_glfwGetFramebufferSize p'win = alloca $ \p'w ->@@ -344,88 +383,146 @@ h <- peek p'h fw <- peek p'fw fh <- peek p'fh- fw @?= w- fh @?= h+ ((fw `mod` w) == 0) @? "Framebuffer width multiple of window's"+ ((fh `mod` h) == 0) @? "Framebuffer height multiple of window's" test_iconification :: Ptr C'GLFWwindow -> IO () test_iconification p'win = do+ c'glfwShowWindow p'win r0 <- c'glfwGetWindowAttrib p'win c'GLFW_ICONIFIED- r0 @?= c'GL_FALSE+ r0 @?= c'GLFW_FALSE c'glfwIconifyWindow p'win giveItTime r1 <- c'glfwGetWindowAttrib p'win c'GLFW_ICONIFIED- r1 @?= c'GL_TRUE+ r1 @?= c'GLFW_TRUE c'glfwRestoreWindow p'win+ c'glfwHideWindow p'win -- test_show_hide :: Ptr C'GLFWwindow -> IO () -- test_show_hide p'win = do -- v0 <- c'glfwGetWindowAttrib p'win c'GLFW_VISIBLE--- v0 @?= c'GL_FALSE+-- v0 @?= c'GLFW_FALSE -- c'glfwShowWindow p'win -- giveItTime -- v1 <- c'glfwGetWindowAttrib p'win c'GLFW_VISIBLE--- v1 @?= c'GL_TRUE+-- v1 @?= c'GLFW_TRUE -- c'glfwHideWindow p'win -- giveItTime -- v2 <- c'glfwGetWindowAttrib p'win c'GLFW_VISIBLE--- v2 @?= c'GL_FALSE+-- v2 @?= c'GLFW_FALSE test_glfwGetWindowMonitor :: Ptr C'GLFWwindow -> Ptr C'GLFWmonitor -> IO () test_glfwGetWindowMonitor p'win _ = do p'mon <- c'glfwGetWindowMonitor p'win p'mon @?= nullPtr +test_glfwSetWindowMonitor :: Ptr C'GLFWwindow -> Ptr C'GLFWmonitor -> IO ()+test_glfwSetWindowMonitor p'win _ = do+ c'glfwSetWindowMonitor p'win nullPtr 0 0 100 100 60++test_glfwSetWindowIcon :: Ptr C'GLFWwindow -> IO ()+test_glfwSetWindowIcon p'win = do+ c'glfwSetWindowIcon p'win 0 nullPtr++test_glfwSetWindowSizeLimits :: Ptr C'GLFWwindow -> IO ()+test_glfwSetWindowSizeLimits p'win = do+ c'glfwSetWindowSizeLimits p'win 640 480 1024 768++test_glfwSetWindowAspectRatio :: Ptr C'GLFWwindow -> IO ()+test_glfwSetWindowAspectRatio p'win = do+ c'glfwSetWindowAspectRatio p'win c'GLFW_DONT_CARE c'GLFW_DONT_CARE++test_glfwFocusWindow :: Ptr C'GLFWwindow -> IO ()+test_glfwFocusWindow = c'glfwFocusWindow++-- NOTE: This test seems to fail in X11. This might be due to the asynchronous+-- nature of focus events in X. We may be able to fix it by waiting for the focus+-- event before setting the cursor position. test_cursor_pos :: Ptr C'GLFWwindow -> IO () test_cursor_pos p'win = alloca $ \p'w -> alloca $ \p'h -> alloca $ \p'cx' -> alloca $ \p'cy' -> do+ c'glfwShowWindow p'win c'glfwGetWindowSize p'win p'w p'h w <- peek p'w h <- peek p'h- let cx = fromIntegral w / 2- cy = fromIntegral h / 2++ -- Make sure we use integral coordinates here so that we don't run into+ -- platform-dependent differences.+ let cx :: CDouble+ cy :: CDouble+ (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.++ c'glfwPollEvents+ c'glfwSetCursorPos p'win cx cy- giveItTime++ c'glfwPollEvents -- !HACK! see comment above+ c'glfwGetCursorPos p'win p'cx' p'cy' cx' <- peek p'cx' cy' <- peek p'cy' cx' @?= cx cy' @?= cy+ c'glfwHideWindow p'win test_glfwGetWindowAttrib :: Ptr C'GLFWwindow -> IO () test_glfwGetWindowAttrib p'win = do let pairs =- [ ( c'GLFW_FOCUSED, c'GL_FALSE )- , ( c'GLFW_ICONIFIED, c'GL_FALSE )- , ( c'GLFW_RESIZABLE, c'GL_TRUE )- , ( c'GLFW_DECORATED, c'GL_TRUE )+ [ ( c'GLFW_FOCUSED, c'GLFW_FALSE )+ , ( c'GLFW_ICONIFIED, c'GLFW_FALSE )+ , ( c'GLFW_RESIZABLE, c'GLFW_TRUE )+ , ( c'GLFW_DECORATED, c'GLFW_TRUE ) , ( c'GLFW_CLIENT_API, c'GLFW_OPENGL_API ) ] rs <- mapM (c'glfwGetWindowAttrib p'win . fst) pairs rs @?= map snd pairs +test_glfwMaximizeWindow :: Ptr C'GLFWwindow -> IO ()+test_glfwMaximizeWindow p'win = do+ c'glfwShowWindow p'win+ startsMaximized <- c'glfwGetWindowAttrib p'win c'GLFW_MAXIMIZED+ startsMaximized @?= c'GLFW_FALSE++ c'glfwMaximizeWindow p'win+ giveItTime++ isMaximized <- c'glfwGetWindowAttrib p'win c'GLFW_MAXIMIZED+ isMaximized @?= c'GLFW_TRUE+ c'glfwHideWindow p'win+ test_glfwPollEvents :: IO () test_glfwPollEvents = c'glfwPollEvents test_glfwWaitEvents :: IO ()-test_glfwWaitEvents =- c'glfwWaitEvents+test_glfwWaitEvents = c'glfwPostEmptyEvent >> c'glfwWaitEvents +test_glfwWaitEventsTimeout :: IO ()+test_glfwWaitEventsTimeout =+ -- to not slow down the test too much we set the timeout to 0.001 second :+ c'glfwWaitEventsTimeout 0.001+ -------------------------------------------------------------------------------- test_glfwJoystickPresent :: IO () test_glfwJoystickPresent = do _ <- c'glfwJoystickPresent c'GLFW_JOYSTICK_1 r <- c'glfwJoystickPresent c'GLFW_JOYSTICK_16- r @?= c'GL_FALSE+ r @?= c'GLFW_FALSE test_glfwGetJoystickAxes :: IO () test_glfwGetJoystickAxes =@@ -461,6 +558,14 @@ name <- peekCString p'name assertBool "" $ not $ null name +test_glfwGetKeyName :: IO ()+test_glfwGetKeyName =+ forM_ [c'GLFW_KEY_SLASH, c'GLFW_KEY_PERIOD] $ \k -> do+ p'name <- c'glfwGetKeyName k 0+ when (p'name /= nullPtr) $ do+ name <- peekCString p'name+ assertBool "" $ not $ null name+ -------------------------------------------------------------------------------- test_glfwGetTime :: IO ()@@ -477,6 +582,18 @@ -------------------------------------------------------------------------------- +test_glfwGetTimerValue :: IO ()+test_glfwGetTimerValue = do+ val <- c'glfwGetTimerValue+ assertBool "" $ val > 0++test_glfwGetTimerFrequency :: IO ()+test_glfwGetTimerFrequency = do+ freq <- c'glfwGetTimerFrequency+ assertBool "" $ freq > 0++--------------------------------------------------------------------------------+ test_glfwGetCurrentContext :: Ptr C'GLFWwindow -> IO () test_glfwGetCurrentContext p'win = do p'win' <- c'glfwGetCurrentContext@@ -493,8 +610,8 @@ test_glfwExtensionSupported :: IO () test_glfwExtensionSupported = do let pairs =- [ ( "GL_ARB_multisample", c'GL_TRUE )- , ( "bogus", c'GL_FALSE )+ [ ( "GL_ARB_multisample", c'GLFW_TRUE )+ , ( "bogus", c'GLFW_FALSE ) ] rs <- forM (map fst pairs) $ \ext -> withCString ext c'glfwExtensionSupported@@ -514,11 +631,67 @@ setGet s = do withCString s $ \p's -> c'glfwSetClipboardString p'win p's+ threadDelay 100000 -- Give it a little time p's' <- c'glfwGetClipboardString p'win if p's' == nullPtr then return "" else peekCString p's' --------------------------------------------------------------------------------++test_glfwVulkanSupported :: IO ()+test_glfwVulkanSupported =+ -- Just test that it doesn't error. If it does, then we have a problem, but+ -- some platforms (like OS X) don't actually support vulkan.+ c'glfwVulkanSupported >> return ()++test_glfwGetRequiredInstanceExtensions :: IO ()+test_glfwGetRequiredInstanceExtensions = do+ support <- c'glfwVulkanSupported+ if (support == 1)+ then alloca $ \p'count ->+ c'glfwGetRequiredInstanceExtensions p'count >> return ()+ else return ()++test_glfwGetInstanceProcAddress :: IO ()+test_glfwGetInstanceProcAddress = do+ support <- c'glfwVulkanSupported+ if support == 1+ then do+ shouldBeNull <- withCString "notafunction" $+ \s -> c'glfwGetInstanceProcAddress nullPtr s+ shouldBeNull @?= nullFunPtr+ assertBool "Function pointer is defined!" $+ p'glfwGetInstanceProcAddress /= nullFunPtr+ else return ()++test_glfwGetPhysicalDevicePresentationSupport :: IO ()+test_glfwGetPhysicalDevicePresentationSupport = do+ -- We don't really have the proper types to test this function+ support <- c'glfwVulkanSupported+ if support == 1+ then do+ shouldBeFalse <-+ c'glfwGetPhysicalDevicePresentationSupport nullPtr nullPtr 0+ shouldBeFalse @?= c'GLFW_FALSE+ assertBool "Function pointer is defined!" $+ p'glfwGetPhysicalDevicePresentationSupport /= nullFunPtr+ else return ()++test_glfwCreateWindowSurface :: Ptr C'GLFWwindow -> IO ()+test_glfwCreateWindowSurface p'win = do+ -- We don't really have the proper types to test this function+ support <- c'glfwVulkanSupported+ if support == 1+ then do+ alloca $ \p'surface -> do+ let resPtr = p'surface :: Ptr ()+ shouldNotBeSuccessful <-+ c'glfwCreateWindowSurface nullPtr p'win nullPtr resPtr+ assertBool "c'glfwCreateSurface was successful??" $+ shouldNotBeSuccessful /= 0+ assertBool "Function pointer is defined!" $+ p'glfwCreateWindowSurface /= nullFunPtr+ else return () {-# ANN module "HLint: ignore Use camelCase" #-}
bindings-GLFW.cabal view
@@ -1,5 +1,5 @@ name: bindings-GLFW-version: 3.1.2.4+version: 3.2.1.0 category: Graphics author: Brian Lewis <brian@lorf.org>@@ -126,6 +126,7 @@ glfw/src/input.c glfw/src/monitor.c glfw/src/window.c+ glfw/src/vulkan.c cc-options: -D_GLFW_USE_CONFIG_H @@ -133,25 +134,27 @@ include-dirs: glfw/include/os/unix-like c-sources:+ glfw/src/glx_context.c+ glfw/src/egl_context.c glfw/src/xkb_unicode.c glfw/src/linux_joystick.c glfw/src/posix_time.c glfw/src/posix_tls.c if flag(X)+ cc-options: -DBINDINGS_GLFW_USE_X11 c-sources:- glfw/src/glx_context.c glfw/src/x11_init.c glfw/src/x11_monitor.c glfw/src/x11_window.c if flag(Wayland)+ cc-options: -DBINDINGS_GLFW_USE_WAYLAND c-sources:- glfw/src/egl_context.c glfw/src/wl_init.c glfw/src/wl_monitor.c glfw/src/wl_window.c if flag(Mir)+ cc-options: -DBINDINGS_GLFW_USE_MIR c-sources:- glfw/src/egl_context.c glfw/src/mir_init.c glfw/src/mir_monitor.c glfw/src/mir_window.c@@ -170,10 +173,10 @@ include-dirs: glfw/include/os/darwin c-sources:- glfw/src/mach_time.c+ glfw/src/cocoa_time.c glfw/src/posix_tls.c glfw/src/cocoa_init.m- glfw/src/iokit_joystick.m+ glfw/src/cocoa_joystick.m glfw/src/cocoa_monitor.m glfw/src/cocoa_window.m glfw/src/nsgl_context.m@@ -189,8 +192,9 @@ include-dirs: glfw/include/os/windows c-sources:+ glfw/src/egl_context.c glfw/src/win32_init.c- glfw/src/winmm_joystick.c+ glfw/src/win32_joystick.c glfw/src/win32_monitor.c glfw/src/win32_time.c glfw/src/win32_window.c@@ -202,7 +206,6 @@ if flag(ExposeNative) cc-options: -DExposeNative- -------------------------------------------------------------------------------- test-suite main
glfw/include/GLFW/glfw3.h view
@@ -1,3335 +1,4224 @@ /*************************************************************************- * GLFW 3.1 - www.glfw.org- * A library for OpenGL, window and input- *------------------------------------------------------------------------- * Copyright (c) 2002-2006 Marcus Geelnard- * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>- *- * This software is provided 'as-is', without any express or implied- * warranty. In no event will the authors be held liable for any damages- * arising from the use of this software.- *- * Permission is granted to anyone to use this software for any purpose,- * including commercial applications, and to alter it and redistribute it- * freely, subject to the following restrictions:- *- * 1. The origin of this software must not be misrepresented; you must not- * claim that you wrote the original software. If you use this software- * in a product, an acknowledgment in the product documentation would- * be appreciated but is not required.- *- * 2. Altered source versions must be plainly marked as such, and must not- * be misrepresented as being the original software.- *- * 3. This notice may not be removed or altered from any source- * distribution.- *- *************************************************************************/--#ifndef _glfw3_h_-#define _glfw3_h_--#ifdef __cplusplus-extern "C" {-#endif---/*************************************************************************- * Doxygen documentation- *************************************************************************/--/*! @defgroup context Context handling- *- * This is the reference documentation for context related functions. For more- * information, see the @ref context.- */-/*! @defgroup init Initialization, version and errors- *- * This is the reference documentation for initialization and termination of- * the library, version management and error handling. For more information,- * see the @ref intro.- */-/*! @defgroup input Input handling- *- * This is the reference documentation for input related functions and types.- * For more information, see the @ref input.- */-/*! @defgroup monitor Monitor handling- *- * This is the reference documentation for monitor related functions and types.- * For more information, see the @ref monitor.- */-/*! @defgroup window Window handling- *- * This is the reference documentation for window related functions and types,- * including creation, deletion and event polling. For more information, see- * the @ref window.- */---/*************************************************************************- * Global definitions- *************************************************************************/--/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */--/* Please report any problems that you find with your compiler, which may- * be solved in this section! There are several compilers that I have not- * been able to test this file with yet.- *- * First: If we are we on Windows, we want a single define for it (_WIN32)- * (Note: For Cygwin the compiler flag -mwin32 should be used, but to- * make sure that things run smoothly for Cygwin users, we add __CYGWIN__- * to the list of "valid Win32 identifiers", which removes the need for- * -mwin32)- */-#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__))- #define _WIN32-#endif /* _WIN32 */--/* In order for extension support to be portable, we need to define an- * OpenGL function call method. We use the keyword APIENTRY, which is- * defined for Win32. (Note: Windows also needs this for <GL/gl.h>)- */-#ifndef APIENTRY- #ifdef _WIN32- #define APIENTRY __stdcall- #else- #define APIENTRY- #endif-#endif /* APIENTRY */--/* The following three defines are here solely to make some Windows-based- * <GL/gl.h> files happy. Theoretically we could include <windows.h>, but- * it has the major drawback of severely polluting our namespace.- */--/* Under Windows, we need WINGDIAPI defined */-#if !defined(WINGDIAPI) && defined(_WIN32)- #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)- /* Microsoft Visual C++, Borland C++ Builder and Pelles C */- #define WINGDIAPI __declspec(dllimport)- #elif defined(__LCC__)- /* LCC-Win32 */- #define WINGDIAPI __stdcall- #else- /* Others (e.g. MinGW, Cygwin) */- #define WINGDIAPI extern- #endif- #define GLFW_WINGDIAPI_DEFINED-#endif /* WINGDIAPI */--/* Some <GL/glu.h> files also need CALLBACK defined */-#if !defined(CALLBACK) && defined(_WIN32)- #if defined(_MSC_VER)- /* Microsoft Visual C++ */- #if (defined(_M_MRX000) || defined(_M_IX86) || defined(_M_ALPHA) || defined(_M_PPC)) && !defined(MIDL_PASS)- #define CALLBACK __stdcall- #else- #define CALLBACK- #endif- #else- /* Other Windows compilers */- #define CALLBACK __stdcall- #endif- #define GLFW_CALLBACK_DEFINED-#endif /* CALLBACK */--/* Most GL/glu.h variants on Windows need wchar_t- * OpenGL/gl.h blocks the definition of ptrdiff_t by glext.h on OS X */-#if !defined(GLFW_INCLUDE_NONE)- #include <stddef.h>-#endif--/* Include the chosen client API headers.- */-#if defined(__APPLE_CC__)- #if defined(GLFW_INCLUDE_GLCOREARB)- #include <OpenGL/gl3.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <OpenGL/gl3ext.h>- #endif- #elif !defined(GLFW_INCLUDE_NONE)- #if !defined(GLFW_INCLUDE_GLEXT)- #define GL_GLEXT_LEGACY- #endif- #include <OpenGL/gl.h>- #endif- #if defined(GLFW_INCLUDE_GLU)- #include <OpenGL/glu.h>- #endif-#else- #if defined(GLFW_INCLUDE_GLCOREARB)- #include <GL/glcorearb.h>- #elif defined(GLFW_INCLUDE_ES1)- #include <GLES/gl.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <GLES/glext.h>- #endif- #elif defined(GLFW_INCLUDE_ES2)- #include <GLES2/gl2.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <GLES2/gl2ext.h>- #endif- #elif defined(GLFW_INCLUDE_ES3)- #include <GLES3/gl3.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <GLES3/gl2ext.h>- #endif- #elif defined(GLFW_INCLUDE_ES31)- #include <GLES3/gl31.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <GLES3/gl2ext.h>- #endif- #elif !defined(GLFW_INCLUDE_NONE)- #include <GL/gl.h>- #if defined(GLFW_INCLUDE_GLEXT)- #include <GL/glext.h>- #endif- #endif- #if defined(GLFW_INCLUDE_GLU)- #include <GL/glu.h>- #endif-#endif--#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)- /* GLFW_DLL must be defined by applications that are linking against the DLL- * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW- * configuration header when compiling the DLL version of the library.- */- #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"-#endif--/* GLFWAPI is used to declare public API functions for export- * from the DLL / shared library / dynamic library.- */-#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)- /* We are building GLFW as a Win32 DLL */- #define GLFWAPI __declspec(dllexport)-#elif defined(_WIN32) && defined(GLFW_DLL)- /* We are calling GLFW as a Win32 DLL */- #if defined(__LCC__)- #define GLFWAPI extern- #else- #define GLFWAPI __declspec(dllimport)- #endif-#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)- /* We are building GLFW as a shared / dynamic library */- #define GLFWAPI __attribute__((visibility("default")))-#else- /* We are building or calling GLFW as a static library */- #define GLFWAPI-#endif--/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */---/*************************************************************************- * GLFW API tokens- *************************************************************************/--/*! @name GLFW version macros- * @{ */-/*! @brief The major version number of the GLFW library.- *- * This is incremented when the API is changed in non-compatible ways.- * @ingroup init- */-#define GLFW_VERSION_MAJOR 3-/*! @brief The minor version number of the GLFW library.- *- * This is incremented when features are added to the API but it remains- * backward-compatible.- * @ingroup init- */-#define GLFW_VERSION_MINOR 1-/*! @brief The revision number of the GLFW library.- *- * This is incremented when a bug fix release is made that does not contain any- * API changes.- * @ingroup init- */-#define GLFW_VERSION_REVISION 1-/*! @} */--/*! @name Key and button actions- * @{ */-/*! @brief The key or mouse button was released.- *- * The key or mouse button was released.- *- * @ingroup input- */-#define GLFW_RELEASE 0-/*! @brief The key or mouse button was pressed.- *- * The key or mouse button was pressed.- *- * @ingroup input- */-#define GLFW_PRESS 1-/*! @brief The key was held down until it repeated.- *- * The key was held down until it repeated.- *- * @ingroup input- */-#define GLFW_REPEAT 2-/*! @} */--/*! @defgroup keys Keyboard keys- *- * See [key input](@ref input_key) for how these are used.- *- * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),- * but re-arranged to map to 7-bit ASCII for printable keys (function keys are- * put in the 256+ range).- *- * The naming of the key codes follow these rules:- * - The US keyboard layout is used- * - Names of printable alpha-numeric characters are used (e.g. "A", "R",- * "3", etc.)- * - For non-alphanumeric characters, Unicode:ish names are used (e.g.- * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not- * correspond to the Unicode standard (usually for brevity)- * - Keys that lack a clear US mapping are named "WORLD_x"- * - For non-printable keys, custom names are used (e.g. "F4",- * "BACKSPACE", etc.)- *- * @ingroup input- * @{- */--/* The unknown key */-#define GLFW_KEY_UNKNOWN -1--/* Printable keys */-#define GLFW_KEY_SPACE 32-#define GLFW_KEY_APOSTROPHE 39 /* ' */-#define GLFW_KEY_COMMA 44 /* , */-#define GLFW_KEY_MINUS 45 /* - */-#define GLFW_KEY_PERIOD 46 /* . */-#define GLFW_KEY_SLASH 47 /* / */-#define GLFW_KEY_0 48-#define GLFW_KEY_1 49-#define GLFW_KEY_2 50-#define GLFW_KEY_3 51-#define GLFW_KEY_4 52-#define GLFW_KEY_5 53-#define GLFW_KEY_6 54-#define GLFW_KEY_7 55-#define GLFW_KEY_8 56-#define GLFW_KEY_9 57-#define GLFW_KEY_SEMICOLON 59 /* ; */-#define GLFW_KEY_EQUAL 61 /* = */-#define GLFW_KEY_A 65-#define GLFW_KEY_B 66-#define GLFW_KEY_C 67-#define GLFW_KEY_D 68-#define GLFW_KEY_E 69-#define GLFW_KEY_F 70-#define GLFW_KEY_G 71-#define GLFW_KEY_H 72-#define GLFW_KEY_I 73-#define GLFW_KEY_J 74-#define GLFW_KEY_K 75-#define GLFW_KEY_L 76-#define GLFW_KEY_M 77-#define GLFW_KEY_N 78-#define GLFW_KEY_O 79-#define GLFW_KEY_P 80-#define GLFW_KEY_Q 81-#define GLFW_KEY_R 82-#define GLFW_KEY_S 83-#define GLFW_KEY_T 84-#define GLFW_KEY_U 85-#define GLFW_KEY_V 86-#define GLFW_KEY_W 87-#define GLFW_KEY_X 88-#define GLFW_KEY_Y 89-#define GLFW_KEY_Z 90-#define GLFW_KEY_LEFT_BRACKET 91 /* [ */-#define GLFW_KEY_BACKSLASH 92 /* \ */-#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */-#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */-#define GLFW_KEY_WORLD_1 161 /* non-US #1 */-#define GLFW_KEY_WORLD_2 162 /* non-US #2 */--/* Function keys */-#define GLFW_KEY_ESCAPE 256-#define GLFW_KEY_ENTER 257-#define GLFW_KEY_TAB 258-#define GLFW_KEY_BACKSPACE 259-#define GLFW_KEY_INSERT 260-#define GLFW_KEY_DELETE 261-#define GLFW_KEY_RIGHT 262-#define GLFW_KEY_LEFT 263-#define GLFW_KEY_DOWN 264-#define GLFW_KEY_UP 265-#define GLFW_KEY_PAGE_UP 266-#define GLFW_KEY_PAGE_DOWN 267-#define GLFW_KEY_HOME 268-#define GLFW_KEY_END 269-#define GLFW_KEY_CAPS_LOCK 280-#define GLFW_KEY_SCROLL_LOCK 281-#define GLFW_KEY_NUM_LOCK 282-#define GLFW_KEY_PRINT_SCREEN 283-#define GLFW_KEY_PAUSE 284-#define GLFW_KEY_F1 290-#define GLFW_KEY_F2 291-#define GLFW_KEY_F3 292-#define GLFW_KEY_F4 293-#define GLFW_KEY_F5 294-#define GLFW_KEY_F6 295-#define GLFW_KEY_F7 296-#define GLFW_KEY_F8 297-#define GLFW_KEY_F9 298-#define GLFW_KEY_F10 299-#define GLFW_KEY_F11 300-#define GLFW_KEY_F12 301-#define GLFW_KEY_F13 302-#define GLFW_KEY_F14 303-#define GLFW_KEY_F15 304-#define GLFW_KEY_F16 305-#define GLFW_KEY_F17 306-#define GLFW_KEY_F18 307-#define GLFW_KEY_F19 308-#define GLFW_KEY_F20 309-#define GLFW_KEY_F21 310-#define GLFW_KEY_F22 311-#define GLFW_KEY_F23 312-#define GLFW_KEY_F24 313-#define GLFW_KEY_F25 314-#define GLFW_KEY_KP_0 320-#define GLFW_KEY_KP_1 321-#define GLFW_KEY_KP_2 322-#define GLFW_KEY_KP_3 323-#define GLFW_KEY_KP_4 324-#define GLFW_KEY_KP_5 325-#define GLFW_KEY_KP_6 326-#define GLFW_KEY_KP_7 327-#define GLFW_KEY_KP_8 328-#define GLFW_KEY_KP_9 329-#define GLFW_KEY_KP_DECIMAL 330-#define GLFW_KEY_KP_DIVIDE 331-#define GLFW_KEY_KP_MULTIPLY 332-#define GLFW_KEY_KP_SUBTRACT 333-#define GLFW_KEY_KP_ADD 334-#define GLFW_KEY_KP_ENTER 335-#define GLFW_KEY_KP_EQUAL 336-#define GLFW_KEY_LEFT_SHIFT 340-#define GLFW_KEY_LEFT_CONTROL 341-#define GLFW_KEY_LEFT_ALT 342-#define GLFW_KEY_LEFT_SUPER 343-#define GLFW_KEY_RIGHT_SHIFT 344-#define GLFW_KEY_RIGHT_CONTROL 345-#define GLFW_KEY_RIGHT_ALT 346-#define GLFW_KEY_RIGHT_SUPER 347-#define GLFW_KEY_MENU 348-#define GLFW_KEY_LAST GLFW_KEY_MENU--/*! @} */--/*! @defgroup mods Modifier key flags- *- * See [key input](@ref input_key) for how these are used.- *- * @ingroup input- * @{ */--/*! @brief If this bit is set one or more Shift keys were held down.- */-#define GLFW_MOD_SHIFT 0x0001-/*! @brief If this bit is set one or more Control keys were held down.- */-#define GLFW_MOD_CONTROL 0x0002-/*! @brief If this bit is set one or more Alt keys were held down.- */-#define GLFW_MOD_ALT 0x0004-/*! @brief If this bit is set one or more Super keys were held down.- */-#define GLFW_MOD_SUPER 0x0008--/*! @} */--/*! @defgroup buttons Mouse buttons- *- * See [mouse button input](@ref input_mouse_button) for how these are used.- *- * @ingroup input- * @{ */-#define GLFW_MOUSE_BUTTON_1 0-#define GLFW_MOUSE_BUTTON_2 1-#define GLFW_MOUSE_BUTTON_3 2-#define GLFW_MOUSE_BUTTON_4 3-#define GLFW_MOUSE_BUTTON_5 4-#define GLFW_MOUSE_BUTTON_6 5-#define GLFW_MOUSE_BUTTON_7 6-#define GLFW_MOUSE_BUTTON_8 7-#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8-#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1-#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2-#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3-/*! @} */--/*! @defgroup joysticks Joysticks- *- * See [joystick input](@ref joystick) for how these are used.- *- * @ingroup input- * @{ */-#define GLFW_JOYSTICK_1 0-#define GLFW_JOYSTICK_2 1-#define GLFW_JOYSTICK_3 2-#define GLFW_JOYSTICK_4 3-#define GLFW_JOYSTICK_5 4-#define GLFW_JOYSTICK_6 5-#define GLFW_JOYSTICK_7 6-#define GLFW_JOYSTICK_8 7-#define GLFW_JOYSTICK_9 8-#define GLFW_JOYSTICK_10 9-#define GLFW_JOYSTICK_11 10-#define GLFW_JOYSTICK_12 11-#define GLFW_JOYSTICK_13 12-#define GLFW_JOYSTICK_14 13-#define GLFW_JOYSTICK_15 14-#define GLFW_JOYSTICK_16 15-#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16-/*! @} */--/*! @defgroup errors Error codes- *- * See [error handling](@ref error_handling) for how these are used.- *- * @ingroup init- * @{ */-/*! @brief GLFW has not been initialized.- *- * This occurs if a GLFW function was called that may not be called unless the- * library is [initialized](@ref intro_init).- *- * @par Analysis- * Application programmer error. Initialize GLFW before calling any function- * that requires initialization.- */-#define GLFW_NOT_INITIALIZED 0x00010001-/*! @brief No context is current for this thread.- *- * This occurs if a GLFW function was called that needs and operates on the- * current OpenGL or OpenGL ES context but no context is current on the calling- * thread. One such function is @ref glfwSwapInterval.- *- * @par Analysis- * Application programmer error. Ensure a context is current before calling- * functions that require a current context.- */-#define GLFW_NO_CURRENT_CONTEXT 0x00010002-/*! @brief One of the arguments to the function was an invalid enum value.- *- * One of the arguments to the function was an invalid enum value, for example- * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref- * glfwGetWindowAttrib.- *- * @par Analysis- * Application programmer error. Fix the offending call.- */-#define GLFW_INVALID_ENUM 0x00010003-/*! @brief One of the arguments to the function was an invalid value.- *- * One of the arguments to the function was an invalid value, for example- * requesting a non-existent OpenGL or OpenGL ES version like 2.7.- *- * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead- * result in a @ref GLFW_VERSION_UNAVAILABLE error.- *- * @par Analysis- * Application programmer error. Fix the offending call.- */-#define GLFW_INVALID_VALUE 0x00010004-/*! @brief A memory allocation failed.- *- * A memory allocation failed.- *- * @par Analysis- * A bug in GLFW or the underlying operating system. Report the bug to our- * [issue tracker](https://github.com/glfw/glfw/issues).- */-#define GLFW_OUT_OF_MEMORY 0x00010005-/*! @brief GLFW could not find support for the requested client API on the- * system.- *- * GLFW could not find support for the requested client API on the system.- *- * @par Analysis- * The installed graphics driver does not support the requested client API, or- * does not support it via the chosen context creation backend. Below are- * a few examples.- *- * @par- * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only- * supports OpenGL ES via EGL, while Nvidia and Intel only supports it via- * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa- * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary- * driver.- */-#define GLFW_API_UNAVAILABLE 0x00010006-/*! @brief The requested OpenGL or OpenGL ES version is not available.- *- * The requested OpenGL or OpenGL ES version (including any requested profile- * or context option) is not available on this machine.- *- * @par Analysis- * The machine does not support your requirements. If your application is- * sufficiently flexible, downgrade your requirements and try again.- * Otherwise, inform the user that their machine does not match your- * requirements.- *- * @par- * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0- * comes out before the 4.x series gets that far, also fail with this error and- * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions- * will exist.- */-#define GLFW_VERSION_UNAVAILABLE 0x00010007-/*! @brief A platform-specific error occurred that does not match any of the- * more specific categories.- *- * A platform-specific error occurred that does not match any of the more- * specific categories.- *- * @par Analysis- * A bug in GLFW or the underlying operating system. Report the bug to our- * [issue tracker](https://github.com/glfw/glfw/issues).- */-#define GLFW_PLATFORM_ERROR 0x00010008-/*! @brief The requested format is not supported or available.- *- * If emitted during window creation, the requested pixel format is not- * supported.- *- * If emitted when querying the clipboard, the contents of the clipboard could- * not be converted to the requested format.- *- * @par Analysis- * If emitted during window creation, one or more- * [hard constraints](@ref window_hints_hard) did not match any of the- * available pixel formats. If your application is sufficiently flexible,- * downgrade your requirements and try again. Otherwise, inform the user that- * their machine does not match your requirements.- *- * @par- * If emitted when querying the clipboard, ignore the error or report it to- * the user, as appropriate.- */-#define GLFW_FORMAT_UNAVAILABLE 0x00010009-/*! @} */--#define GLFW_FOCUSED 0x00020001-#define GLFW_ICONIFIED 0x00020002-#define GLFW_RESIZABLE 0x00020003-#define GLFW_VISIBLE 0x00020004-#define GLFW_DECORATED 0x00020005-#define GLFW_AUTO_ICONIFY 0x00020006-#define GLFW_FLOATING 0x00020007--#define GLFW_RED_BITS 0x00021001-#define GLFW_GREEN_BITS 0x00021002-#define GLFW_BLUE_BITS 0x00021003-#define GLFW_ALPHA_BITS 0x00021004-#define GLFW_DEPTH_BITS 0x00021005-#define GLFW_STENCIL_BITS 0x00021006-#define GLFW_ACCUM_RED_BITS 0x00021007-#define GLFW_ACCUM_GREEN_BITS 0x00021008-#define GLFW_ACCUM_BLUE_BITS 0x00021009-#define GLFW_ACCUM_ALPHA_BITS 0x0002100A-#define GLFW_AUX_BUFFERS 0x0002100B-#define GLFW_STEREO 0x0002100C-#define GLFW_SAMPLES 0x0002100D-#define GLFW_SRGB_CAPABLE 0x0002100E-#define GLFW_REFRESH_RATE 0x0002100F-#define GLFW_DOUBLEBUFFER 0x00021010--#define GLFW_CLIENT_API 0x00022001-#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002-#define GLFW_CONTEXT_VERSION_MINOR 0x00022003-#define GLFW_CONTEXT_REVISION 0x00022004-#define GLFW_CONTEXT_ROBUSTNESS 0x00022005-#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006-#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007-#define GLFW_OPENGL_PROFILE 0x00022008-#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009--#define GLFW_OPENGL_API 0x00030001-#define GLFW_OPENGL_ES_API 0x00030002--#define GLFW_NO_ROBUSTNESS 0-#define GLFW_NO_RESET_NOTIFICATION 0x00031001-#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002--#define GLFW_OPENGL_ANY_PROFILE 0-#define GLFW_OPENGL_CORE_PROFILE 0x00032001-#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002--#define GLFW_CURSOR 0x00033001-#define GLFW_STICKY_KEYS 0x00033002-#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003--#define GLFW_CURSOR_NORMAL 0x00034001-#define GLFW_CURSOR_HIDDEN 0x00034002-#define GLFW_CURSOR_DISABLED 0x00034003--#define GLFW_ANY_RELEASE_BEHAVIOR 0-#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001-#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002--/*! @defgroup shapes Standard cursor shapes- *- * See [standard cursor creation](@ref cursor_standard) for how these are used.- *- * @ingroup input- * @{ */--/*! @brief The regular arrow cursor shape.- *- * The regular arrow cursor.- */-#define GLFW_ARROW_CURSOR 0x00036001-/*! @brief The text input I-beam cursor shape.- *- * The text input I-beam cursor shape.- */-#define GLFW_IBEAM_CURSOR 0x00036002-/*! @brief The crosshair shape.- *- * The crosshair shape.- */-#define GLFW_CROSSHAIR_CURSOR 0x00036003-/*! @brief The hand shape.- *- * The hand shape.- */-#define GLFW_HAND_CURSOR 0x00036004-/*! @brief The horizontal resize arrow shape.- *- * The horizontal resize arrow shape.- */-#define GLFW_HRESIZE_CURSOR 0x00036005-/*! @brief The vertical resize arrow shape.- *- * The vertical resize arrow shape.- */-#define GLFW_VRESIZE_CURSOR 0x00036006-/*! @} */--#define GLFW_CONNECTED 0x00040001-#define GLFW_DISCONNECTED 0x00040002--#define GLFW_DONT_CARE -1---/*************************************************************************- * GLFW API types- *************************************************************************/--/*! @brief Client API function pointer type.- *- * Generic function pointer used for returning client API function pointers- * without forcing a cast from a regular pointer.- *- * @ingroup context- */-typedef void (*GLFWglproc)(void);--/*! @brief Opaque monitor object.- *- * Opaque monitor object.- *- * @ingroup monitor- */-typedef struct GLFWmonitor GLFWmonitor;--/*! @brief Opaque window object.- *- * Opaque window object.- *- * @ingroup window- */-typedef struct GLFWwindow GLFWwindow;--/*! @brief Opaque cursor object.- *- * Opaque cursor object.- *- * @ingroup cursor- */-typedef struct GLFWcursor GLFWcursor;--/*! @brief The function signature for error callbacks.- *- * This is the function signature for error callback functions.- *- * @param[in] error An [error code](@ref errors).- * @param[in] description A UTF-8 encoded string describing the error.- *- * @sa glfwSetErrorCallback- *- * @ingroup init- */-typedef void (* GLFWerrorfun)(int,const char*);--/*! @brief The function signature for window position callbacks.- *- * This is the function signature for window position callback functions.- *- * @param[in] window The window that was moved.- * @param[in] xpos The new x-coordinate, in screen coordinates, of the- * upper-left corner of the client area of the window.- * @param[in] ypos The new y-coordinate, in screen coordinates, of the- * upper-left corner of the client area of the window.- *- * @sa glfwSetWindowPosCallback- *- * @ingroup window- */-typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);--/*! @brief The function signature for window resize callbacks.- *- * This is the function signature for window size callback functions.- *- * @param[in] window The window that was resized.- * @param[in] width The new width, in screen coordinates, of the window.- * @param[in] height The new height, in screen coordinates, of the window.- *- * @sa glfwSetWindowSizeCallback- *- * @ingroup window- */-typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);--/*! @brief The function signature for window close callbacks.- *- * This is the function signature for window close callback functions.- *- * @param[in] window The window that the user attempted to close.- *- * @sa glfwSetWindowCloseCallback- *- * @ingroup window- */-typedef void (* GLFWwindowclosefun)(GLFWwindow*);--/*! @brief The function signature for window content refresh callbacks.- *- * This is the function signature for window refresh callback functions.- *- * @param[in] window The window whose content needs to be refreshed.- *- * @sa glfwSetWindowRefreshCallback- *- * @ingroup window- */-typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);--/*! @brief The function signature for window focus/defocus callbacks.- *- * This is the function signature for window focus callback functions.- *- * @param[in] window The window that gained or lost input focus.- * @param[in] focused `GL_TRUE` if the window was given input focus, or- * `GL_FALSE` if it lost it.- *- * @sa glfwSetWindowFocusCallback- *- * @ingroup window- */-typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);--/*! @brief The function signature for window iconify/restore callbacks.- *- * This is the function signature for window iconify/restore callback- * functions.- *- * @param[in] window The window that was iconified or restored.- * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE`- * if it was restored.- *- * @sa glfwSetWindowIconifyCallback- *- * @ingroup window- */-typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);--/*! @brief The function signature for framebuffer resize callbacks.- *- * This is the function signature for framebuffer resize callback- * functions.- *- * @param[in] window The window whose framebuffer was resized.- * @param[in] width The new width, in pixels, of the framebuffer.- * @param[in] height The new height, in pixels, of the framebuffer.- *- * @sa glfwSetFramebufferSizeCallback- *- * @ingroup window- */-typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);--/*! @brief The function signature for mouse button callbacks.- *- * This is the function signature for mouse button callback functions.- *- * @param[in] window The window that received the event.- * @param[in] button The [mouse button](@ref buttons) that was pressed or- * released.- * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were- * held down.- *- * @sa glfwSetMouseButtonCallback- *- * @ingroup input- */-typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);--/*! @brief The function signature for cursor position callbacks.- *- * This is the function signature for cursor position callback functions.- *- * @param[in] window The window that received the event.- * @param[in] xpos The new x-coordinate, in screen coordinates, of the cursor.- * @param[in] ypos The new y-coordinate, in screen coordinates, of the cursor.- *- * @sa glfwSetCursorPosCallback- *- * @ingroup input- */-typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);--/*! @brief The function signature for cursor enter/leave callbacks.- *- * This is the function signature for cursor enter/leave callback functions.- *- * @param[in] window The window that received the event.- * @param[in] entered `GL_TRUE` if the cursor entered the window's client- * area, or `GL_FALSE` if it left it.- *- * @sa glfwSetCursorEnterCallback- *- * @ingroup input- */-typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);--/*! @brief The function signature for scroll callbacks.- *- * This is the function signature for scroll callback functions.- *- * @param[in] window The window that received the event.- * @param[in] xoffset The scroll offset along the x-axis.- * @param[in] yoffset The scroll offset along the y-axis.- *- * @sa glfwSetScrollCallback- *- * @ingroup input- */-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);--/*! @brief The function signature for keyboard key callbacks.- *- * This is the function signature for keyboard key callback functions.- *- * @param[in] window The window that received the event.- * @param[in] key The [keyboard key](@ref keys) that was pressed or released.- * @param[in] scancode The system-specific scancode of the key.- * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were- * held down.- *- * @sa glfwSetKeyCallback- *- * @ingroup input- */-typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);--/*! @brief The function signature for Unicode character callbacks.- *- * This is the function signature for Unicode character callback functions.- *- * @param[in] window The window that received the event.- * @param[in] codepoint The Unicode code point of the character.- *- * @sa glfwSetCharCallback- *- * @ingroup input- */-typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);--/*! @brief The function signature for Unicode character with modifiers- * callbacks.- *- * This is the function signature for Unicode character with modifiers callback- * functions. It is called for each input character, regardless of what- * modifier keys are held down.- *- * @param[in] window The window that received the event.- * @param[in] codepoint The Unicode code point of the character.- * @param[in] mods Bit field describing which [modifier keys](@ref mods) were- * held down.- *- * @sa glfwSetCharModsCallback- *- * @ingroup input- */-typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);--/*! @brief The function signature for file drop callbacks.- *- * This is the function signature for file drop callbacks.- *- * @param[in] window The window that received the event.- * @param[in] count The number of dropped files.- * @param[in] paths The UTF-8 encoded file and/or directory path names.- *- * @sa glfwSetDropCallback- *- * @ingroup input- */-typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);--/*! @brief The function signature for monitor configuration callbacks.- *- * This is the function signature for monitor configuration callback functions.- *- * @param[in] monitor The monitor that was connected or disconnected.- * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.- *- * @sa glfwSetMonitorCallback- *- * @ingroup monitor- */-typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);--/*! @brief Video mode type.- *- * This describes a single video mode.- *- * @ingroup monitor- */-typedef struct GLFWvidmode-{- /*! The width, in screen coordinates, of the video mode.- */- int width;- /*! The height, in screen coordinates, of the video mode.- */- int height;- /*! The bit depth of the red channel of the video mode.- */- int redBits;- /*! The bit depth of the green channel of the video mode.- */- int greenBits;- /*! The bit depth of the blue channel of the video mode.- */- int blueBits;- /*! The refresh rate, in Hz, of the video mode.- */- int refreshRate;-} GLFWvidmode;--/*! @brief Gamma ramp.- *- * This describes the gamma ramp for a monitor.- *- * @sa glfwGetGammaRamp glfwSetGammaRamp- *- * @ingroup monitor- */-typedef struct GLFWgammaramp-{- /*! An array of value describing the response of the red channel.- */- unsigned short* red;- /*! An array of value describing the response of the green channel.- */- unsigned short* green;- /*! An array of value describing the response of the blue channel.- */- unsigned short* blue;- /*! The number of elements in each array.- */- unsigned int size;-} GLFWgammaramp;--/*! @brief Image data.- */-typedef struct GLFWimage-{- /*! The width, in pixels, of this image.- */- int width;- /*! The height, in pixels, of this image.- */- int height;- /*! The pixel data of this image, arranged left-to-right, top-to-bottom.- */- unsigned char* pixels;-} GLFWimage;---/*************************************************************************- * GLFW API functions- *************************************************************************/--/*! @brief Initializes the GLFW library.- *- * This function initializes the GLFW library. Before most GLFW functions can- * be used, GLFW must be initialized, and before an application terminates GLFW- * should be terminated in order to free any resources allocated during or- * after initialization.- *- * If this function fails, it calls @ref glfwTerminate before returning. If it- * succeeds, you should call @ref glfwTerminate before the application exits.- *- * Additional calls to this function after successful initialization but before- * termination will return `GL_TRUE` immediately.- *- * @return `GL_TRUE` if successful, or `GL_FALSE` if an- * [error](@ref error_handling) occurred.- *- * @remarks __OS X:__ This function will change the current directory of the- * application to the `Contents/Resources` subdirectory of the application's- * bundle, if present. This can be disabled with a- * [compile-time option](@ref compile_options_osx).- *- * @remarks __X11:__ If the `LC_CTYPE` category of the current locale is set to- * `"C"` then the environment's locale will be applied to that category. This- * is done because character input will not function when `LC_CTYPE` is set to- * `"C"`. If another locale was set before this function was called, it will- * be left untouched.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref intro_init- * @sa glfwTerminate- *- * @since Added in GLFW 1.0.- *- * @ingroup init- */-GLFWAPI int glfwInit(void);--/*! @brief Terminates the GLFW library.- *- * This function destroys all remaining windows and cursors, restores any- * modified gamma ramps and frees any other allocated resources. Once this- * function is called, you must again call @ref glfwInit successfully before- * you will be able to use most GLFW functions.- *- * If GLFW has been successfully initialized, this function should be called- * before the application exits. If initialization fails, there is no need to- * call this function, as it is called by @ref glfwInit before it returns- * failure.- *- * @remarks This function may be called before @ref glfwInit.- *- * @warning No window's context may be current on another thread when this- * function is called.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref intro_init- * @sa glfwInit- *- * @since Added in GLFW 1.0.- *- * @ingroup init- */-GLFWAPI void glfwTerminate(void);--/*! @brief Retrieves the version of the GLFW library.- *- * This function retrieves the major, minor and revision numbers of the GLFW- * library. It is intended for when you are using GLFW as a shared library and- * want to ensure that you are using the minimum required version.- *- * Any or all of the version arguments may be `NULL`. This function always- * succeeds.- *- * @param[out] major Where to store the major version number, or `NULL`.- * @param[out] minor Where to store the minor version number, or `NULL`.- * @param[out] rev Where to store the revision number, or `NULL`.- *- * @remarks This function may be called before @ref glfwInit.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref intro_version- * @sa glfwGetVersionString- *- * @since Added in GLFW 1.0.- *- * @ingroup init- */-GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);--/*! @brief Returns a string describing the compile-time configuration.- *- * This function returns the compile-time generated- * [version string](@ref intro_version_string) of the GLFW library binary. It- * describes the version, platform, compiler and any platform-specific- * compile-time options.- *- * __Do not use the version string__ to parse the GLFW library version. The- * @ref glfwGetVersion function already provides the version of the running- * library binary.- *- * This function always succeeds.- *- * @return The GLFW version string.- *- * @remarks This function may be called before @ref glfwInit.- *- * @par Pointer Lifetime- * The returned string is static and compile-time generated.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref intro_version- * @sa glfwGetVersion- *- * @since Added in GLFW 3.0.- *- * @ingroup init- */-GLFWAPI const char* glfwGetVersionString(void);--/*! @brief Sets the error callback.- *- * This function sets the error callback, which is called with an error code- * and a human-readable description each time a GLFW error occurs.- *- * The error callback is called on the thread where the error occurred. If you- * are using GLFW from multiple threads, your error callback needs to be- * written accordingly.- *- * Because the description string may have been generated specifically for that- * error, it is not guaranteed to be valid after the callback has returned. If- * you wish to use it after the callback returns, you need to make a copy.- *- * Once set, the error callback remains set even after the library has been- * terminated.- *- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set.- *- * @remarks This function may be called before @ref glfwInit.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref error_handling- *- * @since Added in GLFW 3.0.- *- * @ingroup init- */-GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);--/*! @brief Returns the currently connected monitors.- *- * This function returns an array of handles for all currently connected- * monitors.- *- * @param[out] count Where to store the number of monitors in the returned- * array. This is set to zero if an error occurred.- * @return An array of monitor handles, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned array is allocated and freed by GLFW. You should not free it- * yourself. It is guaranteed to be valid only until the monitor configuration- * changes or the library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_monitors- * @sa @ref monitor_event- * @sa glfwGetPrimaryMonitor- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);--/*! @brief Returns the primary monitor.- *- * This function returns the primary monitor. This is usually the monitor- * where elements like the Windows task bar or the OS X menu bar is located.- *- * @return The primary monitor, or `NULL` if an [error](@ref error_handling)- * occurred.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_monitors- * @sa glfwGetMonitors- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);--/*! @brief Returns the position of the monitor's viewport on the virtual screen.- *- * This function returns the position, in screen coordinates, of the upper-left- * corner of the specified monitor.- *- * Any or all of the position arguments may be `NULL`. If an error occurs, all- * non-`NULL` position arguments will be set to zero.- *- * @param[in] monitor The monitor to query.- * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.- * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_properties- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);--/*! @brief Returns the physical size of the monitor.- *- * This function returns the size, in millimetres, of the display area of the- * specified monitor.- *- * Some systems do not provide accurate monitor size information, either- * because the monitor- * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)- * data is incorrect or because the driver does not report it accurately.- *- * Any or all of the size arguments may be `NULL`. If an error occurs, all- * non-`NULL` size arguments will be set to zero.- *- * @param[in] monitor The monitor to query.- * @param[out] widthMM Where to store the width, in millimetres, of the- * monitor's display area, or `NULL`.- * @param[out] heightMM Where to store the height, in millimetres, of the- * monitor's display area, or `NULL`.- *- * @remarks __Windows:__ The OS calculates the returned physical size from the- * current resolution and system DPI instead of querying the monitor EDID data.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_properties- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);--/*! @brief Returns the name of the specified monitor.- *- * This function returns a human-readable name, encoded as UTF-8, of the- * specified monitor. The name typically reflects the make and model of the- * monitor and is not guaranteed to be unique among the connected monitors.- *- * @param[in] monitor The monitor to query.- * @return The UTF-8 encoded name of the monitor, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned string is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified monitor is disconnected or the- * library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_properties- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);--/*! @brief Sets the monitor configuration callback.- *- * This function sets the monitor configuration callback, or removes the- * currently set callback. This is called when a monitor is connected to or- * disconnected from the system.- *- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @bug __X11:__ This callback is not yet called on monitor configuration- * changes.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_event- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);--/*! @brief Returns the available video modes for the specified monitor.- *- * This function returns an array of all video modes supported by the specified- * monitor. The returned array is sorted in ascending order, first by color- * bit depth (the sum of all channel depths) and then by resolution area (the- * product of width and height).- *- * @param[in] monitor The monitor to query.- * @param[out] count Where to store the number of video modes in the returned- * array. This is set to zero if an error occurred.- * @return An array of video modes, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned array is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified monitor is disconnected, this- * function is called again for that monitor or the library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_modes- * @sa glfwGetVideoMode- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Changed to return an array of modes for a specific monitor.- *- * @ingroup monitor- */-GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);--/*! @brief Returns the current mode of the specified monitor.- *- * This function returns the current video mode of the specified monitor. If- * you have created a full screen window for that monitor, the return value- * will depend on whether that window is iconified.- *- * @param[in] monitor The monitor to query.- * @return The current mode of the monitor, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned array is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified monitor is disconnected or the- * library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_modes- * @sa glfwGetVideoModes- *- * @since Added in GLFW 3.0. Replaces `glfwGetDesktopMode`.- *- * @ingroup monitor- */-GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);--/*! @brief Generates a gamma ramp and sets it for the specified monitor.- *- * This function generates a 256-element gamma ramp from the specified exponent- * and then calls @ref glfwSetGammaRamp with it.- *- * @param[in] monitor The monitor whose gamma ramp to set.- * @param[in] gamma The desired exponent.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_gamma- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);--/*! @brief Returns the current gamma ramp for the specified monitor.- *- * This function returns the current gamma ramp of the specified monitor.- *- * @param[in] monitor The monitor to query.- * @return The current gamma ramp, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned structure and its arrays are allocated and freed by GLFW. You- * should not free them yourself. They are valid until the specified monitor- * is disconnected, this function is called again for that monitor or the- * library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_gamma- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);--/*! @brief Sets the current gamma ramp for the specified monitor.- *- * This function sets the current gamma ramp for the specified monitor. The- * original gamma ramp for that monitor is saved by GLFW the first time this- * function is called and is restored by @ref glfwTerminate.- *- * @param[in] monitor The monitor whose gamma ramp to set.- * @param[in] ramp The gamma ramp to use.- *- * @note Gamma ramp sizes other than 256 are not supported by all hardware.- *- * @par Pointer Lifetime- * The specified gamma ramp is copied before this function returns.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref monitor_gamma- *- * @since Added in GLFW 3.0.- *- * @ingroup monitor- */-GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);--/*! @brief Resets all window hints to their default values.- *- * This function resets all window hints to their- * [default values](@ref window_hints_values).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_hints- * @sa glfwWindowHint- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwDefaultWindowHints(void);--/*! @brief Sets the specified window hint to the desired value.- *- * This function sets hints for the next call to @ref glfwCreateWindow. The- * hints, once set, retain their values until changed by a call to @ref- * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is- * terminated.- *- * @param[in] target The [window hint](@ref window_hints) to set.- * @param[in] hint The new value of the window hint.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_hints- * @sa glfwDefaultWindowHints- *- * @since Added in GLFW 3.0. Replaces `glfwOpenWindowHint`.- *- * @ingroup window- */-GLFWAPI void glfwWindowHint(int target, int hint);--/*! @brief Creates a window and its associated context.- *- * This function creates a window and its associated OpenGL or OpenGL ES- * context. Most of the options controlling how the window and its context- * should be created are specified with [window hints](@ref window_hints).- *- * Successful creation does not change which context is current. Before you- * can use the newly created context, you need to- * [make it current](@ref context_current). For information about the `share`- * parameter, see @ref context_sharing.- *- * The created window, framebuffer and context may differ from what you- * requested, as not all parameters and hints are- * [hard constraints](@ref window_hints_hard). This includes the size of the- * window, especially for full screen windows. To query the actual attributes- * of the created window, framebuffer and context, use queries like @ref- * glfwGetWindowAttrib and @ref glfwGetWindowSize.- *- * To create a full screen window, you need to specify the monitor the window- * will cover. If no monitor is specified, windowed mode will be used. Unless- * you have a way for the user to choose a specific monitor, it is recommended- * that you pick the primary monitor. For more information on how to query- * connected monitors, see @ref monitor_monitors.- *- * For full screen windows, the specified size becomes the resolution of the- * window's _desired video mode_. As long as a full screen window has input- * focus, the supported video mode most closely matching the desired video mode- * is set for the specified monitor. For more information about full screen- * windows, including the creation of so called _windowed full screen_ or- * _borderless full screen_ windows, see @ref window_windowed_full_screen.- *- * By default, newly created windows use the placement recommended by the- * window system. To create the window at a specific position, make it- * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window- * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)- * it.- *- * If a full screen window has input focus, the screensaver is prohibited from- * starting.- *- * Window systems put limits on window sizes. Very large or very small window- * dimensions may be overridden by the window system on creation. Check the- * actual [size](@ref window_size) after creation.- *- * The [swap interval](@ref buffer_swap) is not set during window creation and- * the initial value may vary depending on driver settings and defaults.- *- * @param[in] width The desired width, in screen coordinates, of the window.- * This must be greater than zero.- * @param[in] height The desired height, in screen coordinates, of the window.- * This must be greater than zero.- * @param[in] title The initial, UTF-8 encoded window title.- * @param[in] monitor The monitor to use for full screen mode, or `NULL` to use- * windowed mode.- * @param[in] share The window whose context to share resources with, or `NULL`- * to not share resources.- * @return The handle of the created window, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @remarks __Windows:__ Window creation will fail if the Microsoft GDI- * software OpenGL implementation is the only one available.- *- * @remarks __Windows:__ If the executable has an icon resource named- * `GLFW_ICON,` it will be set as the icon for the window. If no such icon is- * present, the `IDI_WINLOGO` icon will be used instead.- *- * @remarks __Windows:__ The context to share resources with may not be current- * on any other thread.- *- * @remarks __OS X:__ The GLFW window has no icon, as it is not a document- * window, but the dock icon will be the same as the application bundle's icon.- * For more information on bundles, see the- * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)- * in the Mac Developer Library.- *- * @remarks __OS X:__ The first time a window is created the menu bar is- * populated with common commands like Hide, Quit and About. The About entry- * opens a minimal about dialog with information from the application's bundle.- * The menu bar can be disabled with a- * [compile-time option](@ref compile_options_osx).- *- * @remarks __X11:__ There is no mechanism for setting the window icon yet.- *- * @remarks __X11:__ Some window managers will not respect the placement of- * initially hidden windows.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_creation- * @sa glfwDestroyWindow- *- * @since Added in GLFW 3.0. Replaces `glfwOpenWindow`.- *- * @ingroup window- */-GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);--/*! @brief Destroys the specified window and its context.- *- * This function destroys the specified window and its context. On calling- * this function, no further callbacks will be called for that window.- *- * If the context of the specified window is current on the main thread, it is- * detached before being destroyed.- *- * @param[in] window The window to destroy.- *- * @note The context of the specified window must not be current on any other- * thread when this function is called.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_creation- * @sa glfwCreateWindow- *- * @since Added in GLFW 3.0. Replaces `glfwCloseWindow`.- *- * @ingroup window- */-GLFWAPI void glfwDestroyWindow(GLFWwindow* window);--/*! @brief Checks the close flag of the specified window.- *- * This function returns the value of the close flag of the specified window.- *- * @param[in] window The window to query.- * @return The value of the close flag.- *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.- *- * @sa @ref window_close- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);--/*! @brief Sets the close flag of the specified window.- *- * This function sets the value of the close flag of the specified window.- * This can be used to override the user's attempt to close the window, or- * to signal that it should be closed.- *- * @param[in] window The window whose flag to change.- * @param[in] value The new value.- *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.- *- * @sa @ref window_close- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);--/*! @brief Sets the title of the specified window.- *- * This function sets the window title, encoded as UTF-8, of the specified- * window.- *- * @param[in] window The window whose title to change.- * @param[in] title The UTF-8 encoded window title.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_title- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);--/*! @brief Retrieves the position of the client area of the specified window.- *- * This function retrieves the position, in screen coordinates, of the- * upper-left corner of the client area of the specified window.- *- * Any or all of the position arguments may be `NULL`. If an error occurs, all- * non-`NULL` position arguments will be set to zero.- *- * @param[in] window The window to query.- * @param[out] xpos Where to store the x-coordinate of the upper-left corner of- * the client area, or `NULL`.- * @param[out] ypos Where to store the y-coordinate of the upper-left corner of- * the client area, or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_pos- * @sa glfwSetWindowPos- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);--/*! @brief Sets the position of the client area of the specified window.- *- * This function sets the position, in screen coordinates, of the upper-left- * corner of the client area of the specified windowed mode window. If the- * window is a full screen window, this function does nothing.- *- * __Do not use this function__ to move an already visible window unless you- * have very good reasons for doing so, as it will confuse and annoy the user.- *- * The window manager may put limits on what positions are allowed. GLFW- * cannot and should not override these limits.- *- * @param[in] window The window to query.- * @param[in] xpos The x-coordinate of the upper-left corner of the client area.- * @param[in] ypos The y-coordinate of the upper-left corner of the client area.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_pos- * @sa glfwGetWindowPos- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);--/*! @brief Retrieves the size of the client area of the specified window.- *- * This function retrieves the size, in screen coordinates, of the client area- * of the specified window. If you wish to retrieve the size of the- * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.- *- * Any or all of the size arguments may be `NULL`. If an error occurs, all- * non-`NULL` size arguments will be set to zero.- *- * @param[in] window The window whose size to retrieve.- * @param[out] width Where to store the width, in screen coordinates, of the- * client area, or `NULL`.- * @param[out] height Where to store the height, in screen coordinates, of the- * client area, or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_size- * @sa glfwSetWindowSize- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);--/*! @brief Sets the size of the client area of the specified window.- *- * This function sets the size, in screen coordinates, of the client area of- * the specified window.- *- * For full screen windows, this function selects and switches to the resolution- * closest to the specified size, without affecting the window's context. As- * the context is unaffected, the bit depths of the framebuffer remain- * unchanged.- *- * The window manager may put limits on what sizes are allowed. GLFW cannot- * and should not override these limits.- *- * @param[in] window The window to resize.- * @param[in] width The desired width of the specified window.- * @param[in] height The desired height of the specified window.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_size- * @sa glfwGetWindowSize- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);--/*! @brief Retrieves the size of the framebuffer of the specified window.- *- * This function retrieves the size, in pixels, of the framebuffer of the- * specified window. If you wish to retrieve the size of the window in screen- * coordinates, see @ref glfwGetWindowSize.- *- * Any or all of the size arguments may be `NULL`. If an error occurs, all- * non-`NULL` size arguments will be set to zero.- *- * @param[in] window The window whose framebuffer to query.- * @param[out] width Where to store the width, in pixels, of the framebuffer,- * or `NULL`.- * @param[out] height Where to store the height, in pixels, of the framebuffer,- * or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_fbsize- * @sa glfwSetFramebufferSizeCallback- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);--/*! @brief Retrieves the size of the frame of the window.- *- * This function retrieves the size, in screen coordinates, of each edge of the- * frame of the specified window. This size includes the title bar, if the- * window has one. The size of the frame may vary depending on the- * [window-related hints](@ref window_hints_wnd) used to create it.- *- * Because this function retrieves the size of each window frame edge and not- * the offset along a particular coordinate axis, the retrieved values will- * always be zero or positive.- *- * Any or all of the size arguments may be `NULL`. If an error occurs, all- * non-`NULL` size arguments will be set to zero.- *- * @param[in] window The window whose frame size to query.- * @param[out] left Where to store the size, in screen coordinates, of the left- * edge of the window frame, or `NULL`.- * @param[out] top Where to store the size, in screen coordinates, of the top- * edge of the window frame, or `NULL`.- * @param[out] right Where to store the size, in screen coordinates, of the- * right edge of the window frame, or `NULL`.- * @param[out] bottom Where to store the size, in screen coordinates, of the- * bottom edge of the window frame, or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_size- *- * @since Added in GLFW 3.1.- *- * @ingroup window- */-GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);--/*! @brief Iconifies the specified window.- *- * This function iconifies (minimizes) the specified window if it was- * previously restored. If the window is already iconified, this function does- * nothing.- *- * If the specified window is a full screen window, the original monitor- * resolution is restored until the window is restored.- *- * @param[in] window The window to iconify.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_iconify- * @sa glfwRestoreWindow- *- * @since Added in GLFW 2.1.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwIconifyWindow(GLFWwindow* window);--/*! @brief Restores the specified window.- *- * This function restores the specified window if it was previously iconified- * (minimized). If the window is already restored, this function does nothing.- *- * If the specified window is a full screen window, the resolution chosen for- * the window is restored on the selected monitor.- *- * @param[in] window The window to restore.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_iconify- * @sa glfwIconifyWindow- *- * @since Added in GLFW 2.1.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwRestoreWindow(GLFWwindow* window);--/*! @brief Makes the specified window visible.- *- * This function makes the specified window visible if it was previously- * hidden. If the window is already visible or is in full screen mode, this- * function does nothing.- *- * @param[in] window The window to make visible.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_hide- * @sa glfwHideWindow- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwShowWindow(GLFWwindow* window);--/*! @brief Hides the specified window.- *- * This function hides the specified window if it was previously visible. If- * the window is already hidden or is in full screen mode, this function does- * nothing.- *- * @param[in] window The window to hide.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_hide- * @sa glfwShowWindow- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwHideWindow(GLFWwindow* window);--/*! @brief Returns the monitor that the window uses for full screen mode.- *- * This function returns the handle of the monitor that the specified window is- * in full screen on.- *- * @param[in] window The window to query.- * @return The monitor, or `NULL` if the window is in windowed mode or an error- * occurred.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_monitor- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);--/*! @brief Returns an attribute of the specified window.- *- * This function returns the value of an attribute of the specified window or- * its OpenGL or OpenGL ES context.- *- * @param[in] window The window to query.- * @param[in] attrib The [window attribute](@ref window_attribs) whose value to- * return.- * @return The value of the attribute, or zero if an- * [error](@ref error_handling) occurred.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_attribs- *- * @since Added in GLFW 3.0. Replaces `glfwGetWindowParam` and- * `glfwGetGLVersion`.- *- * @ingroup window- */-GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);--/*! @brief Sets the user pointer of the specified window.- *- * This function sets the user-defined pointer of the specified window. The- * current value is retained until the window is destroyed. The initial value- * is `NULL`.- *- * @param[in] window The window whose pointer to set.- * @param[in] pointer The new value.- *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.- *- * @sa @ref window_userptr- * @sa glfwGetWindowUserPointer- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);--/*! @brief Returns the user pointer of the specified window.- *- * This function returns the current value of the user-defined pointer of the- * specified window. The initial value is `NULL`.- *- * @param[in] window The window whose pointer to return.- *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.- *- * @sa @ref window_userptr- * @sa glfwSetWindowUserPointer- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);--/*! @brief Sets the position callback for the specified window.- *- * This function sets the position callback of the specified window, which is- * called when the window is moved. The callback is provided with the screen- * position of the upper-left corner of the client area of the window.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_pos- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun);--/*! @brief Sets the size callback for the specified window.- *- * This function sets the size callback of the specified window, which is- * called when the window is resized. The callback is provided with the size,- * in screen coordinates, of the client area of the window.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_size- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup window- */-GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun);--/*! @brief Sets the close callback for the specified window.- *- * This function sets the close callback of the specified window, which is- * called when the user attempts to close the window, for example by clicking- * the close widget in the title bar.- *- * The close flag is set before this callback is called, but you can modify it- * at any time with @ref glfwSetWindowShouldClose.- *- * The close callback is not triggered by @ref glfwDestroyWindow.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @remarks __OS X:__ Selecting Quit from the application menu will- * trigger the close callback for all windows.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_close- *- * @since Added in GLFW 2.5.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup window- */-GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun);--/*! @brief Sets the refresh callback for the specified window.- *- * This function sets the refresh callback of the specified window, which is- * called when the client area of the window needs to be redrawn, for example- * if the window has been exposed after having been covered by another window.- *- * On compositing window systems such as Aero, Compiz or Aqua, where the window- * contents are saved off-screen, this callback may be called only very- * infrequently or never at all.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_refresh- *- * @since Added in GLFW 2.5.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup window- */-GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun);--/*! @brief Sets the focus callback for the specified window.- *- * This function sets the focus callback of the specified window, which is- * called when the window gains or loses input focus.- *- * After the focus callback is called for a window that lost input focus,- * synthetic key and mouse button release events will be generated for all such- * that had been pressed. For more information, see @ref glfwSetKeyCallback- * and @ref glfwSetMouseButtonCallback.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_focus- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);--/*! @brief Sets the iconify callback for the specified window.- *- * This function sets the iconification callback of the specified window, which- * is called when the window is iconified or restored.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_iconify- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);--/*! @brief Sets the framebuffer resize callback for the specified window.- *- * This function sets the framebuffer resize callback of the specified window,- * which is called when the framebuffer of the specified window is resized.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref window_fbsize- *- * @since Added in GLFW 3.0.- *- * @ingroup window- */-GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);--/*! @brief Processes all pending events.- *- * This function processes only those events that are already in the event- * queue and then returns immediately. Processing events will cause the window- * and input callbacks associated with those events to be called.- *- * On some platforms, a window move, resize or menu operation will cause event- * processing to block. This is due to how event processing is designed on- * those platforms. You can use the- * [window refresh callback](@ref window_refresh) to redraw the contents of- * your window when necessary during such operations.- *- * On some platforms, certain events are sent directly to the application- * without going through the event queue, causing callbacks to be called- * outside of a call to one of the event processing functions.- *- * Event processing is not required for joystick input to work.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref events- * @sa glfwWaitEvents- *- * @since Added in GLFW 1.0.- *- * @ingroup window- */-GLFWAPI void glfwPollEvents(void);--/*! @brief Waits until events are queued and processes them.- *- * This function puts the calling thread to sleep until at least one event is- * available in the event queue. Once one or more events are available,- * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue- * are processed and the function then returns immediately. Processing events- * will cause the window and input callbacks associated with those events to be- * called.- *- * Since not all events are associated with callbacks, this function may return- * without a callback having been called even if you are monitoring all- * callbacks.- *- * On some platforms, a window move, resize or menu operation will cause event- * processing to block. This is due to how event processing is designed on- * those platforms. You can use the- * [window refresh callback](@ref window_refresh) to redraw the contents of- * your window when necessary during such operations.- *- * On some platforms, certain callbacks may be called outside of a call to one- * of the event processing functions.- *- * If no windows exist, this function returns immediately. For synchronization- * of threads in applications that do not create windows, use your threading- * library of choice.- *- * Event processing is not required for joystick input to work.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref events- * @sa glfwPollEvents- *- * @since Added in GLFW 2.5.- *- * @ingroup window- */-GLFWAPI void glfwWaitEvents(void);--/*! @brief Posts an empty event to the event queue.- *- * This function posts an empty event from the current thread to the event- * queue, causing @ref glfwWaitEvents to return.- *- * If no windows exist, this function returns immediately. For synchronization- * of threads in applications that do not create windows, use your threading- * library of choice.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref events- * @sa glfwWaitEvents- *- * @since Added in GLFW 3.1.- *- * @ingroup window- */-GLFWAPI void glfwPostEmptyEvent(void);--/*! @brief Returns the value of an input option for the specified window.- *- * This function returns the value of an input option for the specified window.- * The mode must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or- * `GLFW_STICKY_MOUSE_BUTTONS`.- *- * @param[in] window The window to query.- * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or- * `GLFW_STICKY_MOUSE_BUTTONS`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa glfwSetInputMode- *- * @since Added in GLFW 3.0.- *- * @ingroup input- */-GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);--/*! @brief Sets an input option for the specified window.- *- * This function sets an input mode option for the specified window. The mode- * must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or- * `GLFW_STICKY_MOUSE_BUTTONS`.- *- * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor- * modes:- * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.- * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client- * area of the window but does not restrict the cursor from leaving.- * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual- * and unlimited cursor movement. This is useful for implementing for- * example 3D camera controls.- *- * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GL_TRUE` to- * enable sticky keys, or `GL_FALSE` to disable it. If sticky keys are- * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`- * the next time it is called even if the key had been released before the- * call. This is useful when you are only interested in whether keys have been- * pressed but not when or in which order.- *- * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either- * `GL_TRUE` to enable sticky mouse buttons, or `GL_FALSE` to disable it. If- * sticky mouse buttons are enabled, a mouse button press will ensure that @ref- * glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even if- * the mouse button had been released before the call. This is useful when you- * are only interested in whether mouse buttons have been pressed but not when- * or in which order.- *- * @param[in] window The window whose input mode to set.- * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or- * `GLFW_STICKY_MOUSE_BUTTONS`.- * @param[in] value The new value of the specified input mode.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa glfwGetInputMode- *- * @since Added in GLFW 3.0. Replaces `glfwEnable` and `glfwDisable`.- *- * @ingroup input- */-GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);--/*! @brief Returns the last reported state of a keyboard key for the specified- * window.- *- * This function returns the last state reported for the specified key to the- * specified window. The returned state is one of `GLFW_PRESS` or- * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to- * the key callback.- *- * If the `GLFW_STICKY_KEYS` input mode is enabled, this function returns- * `GLFW_PRESS` the first time you call it for a key that was pressed, even if- * that key has already been released.- *- * The key functions deal with physical keys, with [key tokens](@ref keys)- * named after their use on the standard US keyboard layout. If you want to- * input text, use the Unicode character callback instead.- *- * The [modifier key bit masks](@ref mods) are not key tokens and cannot be- * used with this function.- *- * @param[in] window The desired window.- * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is- * not a valid key for this function.- * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_key- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup input- */-GLFWAPI int glfwGetKey(GLFWwindow* window, int key);--/*! @brief Returns the last reported state of a mouse button for the specified- * window.- *- * This function returns the last state reported for the specified mouse button- * to the specified window. The returned state is one of `GLFW_PRESS` or- * `GLFW_RELEASE`.- *- * If the `GLFW_STICKY_MOUSE_BUTTONS` input mode is enabled, this function- * `GLFW_PRESS` the first time you call it for a mouse button that was pressed,- * even if that mouse button has already been released.- *- * @param[in] window The desired window.- * @param[in] button The desired [mouse button](@ref buttons).- * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_mouse_button- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup input- */-GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);--/*! @brief Retrieves the position of the cursor relative to the client area of- * the window.- *- * This function returns the position of the cursor, in screen coordinates,- * relative to the upper-left corner of the client area of the specified- * window.- *- * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor- * position is unbounded and limited only by the minimum and maximum values of- * a `double`.- *- * The coordinate can be converted to their integer equivalents with the- * `floor` function. Casting directly to an integer type works for positive- * coordinates, but fails for negative ones.- *- * Any or all of the position arguments may be `NULL`. If an error occurs, all- * non-`NULL` position arguments will be set to zero.- *- * @param[in] window The desired window.- * @param[out] xpos Where to store the cursor x-coordinate, relative to the- * left edge of the client area, or `NULL`.- * @param[out] ypos Where to store the cursor y-coordinate, relative to the to- * top edge of the client area, or `NULL`.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_pos- * @sa glfwSetCursorPos- *- * @since Added in GLFW 3.0. Replaces `glfwGetMousePos`.- *- * @ingroup input- */-GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);--/*! @brief Sets the position of the cursor, relative to the client area of the- * window.- *- * This function sets the position, in screen coordinates, of the cursor- * relative to the upper-left corner of the client area of the specified- * window. The window must have input focus. If the window does not have- * input focus when this function is called, it fails silently.- *- * __Do not use this function__ to implement things like camera controls. GLFW- * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the- * cursor, transparently re-centers it and provides unconstrained cursor- * motion. See @ref glfwSetInputMode for more information.- *- * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is- * unconstrained and limited only by the minimum and maximum values of- * a `double`.- *- * @param[in] window The desired window.- * @param[in] xpos The desired x-coordinate, relative to the left edge of the- * client area.- * @param[in] ypos The desired y-coordinate, relative to the top edge of the- * client area.- *- * @remarks __X11:__ Due to the asynchronous nature of a modern X desktop, it- * may take a moment for the window focus event to arrive. This means you will- * not be able to set the cursor position directly after window creation.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_pos- * @sa glfwGetCursorPos- *- * @since Added in GLFW 3.0. Replaces `glfwSetMousePos`.- *- * @ingroup input- */-GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);--/*! @brief Creates a custom cursor.- *- * Creates a new custom cursor image that can be set for a window with @ref- * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.- * Any remaining cursors are destroyed by @ref glfwTerminate.- *- * The pixels are 32-bit little-endian RGBA, i.e. eight bits per channel. They- * are arranged canonically as packed sequential rows, starting from the- * top-left corner.- *- * The cursor hotspot is specified in pixels, relative to the upper-left corner- * of the cursor image. Like all other coordinate systems in GLFW, the X-axis- * points to the right and the Y-axis points down.- *- * @param[in] image The desired cursor image.- * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.- * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.- *- * @return The handle of the created cursor, or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The specified image data is copied before this function returns.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_object- * @sa glfwDestroyCursor- * @sa glfwCreateStandardCursor- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);--/*! @brief Creates a cursor with a standard shape.- *- * Returns a cursor with a [standard shape](@ref shapes), that can be set for- * a window with @ref glfwSetCursor.- *- * @param[in] shape One of the [standard shapes](@ref shapes).- *- * @return A new cursor ready to use or `NULL` if an- * [error](@ref error_handling) occurred.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_object- * @sa glfwCreateCursor- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);--/*! @brief Destroys a cursor.- *- * This function destroys a cursor previously created with @ref- * glfwCreateCursor. Any remaining cursors will be destroyed by @ref- * glfwTerminate.- *- * @param[in] cursor The cursor object to destroy.- *- * @par Reentrancy- * This function may not be called from a callback.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_object- * @sa glfwCreateCursor- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);--/*! @brief Sets the cursor for the window.- *- * This function 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](@ref 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.- *- * @param[in] window The window to set the cursor for.- * @param[in] cursor The cursor to set, or `NULL` to switch back to the default- * arrow cursor.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_object- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);--/*! @brief Sets the key callback.- *- * This function sets the key callback of the specified window, which is called- * when a key is pressed, repeated or released.- *- * The key functions deal with physical keys, with layout independent- * [key tokens](@ref keys) named after their values in the standard US keyboard- * layout. If you want to input text, use the- * [character callback](@ref glfwSetCharCallback) instead.- *- * When a window loses input focus, it will generate synthetic key release- * events for all pressed keys. You can tell these events from user-generated- * events by the fact that the synthetic ones are generated after the focus- * loss event has been processed, i.e. after the- * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.- *- * The scancode of a key is specific to that platform or sometimes even to that- * machine. Scancodes are intended to allow users to bind keys that don't have- * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their- * state is not saved and so it cannot be queried with @ref glfwGetKey.- *- * Sometimes GLFW needs to generate synthetic key events, in which case the- * scancode may be zero.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new key callback, or `NULL` to remove the currently- * set callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_key- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup input- */-GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);--/*! @brief Sets the Unicode character callback.- *- * This function sets the character callback of the specified window, which is- * called when a Unicode character is input.- *- * The character callback is intended for Unicode text input. As it deals with- * characters, it is keyboard layout dependent, whereas the- * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1- * to physical keys, as a key may produce zero, one or more characters. If you- * want to know whether a specific physical key was pressed or released, see- * the key callback instead.- *- * The character callback behaves as system text input normally does and will- * not be called if modifier keys are held down that would prevent normal text- * input on that platform, for example a Super (Command) key on OS X or Alt key- * on Windows. There is a- * [character with modifiers callback](@ref glfwSetCharModsCallback) that- * receives these events.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_char- *- * @since Added in GLFW 2.4.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup input- */-GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);--/*! @brief Sets the Unicode character with modifiers callback.- *- * This function sets the character with modifiers callback of the specified- * window, which is called when a Unicode character is input regardless of what- * modifier keys are used.- *- * The character with modifiers callback is intended for implementing custom- * Unicode character input. For regular Unicode text input, see the- * [character callback](@ref glfwSetCharCallback). Like the character- * callback, the character with modifiers callback deals with characters and is- * keyboard layout dependent. Characters do not map 1:1 to physical keys, as- * a key may produce zero, one or more characters. If you want to know whether- * a specific physical key was pressed or released, see the- * [key callback](@ref glfwSetKeyCallback) instead.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or an- * error occurred.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_char- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);--/*! @brief Sets the mouse button callback.- *- * This function sets the mouse button callback of the specified window, which- * is called when a mouse button is pressed or released.- *- * When a window loses input focus, it will generate synthetic mouse button- * release events for all pressed mouse buttons. You can tell these events- * from user-generated events by the fact that the synthetic ones are generated- * after the focus loss event has been processed, i.e. after the- * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref input_mouse_button- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter. Updated callback signature.- *- * @ingroup input- */-GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun);--/*! @brief Sets the cursor position callback.- *- * This function sets the cursor position callback of the specified window,- * which is called when the cursor is moved. The callback is provided with the- * position, in screen coordinates, relative to the upper-left corner of the- * client area of the window.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_pos- *- * @since Added in GLFW 3.0. Replaces `glfwSetMousePosCallback`.- *- * @ingroup input- */-GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun);--/*! @brief Sets the cursor enter/exit callback.- *- * This function sets the cursor boundary crossing callback of the specified- * window, which is called when the cursor enters or leaves the client area of- * the window.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new callback, or `NULL` to remove the currently set- * callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref cursor_enter- *- * @since Added in GLFW 3.0.- *- * @ingroup input- */-GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun);--/*! @brief Sets the scroll callback.- *- * This function sets the scroll callback of the specified window, which is- * called when a scrolling device is used, such as a mouse wheel or scrolling- * area of a touchpad.- *- * The scroll callback receives all scrolling input, like that from a mouse- * wheel or a touchpad scrolling area.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently- * set callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref scrolling- *- * @since Added in GLFW 3.0. Replaces `glfwSetMouseWheelCallback`.- *- * @ingroup input- */-GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun);--/*! @brief Sets the file drop callback.- *- * This function sets the file drop callback of the specified window, which is- * called when one or more dragged files are dropped on the window.- *- * Because the path array and its strings may have been generated specifically- * for that event, they are not guaranteed to be valid after the callback has- * returned. If you wish to use them after the callback returns, you need to- * make a deep copy.- *- * @param[in] window The window whose callback to set.- * @param[in] cbfun The new file drop callback, or `NULL` to remove the- * currently set callback.- * @return The previously set callback, or `NULL` if no callback was set or the- * library had not been [initialized](@ref intro_init).- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref path_drop- *- * @since Added in GLFW 3.1.- *- * @ingroup input- */-GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);--/*! @brief Returns whether the specified joystick is present.- *- * This function returns whether the specified joystick is present.- *- * @param[in] joy The [joystick](@ref joysticks) to query.- * @return `GL_TRUE` if the joystick is present, or `GL_FALSE` otherwise.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref joystick- *- * @since Added in GLFW 3.0. Replaces `glfwGetJoystickParam`.- *- * @ingroup input- */-GLFWAPI int glfwJoystickPresent(int joy);--/*! @brief Returns the values of all axes of the specified joystick.- *- * This function returns the values of all axes of the specified joystick.- * Each element in the array is a value between -1.0 and 1.0.- *- * @param[in] joy The [joystick](@ref joysticks) to query.- * @param[out] count Where to store the number of axis values in the returned- * array. This is set to zero if an error occurred.- * @return An array of axis values, or `NULL` if the joystick is not present.- *- * @par Pointer Lifetime- * The returned array is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified joystick is disconnected, this- * function is called again for that joystick or the library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref joystick_axis- *- * @since Added in GLFW 3.0. Replaces `glfwGetJoystickPos`.- *- * @ingroup input- */-GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);--/*! @brief Returns the state of all buttons of the specified joystick.- *- * This function returns the state of all buttons of the specified joystick.- * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.- *- * @param[in] joy The [joystick](@ref joysticks) to query.- * @param[out] count Where to store the number of button states in the returned- * array. This is set to zero if an error occurred.- * @return An array of button states, or `NULL` if the joystick is not present.- *- * @par Pointer Lifetime- * The returned array is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified joystick is disconnected, this- * function is called again for that joystick or the library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref joystick_button- *- * @since Added in GLFW 2.2.- *- * @par- * __GLFW 3:__ Changed to return a dynamic array.- *- * @ingroup input- */-GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);--/*! @brief Returns the name of the specified joystick.- *- * This function returns the name, encoded as UTF-8, of the specified joystick.- * The returned string is allocated and freed by GLFW. You should not free it- * yourself.- *- * @param[in] joy The [joystick](@ref joysticks) to query.- * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick- * is not present.- *- * @par Pointer Lifetime- * The returned string is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the specified joystick is disconnected, this- * function is called again for that joystick or the library is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref joystick_name- *- * @since Added in GLFW 3.0.- *- * @ingroup input- */-GLFWAPI const char* glfwGetJoystickName(int joy);--/*! @brief Sets the clipboard to the specified string.- *- * This function sets the system clipboard to the specified, UTF-8 encoded- * string.- *- * @param[in] window The window that will own the clipboard contents.- * @param[in] string A UTF-8 encoded string.- *- * @par Pointer Lifetime- * The specified string is copied before this function returns.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref clipboard- * @sa glfwGetClipboardString- *- * @since Added in GLFW 3.0.- *- * @ingroup input- */-GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);--/*! @brief Returns the contents of the clipboard as a string.- *- * This function returns the contents of the system clipboard, if it contains- * or is convertible to a UTF-8 encoded string.- *- * @param[in] window The window that will request the clipboard contents.- * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`- * if an [error](@ref error_handling) occurred.- *- * @par Pointer Lifetime- * The returned string is allocated and freed by GLFW. You should not free it- * yourself. It is valid until the next call to @ref- * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library- * is terminated.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref clipboard- * @sa glfwSetClipboardString- *- * @since Added in GLFW 3.0.- *- * @ingroup input- */-GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);--/*! @brief Returns the value of the GLFW timer.- *- * This function returns the value of the GLFW timer. Unless the timer has- * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW- * was initialized.- *- * The resolution of the timer is system dependent, but is usually on the order- * of a few micro- or nanoseconds. It uses the highest-resolution monotonic- * time source on each supported platform.- *- * @return The current value, in seconds, or zero if an- * [error](@ref error_handling) occurred.- *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.- *- * @sa @ref time- *- * @since Added in GLFW 1.0.- *- * @ingroup input- */-GLFWAPI double glfwGetTime(void);--/*! @brief Sets the GLFW timer.- *- * This function sets the value of the GLFW timer. It then continues to count- * up from that value. The value must be a positive finite number.- *- * @param[in] time The new value, in seconds.- *- * @par Thread Safety- * This function may only be called from the main thread.- *- * @sa @ref time- *- * @since Added in GLFW 2.2.- *- * @ingroup input- */-GLFWAPI void glfwSetTime(double time);--/*! @brief Makes the context of the specified window current for the calling- * thread.- *- * This function makes the OpenGL or OpenGL ES context of the specified window- * current on 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.- *- * By default, making a context non-current implicitly forces a pipeline flush.- * On machines that support `GL_KHR_context_flush_control`, you can control- * whether a context performs this flush by setting the- * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint.- *- * @param[in] window The window whose context to make current, or `NULL` to- * detach the current context.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref context_current- * @sa glfwGetCurrentContext- *- * @since Added in GLFW 3.0.- *- * @ingroup context- */-GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);--/*! @brief Returns the window whose context is current on the calling thread.- *- * This function returns the window whose OpenGL or OpenGL ES context is- * current on the calling thread.- *- * @return The window whose context is current, or `NULL` if no window's- * context is current.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref context_current- * @sa glfwMakeContextCurrent- *- * @since Added in GLFW 3.0.- *- * @ingroup context- */-GLFWAPI GLFWwindow* glfwGetCurrentContext(void);--/*! @brief Swaps the front and back buffers of the specified window.- *- * This function swaps the front and back buffers of the specified window. If- * the swap interval is greater than zero, the GPU driver waits the specified- * number of screen updates before swapping the buffers.- *- * @param[in] window The window whose buffers to swap.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref buffer_swap- * @sa glfwSwapInterval- *- * @since Added in GLFW 1.0.- *- * @par- * __GLFW 3:__ Added window handle parameter.- *- * @ingroup window- */-GLFWAPI void glfwSwapBuffers(GLFWwindow* window);--/*! @brief Sets the swap interval for the current context.- *- * This function sets the swap interval for the current context, i.e. the- * number of screen updates to wait from the time @ref glfwSwapBuffers was- * called before swapping the buffers and returning. This is sometimes called- * _vertical synchronization_, _vertical retrace synchronization_ or just- * _vsync_.- *- * Contexts that support either of the `WGL_EXT_swap_control_tear` and- * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,- * which allow the driver to swap even if a frame arrives a little bit late.- * You can check for the presence of these extensions using @ref- * glfwExtensionSupported. For more information about swap tearing, see the- * extension specifications.- *- * A context must be current on the calling thread. Calling this function- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.- *- * @param[in] interval The minimum number of screen updates to wait for- * until the buffers are swapped by @ref glfwSwapBuffers.- *- * @remarks This function is not called during context creation, leaving the- * swap interval set to whatever is the default on that platform. This is done- * because some swap interval extensions used by GLFW do not allow the swap- * interval to be reset to zero once it has been set to a non-zero value.- *- * @remarks Some GPU drivers do not honor the requested swap interval, either- * because of a user setting that overrides the application's request or due to- * bugs in the driver.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref buffer_swap- * @sa glfwSwapBuffers- *- * @since Added in GLFW 1.0.- *- * @ingroup context- */-GLFWAPI void glfwSwapInterval(int interval);--/*! @brief Returns whether the specified extension is available.- *- * This function returns whether the specified- * [client API extension](@ref context_glext) is supported by the current- * OpenGL or OpenGL ES context. It searches both for OpenGL and OpenGL ES- * extension and platform-specific context creation API extensions.- *- * A context must be current on the calling thread. Calling this function- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.- *- * As this functions retrieves and searches one or more extension strings each- * call, it is recommended that you cache its results if it is going to be used- * frequently. The extension strings will not change during the lifetime of- * a context, so there is no danger in doing this.- *- * @param[in] extension The ASCII encoded name of the extension.- * @return `GL_TRUE` if the extension is available, or `GL_FALSE` otherwise.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref context_glext- * @sa glfwGetProcAddress- *- * @since Added in GLFW 1.0.- *- * @ingroup context- */-GLFWAPI int glfwExtensionSupported(const char* extension);--/*! @brief Returns the address of the specified function for the current- * context.- *- * This function returns the address of the specified- * [core or extension function](@ref context_glext), if it is supported- * by the current context.- *- * A context must be current on the calling thread. Calling this function- * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.- *- * @param[in] procname The ASCII encoded name of the function.- * @return The address of the function, or `NULL` if the function is- * unavailable or an [error](@ref error_handling) occurred.- *- * @remarks The addresses of a given function is not guaranteed to be the same- * between contexts.- *- * @remarks This function may return a non-`NULL` address despite the- * associated version or extension not being available. Always check the- * context version or extension string presence first.- *- * @par Pointer Lifetime- * The returned function pointer is valid until the context is destroyed or the- * library is terminated.- *- * @par Thread Safety- * This function may be called from any thread.- *- * @sa @ref context_glext- * @sa glfwExtensionSupported- *- * @since Added in GLFW 1.0.- *- * @ingroup context- */-GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);+ * GLFW 3.2 - www.glfw.org+ * A library for OpenGL, window and input+ *------------------------------------------------------------------------+ * Copyright (c) 2002-2006 Marcus Geelnard+ * Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+ *+ * This software is provided 'as-is', without any express or implied+ * warranty. In no event will the authors be held liable for any damages+ * arising from the use of this software.+ *+ * Permission is granted to anyone to use this software for any purpose,+ * including commercial applications, and to alter it and redistribute it+ * freely, subject to the following restrictions:+ *+ * 1. The origin of this software must not be misrepresented; you must not+ * claim that you wrote the original software. If you use this software+ * in a product, an acknowledgment in the product documentation would+ * be appreciated but is not required.+ *+ * 2. Altered source versions must be plainly marked as such, and must not+ * be misrepresented as being the original software.+ *+ * 3. This notice may not be removed or altered from any source+ * distribution.+ *+ *************************************************************************/++#ifndef _glfw3_h_+#define _glfw3_h_++#ifdef __cplusplus+extern "C" {+#endif+++/*************************************************************************+ * Doxygen documentation+ *************************************************************************/++/*! @file glfw3.h+ * @brief The header of the GLFW 3 API.+ *+ * This is the header file of the GLFW 3 API. It defines all its types and+ * declares all its functions.+ *+ * For more information about how to use this file, see @ref build_include.+ */+/*! @defgroup context Context reference+ *+ * This is the reference documentation for OpenGL and OpenGL ES context related+ * functions. For more task-oriented information, see the @ref context_guide.+ */+/*! @defgroup vulkan Vulkan reference+ *+ * This is the reference documentation for Vulkan related functions and types.+ * For more task-oriented information, see the @ref vulkan_guide.+ */+/*! @defgroup init Initialization, version and error reference+ *+ * This is the reference documentation for initialization and termination of+ * the library, version management and error handling. For more task-oriented+ * information, see the @ref intro_guide.+ */+/*! @defgroup input Input reference+ *+ * This is the reference documentation for input related functions and types.+ * For more task-oriented information, see the @ref input_guide.+ */+/*! @defgroup monitor Monitor reference+ *+ * This is the reference documentation for monitor related functions and types.+ * For more task-oriented information, see the @ref monitor_guide.+ */+/*! @defgroup window Window reference+ *+ * This is the reference documentation for window related functions and types,+ * including creation, deletion and event polling. For more task-oriented+ * information, see the @ref window_guide.+ */+++/*************************************************************************+ * Compiler- and platform-specific preprocessor work+ *************************************************************************/++/* If we are we on Windows, we want a single define for it.+ */+#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))+ #define _WIN32+#endif /* _WIN32 */++/* It is customary to use APIENTRY for OpenGL function pointer declarations on+ * all platforms. Additionally, the Windows OpenGL header needs APIENTRY.+ */+#ifndef APIENTRY+ #ifdef _WIN32+ #define APIENTRY __stdcall+ #else+ #define APIENTRY+ #endif+#endif /* APIENTRY */++/* Some Windows OpenGL headers need this.+ */+#if !defined(WINGDIAPI) && defined(_WIN32)+ #define WINGDIAPI __declspec(dllimport)+ #define GLFW_WINGDIAPI_DEFINED+#endif /* WINGDIAPI */++/* Some Windows GLU headers need this.+ */+#if !defined(CALLBACK) && defined(_WIN32)+ #define CALLBACK __stdcall+ #define GLFW_CALLBACK_DEFINED+#endif /* CALLBACK */++/* Include because most Windows GLU headers need wchar_t and+ * the OS X OpenGL header blocks the definition of ptrdiff_t by glext.h.+ * Include it unconditionally to avoid surprising side-effects.+ */+#include <stddef.h>++/* Include because it is needed by Vulkan and related functions.+ */+#include <stdint.h>++/* Include the chosen client API headers.+ */+#if defined(__APPLE__)+ #if defined(GLFW_INCLUDE_GLCOREARB)+ #include <OpenGL/gl3.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <OpenGL/gl3ext.h>+ #endif+ #elif !defined(GLFW_INCLUDE_NONE)+ #if !defined(GLFW_INCLUDE_GLEXT)+ #define GL_GLEXT_LEGACY+ #endif+ #include <OpenGL/gl.h>+ #endif+ #if defined(GLFW_INCLUDE_GLU)+ #include <OpenGL/glu.h>+ #endif+#else+ #if defined(GLFW_INCLUDE_GLCOREARB)+ #include <GL/glcorearb.h>+ #elif defined(GLFW_INCLUDE_ES1)+ #include <GLES/gl.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <GLES/glext.h>+ #endif+ #elif defined(GLFW_INCLUDE_ES2)+ #include <GLES2/gl2.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <GLES2/gl2ext.h>+ #endif+ #elif defined(GLFW_INCLUDE_ES3)+ #include <GLES3/gl3.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <GLES2/gl2ext.h>+ #endif+ #elif defined(GLFW_INCLUDE_ES31)+ #include <GLES3/gl31.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <GLES2/gl2ext.h>+ #endif+ #elif defined(GLFW_INCLUDE_VULKAN)+ #include <vulkan/vulkan.h>+ #elif !defined(GLFW_INCLUDE_NONE)+ #include <GL/gl.h>+ #if defined(GLFW_INCLUDE_GLEXT)+ #include <GL/glext.h>+ #endif+ #endif+ #if defined(GLFW_INCLUDE_GLU)+ #include <GL/glu.h>+ #endif+#endif++#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL)+ /* GLFW_DLL must be defined by applications that are linking against the DLL+ * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW+ * configuration header when compiling the DLL version of the library.+ */+ #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined"+#endif++/* GLFWAPI is used to declare public API functions for export+ * from the DLL / shared library / dynamic library.+ */+#if defined(_WIN32) && defined(_GLFW_BUILD_DLL)+ /* We are building GLFW as a Win32 DLL */+ #define GLFWAPI __declspec(dllexport)+#elif defined(_WIN32) && defined(GLFW_DLL)+ /* We are calling GLFW as a Win32 DLL */+ #define GLFWAPI __declspec(dllimport)+#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL)+ /* We are building GLFW as a shared / dynamic library */+ #define GLFWAPI __attribute__((visibility("default")))+#else+ /* We are building or calling GLFW as a static library */+ #define GLFWAPI+#endif+++/*************************************************************************+ * GLFW API tokens+ *************************************************************************/++/*! @name GLFW version macros+ * @{ */+/*! @brief The major version number of the GLFW library.+ *+ * This is incremented when the API is changed in non-compatible ways.+ * @ingroup init+ */+#define GLFW_VERSION_MAJOR 3+/*! @brief The minor version number of the GLFW library.+ *+ * This is incremented when features are added to the API but it remains+ * backward-compatible.+ * @ingroup init+ */+#define GLFW_VERSION_MINOR 2+/*! @brief The revision number of the GLFW library.+ *+ * This is incremented when a bug fix release is made that does not contain any+ * API changes.+ * @ingroup init+ */+#define GLFW_VERSION_REVISION 1+/*! @} */++/*! @name Boolean values+ * @{ */+/*! @brief One.+ *+ * One. Seriously. You don't _need_ to use this symbol in your code. It's+ * just semantic sugar for the number 1. You can use `1` or `true` or `_True`+ * or `GL_TRUE` or whatever you want.+ */+#define GLFW_TRUE 1+/*! @brief Zero.+ *+ * Zero. Seriously. You don't _need_ to use this symbol in your code. It's+ * just just semantic sugar for the number 0. You can use `0` or `false` or+ * `_False` or `GL_FALSE` or whatever you want.+ */+#define GLFW_FALSE 0+/*! @} */++/*! @name Key and button actions+ * @{ */+/*! @brief The key or mouse button was released.+ *+ * The key or mouse button was released.+ *+ * @ingroup input+ */+#define GLFW_RELEASE 0+/*! @brief The key or mouse button was pressed.+ *+ * The key or mouse button was pressed.+ *+ * @ingroup input+ */+#define GLFW_PRESS 1+/*! @brief The key was held down until it repeated.+ *+ * The key was held down until it repeated.+ *+ * @ingroup input+ */+#define GLFW_REPEAT 2+/*! @} */++/*! @defgroup keys Keyboard keys+ *+ * See [key input](@ref input_key) for how these are used.+ *+ * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60),+ * but re-arranged to map to 7-bit ASCII for printable keys (function keys are+ * put in the 256+ range).+ *+ * The naming of the key codes follow these rules:+ * - The US keyboard layout is used+ * - Names of printable alpha-numeric characters are used (e.g. "A", "R",+ * "3", etc.)+ * - For non-alphanumeric characters, Unicode:ish names are used (e.g.+ * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not+ * correspond to the Unicode standard (usually for brevity)+ * - Keys that lack a clear US mapping are named "WORLD_x"+ * - For non-printable keys, custom names are used (e.g. "F4",+ * "BACKSPACE", etc.)+ *+ * @ingroup input+ * @{+ */++/* The unknown key */+#define GLFW_KEY_UNKNOWN -1++/* Printable keys */+#define GLFW_KEY_SPACE 32+#define GLFW_KEY_APOSTROPHE 39 /* ' */+#define GLFW_KEY_COMMA 44 /* , */+#define GLFW_KEY_MINUS 45 /* - */+#define GLFW_KEY_PERIOD 46 /* . */+#define GLFW_KEY_SLASH 47 /* / */+#define GLFW_KEY_0 48+#define GLFW_KEY_1 49+#define GLFW_KEY_2 50+#define GLFW_KEY_3 51+#define GLFW_KEY_4 52+#define GLFW_KEY_5 53+#define GLFW_KEY_6 54+#define GLFW_KEY_7 55+#define GLFW_KEY_8 56+#define GLFW_KEY_9 57+#define GLFW_KEY_SEMICOLON 59 /* ; */+#define GLFW_KEY_EQUAL 61 /* = */+#define GLFW_KEY_A 65+#define GLFW_KEY_B 66+#define GLFW_KEY_C 67+#define GLFW_KEY_D 68+#define GLFW_KEY_E 69+#define GLFW_KEY_F 70+#define GLFW_KEY_G 71+#define GLFW_KEY_H 72+#define GLFW_KEY_I 73+#define GLFW_KEY_J 74+#define GLFW_KEY_K 75+#define GLFW_KEY_L 76+#define GLFW_KEY_M 77+#define GLFW_KEY_N 78+#define GLFW_KEY_O 79+#define GLFW_KEY_P 80+#define GLFW_KEY_Q 81+#define GLFW_KEY_R 82+#define GLFW_KEY_S 83+#define GLFW_KEY_T 84+#define GLFW_KEY_U 85+#define GLFW_KEY_V 86+#define GLFW_KEY_W 87+#define GLFW_KEY_X 88+#define GLFW_KEY_Y 89+#define GLFW_KEY_Z 90+#define GLFW_KEY_LEFT_BRACKET 91 /* [ */+#define GLFW_KEY_BACKSLASH 92 /* \ */+#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */+#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */+#define GLFW_KEY_WORLD_1 161 /* non-US #1 */+#define GLFW_KEY_WORLD_2 162 /* non-US #2 */++/* Function keys */+#define GLFW_KEY_ESCAPE 256+#define GLFW_KEY_ENTER 257+#define GLFW_KEY_TAB 258+#define GLFW_KEY_BACKSPACE 259+#define GLFW_KEY_INSERT 260+#define GLFW_KEY_DELETE 261+#define GLFW_KEY_RIGHT 262+#define GLFW_KEY_LEFT 263+#define GLFW_KEY_DOWN 264+#define GLFW_KEY_UP 265+#define GLFW_KEY_PAGE_UP 266+#define GLFW_KEY_PAGE_DOWN 267+#define GLFW_KEY_HOME 268+#define GLFW_KEY_END 269+#define GLFW_KEY_CAPS_LOCK 280+#define GLFW_KEY_SCROLL_LOCK 281+#define GLFW_KEY_NUM_LOCK 282+#define GLFW_KEY_PRINT_SCREEN 283+#define GLFW_KEY_PAUSE 284+#define GLFW_KEY_F1 290+#define GLFW_KEY_F2 291+#define GLFW_KEY_F3 292+#define GLFW_KEY_F4 293+#define GLFW_KEY_F5 294+#define GLFW_KEY_F6 295+#define GLFW_KEY_F7 296+#define GLFW_KEY_F8 297+#define GLFW_KEY_F9 298+#define GLFW_KEY_F10 299+#define GLFW_KEY_F11 300+#define GLFW_KEY_F12 301+#define GLFW_KEY_F13 302+#define GLFW_KEY_F14 303+#define GLFW_KEY_F15 304+#define GLFW_KEY_F16 305+#define GLFW_KEY_F17 306+#define GLFW_KEY_F18 307+#define GLFW_KEY_F19 308+#define GLFW_KEY_F20 309+#define GLFW_KEY_F21 310+#define GLFW_KEY_F22 311+#define GLFW_KEY_F23 312+#define GLFW_KEY_F24 313+#define GLFW_KEY_F25 314+#define GLFW_KEY_KP_0 320+#define GLFW_KEY_KP_1 321+#define GLFW_KEY_KP_2 322+#define GLFW_KEY_KP_3 323+#define GLFW_KEY_KP_4 324+#define GLFW_KEY_KP_5 325+#define GLFW_KEY_KP_6 326+#define GLFW_KEY_KP_7 327+#define GLFW_KEY_KP_8 328+#define GLFW_KEY_KP_9 329+#define GLFW_KEY_KP_DECIMAL 330+#define GLFW_KEY_KP_DIVIDE 331+#define GLFW_KEY_KP_MULTIPLY 332+#define GLFW_KEY_KP_SUBTRACT 333+#define GLFW_KEY_KP_ADD 334+#define GLFW_KEY_KP_ENTER 335+#define GLFW_KEY_KP_EQUAL 336+#define GLFW_KEY_LEFT_SHIFT 340+#define GLFW_KEY_LEFT_CONTROL 341+#define GLFW_KEY_LEFT_ALT 342+#define GLFW_KEY_LEFT_SUPER 343+#define GLFW_KEY_RIGHT_SHIFT 344+#define GLFW_KEY_RIGHT_CONTROL 345+#define GLFW_KEY_RIGHT_ALT 346+#define GLFW_KEY_RIGHT_SUPER 347+#define GLFW_KEY_MENU 348++#define GLFW_KEY_LAST GLFW_KEY_MENU++/*! @} */++/*! @defgroup mods Modifier key flags+ *+ * See [key input](@ref input_key) for how these are used.+ *+ * @ingroup input+ * @{ */++/*! @brief If this bit is set one or more Shift keys were held down.+ */+#define GLFW_MOD_SHIFT 0x0001+/*! @brief If this bit is set one or more Control keys were held down.+ */+#define GLFW_MOD_CONTROL 0x0002+/*! @brief If this bit is set one or more Alt keys were held down.+ */+#define GLFW_MOD_ALT 0x0004+/*! @brief If this bit is set one or more Super keys were held down.+ */+#define GLFW_MOD_SUPER 0x0008++/*! @} */++/*! @defgroup buttons Mouse buttons+ *+ * See [mouse button input](@ref input_mouse_button) for how these are used.+ *+ * @ingroup input+ * @{ */+#define GLFW_MOUSE_BUTTON_1 0+#define GLFW_MOUSE_BUTTON_2 1+#define GLFW_MOUSE_BUTTON_3 2+#define GLFW_MOUSE_BUTTON_4 3+#define GLFW_MOUSE_BUTTON_5 4+#define GLFW_MOUSE_BUTTON_6 5+#define GLFW_MOUSE_BUTTON_7 6+#define GLFW_MOUSE_BUTTON_8 7+#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8+#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1+#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2+#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3+/*! @} */++/*! @defgroup joysticks Joysticks+ *+ * See [joystick input](@ref joystick) for how these are used.+ *+ * @ingroup input+ * @{ */+#define GLFW_JOYSTICK_1 0+#define GLFW_JOYSTICK_2 1+#define GLFW_JOYSTICK_3 2+#define GLFW_JOYSTICK_4 3+#define GLFW_JOYSTICK_5 4+#define GLFW_JOYSTICK_6 5+#define GLFW_JOYSTICK_7 6+#define GLFW_JOYSTICK_8 7+#define GLFW_JOYSTICK_9 8+#define GLFW_JOYSTICK_10 9+#define GLFW_JOYSTICK_11 10+#define GLFW_JOYSTICK_12 11+#define GLFW_JOYSTICK_13 12+#define GLFW_JOYSTICK_14 13+#define GLFW_JOYSTICK_15 14+#define GLFW_JOYSTICK_16 15+#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16+/*! @} */++/*! @defgroup errors Error codes+ *+ * See [error handling](@ref error_handling) for how these are used.+ *+ * @ingroup init+ * @{ */+/*! @brief GLFW has not been initialized.+ *+ * This occurs if a GLFW function was called that must not be called unless the+ * library is [initialized](@ref intro_init).+ *+ * @analysis Application programmer error. Initialize GLFW before calling any+ * function that requires initialization.+ */+#define GLFW_NOT_INITIALIZED 0x00010001+/*! @brief No context is current for this thread.+ *+ * This occurs if a GLFW function was called that needs and operates on the+ * current OpenGL or OpenGL ES context but no context is current on the calling+ * thread. One such function is @ref glfwSwapInterval.+ *+ * @analysis Application programmer error. Ensure a context is current before+ * calling functions that require a current context.+ */+#define GLFW_NO_CURRENT_CONTEXT 0x00010002+/*! @brief One of the arguments to the function was an invalid enum value.+ *+ * One of the arguments to the function was an invalid enum value, for example+ * requesting [GLFW_RED_BITS](@ref window_hints_fb) with @ref+ * glfwGetWindowAttrib.+ *+ * @analysis Application programmer error. Fix the offending call.+ */+#define GLFW_INVALID_ENUM 0x00010003+/*! @brief One of the arguments to the function was an invalid value.+ *+ * One of the arguments to the function was an invalid value, for example+ * requesting a non-existent OpenGL or OpenGL ES version like 2.7.+ *+ * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead+ * result in a @ref GLFW_VERSION_UNAVAILABLE error.+ *+ * @analysis Application programmer error. Fix the offending call.+ */+#define GLFW_INVALID_VALUE 0x00010004+/*! @brief A memory allocation failed.+ *+ * A memory allocation failed.+ *+ * @analysis A bug in GLFW or the underlying operating system. Report the bug+ * to our [issue tracker](https://github.com/glfw/glfw/issues).+ */+#define GLFW_OUT_OF_MEMORY 0x00010005+/*! @brief GLFW could not find support for the requested API on the system.+ *+ * GLFW could not find support for the requested API on the system.+ *+ * @analysis The installed graphics driver does not support the requested+ * API, or does not support it via the chosen context creation backend.+ * Below are a few examples.+ *+ * @par+ * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only+ * supports OpenGL ES via EGL, while Nvidia and Intel only support it via+ * a WGL or GLX extension. OS X does not provide OpenGL ES at all. The Mesa+ * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary+ * driver. Older graphics drivers do not support Vulkan.+ */+#define GLFW_API_UNAVAILABLE 0x00010006+/*! @brief The requested OpenGL or OpenGL ES version is not available.+ *+ * The requested OpenGL or OpenGL ES version (including any requested context+ * or framebuffer hints) is not available on this machine.+ *+ * @analysis The machine does not support your requirements. If your+ * application is sufficiently flexible, downgrade your requirements and try+ * again. Otherwise, inform the user that their machine does not match your+ * requirements.+ *+ * @par+ * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0+ * comes out before the 4.x series gets that far, also fail with this error and+ * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions+ * will exist.+ */+#define GLFW_VERSION_UNAVAILABLE 0x00010007+/*! @brief A platform-specific error occurred that does not match any of the+ * more specific categories.+ *+ * A platform-specific error occurred that does not match any of the more+ * specific categories.+ *+ * @analysis A bug or configuration error in GLFW, the underlying operating+ * system or its drivers, or a lack of required resources. Report the issue to+ * our [issue tracker](https://github.com/glfw/glfw/issues).+ */+#define GLFW_PLATFORM_ERROR 0x00010008+/*! @brief The requested format is not supported or available.+ *+ * If emitted during window creation, the requested pixel format is not+ * supported.+ *+ * If emitted when querying the clipboard, the contents of the clipboard could+ * not be converted to the requested format.+ *+ * @analysis If emitted during window creation, one or more+ * [hard constraints](@ref window_hints_hard) did not match any of the+ * available pixel formats. If your application is sufficiently flexible,+ * downgrade your requirements and try again. Otherwise, inform the user that+ * their machine does not match your requirements.+ *+ * @par+ * If emitted when querying the clipboard, ignore the error or report it to+ * the user, as appropriate.+ */+#define GLFW_FORMAT_UNAVAILABLE 0x00010009+/*! @brief The specified window does not have an OpenGL or OpenGL ES context.+ *+ * A window that does not have an OpenGL or OpenGL ES context was passed to+ * a function that requires it to have one.+ *+ * @analysis Application programmer error. Fix the offending call.+ */+#define GLFW_NO_WINDOW_CONTEXT 0x0001000A+/*! @} */++#define GLFW_FOCUSED 0x00020001+#define GLFW_ICONIFIED 0x00020002+#define GLFW_RESIZABLE 0x00020003+#define GLFW_VISIBLE 0x00020004+#define GLFW_DECORATED 0x00020005+#define GLFW_AUTO_ICONIFY 0x00020006+#define GLFW_FLOATING 0x00020007+#define GLFW_MAXIMIZED 0x00020008++#define GLFW_RED_BITS 0x00021001+#define GLFW_GREEN_BITS 0x00021002+#define GLFW_BLUE_BITS 0x00021003+#define GLFW_ALPHA_BITS 0x00021004+#define GLFW_DEPTH_BITS 0x00021005+#define GLFW_STENCIL_BITS 0x00021006+#define GLFW_ACCUM_RED_BITS 0x00021007+#define GLFW_ACCUM_GREEN_BITS 0x00021008+#define GLFW_ACCUM_BLUE_BITS 0x00021009+#define GLFW_ACCUM_ALPHA_BITS 0x0002100A+#define GLFW_AUX_BUFFERS 0x0002100B+#define GLFW_STEREO 0x0002100C+#define GLFW_SAMPLES 0x0002100D+#define GLFW_SRGB_CAPABLE 0x0002100E+#define GLFW_REFRESH_RATE 0x0002100F+#define GLFW_DOUBLEBUFFER 0x00021010++#define GLFW_CLIENT_API 0x00022001+#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002+#define GLFW_CONTEXT_VERSION_MINOR 0x00022003+#define GLFW_CONTEXT_REVISION 0x00022004+#define GLFW_CONTEXT_ROBUSTNESS 0x00022005+#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007+#define GLFW_OPENGL_PROFILE 0x00022008+#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009+#define GLFW_CONTEXT_NO_ERROR 0x0002200A+#define GLFW_CONTEXT_CREATION_API 0x0002200B++#define GLFW_NO_API 0+#define GLFW_OPENGL_API 0x00030001+#define GLFW_OPENGL_ES_API 0x00030002++#define GLFW_NO_ROBUSTNESS 0+#define GLFW_NO_RESET_NOTIFICATION 0x00031001+#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002++#define GLFW_OPENGL_ANY_PROFILE 0+#define GLFW_OPENGL_CORE_PROFILE 0x00032001+#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002++#define GLFW_CURSOR 0x00033001+#define GLFW_STICKY_KEYS 0x00033002+#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003++#define GLFW_CURSOR_NORMAL 0x00034001+#define GLFW_CURSOR_HIDDEN 0x00034002+#define GLFW_CURSOR_DISABLED 0x00034003++#define GLFW_ANY_RELEASE_BEHAVIOR 0+#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001+#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002++#define GLFW_NATIVE_CONTEXT_API 0x00036001+#define GLFW_EGL_CONTEXT_API 0x00036002++/*! @defgroup shapes Standard cursor shapes+ *+ * See [standard cursor creation](@ref cursor_standard) for how these are used.+ *+ * @ingroup input+ * @{ */++/*! @brief The regular arrow cursor shape.+ *+ * The regular arrow cursor.+ */+#define GLFW_ARROW_CURSOR 0x00036001+/*! @brief The text input I-beam cursor shape.+ *+ * The text input I-beam cursor shape.+ */+#define GLFW_IBEAM_CURSOR 0x00036002+/*! @brief The crosshair shape.+ *+ * The crosshair shape.+ */+#define GLFW_CROSSHAIR_CURSOR 0x00036003+/*! @brief The hand shape.+ *+ * The hand shape.+ */+#define GLFW_HAND_CURSOR 0x00036004+/*! @brief The horizontal resize arrow shape.+ *+ * The horizontal resize arrow shape.+ */+#define GLFW_HRESIZE_CURSOR 0x00036005+/*! @brief The vertical resize arrow shape.+ *+ * The vertical resize arrow shape.+ */+#define GLFW_VRESIZE_CURSOR 0x00036006+/*! @} */++#define GLFW_CONNECTED 0x00040001+#define GLFW_DISCONNECTED 0x00040002++#define GLFW_DONT_CARE -1+++/*************************************************************************+ * GLFW API types+ *************************************************************************/++/*! @brief Client API function pointer type.+ *+ * Generic function pointer used for returning client API function pointers+ * without forcing a cast from a regular pointer.+ *+ * @sa @ref context_glext+ * @sa glfwGetProcAddress+ *+ * @since Added in version 3.0.+ + * @ingroup context+ */+typedef void (*GLFWglproc)(void);++/*! @brief Vulkan API function pointer type.+ *+ * Generic function pointer used for returning Vulkan API function pointers+ * without forcing a cast from a regular pointer.+ *+ * @sa @ref vulkan_proc+ * @sa glfwGetInstanceProcAddress+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+typedef void (*GLFWvkproc)(void);++/*! @brief Opaque monitor object.+ *+ * Opaque monitor object.+ *+ * @see @ref monitor_object+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+typedef struct GLFWmonitor GLFWmonitor;++/*! @brief Opaque window object.+ *+ * Opaque window object.+ *+ * @see @ref window_object+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+typedef struct GLFWwindow GLFWwindow;++/*! @brief Opaque cursor object.+ *+ * Opaque cursor object.+ *+ * @see @ref cursor_object+ *+ * @since Added in version 3.1.+ *+ * @ingroup cursor+ */+typedef struct GLFWcursor GLFWcursor;++/*! @brief The function signature for error callbacks.+ *+ * This is the function signature for error callback functions.+ *+ * @param[in] error An [error code](@ref errors).+ * @param[in] description A UTF-8 encoded string describing the error.+ *+ * @sa @ref error_handling+ * @sa glfwSetErrorCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup init+ */+typedef void (* GLFWerrorfun)(int,const char*);++/*! @brief The function signature for window position callbacks.+ *+ * This is the function signature for window position callback functions.+ *+ * @param[in] window The window that was moved.+ * @param[in] xpos The new x-coordinate, in screen coordinates, of the+ * upper-left corner of the client area of the window.+ * @param[in] ypos The new y-coordinate, in screen coordinates, of the+ * upper-left corner of the client area of the window.+ *+ * @sa @ref window_pos+ * @sa glfwSetWindowPosCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);++/*! @brief The function signature for window resize callbacks.+ *+ * This is the function signature for window size callback functions.+ *+ * @param[in] window The window that was resized.+ * @param[in] width The new width, in screen coordinates, of the window.+ * @param[in] height The new height, in screen coordinates, of the window.+ *+ * @sa @ref window_size+ * @sa glfwSetWindowSizeCallback+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);++/*! @brief The function signature for window close callbacks.+ *+ * This is the function signature for window close callback functions.+ *+ * @param[in] window The window that the user attempted to close.+ *+ * @sa @ref window_close+ * @sa glfwSetWindowCloseCallback+ *+ * @since Added in version 2.5.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowclosefun)(GLFWwindow*);++/*! @brief The function signature for window content refresh callbacks.+ *+ * This is the function signature for window refresh callback functions.+ *+ * @param[in] window The window whose content needs to be refreshed.+ *+ * @sa @ref window_refresh+ * @sa glfwSetWindowRefreshCallback+ *+ * @since Added in version 2.5.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);++/*! @brief The function signature for window focus/defocus callbacks.+ *+ * This is the function signature for window focus callback functions.+ *+ * @param[in] window The window that gained or lost input focus.+ * @param[in] focused `GLFW_TRUE` if the window was given input focus, or+ * `GLFW_FALSE` if it lost it.+ *+ * @sa @ref window_focus+ * @sa glfwSetWindowFocusCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);++/*! @brief The function signature for window iconify/restore callbacks.+ *+ * This is the function signature for window iconify/restore callback+ * functions.+ *+ * @param[in] window The window that was iconified or restored.+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or+ * `GLFW_FALSE` if it was restored.+ *+ * @sa @ref window_iconify+ * @sa glfwSetWindowIconifyCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);++/*! @brief The function signature for framebuffer resize callbacks.+ *+ * This is the function signature for framebuffer resize callback+ * functions.+ *+ * @param[in] window The window whose framebuffer was resized.+ * @param[in] width The new width, in pixels, of the framebuffer.+ * @param[in] height The new height, in pixels, of the framebuffer.+ *+ * @sa @ref window_fbsize+ * @sa glfwSetFramebufferSizeCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);++/*! @brief The function signature for mouse button callbacks.+ *+ * This is the function signature for mouse button callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] button The [mouse button](@ref buttons) that was pressed or+ * released.+ * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`.+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were+ * held down.+ *+ * @sa @ref input_mouse_button+ * @sa glfwSetMouseButtonCallback+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle and modifier mask parameters.+ *+ * @ingroup input+ */+typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int);++/*! @brief The function signature for cursor position callbacks.+ *+ * This is the function signature for cursor position callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] xpos The new cursor x-coordinate, relative to the left edge of+ * the client area.+ * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the+ * client area.+ *+ * @sa @ref cursor_pos+ * @sa glfwSetCursorPosCallback+ *+ * @since Added in version 3.0. Replaces `GLFWmouseposfun`.+ *+ * @ingroup input+ */+typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);++/*! @brief The function signature for cursor enter/leave callbacks.+ *+ * This is the function signature for cursor enter/leave callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] entered `GLFW_TRUE` if the cursor entered the window's client+ * area, or `GLFW_FALSE` if it left it.+ *+ * @sa @ref cursor_enter+ * @sa glfwSetCursorEnterCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);++/*! @brief The function signature for scroll callbacks.+ *+ * This is the function signature for scroll callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] xoffset The scroll offset along the x-axis.+ * @param[in] yoffset The scroll offset along the y-axis.+ *+ * @sa @ref scrolling+ * @sa glfwSetScrollCallback+ *+ * @since Added in version 3.0. Replaces `GLFWmousewheelfun`.+ *+ * @ingroup input+ */+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);++/*! @brief The function signature for keyboard key callbacks.+ *+ * This is the function signature for keyboard key callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] key The [keyboard key](@ref keys) that was pressed or released.+ * @param[in] scancode The system-specific scancode of the key.+ * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`.+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were+ * held down.+ *+ * @sa @ref input_key+ * @sa glfwSetKeyCallback+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle, scancode and modifier mask parameters.+ *+ * @ingroup input+ */+typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int);++/*! @brief The function signature for Unicode character callbacks.+ *+ * This is the function signature for Unicode character callback functions.+ *+ * @param[in] window The window that received the event.+ * @param[in] codepoint The Unicode code point of the character.+ *+ * @sa @ref input_char+ * @sa glfwSetCharCallback+ *+ * @since Added in version 2.4.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup input+ */+typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);++/*! @brief The function signature for Unicode character with modifiers+ * callbacks.+ *+ * This is the function signature for Unicode character with modifiers callback+ * functions. It is called for each input character, regardless of what+ * modifier keys are held down.+ *+ * @param[in] window The window that received the event.+ * @param[in] codepoint The Unicode code point of the character.+ * @param[in] mods Bit field describing which [modifier keys](@ref mods) were+ * held down.+ *+ * @sa @ref input_char+ * @sa glfwSetCharModsCallback+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);++/*! @brief The function signature for file drop callbacks.+ *+ * This is the function signature for file drop callbacks.+ *+ * @param[in] window The window that received the event.+ * @param[in] count The number of dropped files.+ * @param[in] paths The UTF-8 encoded file and/or directory path names.+ *+ * @sa @ref path_drop+ * @sa glfwSetDropCallback+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+typedef void (* GLFWdropfun)(GLFWwindow*,int,const char**);++/*! @brief The function signature for monitor configuration callbacks.+ *+ * This is the function signature for monitor configuration callback functions.+ *+ * @param[in] monitor The monitor that was connected or disconnected.+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.+ *+ * @sa @ref monitor_event+ * @sa glfwSetMonitorCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);++/*! @brief The function signature for joystick configuration callbacks.+ *+ * This is the function signature for joystick configuration callback+ * functions.+ *+ * @param[in] joy The joystick that was connected or disconnected.+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.+ *+ * @sa @ref joystick_event+ * @sa glfwSetJoystickCallback+ *+ * @since Added in version 3.2.+ *+ * @ingroup input+ */+typedef void (* GLFWjoystickfun)(int,int);++/*! @brief Video mode type.+ *+ * This describes a single video mode.+ *+ * @sa @ref monitor_modes+ * @sa glfwGetVideoMode glfwGetVideoModes+ *+ * @since Added in version 1.0.+ * @glfw3 Added refresh rate member.+ *+ * @ingroup monitor+ */+typedef struct GLFWvidmode+{+ /*! The width, in screen coordinates, of the video mode.+ */+ int width;+ /*! The height, in screen coordinates, of the video mode.+ */+ int height;+ /*! The bit depth of the red channel of the video mode.+ */+ int redBits;+ /*! The bit depth of the green channel of the video mode.+ */+ int greenBits;+ /*! The bit depth of the blue channel of the video mode.+ */+ int blueBits;+ /*! The refresh rate, in Hz, of the video mode.+ */+ int refreshRate;+} GLFWvidmode;++/*! @brief Gamma ramp.+ *+ * This describes the gamma ramp for a monitor.+ *+ * @sa @ref monitor_gamma+ * @sa glfwGetGammaRamp glfwSetGammaRamp+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+typedef struct GLFWgammaramp+{+ /*! An array of value describing the response of the red channel.+ */+ unsigned short* red;+ /*! An array of value describing the response of the green channel.+ */+ unsigned short* green;+ /*! An array of value describing the response of the blue channel.+ */+ unsigned short* blue;+ /*! The number of elements in each array.+ */+ unsigned int size;+} GLFWgammaramp;++/*! @brief Image data.+ *+ * @sa @ref cursor_custom+ * @sa @ref window_icon+ *+ * @since Added in version 2.1.+ * @glfw3 Removed format and bytes-per-pixel members.+ */+typedef struct GLFWimage+{+ /*! The width, in pixels, of this image.+ */+ int width;+ /*! The height, in pixels, of this image.+ */+ int height;+ /*! The pixel data of this image, arranged left-to-right, top-to-bottom.+ */+ unsigned char* pixels;+} GLFWimage;+++/*************************************************************************+ * GLFW API functions+ *************************************************************************/++/*! @brief Initializes the GLFW library.+ *+ * This function initializes the GLFW library. Before most GLFW functions can+ * be used, GLFW must be initialized, and before an application terminates GLFW+ * should be terminated in order to free any resources allocated during or+ * after initialization.+ *+ * If this function fails, it calls @ref glfwTerminate before returning. If it+ * succeeds, you should call @ref glfwTerminate before the application exits.+ *+ * Additional calls to this function after successful initialization but before+ * termination will return `GLFW_TRUE` immediately.+ *+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.+ *+ * @remark @osx This function will change the current directory of the+ * application to the `Contents/Resources` subdirectory of the application's+ * bundle, if present. This can be disabled with a+ * [compile-time option](@ref compile_options_osx).+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref intro_init+ * @sa glfwTerminate+ *+ * @since Added in version 1.0.+ *+ * @ingroup init+ */+GLFWAPI int glfwInit(void);++/*! @brief Terminates the GLFW library.+ *+ * This function destroys all remaining windows and cursors, restores any+ * modified gamma ramps and frees any other allocated resources. Once this+ * function is called, you must again call @ref glfwInit successfully before+ * you will be able to use most GLFW functions.+ *+ * If GLFW has been successfully initialized, this function should be called+ * before the application exits. If initialization fails, there is no need to+ * call this function, as it is called by @ref glfwInit before it returns+ * failure.+ *+ * @errors Possible errors include @ref GLFW_PLATFORM_ERROR.+ *+ * @remark This function may be called before @ref glfwInit.+ *+ * @warning The contexts of any remaining windows must not be current on any+ * other thread when this function is called.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref intro_init+ * @sa glfwInit+ *+ * @since Added in version 1.0.+ *+ * @ingroup init+ */+GLFWAPI void glfwTerminate(void);++/*! @brief Retrieves the version of the GLFW library.+ *+ * This function retrieves the major, minor and revision numbers of the GLFW+ * library. It is intended for when you are using GLFW as a shared library and+ * want to ensure that you are using the minimum required version.+ *+ * Any or all of the version arguments may be `NULL`.+ *+ * @param[out] major Where to store the major version number, or `NULL`.+ * @param[out] minor Where to store the minor version number, or `NULL`.+ * @param[out] rev Where to store the revision number, or `NULL`.+ *+ * @errors None.+ *+ * @remark This function may be called before @ref glfwInit.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref intro_version+ * @sa glfwGetVersionString+ *+ * @since Added in version 1.0.+ *+ * @ingroup init+ */+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev);++/*! @brief Returns a string describing the compile-time configuration.+ *+ * This function returns the compile-time generated+ * [version string](@ref intro_version_string) of the GLFW library binary. It+ * describes the version, platform, compiler and any platform-specific+ * compile-time options. It should not be confused with the OpenGL or OpenGL+ * ES version string, queried with `glGetString`.+ *+ * __Do not use the version string__ to parse the GLFW library version. The+ * @ref glfwGetVersion function provides the version of the running library+ * binary in numerical format.+ *+ * @return The ASCII encoded GLFW version string.+ *+ * @errors None.+ *+ * @remark This function may be called before @ref glfwInit.+ *+ * @pointer_lifetime The returned string is static and compile-time generated.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref intro_version+ * @sa glfwGetVersion+ *+ * @since Added in version 3.0.+ *+ * @ingroup init+ */+GLFWAPI const char* glfwGetVersionString(void);++/*! @brief Sets the error callback.+ *+ * This function sets the error callback, which is called with an error code+ * and a human-readable description each time a GLFW error occurs.+ *+ * The error callback is called on the thread where the error occurred. If you+ * are using GLFW from multiple threads, your error callback needs to be+ * written accordingly.+ *+ * Because the description string may have been generated specifically for that+ * error, it is not guaranteed to be valid after the callback has returned. If+ * you wish to use it after the callback returns, you need to make a copy.+ *+ * Once set, the error callback remains set even after the library has been+ * terminated.+ *+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set.+ *+ * @errors None.+ *+ * @remark This function may be called before @ref glfwInit.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref error_handling+ *+ * @since Added in version 3.0.+ *+ * @ingroup init+ */+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun);++/*! @brief Returns the currently connected monitors.+ *+ * This function returns an array of handles for all currently connected+ * monitors. The primary monitor is always first in the returned array. If no+ * monitors were found, this function returns `NULL`.+ *+ * @param[out] count Where to store the number of monitors in the returned+ * array. This is set to zero if an error occurred.+ * @return An array of monitor handles, or `NULL` if no monitors were found or+ * if an [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is guaranteed to be valid only until the+ * monitor configuration changes or the library is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_monitors+ * @sa @ref monitor_event+ * @sa glfwGetPrimaryMonitor+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count);++/*! @brief Returns the primary monitor.+ *+ * This function returns the primary monitor. This is usually the monitor+ * where elements like the task bar or global menu bar are located.+ *+ * @return The primary monitor, or `NULL` if no monitors were found or if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @remark The primary monitor is always first in the array returned by @ref+ * glfwGetMonitors.+ *+ * @sa @ref monitor_monitors+ * @sa glfwGetMonitors+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void);++/*! @brief Returns the position of the monitor's viewport on the virtual screen.+ *+ * This function returns the position, in screen coordinates, of the upper-left+ * corner of the specified monitor.+ *+ * Any or all of the position arguments may be `NULL`. If an error occurs, all+ * non-`NULL` position arguments will be set to zero.+ *+ * @param[in] monitor The monitor to query.+ * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`.+ * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_properties+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos);++/*! @brief Returns the physical size of the monitor.+ *+ * This function returns the size, in millimetres, of the display area of the+ * specified monitor.+ *+ * Some systems do not provide accurate monitor size information, either+ * because the monitor+ * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data)+ * data is incorrect or because the driver does not report it accurately.+ *+ * Any or all of the size arguments may be `NULL`. If an error occurs, all+ * non-`NULL` size arguments will be set to zero.+ *+ * @param[in] monitor The monitor to query.+ * @param[out] widthMM Where to store the width, in millimetres, of the+ * monitor's display area, or `NULL`.+ * @param[out] heightMM Where to store the height, in millimetres, of the+ * monitor's display area, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @remark @win32 calculates the returned physical size from the+ * current resolution and system DPI instead of querying the monitor EDID data.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_properties+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM);++/*! @brief Returns the name of the specified monitor.+ *+ * This function returns a human-readable name, encoded as UTF-8, of the+ * specified monitor. The name typically reflects the make and model of the+ * monitor and is not guaranteed to be unique among the connected monitors.+ *+ * @param[in] monitor The monitor to query.+ * @return The UTF-8 encoded name of the monitor, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified monitor is+ * disconnected or the library is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_properties+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor);++/*! @brief Sets the monitor configuration callback.+ *+ * This function sets the monitor configuration callback, or removes the+ * currently set callback. This is called when a monitor is connected to or+ * disconnected from the system.+ *+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_event+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun);++/*! @brief Returns the available video modes for the specified monitor.+ *+ * This function returns an array of all video modes supported by the specified+ * monitor. The returned array is sorted in ascending order, first by color+ * bit depth (the sum of all channel depths) and then by resolution area (the+ * product of width and height).+ *+ * @param[in] monitor The monitor to query.+ * @param[out] count Where to store the number of video modes in the returned+ * array. This is set to zero if an error occurred.+ * @return An array of video modes, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified monitor is+ * disconnected, this function is called again for that monitor or the library+ * is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_modes+ * @sa glfwGetVideoMode+ *+ * @since Added in version 1.0.+ * @glfw3 Changed to return an array of modes for a specific monitor.+ *+ * @ingroup monitor+ */+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count);++/*! @brief Returns the current mode of the specified monitor.+ *+ * This function returns the current video mode of the specified monitor. If+ * you have created a full screen window for that monitor, the return value+ * will depend on whether that window is iconified.+ *+ * @param[in] monitor The monitor to query.+ * @return The current mode of the monitor, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified monitor is+ * disconnected or the library is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_modes+ * @sa glfwGetVideoModes+ *+ * @since Added in version 3.0. Replaces `glfwGetDesktopMode`.+ *+ * @ingroup monitor+ */+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);++/*! @brief Generates a gamma ramp and sets it for the specified monitor.+ *+ * This function generates a 256-element gamma ramp from the specified exponent+ * and then calls @ref glfwSetGammaRamp with it. The value must be a finite+ * number greater than zero.+ *+ * @param[in] monitor The monitor whose gamma ramp to set.+ * @param[in] gamma The desired exponent.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_gamma+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);++/*! @brief Returns the current gamma ramp for the specified monitor.+ *+ * This function returns the current gamma ramp of the specified monitor.+ *+ * @param[in] monitor The monitor to query.+ * @return The current gamma ramp, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned structure and its arrays are allocated and+ * freed by GLFW. You should not free them yourself. They are valid until the+ * specified monitor is disconnected, this function is called again for that+ * monitor or the library is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_gamma+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);++/*! @brief Sets the current gamma ramp for the specified monitor.+ *+ * This function sets the current gamma ramp for the specified monitor. The+ * original gamma ramp for that monitor is saved by GLFW the first time this+ * function is called and is restored by @ref glfwTerminate.+ *+ * @param[in] monitor The monitor whose gamma ramp to set.+ * @param[in] ramp The gamma ramp to use.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @remark Gamma ramp sizes other than 256 are not supported by all platforms+ * or graphics hardware.+ *+ * @remark @win32 The gamma ramp size must be 256.+ *+ * @pointer_lifetime The specified gamma ramp is copied before this function+ * returns.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref monitor_gamma+ *+ * @since Added in version 3.0.+ *+ * @ingroup monitor+ */+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp);++/*! @brief Resets all window hints to their default values.+ *+ * This function resets all window hints to their+ * [default values](@ref window_hints_values).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_hints+ * @sa glfwWindowHint+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwDefaultWindowHints(void);++/*! @brief Sets the specified window hint to the desired value.+ *+ * This function sets hints for the next call to @ref glfwCreateWindow. The+ * hints, once set, retain their values until changed by a call to @ref+ * glfwWindowHint or @ref glfwDefaultWindowHints, or until the library is+ * terminated.+ *+ * This function does not check whether the specified hint values are valid.+ * If you set hints to invalid values this will instead be reported by the next+ * call to @ref glfwCreateWindow.+ *+ * @param[in] hint The [window hint](@ref window_hints) to set.+ * @param[in] value The new value of the window hint.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_INVALID_ENUM.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_hints+ * @sa glfwDefaultWindowHints+ *+ * @since Added in version 3.0. Replaces `glfwOpenWindowHint`.+ *+ * @ingroup window+ */+GLFWAPI void glfwWindowHint(int hint, int value);++/*! @brief Creates a window and its associated context.+ *+ * This function creates a window and its associated OpenGL or OpenGL ES+ * context. Most of the options controlling how the window and its context+ * should be created are specified with [window hints](@ref window_hints).+ *+ * Successful creation does not change which context is current. Before you+ * can use the newly created context, you need to+ * [make it current](@ref context_current). For information about the `share`+ * parameter, see @ref context_sharing.+ *+ * The created window, framebuffer and context may differ from what you+ * requested, as not all parameters and hints are+ * [hard constraints](@ref window_hints_hard). This includes the size of the+ * window, especially for full screen windows. To query the actual attributes+ * of the created window, framebuffer and context, see @ref+ * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize.+ *+ * To create a full screen window, you need to specify the monitor the window+ * will cover. If no monitor is specified, the window will be windowed mode.+ * Unless you have a way for the user to choose a specific monitor, it is+ * recommended that you pick the primary monitor. For more information on how+ * to query connected monitors, see @ref monitor_monitors.+ *+ * For full screen windows, the specified size becomes the resolution of the+ * window's _desired video mode_. As long as a full screen window is not+ * iconified, the supported video mode most closely matching the desired video+ * mode is set for the specified monitor. For more information about full+ * screen windows, including the creation of so called _windowed full screen_+ * or _borderless full screen_ windows, see @ref window_windowed_full_screen.+ *+ * Once you have created the window, you can switch it between windowed and+ * full screen mode with @ref glfwSetWindowMonitor. If the window has an+ * OpenGL or OpenGL ES context, it will be unaffected.+ *+ * By default, newly created windows use the placement recommended by the+ * window system. To create the window at a specific position, make it+ * initially invisible using the [GLFW_VISIBLE](@ref window_hints_wnd) window+ * hint, set its [position](@ref window_pos) and then [show](@ref window_hide)+ * it.+ *+ * As long as at least one full screen window is not iconified, the screensaver+ * is prohibited from starting.+ *+ * Window systems put limits on window sizes. Very large or very small window+ * dimensions may be overridden by the window system on creation. Check the+ * actual [size](@ref window_size) after creation.+ *+ * The [swap interval](@ref buffer_swap) is not set during window creation and+ * the initial value may vary depending on driver settings and defaults.+ *+ * @param[in] width The desired width, in screen coordinates, of the window.+ * This must be greater than zero.+ * @param[in] height The desired height, in screen coordinates, of the window.+ * This must be greater than zero.+ * @param[in] title The initial, UTF-8 encoded window title.+ * @param[in] monitor The monitor to use for full screen mode, or `NULL` for+ * windowed mode.+ * @param[in] share The window whose context to share resources with, or `NULL`+ * to not share resources.+ * @return The handle of the created window, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref+ * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @remark @win32 Window creation will fail if the Microsoft GDI software+ * OpenGL implementation is the only one available.+ *+ * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it+ * will be set as the initial icon for the window. If no such icon is present,+ * the `IDI_WINLOGO` icon will be used instead. To set a different icon, see+ * @ref glfwSetWindowIcon.+ *+ * @remark @win32 The context to share resources with must not be current on+ * any other thread.+ *+ * @remark @osx The GLFW window has no icon, as it is not a document+ * window, but the dock icon will be the same as the application bundle's icon.+ * For more information on bundles, see the+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)+ * in the Mac Developer Library.+ *+ * @remark @osx The first time a window is created the menu bar is populated+ * with common commands like Hide, Quit and About. The About entry opens+ * a minimal about dialog with information from the application's bundle. The+ * menu bar can be disabled with a+ * [compile-time option](@ref compile_options_osx).+ *+ * @remark @osx On OS X 10.10 and later the window frame will not be rendered+ * at full resolution on Retina displays unless the `NSHighResolutionCapable`+ * key is enabled in the application bundle's `Info.plist`. For more+ * information, see+ * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html)+ * in the Mac Developer Library. The GLFW test and example programs use+ * a custom `Info.plist` template for this, which can be found as+ * `CMake/MacOSXBundleInfo.plist.in` in the source tree.+ *+ * @remark @x11 Some window managers will not respect the placement of+ * initially hidden windows.+ *+ * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for+ * a window to reach its requested state. This means you may not be able to+ * query the final size, position or other attributes directly after window+ * creation.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_creation+ * @sa glfwDestroyWindow+ *+ * @since Added in version 3.0. Replaces `glfwOpenWindow`.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share);++/*! @brief Destroys the specified window and its context.+ *+ * This function destroys the specified window and its context. On calling+ * this function, no further callbacks will be called for that window.+ *+ * If the context of the specified window is current on the main thread, it is+ * detached before being destroyed.+ *+ * @param[in] window The window to destroy.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @note The context of the specified window must not be current on any other+ * thread when this function is called.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_creation+ * @sa glfwCreateWindow+ *+ * @since Added in version 3.0. Replaces `glfwCloseWindow`.+ *+ * @ingroup window+ */+GLFWAPI void glfwDestroyWindow(GLFWwindow* window);++/*! @brief Checks the close flag of the specified window.+ *+ * This function returns the value of the close flag of the specified window.+ *+ * @param[in] window The window to query.+ * @return The value of the close flag.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @sa @ref window_close+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI int glfwWindowShouldClose(GLFWwindow* window);++/*! @brief Sets the close flag of the specified window.+ *+ * This function sets the value of the close flag of the specified window.+ * This can be used to override the user's attempt to close the window, or+ * to signal that it should be closed.+ *+ * @param[in] window The window whose flag to change.+ * @param[in] value The new value.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @sa @ref window_close+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value);++/*! @brief Sets the title of the specified window.+ *+ * This function sets the window title, encoded as UTF-8, of the specified+ * window.+ *+ * @param[in] window The window whose title to change.+ * @param[in] title The UTF-8 encoded window title.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @remark @osx The window title will not be updated until the next time you+ * process events.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_title+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title);++/*! @brief Sets the icon for the specified window.+ *+ * This function sets the icon of the specified window. If passed an array of+ * candidate images, those of or closest to the sizes desired by the system are+ * selected. If no images are specified, the window reverts to its default+ * icon.+ *+ * The desired image sizes varies depending on platform and system settings.+ * The selected images will be rescaled as needed. Good sizes include 16x16,+ * 32x32 and 48x48.+ *+ * @param[in] window The window whose icon to set.+ * @param[in] count The number of images in the specified array, or zero to+ * revert to the default window icon.+ * @param[in] images The images to create the icon from. This is ignored if+ * count is zero.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The specified image data is copied before this function+ * returns.+ *+ * @remark @osx The GLFW window has no icon, as it is not a document+ * window, so this function does nothing. The dock icon will be the same as+ * the application bundle's icon. For more information on bundles, see the+ * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/)+ * in the Mac Developer Library.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_icon+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images);++/*! @brief Retrieves the position of the client area of the specified window.+ *+ * This function retrieves the position, in screen coordinates, of the+ * upper-left corner of the client area of the specified window.+ *+ * Any or all of the position arguments may be `NULL`. If an error occurs, all+ * non-`NULL` position arguments will be set to zero.+ *+ * @param[in] window The window to query.+ * @param[out] xpos Where to store the x-coordinate of the upper-left corner of+ * the client area, or `NULL`.+ * @param[out] ypos Where to store the y-coordinate of the upper-left corner of+ * the client area, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_pos+ * @sa glfwSetWindowPos+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);++/*! @brief Sets the position of the client area of the specified window.+ *+ * This function sets the position, in screen coordinates, of the upper-left+ * corner of the client area of the specified windowed mode window. If the+ * window is a full screen window, this function does nothing.+ *+ * __Do not use this function__ to move an already visible window unless you+ * have very good reasons for doing so, as it will confuse and annoy the user.+ *+ * The window manager may put limits on what positions are allowed. GLFW+ * cannot and should not override these limits.+ *+ * @param[in] window The window to query.+ * @param[in] xpos The x-coordinate of the upper-left corner of the client area.+ * @param[in] ypos The y-coordinate of the upper-left corner of the client area.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_pos+ * @sa glfwGetWindowPos+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos);++/*! @brief Retrieves the size of the client area of the specified window.+ *+ * This function retrieves the size, in screen coordinates, of the client area+ * of the specified window. If you wish to retrieve the size of the+ * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize.+ *+ * Any or all of the size arguments may be `NULL`. If an error occurs, all+ * non-`NULL` size arguments will be set to zero.+ *+ * @param[in] window The window whose size to retrieve.+ * @param[out] width Where to store the width, in screen coordinates, of the+ * client area, or `NULL`.+ * @param[out] height Where to store the height, in screen coordinates, of the+ * client area, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_size+ * @sa glfwSetWindowSize+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height);++/*! @brief Sets the size limits of the specified window.+ *+ * This function 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.+ *+ * The size limits are applied immediately to a windowed mode window and may+ * cause it to be resized.+ *+ * The maximum dimensions must be greater than or equal to the minimum+ * dimensions and all must be greater than or equal to zero.+ *+ * @param[in] window The window to set limits for.+ * @param[in] minwidth The minimum width, in screen coordinates, of the client+ * area, or `GLFW_DONT_CARE`.+ * @param[in] minheight The minimum height, in screen coordinates, of the+ * client area, or `GLFW_DONT_CARE`.+ * @param[in] maxwidth The maximum width, in screen coordinates, of the client+ * area, or `GLFW_DONT_CARE`.+ * @param[in] maxheight The maximum height, in screen coordinates, of the+ * client area, or `GLFW_DONT_CARE`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark If you set size limits and an aspect ratio that conflict, the+ * results are undefined.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_sizelimits+ * @sa glfwSetWindowAspectRatio+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);++/*! @brief Sets the aspect ratio of the specified window.+ *+ * This function sets the required aspect ratio of the client area of the+ * specified window. If the window is full screen, the aspect ratio only takes+ * effect once it is made windowed. If the window is not resizable, this+ * function does nothing.+ *+ * The aspect ratio is specified as a numerator and a denominator and both+ * values must be greater than zero. For example, the common 16:9 aspect ratio+ * is specified as 16 and 9, respectively.+ *+ * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect+ * ratio limit is disabled.+ *+ * The aspect ratio is applied immediately to a windowed mode window and may+ * cause it to be resized.+ *+ * @param[in] window The window to set limits for.+ * @param[in] numer The numerator of the desired aspect ratio, or+ * `GLFW_DONT_CARE`.+ * @param[in] denom The denominator of the desired aspect ratio, or+ * `GLFW_DONT_CARE`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark If you set size limits and an aspect ratio that conflict, the+ * results are undefined.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_sizelimits+ * @sa glfwSetWindowSizeLimits+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);++/*! @brief Sets the size of the client area of the specified window.+ *+ * This function sets the size, in screen coordinates, of the client area of+ * the specified window.+ *+ * For full screen windows, this function updates the resolution of its desired+ * video mode and switches to the video mode closest to it, without affecting+ * the window's context. As the context is unaffected, the bit depths of the+ * framebuffer remain unchanged.+ *+ * If you wish to update the refresh rate of the desired video mode in addition+ * to its resolution, see @ref glfwSetWindowMonitor.+ *+ * The window manager may put limits on what sizes are allowed. GLFW cannot+ * and should not override these limits.+ *+ * @param[in] window The window to resize.+ * @param[in] width The desired width, in screen coordinates, of the window+ * client area.+ * @param[in] height The desired height, in screen coordinates, of the window+ * client area.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_size+ * @sa glfwGetWindowSize+ * @sa glfwSetWindowMonitor+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height);++/*! @brief Retrieves the size of the framebuffer of the specified window.+ *+ * This function retrieves the size, in pixels, of the framebuffer of the+ * specified window. If you wish to retrieve the size of the window in screen+ * coordinates, see @ref glfwGetWindowSize.+ *+ * Any or all of the size arguments may be `NULL`. If an error occurs, all+ * non-`NULL` size arguments will be set to zero.+ *+ * @param[in] window The window whose framebuffer to query.+ * @param[out] width Where to store the width, in pixels, of the framebuffer,+ * or `NULL`.+ * @param[out] height Where to store the height, in pixels, of the framebuffer,+ * or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_fbsize+ * @sa glfwSetFramebufferSizeCallback+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height);++/*! @brief Retrieves the size of the frame of the window.+ *+ * This function retrieves the size, in screen coordinates, of each edge of the+ * frame of the specified window. This size includes the title bar, if the+ * window has one. The size of the frame may vary depending on the+ * [window-related hints](@ref window_hints_wnd) used to create it.+ *+ * Because this function retrieves the size of each window frame edge and not+ * the offset along a particular coordinate axis, the retrieved values will+ * always be zero or positive.+ *+ * Any or all of the size arguments may be `NULL`. If an error occurs, all+ * non-`NULL` size arguments will be set to zero.+ *+ * @param[in] window The window whose frame size to query.+ * @param[out] left Where to store the size, in screen coordinates, of the left+ * edge of the window frame, or `NULL`.+ * @param[out] top Where to store the size, in screen coordinates, of the top+ * edge of the window frame, or `NULL`.+ * @param[out] right Where to store the size, in screen coordinates, of the+ * right edge of the window frame, or `NULL`.+ * @param[out] bottom Where to store the size, in screen coordinates, of the+ * bottom edge of the window frame, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_size+ *+ * @since Added in version 3.1.+ *+ * @ingroup window+ */+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom);++/*! @brief Iconifies the specified window.+ *+ * This function iconifies (minimizes) the specified window if it was+ * previously restored. If the window is already iconified, this function does+ * nothing.+ *+ * If the specified window is a full screen window, the original monitor+ * resolution is restored until the window is restored.+ *+ * @param[in] window The window to iconify.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_iconify+ * @sa glfwRestoreWindow+ * @sa glfwMaximizeWindow+ *+ * @since Added in version 2.1.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwIconifyWindow(GLFWwindow* window);++/*! @brief Restores the specified window.+ *+ * This function restores the specified window if it was previously iconified+ * (minimized) or maximized. If the window is already restored, this function+ * does nothing.+ *+ * If the specified window is a full screen window, the resolution chosen for+ * the window is restored on the selected monitor.+ *+ * @param[in] window The window to restore.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_iconify+ * @sa glfwIconifyWindow+ * @sa glfwMaximizeWindow+ *+ * @since Added in version 2.1.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwRestoreWindow(GLFWwindow* window);++/*! @brief Maximizes the specified window.+ *+ * This function maximizes the specified window if it was previously not+ * maximized. If the window is already maximized, this function does nothing.+ *+ * If the specified window is a full screen window, this function does nothing.+ *+ * @param[in] window The window to maximize.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @par Thread Safety+ * This function may only be called from the main thread.+ *+ * @sa @ref window_iconify+ * @sa glfwIconifyWindow+ * @sa glfwRestoreWindow+ *+ * @since Added in GLFW 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwMaximizeWindow(GLFWwindow* window);++/*! @brief Makes the specified window visible.+ *+ * This function makes the specified window visible if it was previously+ * hidden. If the window is already visible or is in full screen mode, this+ * function does nothing.+ *+ * @param[in] window The window to make visible.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_hide+ * @sa glfwHideWindow+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwShowWindow(GLFWwindow* window);++/*! @brief Hides the specified window.+ *+ * This function hides the specified window if it was previously visible. If+ * the window is already hidden or is in full screen mode, this function does+ * nothing.+ *+ * @param[in] window The window to hide.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_hide+ * @sa glfwShowWindow+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwHideWindow(GLFWwindow* window);++/*! @brief Brings the specified window to front and sets input focus.+ *+ * This function brings the specified window to front and sets input focus.+ * The window should already be visible and not iconified.+ *+ * By default, both windowed and full screen mode windows are focused when+ * initially created. Set the [GLFW_FOCUSED](@ref window_hints_wnd) to disable+ * this behavior.+ *+ * __Do not use this function__ to steal focus from other applications unless+ * you are certain that is what the user wants. Focus stealing can be+ * extremely disruptive.+ *+ * @param[in] window The window to give input focus.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_focus+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwFocusWindow(GLFWwindow* window);++/*! @brief Returns the monitor that the window uses for full screen mode.+ *+ * This function returns the handle of the monitor that the specified window is+ * in full screen on.+ *+ * @param[in] window The window to query.+ * @return The monitor, or `NULL` if the window is in windowed mode or an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_monitor+ * @sa glfwSetWindowMonitor+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);++/*! @brief Sets the mode, monitor, video mode and placement of a window.+ *+ * This function sets the monitor that the window uses for full screen mode or,+ * if the monitor is `NULL`, makes it windowed mode.+ *+ * When setting a monitor, this function updates the width, height and refresh+ * rate of the desired video mode and switches to the video mode closest to it.+ * The window position is ignored when setting a monitor.+ *+ * When the monitor is `NULL`, the position, width and height are used to+ * place the window client area. The refresh rate is ignored when no monitor+ * is specified.+ *+ * If you only wish to update the resolution of a full screen window or the+ * size of a windowed mode window, see @ref glfwSetWindowSize.+ *+ * When a window transitions from full screen to windowed mode, this function+ * restores any previous window settings such as whether it is decorated,+ * floating, resizable, has size or aspect ratio limits, etc..+ *+ * @param[in] window The window whose monitor, size or video mode to set.+ * @param[in] monitor The desired monitor, or `NULL` to set windowed mode.+ * @param[in] xpos The desired x-coordinate of the upper-left corner of the+ * client area.+ * @param[in] ypos The desired y-coordinate of the upper-left corner of the+ * client area.+ * @param[in] width The desired with, in screen coordinates, of the client area+ * or video mode.+ * @param[in] height The desired height, in screen coordinates, of the client+ * area or video mode.+ * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode,+ * or `GLFW_DONT_CARE`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_monitor+ * @sa @ref window_full_screen+ * @sa glfwGetWindowMonitor+ * @sa glfwSetWindowSize+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);++/*! @brief Returns an attribute of the specified window.+ *+ * This function returns the value of an attribute of the specified window or+ * its OpenGL or OpenGL ES context.+ *+ * @param[in] window The window to query.+ * @param[in] attrib The [window attribute](@ref window_attribs) whose value to+ * return.+ * @return The value of the attribute, or zero if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark Framebuffer related hints are not window attributes. See @ref+ * window_attribs_fb for more information.+ *+ * @remark Zero is a valid value for many window and context related+ * attributes so you cannot use a return value of zero as an indication of+ * errors. However, this function should not fail as long as it is passed+ * valid arguments and the library has been [initialized](@ref intro_init).+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_attribs+ *+ * @since Added in version 3.0. Replaces `glfwGetWindowParam` and+ * `glfwGetGLVersion`.+ *+ * @ingroup window+ */+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);++/*! @brief Sets the user pointer of the specified window.+ *+ * This function sets the user-defined pointer of the specified window. The+ * current value is retained until the window is destroyed. The initial value+ * is `NULL`.+ *+ * @param[in] window The window whose pointer to set.+ * @param[in] pointer The new value.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @sa @ref window_userptr+ * @sa glfwGetWindowUserPointer+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer);++/*! @brief Returns the user pointer of the specified window.+ *+ * This function returns the current value of the user-defined pointer of the+ * specified window. The initial value is `NULL`.+ *+ * @param[in] window The window whose pointer to return.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @sa @ref window_userptr+ * @sa glfwSetWindowUserPointer+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);++/*! @brief Sets the position callback for the specified window.+ *+ * This function sets the position callback of the specified window, which is+ * called when the window is moved. The callback is provided with the screen+ * position of the upper-left corner of the client area of the window.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_pos+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun cbfun);++/*! @brief Sets the size callback for the specified window.+ *+ * This function sets the size callback of the specified window, which is+ * called when the window is resized. The callback is provided with the size,+ * in screen coordinates, of the client area of the window.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_size+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun cbfun);++/*! @brief Sets the close callback for the specified window.+ *+ * This function sets the close callback of the specified window, which is+ * called when the user attempts to close the window, for example by clicking+ * the close widget in the title bar.+ *+ * The close flag is set before this callback is called, but you can modify it+ * at any time with @ref glfwSetWindowShouldClose.+ *+ * The close callback is not triggered by @ref glfwDestroyWindow.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @remark @osx Selecting Quit from the application menu will trigger the close+ * callback for all windows.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_close+ *+ * @since Added in version 2.5.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun cbfun);++/*! @brief Sets the refresh callback for the specified window.+ *+ * This function sets the refresh callback of the specified window, which is+ * called when the client area of the window needs to be redrawn, for example+ * if the window has been exposed after having been covered by another window.+ *+ * On compositing window systems such as Aero, Compiz or Aqua, where the window+ * contents are saved off-screen, this callback may be called only very+ * infrequently or never at all.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_refresh+ *+ * @since Added in version 2.5.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun cbfun);++/*! @brief Sets the focus callback for the specified window.+ *+ * This function sets the focus callback of the specified window, which is+ * called when the window gains or loses input focus.+ *+ * After the focus callback is called for a window that lost input focus,+ * synthetic key and mouse button release events will be generated for all such+ * that had been pressed. For more information, see @ref glfwSetKeyCallback+ * and @ref glfwSetMouseButtonCallback.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_focus+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun cbfun);++/*! @brief Sets the iconify callback for the specified window.+ *+ * This function sets the iconification callback of the specified window, which+ * is called when the window is iconified or restored.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_iconify+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun cbfun);++/*! @brief Sets the framebuffer resize callback for the specified window.+ *+ * This function sets the framebuffer resize callback of the specified window,+ * which is called when the framebuffer of the specified window is resized.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref window_fbsize+ *+ * @since Added in version 3.0.+ *+ * @ingroup window+ */+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun cbfun);++/*! @brief Processes all pending events.+ *+ * This function processes only those events that are already in the event+ * queue and then returns immediately. Processing events will cause the window+ * and input callbacks associated with those events to be called.+ *+ * On some platforms, a window move, resize or menu operation will cause event+ * processing to block. This is due to how event processing is designed on+ * those platforms. You can use the+ * [window refresh callback](@ref window_refresh) to redraw the contents of+ * your window when necessary during such operations.+ *+ * On some platforms, certain events are sent directly to the application+ * without going through the event queue, causing callbacks to be called+ * outside of a call to one of the event processing functions.+ *+ * Event processing is not required for joystick input to work.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref events+ * @sa glfwWaitEvents+ * @sa glfwWaitEventsTimeout+ *+ * @since Added in version 1.0.+ *+ * @ingroup window+ */+GLFWAPI void glfwPollEvents(void);++/*! @brief Waits until events are queued and processes them.+ *+ * This function puts the calling thread to sleep until at least one event is+ * available in the event queue. Once one or more events are available,+ * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue+ * are processed and the function then returns immediately. Processing events+ * will cause the window and input callbacks associated with those events to be+ * called.+ *+ * Since not all events are associated with callbacks, this function may return+ * without a callback having been called even if you are monitoring all+ * callbacks.+ *+ * On some platforms, a window move, resize or menu operation will cause event+ * processing to block. This is due to how event processing is designed on+ * those platforms. You can use the+ * [window refresh callback](@ref window_refresh) to redraw the contents of+ * your window when necessary during such operations.+ *+ * On some platforms, certain callbacks may be called outside of a call to one+ * of the event processing functions.+ *+ * If no windows exist, this function returns immediately. For synchronization+ * of threads in applications that do not create windows, use your threading+ * library of choice.+ *+ * Event processing is not required for joystick input to work.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref events+ * @sa glfwPollEvents+ * @sa glfwWaitEventsTimeout+ *+ * @since Added in version 2.5.+ *+ * @ingroup window+ */+GLFWAPI void glfwWaitEvents(void);++/*! @brief Waits with timeout until events are queued and processes them.+ *+ * This function puts the calling thread to sleep until at least one event is+ * available in the event queue, or until the specified timeout is reached. If+ * one or more events are available, it behaves exactly like @ref+ * glfwPollEvents, i.e. the events in the queue are processed and the function+ * then returns immediately. Processing events will cause the window and input+ * callbacks associated with those events to be called.+ *+ * The timeout value must be a positive finite number.+ *+ * Since not all events are associated with callbacks, this function may return+ * without a callback having been called even if you are monitoring all+ * callbacks.+ *+ * On some platforms, a window move, resize or menu operation will cause event+ * processing to block. This is due to how event processing is designed on+ * those platforms. You can use the+ * [window refresh callback](@ref window_refresh) to redraw the contents of+ * your window when necessary during such operations.+ *+ * On some platforms, certain callbacks may be called outside of a call to one+ * of the event processing functions.+ *+ * If no windows exist, this function returns immediately. For synchronization+ * of threads in applications that do not create windows, use your threading+ * library of choice.+ *+ * Event processing is not required for joystick input to work.+ *+ * @param[in] timeout The maximum amount of time, in seconds, to wait.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref events+ * @sa glfwPollEvents+ * @sa glfwWaitEvents+ *+ * @since Added in version 3.2.+ *+ * @ingroup window+ */+GLFWAPI void glfwWaitEventsTimeout(double timeout);++/*! @brief Posts an empty event to the event queue.+ *+ * This function posts an empty event from the current thread to the event+ * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return.+ *+ * If no windows exist, this function returns immediately. For synchronization+ * of threads in applications that do not create windows, use your threading+ * library of choice.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref events+ * @sa glfwWaitEvents+ * @sa glfwWaitEventsTimeout+ *+ * @since Added in version 3.1.+ *+ * @ingroup window+ */+GLFWAPI void glfwPostEmptyEvent(void);++/*! @brief Returns the value of an input option for the specified window.+ *+ * This function returns the value of an input option for the specified window.+ * The mode must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or+ * `GLFW_STICKY_MOUSE_BUTTONS`.+ *+ * @param[in] window The window to query.+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or+ * `GLFW_STICKY_MOUSE_BUTTONS`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_INVALID_ENUM.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa glfwSetInputMode+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode);++/*! @brief Sets an input option for the specified window.+ *+ * This function sets an input mode option for the specified window. The mode+ * must be one of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or+ * `GLFW_STICKY_MOUSE_BUTTONS`.+ *+ * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor+ * modes:+ * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally.+ * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the client+ * area of the window but does not restrict the cursor from leaving.+ * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual+ * and unlimited cursor movement. This is useful for implementing for+ * example 3D camera controls.+ *+ * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to+ * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are+ * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS`+ * the next time it is called even if the key had been released before the+ * call. This is useful when you are only interested in whether keys have been+ * pressed but not when or in which order.+ *+ * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either+ * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it.+ * If sticky mouse buttons are enabled, a mouse button press will ensure that+ * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even+ * if the mouse button had been released before the call. This is useful when+ * you are only interested in whether mouse buttons have been pressed but not+ * when or in which order.+ *+ * @param[in] window The window whose input mode to set.+ * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS` or+ * `GLFW_STICKY_MOUSE_BUTTONS`.+ * @param[in] value The new value of the specified input mode.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa glfwGetInputMode+ *+ * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`.+ *+ * @ingroup input+ */+GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);++/*! @brief Returns the localized name of the specified printable key.+ *+ * This function returns the localized name of the specified printable key.+ * This is intended for displaying key bindings to the user.+ *+ * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used instead, otherwise+ * the scancode is ignored. If a non-printable key or (if the key is+ * `GLFW_KEY_UNKNOWN`) a scancode that maps to a non-printable key is+ * specified, this function returns `NULL`. + *+ * This behavior allows you to pass in the arguments passed to the+ * [key callback](@ref input_key) without modification.+ *+ * The printable keys are:+ * - `GLFW_KEY_APOSTROPHE`+ * - `GLFW_KEY_COMMA`+ * - `GLFW_KEY_MINUS`+ * - `GLFW_KEY_PERIOD`+ * - `GLFW_KEY_SLASH`+ * - `GLFW_KEY_SEMICOLON`+ * - `GLFW_KEY_EQUAL`+ * - `GLFW_KEY_LEFT_BRACKET`+ * - `GLFW_KEY_RIGHT_BRACKET`+ * - `GLFW_KEY_BACKSLASH`+ * - `GLFW_KEY_WORLD_1`+ * - `GLFW_KEY_WORLD_2`+ * - `GLFW_KEY_0` to `GLFW_KEY_9`+ * - `GLFW_KEY_A` to `GLFW_KEY_Z`+ * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`+ * - `GLFW_KEY_KP_DECIMAL`+ * - `GLFW_KEY_KP_DIVIDE`+ * - `GLFW_KEY_KP_MULTIPLY`+ * - `GLFW_KEY_KP_SUBTRACT`+ * - `GLFW_KEY_KP_ADD`+ * - `GLFW_KEY_KP_EQUAL`+ *+ * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.+ * @param[in] scancode The scancode of the key to query.+ * @return The localized name of the key, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the next call to @ref+ * glfwGetKeyName, or until the library is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_key_name+ *+ * @since Added in version 3.2.+ *+ * @ingroup input+ */+GLFWAPI const char* glfwGetKeyName(int key, int scancode);++/*! @brief Returns the last reported state of a keyboard key for the specified+ * window.+ *+ * This function returns the last state reported for the specified key to the+ * specified window. The returned state is one of `GLFW_PRESS` or+ * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to+ * the key callback.+ *+ * If the `GLFW_STICKY_KEYS` input mode is enabled, this function returns+ * `GLFW_PRESS` the first time you call it for a key that was pressed, even if+ * that key has already been released.+ *+ * The key functions deal with physical keys, with [key tokens](@ref keys)+ * named after their use on the standard US keyboard layout. If you want to+ * input text, use the Unicode character callback instead.+ *+ * The [modifier key bit masks](@ref mods) are not key tokens and cannot be+ * used with this function.+ *+ * __Do not use this function__ to implement [text input](@ref input_char).+ *+ * @param[in] window The desired window.+ * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is+ * not a valid key for this function.+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_INVALID_ENUM.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_key+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup input+ */+GLFWAPI int glfwGetKey(GLFWwindow* window, int key);++/*! @brief Returns the last reported state of a mouse button for the specified+ * window.+ *+ * This function returns the last state reported for the specified mouse button+ * to the specified window. The returned state is one of `GLFW_PRESS` or+ * `GLFW_RELEASE`.+ *+ * If the `GLFW_STICKY_MOUSE_BUTTONS` input mode is enabled, this function+ * `GLFW_PRESS` the first time you call it for a mouse button that was pressed,+ * even if that mouse button has already been released.+ *+ * @param[in] window The desired window.+ * @param[in] button The desired [mouse button](@ref buttons).+ * @return One of `GLFW_PRESS` or `GLFW_RELEASE`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_INVALID_ENUM.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_mouse_button+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup input+ */+GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button);++/*! @brief Retrieves the position of the cursor relative to the client area of+ * the window.+ *+ * This function returns the position of the cursor, in screen coordinates,+ * relative to the upper-left corner of the client area of the specified+ * window.+ *+ * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor+ * position is unbounded and limited only by the minimum and maximum values of+ * a `double`.+ *+ * The coordinate can be converted to their integer equivalents with the+ * `floor` function. Casting directly to an integer type works for positive+ * coordinates, but fails for negative ones.+ *+ * Any or all of the position arguments may be `NULL`. If an error occurs, all+ * non-`NULL` position arguments will be set to zero.+ *+ * @param[in] window The desired window.+ * @param[out] xpos Where to store the cursor x-coordinate, relative to the+ * left edge of the client area, or `NULL`.+ * @param[out] ypos Where to store the cursor y-coordinate, relative to the to+ * top edge of the client area, or `NULL`.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_pos+ * @sa glfwSetCursorPos+ *+ * @since Added in version 3.0. Replaces `glfwGetMousePos`.+ *+ * @ingroup input+ */+GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos);++/*! @brief Sets the position of the cursor, relative to the client area of the+ * window.+ *+ * This function sets the position, in screen coordinates, of the cursor+ * relative to the upper-left corner of the client area of the specified+ * window. The window must have input focus. If the window does not have+ * input focus when this function is called, it fails silently.+ *+ * __Do not use this function__ to implement things like camera controls. GLFW+ * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the+ * cursor, transparently re-centers it and provides unconstrained cursor+ * motion. See @ref glfwSetInputMode for more information.+ *+ * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is+ * unconstrained and limited only by the minimum and maximum values of+ * a `double`.+ *+ * @param[in] window The desired window.+ * @param[in] xpos The desired x-coordinate, relative to the left edge of the+ * client area.+ * @param[in] ypos The desired y-coordinate, relative to the top edge of the+ * client area.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_pos+ * @sa glfwGetCursorPos+ *+ * @since Added in version 3.0. Replaces `glfwSetMousePos`.+ *+ * @ingroup input+ */+GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos);++/*! @brief Creates a custom cursor.+ *+ * Creates a new custom cursor image that can be set for a window with @ref+ * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor.+ * Any remaining cursors are destroyed by @ref glfwTerminate.+ *+ * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight+ * bits per channel. They are arranged canonically as packed sequential rows,+ * starting from the top-left corner.+ *+ * The cursor hotspot is specified in pixels, relative to the upper-left corner+ * of the cursor image. Like all other coordinate systems in GLFW, the X-axis+ * points to the right and the Y-axis points down.+ *+ * @param[in] image The desired cursor image.+ * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot.+ * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot.+ * @return The handle of the created cursor, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The specified image data is copied before this function+ * returns.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_object+ * @sa glfwDestroyCursor+ * @sa glfwCreateStandardCursor+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);++/*! @brief Creates a cursor with a standard shape.+ *+ * Returns a cursor with a [standard shape](@ref shapes), that can be set for+ * a window with @ref glfwSetCursor.+ *+ * @param[in] shape One of the [standard shapes](@ref shapes).+ * @return A new cursor ready to use or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_object+ * @sa glfwCreateCursor+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape);++/*! @brief Destroys a cursor.+ *+ * This function destroys a cursor previously created with @ref+ * glfwCreateCursor. Any remaining cursors will be destroyed by @ref+ * glfwTerminate.+ *+ * @param[in] cursor The cursor object to destroy.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @reentrancy This function must not be called from a callback.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_object+ * @sa glfwCreateCursor+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor);++/*! @brief Sets the cursor for the window.+ *+ * This function 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](@ref 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.+ *+ * @param[in] window The window to set the cursor for.+ * @param[in] cursor The cursor to set, or `NULL` to switch back to the default+ * arrow cursor.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_object+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor);++/*! @brief Sets the key callback.+ *+ * This function sets the key callback of the specified window, which is called+ * when a key is pressed, repeated or released.+ *+ * The key functions deal with physical keys, with layout independent+ * [key tokens](@ref keys) named after their values in the standard US keyboard+ * layout. If you want to input text, use the+ * [character callback](@ref glfwSetCharCallback) instead.+ *+ * When a window loses input focus, it will generate synthetic key release+ * events for all pressed keys. You can tell these events from user-generated+ * events by the fact that the synthetic ones are generated after the focus+ * loss event has been processed, i.e. after the+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.+ *+ * The scancode of a key is specific to that platform or sometimes even to that+ * machine. Scancodes are intended to allow users to bind keys that don't have+ * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their+ * state is not saved and so it cannot be queried with @ref glfwGetKey.+ *+ * Sometimes GLFW needs to generate synthetic key events, in which case the+ * scancode may be zero.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new key callback, or `NULL` to remove the currently+ * set callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_key+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup input+ */+GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun cbfun);++/*! @brief Sets the Unicode character callback.+ *+ * This function sets the character callback of the specified window, which is+ * called when a Unicode character is input.+ *+ * The character callback is intended for Unicode text input. As it deals with+ * characters, it is keyboard layout dependent, whereas the+ * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1+ * to physical keys, as a key may produce zero, one or more characters. If you+ * want to know whether a specific physical key was pressed or released, see+ * the key callback instead.+ *+ * The character callback behaves as system text input normally does and will+ * not be called if modifier keys are held down that would prevent normal text+ * input on that platform, for example a Super (Command) key on OS X or Alt key+ * on Windows. There is a+ * [character with modifiers callback](@ref glfwSetCharModsCallback) that+ * receives these events.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_char+ *+ * @since Added in version 2.4.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup input+ */+GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun cbfun);++/*! @brief Sets the Unicode character with modifiers callback.+ *+ * This function sets the character with modifiers callback of the specified+ * window, which is called when a Unicode character is input regardless of what+ * modifier keys are used.+ *+ * The character with modifiers callback is intended for implementing custom+ * Unicode character input. For regular Unicode text input, see the+ * [character callback](@ref glfwSetCharCallback). Like the character+ * callback, the character with modifiers callback deals with characters and is+ * keyboard layout dependent. Characters do not map 1:1 to physical keys, as+ * a key may produce zero, one or more characters. If you want to know whether+ * a specific physical key was pressed or released, see the+ * [key callback](@ref glfwSetKeyCallback) instead.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_char+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun cbfun);++/*! @brief Sets the mouse button callback.+ *+ * This function sets the mouse button callback of the specified window, which+ * is called when a mouse button is pressed or released.+ *+ * When a window loses input focus, it will generate synthetic mouse button+ * release events for all pressed mouse buttons. You can tell these events+ * from user-generated events by the fact that the synthetic ones are generated+ * after the focus loss event has been processed, i.e. after the+ * [window focus callback](@ref glfwSetWindowFocusCallback) has been called.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref input_mouse_button+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter and return value.+ *+ * @ingroup input+ */+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun cbfun);++/*! @brief Sets the cursor position callback.+ *+ * This function sets the cursor position callback of the specified window,+ * which is called when the cursor is moved. The callback is provided with the+ * position, in screen coordinates, relative to the upper-left corner of the+ * client area of the window.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_pos+ *+ * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`.+ *+ * @ingroup input+ */+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun cbfun);++/*! @brief Sets the cursor enter/exit callback.+ *+ * This function sets the cursor boundary crossing callback of the specified+ * window, which is called when the cursor enters or leaves the client area of+ * the window.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref cursor_enter+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun cbfun);++/*! @brief Sets the scroll callback.+ *+ * This function sets the scroll callback of the specified window, which is+ * called when a scrolling device is used, such as a mouse wheel or scrolling+ * area of a touchpad.+ *+ * The scroll callback receives all scrolling input, like that from a mouse+ * wheel or a touchpad scrolling area.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new scroll callback, or `NULL` to remove the currently+ * set callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref scrolling+ *+ * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`.+ *+ * @ingroup input+ */+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun cbfun);++/*! @brief Sets the file drop callback.+ *+ * This function sets the file drop callback of the specified window, which is+ * called when one or more dragged files are dropped on the window.+ *+ * Because the path array and its strings may have been generated specifically+ * for that event, they are not guaranteed to be valid after the callback has+ * returned. If you wish to use them after the callback returns, you need to+ * make a deep copy.+ *+ * @param[in] window The window whose callback to set.+ * @param[in] cbfun The new file drop callback, or `NULL` to remove the+ * currently set callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref path_drop+ *+ * @since Added in version 3.1.+ *+ * @ingroup input+ */+GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun cbfun);++/*! @brief Returns whether the specified joystick is present.+ *+ * This function returns whether the specified joystick is present.+ *+ * @param[in] joy The [joystick](@ref joysticks) to query.+ * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref joystick+ *+ * @since Added in version 3.0. Replaces `glfwGetJoystickParam`.+ *+ * @ingroup input+ */+GLFWAPI int glfwJoystickPresent(int joy);++/*! @brief Returns the values of all axes of the specified joystick.+ *+ * This function returns the values of all axes of the specified joystick.+ * Each element in the array is a value between -1.0 and 1.0.+ *+ * Querying a joystick slot with no device present is not an error, but will+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to+ * check device presence.+ *+ * @param[in] joy The [joystick](@ref joysticks) to query.+ * @param[out] count Where to store the number of axis values in the returned+ * array. This is set to zero if the joystick is not present or an error+ * occurred.+ * @return An array of axis values, or `NULL` if the joystick is not present or+ * an [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified joystick is+ * disconnected, this function is called again for that joystick or the library+ * is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref joystick_axis+ *+ * @since Added in version 3.0. Replaces `glfwGetJoystickPos`.+ *+ * @ingroup input+ */+GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count);++/*! @brief Returns the state of all buttons of the specified joystick.+ *+ * This function returns the state of all buttons of the specified joystick.+ * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`.+ *+ * Querying a joystick slot with no device present is not an error, but will+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to+ * check device presence.+ *+ * @param[in] joy The [joystick](@ref joysticks) to query.+ * @param[out] count Where to store the number of button states in the returned+ * array. This is set to zero if the joystick is not present or an error+ * occurred.+ * @return An array of button states, or `NULL` if the joystick is not present+ * or an [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified joystick is+ * disconnected, this function is called again for that joystick or the library+ * is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref joystick_button+ *+ * @since Added in version 2.2.+ * @glfw3 Changed to return a dynamic array.+ *+ * @ingroup input+ */+GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count);++/*! @brief Returns the name of the specified joystick.+ *+ * This function returns the name, encoded as UTF-8, of the specified joystick.+ * The returned string is allocated and freed by GLFW. You should not free it+ * yourself.+ *+ * Querying a joystick slot with no device present is not an error, but will+ * cause this function to return `NULL`. Call @ref glfwJoystickPresent to+ * check device presence.+ *+ * @param[in] joy The [joystick](@ref joysticks) to query.+ * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick+ * is not present or an [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the specified joystick is+ * disconnected, this function is called again for that joystick or the library+ * is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref joystick_name+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+GLFWAPI const char* glfwGetJoystickName(int joy);++/*! @brief Sets the joystick configuration callback.+ *+ * This function sets the joystick configuration callback, or removes the+ * currently set callback. This is called when a joystick is connected to or+ * disconnected from the system.+ *+ * @param[in] cbfun The new callback, or `NULL` to remove the currently set+ * callback.+ * @return The previously set callback, or `NULL` if no callback was set or the+ * library had not been [initialized](@ref intro_init).+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref joystick_event+ *+ * @since Added in version 3.2.+ *+ * @ingroup input+ */+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun);++/*! @brief Sets the clipboard to the specified string.+ *+ * This function sets the system clipboard to the specified, UTF-8 encoded+ * string.+ *+ * @param[in] window The window that will own the clipboard contents.+ * @param[in] string A UTF-8 encoded string.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The specified string is copied before this function+ * returns.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref clipboard+ * @sa glfwGetClipboardString+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);++/*! @brief Returns the contents of the clipboard as a string.+ *+ * This function returns the contents of the system clipboard, if it contains+ * or is convertible to a UTF-8 encoded string. If the clipboard is empty or+ * if its contents cannot be converted, `NULL` is returned and a @ref+ * GLFW_FORMAT_UNAVAILABLE error is generated.+ *+ * @param[in] window The window that will request the clipboard contents.+ * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL`+ * if an [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @pointer_lifetime The returned string is allocated and freed by GLFW. You+ * should not free it yourself. It is valid until the next call to @ref+ * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library+ * is terminated.+ *+ * @thread_safety This function must only be called from the main thread.+ *+ * @sa @ref clipboard+ * @sa glfwSetClipboardString+ *+ * @since Added in version 3.0.+ *+ * @ingroup input+ */+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);++/*! @brief Returns the value of the GLFW timer.+ *+ * This function returns the value of the GLFW timer. Unless the timer has+ * been set using @ref glfwSetTime, the timer measures time elapsed since GLFW+ * was initialized.+ *+ * The resolution of the timer is system dependent, but is usually on the order+ * of a few micro- or nanoseconds. It uses the highest-resolution monotonic+ * time source on each supported platform.+ *+ * @return The current value, in seconds, or zero if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread. Reading and+ * writing of the internal timer offset is not atomic, so it needs to be+ * externally synchronized with calls to @ref glfwSetTime.+ *+ * @sa @ref time+ *+ * @since Added in version 1.0.+ *+ * @ingroup input+ */+GLFWAPI double glfwGetTime(void);++/*! @brief Sets the GLFW timer.+ *+ * This function sets the value of the GLFW timer. It then continues to count+ * up from that value. The value must be a positive finite number less than+ * or equal to 18446744073.0, which is approximately 584.5 years.+ *+ * @param[in] time The new value, in seconds.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_INVALID_VALUE.+ *+ * @remark The upper limit of the timer is calculated as+ * floor((2<sup>64</sup> - 1) / 10<sup>9</sup>) and is due to implementations+ * storing nanoseconds in 64 bits. The limit may be increased in the future.+ *+ * @thread_safety This function may be called from any thread. Reading and+ * writing of the internal timer offset is not atomic, so it needs to be+ * externally synchronized with calls to @ref glfwGetTime.+ *+ * @sa @ref time+ *+ * @since Added in version 2.2.+ *+ * @ingroup input+ */+GLFWAPI void glfwSetTime(double time);++/*! @brief Returns the current value of the raw timer.+ *+ * This function returns the current value of the raw timer, measured in+ * 1 / frequency seconds. To get the frequency, call @ref+ * glfwGetTimerFrequency.+ *+ * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref time+ * @sa glfwGetTimerFrequency+ *+ * @since Added in version 3.2.+ *+ * @ingroup input+ */+GLFWAPI uint64_t glfwGetTimerValue(void);++/*! @brief Returns the frequency, in Hz, of the raw timer.+ *+ * This function returns the frequency, in Hz, of the raw timer.+ *+ * @return The frequency of the timer, in Hz, or zero if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref time+ * @sa glfwGetTimerValue+ *+ * @since Added in version 3.2.+ *+ * @ingroup input+ */+GLFWAPI uint64_t glfwGetTimerFrequency(void);++/*! @brief Makes the context of the specified window current for the calling+ * thread.+ *+ * This function makes the OpenGL or OpenGL ES context of the specified window+ * current on 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.+ *+ * By default, making a context non-current implicitly forces a pipeline flush.+ * On machines that support `GL_KHR_context_flush_control`, you can control+ * whether a context performs this flush by setting the+ * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref window_hints_ctx) window hint.+ *+ * The specified window must have an OpenGL or OpenGL ES context. Specifying+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT+ * error.+ *+ * @param[in] window The window whose context to make current, or `NULL` to+ * detach the current context.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref context_current+ * @sa glfwGetCurrentContext+ *+ * @since Added in version 3.0.+ *+ * @ingroup context+ */+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window);++/*! @brief Returns the window whose context is current on the calling thread.+ *+ * This function returns the window whose OpenGL or OpenGL ES context is+ * current on the calling thread.+ *+ * @return The window whose context is current, or `NULL` if no window's+ * context is current.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref context_current+ * @sa glfwMakeContextCurrent+ *+ * @since Added in version 3.0.+ *+ * @ingroup context+ */+GLFWAPI GLFWwindow* glfwGetCurrentContext(void);++/*! @brief Swaps the front and back buffers of the specified window.+ *+ * This function swaps the front and back buffers of the specified window when+ * rendering with OpenGL or OpenGL ES. If the swap interval is greater than+ * zero, the GPU driver waits the specified number of screen updates before+ * swapping the buffers.+ *+ * The specified window must have an OpenGL or OpenGL ES context. Specifying+ * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT+ * error.+ *+ * This function does not apply to Vulkan. If you are rendering with Vulkan,+ * see `vkQueuePresentKHR` instead.+ *+ * @param[in] window The window whose buffers to swap.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark __EGL:__ The context of the specified window must be current on the+ * calling thread.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref buffer_swap+ * @sa glfwSwapInterval+ *+ * @since Added in version 1.0.+ * @glfw3 Added window handle parameter.+ *+ * @ingroup window+ */+GLFWAPI void glfwSwapBuffers(GLFWwindow* window);++/*! @brief Sets the swap interval for the current context.+ *+ * This function sets the swap interval for the current OpenGL or OpenGL ES+ * context, i.e. the number of screen updates to wait from the time @ref+ * glfwSwapBuffers was called before swapping the buffers and returning. This+ * is sometimes called _vertical synchronization_, _vertical retrace+ * synchronization_ or just _vsync_.+ *+ * Contexts that support either of the `WGL_EXT_swap_control_tear` and+ * `GLX_EXT_swap_control_tear` extensions also accept negative swap intervals,+ * which allow the driver to swap even if a frame arrives a little bit late.+ * You can check for the presence of these extensions using @ref+ * glfwExtensionSupported. For more information about swap tearing, see the+ * extension specifications.+ *+ * A context must be current on the calling thread. Calling this function+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.+ *+ * This function does not apply to Vulkan. If you are rendering with Vulkan,+ * see the present mode of your swapchain instead.+ *+ * @param[in] interval The minimum number of screen updates to wait for+ * until the buffers are swapped by @ref glfwSwapBuffers.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark This function is not called during context creation, leaving the+ * swap interval set to whatever is the default on that platform. This is done+ * because some swap interval extensions used by GLFW do not allow the swap+ * interval to be reset to zero once it has been set to a non-zero value.+ *+ * @remark Some GPU drivers do not honor the requested swap interval, either+ * because of a user setting that overrides the application's request or due to+ * bugs in the driver.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref buffer_swap+ * @sa glfwSwapBuffers+ *+ * @since Added in version 1.0.+ *+ * @ingroup context+ */+GLFWAPI void glfwSwapInterval(int interval);++/*! @brief Returns whether the specified extension is available.+ *+ * This function returns whether the specified+ * [API extension](@ref context_glext) is supported by the current OpenGL or+ * OpenGL ES context. It searches both for client API extension and context+ * creation API extensions.+ *+ * A context must be current on the calling thread. Calling this function+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.+ *+ * As this functions retrieves and searches one or more extension strings each+ * call, it is recommended that you cache its results if it is going to be used+ * frequently. The extension strings will not change during the lifetime of+ * a context, so there is no danger in doing this.+ *+ * This function does not apply to Vulkan. If you are using Vulkan, see @ref+ * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties`+ * and `vkEnumerateDeviceExtensionProperties` instead.+ *+ * @param[in] extension The ASCII encoded name of the extension.+ * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE`+ * otherwise.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref+ * GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref context_glext+ * @sa glfwGetProcAddress+ *+ * @since Added in version 1.0.+ *+ * @ingroup context+ */+GLFWAPI int glfwExtensionSupported(const char* extension);++/*! @brief Returns the address of the specified function for the current+ * context.+ *+ * This function returns the address of the specified OpenGL or OpenGL ES+ * [core or extension function](@ref context_glext), if it is supported+ * by the current context.+ *+ * A context must be current on the calling thread. Calling this function+ * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error.+ *+ * This function does not apply to Vulkan. If you are rendering with Vulkan,+ * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and+ * `vkGetDeviceProcAddr` instead.+ *+ * @param[in] procname The ASCII encoded name of the function.+ * @return The address of the function, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR.+ *+ * @remark The address of a given function is not guaranteed to be the same+ * between contexts.+ *+ * @remark This function may return a non-`NULL` address despite the+ * associated version or extension not being available. Always check the+ * context version or extension string first.+ *+ * @pointer_lifetime The returned function pointer is valid until the context+ * is destroyed or the library is terminated.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref context_glext+ * @sa glfwExtensionSupported+ *+ * @since Added in version 1.0.+ *+ * @ingroup context+ */+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);++/*! @brief Returns whether the Vulkan loader has been found.+ *+ * This function returns whether the Vulkan loader has been found. This check+ * is performed by @ref glfwInit.+ *+ * The availability of a Vulkan loader does not by itself guarantee that window+ * surface creation or even device creation is possible. Call @ref+ * glfwGetRequiredInstanceExtensions to check whether the extensions necessary+ * for Vulkan surface creation are available and @ref+ * glfwGetPhysicalDevicePresentationSupport to check whether a queue family of+ * a physical device supports image presentation.+ *+ * @return `GLFW_TRUE` if Vulkan is available, or `GLFW_FALSE` otherwise.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref vulkan_support+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+GLFWAPI int glfwVulkanSupported(void);++/*! @brief Returns the Vulkan instance extensions required by GLFW.+ *+ * This function returns an array of names of Vulkan instance extensions required+ * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the+ * list will always contains `VK_KHR_surface`, so if you don't require any+ * additional extensions you can pass this list directly to the+ * `VkInstanceCreateInfo` struct.+ *+ * If Vulkan is not available on the machine, this function returns `NULL` and+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported+ * to check whether Vulkan is available.+ *+ * If Vulkan is available but no set of extensions allowing window surface+ * creation was found, this function returns `NULL`. You may still use Vulkan+ * for off-screen rendering and compute work.+ *+ * @param[out] count Where to store the number of extensions in the returned+ * array. This is set to zero if an error occurred.+ * @return An array of ASCII encoded extension names, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_API_UNAVAILABLE.+ *+ * @remarks Additional extensions may be required by future versions of GLFW.+ * You should check if any extensions you wish to enable are already in the+ * returned array, as it is an error to specify an extension more than once in+ * the `VkInstanceCreateInfo` struct.+ *+ * @pointer_lifetime The returned array is allocated and freed by GLFW. You+ * should not free it yourself. It is guaranteed to be valid only until the+ * library is terminated.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref vulkan_ext+ * @sa glfwCreateWindowSurface+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count);++#if defined(VK_VERSION_1_0)++/*! @brief Returns the address of the specified Vulkan instance function.+ *+ * This function returns the address of the specified Vulkan core or extension+ * function for the specified instance. If instance is set to `NULL` it can+ * return any function exported from the Vulkan loader, including at least the+ * following functions:+ *+ * - `vkEnumerateInstanceExtensionProperties`+ * - `vkEnumerateInstanceLayerProperties`+ * - `vkCreateInstance`+ * - `vkGetInstanceProcAddr`+ *+ * If Vulkan is not available on the machine, this function returns `NULL` and+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported+ * to check whether Vulkan is available.+ *+ * This function is equivalent to calling `vkGetInstanceProcAddr` with+ * a platform-specific query of the Vulkan loader as a fallback.+ *+ * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve+ * functions related to instance creation.+ * @param[in] procname The ASCII encoded name of the function.+ * @return The address of the function, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref+ * GLFW_API_UNAVAILABLE.+ *+ * @pointer_lifetime The returned function pointer is valid until the library+ * is terminated.+ *+ * @thread_safety This function may be called from any thread.+ *+ * @sa @ref vulkan_proc+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname);++/*! @brief Returns whether the specified queue family can present images.+ *+ * This function returns whether the specified queue family of the specified+ * physical device supports presentation to the platform GLFW was built for.+ *+ * If Vulkan or the required window surface creation instance extensions are+ * not available on the machine, or if the specified instance was not created+ * with the required extensions, this function returns `GLFW_FALSE` and+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported+ * to check whether Vulkan is available and @ref+ * glfwGetRequiredInstanceExtensions to check what instance extensions are+ * required.+ *+ * @param[in] instance The instance that the physical device belongs to.+ * @param[in] device The physical device that the queue family belongs to.+ * @param[in] queuefamily The index of the queue family to query.+ * @return `GLFW_TRUE` if the queue family supports presentation, or+ * `GLFW_FALSE` otherwise.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.+ *+ * @thread_safety This function may be called from any thread. For+ * synchronization details of Vulkan objects, see the Vulkan specification.+ *+ * @sa @ref vulkan_present+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);++/*! @brief Creates a Vulkan surface for the specified window.+ *+ * This function creates a Vulkan surface for the specified window.+ *+ * If the Vulkan loader was not found at initialization, this function returns+ * `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref GLFW_API_UNAVAILABLE+ * error. Call @ref glfwVulkanSupported to check whether the Vulkan loader was+ * found.+ *+ * If the required window surface creation instance extensions are not+ * available or if the specified instance was not created with these extensions+ * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and+ * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref+ * glfwGetRequiredInstanceExtensions to check what instance extensions are+ * required.+ *+ * The window surface must be destroyed before the specified Vulkan instance.+ * It is the responsibility of the caller to destroy the window surface. GLFW+ * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the+ * surface.+ *+ * @param[in] instance The Vulkan instance to create the surface in.+ * @param[in] window The window to create the surface for.+ * @param[in] allocator The allocator to use, or `NULL` to use the default+ * allocator.+ * @param[out] surface Where to store the handle of the surface. This is set+ * to `VK_NULL_HANDLE` if an error occurred.+ * @return `VK_SUCCESS` if successful, or a Vulkan error code if an+ * [error](@ref error_handling) occurred.+ *+ * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref+ * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.+ *+ * @remarks If an error occurs before the creation call is made, GLFW returns+ * the Vulkan error code most appropriate for the error. Appropriate use of+ * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should+ * eliminate almost all occurrences of these errors.+ *+ * @thread_safety This function may be called from any thread. For+ * synchronization details of Vulkan objects, see the Vulkan specification.+ *+ * @sa @ref vulkan_surface+ * @sa glfwGetRequiredInstanceExtensions+ *+ * @since Added in version 3.2.+ *+ * @ingroup vulkan+ */+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);++#endif /*VK_VERSION_1_0*/ /*************************************************************************
glfw/include/GLFW/glfw3native.h view
@@ -1,9 +1,9 @@ /*************************************************************************- * GLFW 3.1 - www.glfw.org+ * GLFW 3.2 - www.glfw.org * A library for OpenGL, window and input *------------------------------------------------------------------------ * Copyright (c) 2002-2006 Marcus Geelnard- * Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+ * Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages@@ -38,20 +38,30 @@ * Doxygen documentation *************************************************************************/ +/*! @file glfw3native.h+ * @brief The header of the native access functions.+ *+ * This is the header file of the native access functions. See @ref native for+ * more information.+ */ /*! @defgroup native Native access * * **By using the native access functions you assert that you know what you're * doing and how to fix problems caused by using them. If you don't, you * shouldn't be using them.** *- * Before the inclusion of @ref glfw3native.h, you must define exactly one- * window system API macro and exactly one context creation API macro. Failure- * to do this will cause a compile-time error.+ * Before the inclusion of @ref glfw3native.h, you may define exactly one+ * window system API macro and zero or more context creation API macros. *+ * The chosen backends must match those the library was compiled for. Failure+ * to do this will cause a link-time error.+ * * The available window API macros are: * * `GLFW_EXPOSE_NATIVE_WIN32` * * `GLFW_EXPOSE_NATIVE_COCOA` * * `GLFW_EXPOSE_NATIVE_X11`+ * * `GLFW_EXPOSE_NATIVE_WAYLAND`+ * * `GLFW_EXPOSE_NATIVE_MIR` * * The available context API macros are: * * `GLFW_EXPOSE_NATIVE_WGL`@@ -86,20 +96,23 @@ #elif defined(GLFW_EXPOSE_NATIVE_X11) #include <X11/Xlib.h> #include <X11/extensions/Xrandr.h>-#else- #error "No window API selected"+#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND)+ #include <wayland-client.h>+#elif defined(GLFW_EXPOSE_NATIVE_MIR)+ #include <mir_toolkit/mir_client_library.h> #endif #if defined(GLFW_EXPOSE_NATIVE_WGL) /* WGL is declared by windows.h */-#elif defined(GLFW_EXPOSE_NATIVE_NSGL)+#endif+#if defined(GLFW_EXPOSE_NATIVE_NSGL) /* NSGL is declared by Cocoa.h */-#elif defined(GLFW_EXPOSE_NATIVE_GLX)+#endif+#if defined(GLFW_EXPOSE_NATIVE_GLX) #include <GL/glx.h>-#elif defined(GLFW_EXPOSE_NATIVE_EGL)+#endif+#if defined(GLFW_EXPOSE_NATIVE_EGL) #include <EGL/egl.h>-#else- #error "No context API selected" #endif @@ -114,11 +127,10 @@ * of the specified monitor, or `NULL` if an [error](@ref error_handling) * occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.1.+ * @since Added in version 3.1. * * @ingroup native */@@ -130,11 +142,10 @@ * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.1.+ * @since Added in version 3.1. * * @ingroup native */@@ -145,11 +156,10 @@ * @return The `HWND` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -162,11 +172,10 @@ * @return The `HGLRC` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -179,11 +188,10 @@ * @return The `CGDirectDisplayID` of the specified monitor, or * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.1.+ * @since Added in version 3.1. * * @ingroup native */@@ -194,11 +202,10 @@ * @return The `NSWindow` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -211,11 +218,10 @@ * @return The `NSOpenGLContext` of the specified window, or `nil` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -228,11 +234,10 @@ * @return The `Display` used by GLFW, or `NULL` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -243,11 +248,10 @@ * @return The `RRCrtc` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.1.+ * @since Added in version 3.1. * * @ingroup native */@@ -258,11 +262,10 @@ * @return The `RROutput` of the specified monitor, or `None` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.1.+ * @since Added in version 3.1. * * @ingroup native */@@ -273,11 +276,10 @@ * @return The `Window` of the specified window, or `None` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -290,28 +292,128 @@ * @return The `GLXContext` of the specified window, or `NULL` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */ GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window);++/*! @brief Returns the `GLXWindow` of the specified window.+ *+ * @return The `GLXWindow` of the specified window, or `None` if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); #endif +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)+/*! @brief Returns the `struct wl_display*` used by GLFW.+ *+ * @return The `struct wl_display*` used by GLFW, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void);++/*! @brief Returns the `struct wl_output*` of the specified monitor.+ *+ * @return The `struct wl_output*` of the specified monitor, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor);++/*! @brief Returns the main `struct wl_surface*` of the specified window.+ *+ * @return The main `struct wl_surface*` of the specified window, or `NULL` if+ * an [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window);+#endif++#if defined(GLFW_EXPOSE_NATIVE_MIR)+/*! @brief Returns the `MirConnection*` used by GLFW.+ *+ * @return The `MirConnection*` used by GLFW, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI MirConnection* glfwGetMirDisplay(void);++/*! @brief Returns the Mir output ID of the specified monitor.+ *+ * @return The Mir output ID of the specified monitor, or zero if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor);++/*! @brief Returns the `MirSurface*` of the specified window.+ *+ * @return The `MirSurface*` of the specified window, or `NULL` if an+ * [error](@ref error_handling) occurred.+ *+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized.+ *+ * @since Added in version 3.2.+ *+ * @ingroup native+ */+GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window);+#endif+ #if defined(GLFW_EXPOSE_NATIVE_EGL) /*! @brief Returns the `EGLDisplay` used by GLFW. * * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -322,11 +424,10 @@ * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */@@ -337,11 +438,10 @@ * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an * [error](@ref error_handling) occurred. *- * @par Thread Safety- * This function may be called from any thread. Access is not synchronized.+ * @thread_safety This function may be called from any thread. Access is not+ * synchronized. *- * @par History- * Added in GLFW 3.0.+ * @since Added in version 3.0. * * @ingroup native */
glfw/src/cocoa_init.m view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -72,7 +72,10 @@ // static void createKeyTables(void) {+ int scancode;+ memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));+ memset(_glfw.ns.nativeKeys, -1, sizeof(_glfw.ns.nativeKeys)); _glfw.ns.publicKeys[0x1D] = GLFW_KEY_0; _glfw.ns.publicKeys[0x12] = GLFW_KEY_1;@@ -188,9 +191,107 @@ _glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL; _glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY; _glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;++ for (scancode = 0; scancode < 256; scancode++)+ {+ // Store the reverse translation for faster key name lookup+ if (_glfw.ns.publicKeys[scancode] >= 0)+ _glfw.ns.nativeKeys[_glfw.ns.publicKeys[scancode]] = scancode;+ } } +// Retrieve Unicode data for the current keyboard layout+//+static GLFWbool updateUnicodeDataNS(void)+{+ if (_glfw.ns.inputSource)+ {+ CFRelease(_glfw.ns.inputSource);+ _glfw.ns.inputSource = NULL;+ _glfw.ns.unicodeData = nil;+ } + _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();+ if (!_glfw.ns.inputSource)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to retrieve keyboard layout input source");+ return GLFW_FALSE;+ }++ _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,+ kTISPropertyUnicodeKeyLayoutData);+ if (!_glfw.ns.unicodeData)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to retrieve keyboard layout Unicode data");+ return GLFW_FALSE;+ }++ return GLFW_TRUE;+}++// Load HIToolbox.framework and the TIS symbols we need from it+//+static GLFWbool initializeTIS(void)+{+ // This works only because Cocoa has already loaded it properly+ _glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));+ if (!_glfw.ns.tis.bundle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to load HIToolbox.framework");+ return GLFW_FALSE;+ }++ CFStringRef* kPropertyUnicodeKeyLayoutData =+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,+ CFSTR("kTISPropertyUnicodeKeyLayoutData"));+ CFStringRef* kNotifySelectedKeyboardInputSourceChanged =+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,+ CFSTR("kTISNotifySelectedKeyboardInputSourceChanged"));+ _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,+ CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));+ _glfw.ns.tis.GetInputSourceProperty =+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,+ CFSTR("TISGetInputSourceProperty"));+ _glfw.ns.tis.GetKbdType =+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,+ CFSTR("LMGetKbdType"));++ if (!kPropertyUnicodeKeyLayoutData ||+ !kNotifySelectedKeyboardInputSourceChanged ||+ !TISCopyCurrentKeyboardLayoutInputSource ||+ !TISGetInputSourceProperty ||+ !LMGetKbdType)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to load TIS API symbols");+ return GLFW_FALSE;+ }++ _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =+ *kPropertyUnicodeKeyLayoutData;+ _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged =+ *kNotifySelectedKeyboardInputSourceChanged;++ return updateUnicodeDataNS();+}++@interface GLFWLayoutListener : NSObject+@end++@implementation GLFWLayoutListener++- (void)selectedKeyboardInputSourceChanged:(NSObject* )object+{+ updateUnicodeDataNS();+}++@end++ ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////@@ -199,6 +300,13 @@ { _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init]; + _glfw.ns.listener = [[GLFWLayoutListener alloc] init];+ [[NSDistributedNotificationCenter defaultCenter]+ addObserver:_glfw.ns.listener+ selector:@selector(selectedKeyboardInputSourceChanged:)+ name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged+ object:nil];+ #if defined(_GLFW_USE_CHDIR) changeToResourcesDirectory(); #endif@@ -207,21 +315,31 @@ _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); if (!_glfw.ns.eventSource)- return GL_FALSE;+ return GLFW_FALSE; CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0); - if (!_glfwInitContextAPI())- return GL_FALSE;+ if (!initializeTIS())+ return GLFW_FALSE; - _glfwInitTimer();- _glfwInitJoysticks();+ if (!_glfwInitThreadLocalStoragePOSIX())+ return GLFW_FALSE; - return GL_TRUE;+ _glfwInitTimerNS();+ _glfwInitJoysticksNS();++ return GLFW_TRUE; } void _glfwPlatformTerminate(void) {+ if (_glfw.ns.inputSource)+ {+ CFRelease(_glfw.ns.inputSource);+ _glfw.ns.inputSource = NULL;+ _glfw.ns.unicodeData = nil;+ }+ if (_glfw.ns.eventSource) { CFRelease(_glfw.ns.eventSource);@@ -235,24 +353,34 @@ _glfw.ns.delegate = nil; } - [_glfw.ns.autoreleasePool release];- _glfw.ns.autoreleasePool = nil;+ if (_glfw.ns.listener)+ {+ [[NSDistributedNotificationCenter defaultCenter]+ removeObserver:_glfw.ns.listener+ name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged+ object:nil];+ [[NSDistributedNotificationCenter defaultCenter]+ removeObserver:_glfw.ns.listener];+ [_glfw.ns.listener release];+ _glfw.ns.listener = nil;+ } [_glfw.ns.cursor release]; _glfw.ns.cursor = nil; free(_glfw.ns.clipboardString); - _glfwTerminateJoysticks();- _glfwTerminateContextAPI();+ _glfwTerminateNSGL();+ _glfwTerminateJoysticksNS();+ _glfwTerminateThreadLocalStoragePOSIX();++ [_glfw.ns.autoreleasePool release];+ _glfw.ns.autoreleasePool = nil; } const char* _glfwPlatformGetVersionString(void) {- const char* version = _GLFW_VERSION_NUMBER " Cocoa"-#if defined(_GLFW_NSGL)- " NSGL"-#endif+ return _GLFW_VERSION_NUMBER " Cocoa NSGL" #if defined(_GLFW_USE_CHDIR) " chdir" #endif@@ -266,7 +394,5 @@ " dynamic" #endif ;-- return version; }
+ glfw/src/cocoa_joystick.h view
@@ -0,0 +1,60 @@+//========================================================================+// GLFW 3.2 Cocoa - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#ifndef _glfw3_cocoa_joystick_h_+#define _glfw3_cocoa_joystick_h_++#include <IOKit/IOKitLib.h>+#include <IOKit/IOCFPlugIn.h>+#include <IOKit/hid/IOHIDLib.h>+#include <IOKit/hid/IOHIDKeys.h>++#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \+ _GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]+++// Cocoa-specific per-joystick data+//+typedef struct _GLFWjoystickNS+{+ GLFWbool present;+ char name[256];++ IOHIDDeviceRef deviceRef;++ CFMutableArrayRef axisElements;+ CFMutableArrayRef buttonElements;+ CFMutableArrayRef hatElements;++ float* axes;+ unsigned char* buttons;+} _GLFWjoystickNS;+++void _glfwInitJoysticksNS(void);+void _glfwTerminateJoysticksNS(void);++#endif // _glfw3_cocoa_joystick_h_
+ glfw/src/cocoa_joystick.m view
@@ -0,0 +1,511 @@+//========================================================================+// GLFW 3.2 Cocoa - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <unistd.h>+#include <ctype.h>+#include <string.h>++#include <mach/mach.h>+#include <mach/mach_error.h>++#include <CoreFoundation/CoreFoundation.h>+#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>+++// Joystick element information+//+typedef struct _GLFWjoyelementNS+{+ IOHIDElementRef elementRef;++ long min;+ long max;++ long minReport;+ long maxReport;++} _GLFWjoyelementNS;+++static void getElementsCFArrayHandler(const void* value, void* parameter);++// Adds an element to the specified joystick+//+static void addJoystickElement(_GLFWjoystickNS* js,+ IOHIDElementRef elementRef)+{+ IOHIDElementType elementType;+ long usagePage, usage;+ CFMutableArrayRef elementsArray = NULL;++ elementType = IOHIDElementGetType(elementRef);+ usagePage = IOHIDElementGetUsagePage(elementRef);+ usage = IOHIDElementGetUsage(elementRef);++ if ((elementType != kIOHIDElementTypeInput_Axis) &&+ (elementType != kIOHIDElementTypeInput_Button) &&+ (elementType != kIOHIDElementTypeInput_Misc))+ {+ return;+ }++ switch (usagePage)+ {+ case kHIDPage_GenericDesktop:+ {+ switch (usage)+ {+ case kHIDUsage_GD_X:+ case kHIDUsage_GD_Y:+ case kHIDUsage_GD_Z:+ case kHIDUsage_GD_Rx:+ case kHIDUsage_GD_Ry:+ case kHIDUsage_GD_Rz:+ case kHIDUsage_GD_Slider:+ case kHIDUsage_GD_Dial:+ case kHIDUsage_GD_Wheel:+ elementsArray = js->axisElements;+ break;+ case kHIDUsage_GD_Hatswitch:+ elementsArray = js->hatElements;+ break;+ }++ break;+ }++ case kHIDPage_Button:+ elementsArray = js->buttonElements;+ break;+ default:+ break;+ }++ if (elementsArray)+ {+ _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));++ CFArrayAppendValue(elementsArray, element);++ element->elementRef = elementRef;++ element->minReport = IOHIDElementGetLogicalMin(elementRef);+ element->maxReport = IOHIDElementGetLogicalMax(elementRef);+ }+}++// Adds an element to the specified joystick+//+static void getElementsCFArrayHandler(const void* value, void* parameter)+{+ if (CFGetTypeID(value) == IOHIDElementGetTypeID())+ {+ addJoystickElement((_GLFWjoystickNS*) parameter,+ (IOHIDElementRef) value);+ }+}++// Returns the value of the specified element of the specified joystick+//+static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element)+{+ IOReturn result = kIOReturnSuccess;+ IOHIDValueRef valueRef;+ long value = 0;++ if (js && element && js->deviceRef)+ {+ result = IOHIDDeviceGetValue(js->deviceRef,+ element->elementRef,+ &valueRef);++ if (kIOReturnSuccess == result)+ {+ value = IOHIDValueGetIntegerValue(valueRef);++ // Record min and max for auto calibration+ if (value < element->minReport)+ element->minReport = value;+ if (value > element->maxReport)+ element->maxReport = value;+ }+ }++ // Auto user scale+ return value;+}++// Removes the specified joystick+//+static void removeJoystick(_GLFWjoystickNS* js)+{+ int i;++ if (!js->present)+ return;++ for (i = 0; i < CFArrayGetCount(js->axisElements); i++)+ free((void*) CFArrayGetValueAtIndex(js->axisElements, i));+ CFArrayRemoveAllValues(js->axisElements);+ CFRelease(js->axisElements);++ for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)+ free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));+ CFArrayRemoveAllValues(js->buttonElements);+ CFRelease(js->buttonElements);++ for (i = 0; i < CFArrayGetCount(js->hatElements); i++)+ free((void*) CFArrayGetValueAtIndex(js->hatElements, i));+ CFArrayRemoveAllValues(js->hatElements);+ CFRelease(js->hatElements);++ free(js->axes);+ free(js->buttons);++ memset(js, 0, sizeof(_GLFWjoystickNS));++ _glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);+}++// Polls for joystick axis events and updates GLFW state+//+static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)+{+ CFIndex i;++ if (!js->present)+ return GLFW_FALSE;++ for (i = 0; i < CFArrayGetCount(js->axisElements); i++)+ {+ _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)+ CFArrayGetValueAtIndex(js->axisElements, i);++ long value = getElementValue(js, axis);+ long readScale = axis->maxReport - axis->minReport;++ if (readScale == 0)+ js->axes[i] = value;+ else+ js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;+ }++ return GLFW_TRUE;+}++// Polls for joystick button events and updates GLFW state+//+static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)+{+ CFIndex i;+ int buttonIndex = 0;++ if (!js->present)+ return GLFW_FALSE;++ for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)+ {+ _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)+ CFArrayGetValueAtIndex(js->buttonElements, i);++ if (getElementValue(js, button))+ js->buttons[buttonIndex++] = GLFW_PRESS;+ else+ js->buttons[buttonIndex++] = GLFW_RELEASE;+ }++ for (i = 0; i < CFArrayGetCount(js->hatElements); i++)+ {+ _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)+ CFArrayGetValueAtIndex(js->hatElements, i);++ // Bit fields of button presses for each direction, including nil+ const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };++ long j, value = getElementValue(js, hat);+ if (value < 0 || value > 8)+ value = 8;++ for (j = 0; j < 4; j++)+ {+ if (directions[value] & (1 << j))+ js->buttons[buttonIndex++] = GLFW_PRESS;+ else+ js->buttons[buttonIndex++] = GLFW_RELEASE;+ }+ }++ return GLFW_TRUE;+}++// Callback for user-initiated joystick addition+//+static void matchCallback(void* context,+ IOReturn result,+ void* sender,+ IOHIDDeviceRef deviceRef)+{+ _GLFWjoystickNS* js;+ int joy;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (_glfw.ns_js[joy].present && _glfw.ns_js[joy].deviceRef == deviceRef)+ return;+ }++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (!_glfw.ns_js[joy].present)+ break;+ }++ if (joy > GLFW_JOYSTICK_LAST)+ return;++ js = _glfw.ns_js + joy;+ js->present = GLFW_TRUE;+ js->deviceRef = deviceRef;++ CFStringRef name = IOHIDDeviceGetProperty(deviceRef,+ CFSTR(kIOHIDProductKey));+ if (name)+ {+ CFStringGetCString(name,+ js->name,+ sizeof(js->name),+ kCFStringEncodingUTF8);+ }+ else+ strncpy(js->name, "Unknown", sizeof(js->name));++ js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);+ js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);+ js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);++ CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,+ NULL,+ kIOHIDOptionsTypeNone);+ CFRange range = { 0, CFArrayGetCount(arrayRef) };+ CFArrayApplyFunction(arrayRef,+ range,+ getElementsCFArrayHandler,+ (void*) js);++ CFRelease(arrayRef);++ js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));+ js->buttons = calloc(CFArrayGetCount(js->buttonElements) ++ CFArrayGetCount(js->hatElements) * 4, 1);++ _glfwInputJoystickChange(joy, GLFW_CONNECTED);+}++// Callback for user-initiated joystick removal+//+static void removeCallback(void* context,+ IOReturn result,+ void* sender,+ IOHIDDeviceRef deviceRef)+{+ int joy;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (_glfw.ns_js[joy].deviceRef == deviceRef)+ {+ removeJoystick(_glfw.ns_js + joy);+ break;+ }+ }+}++// Creates a dictionary to match against devices with the specified usage page+// and usage+//+static CFMutableDictionaryRef createMatchingDictionary(long usagePage,+ long usage)+{+ CFMutableDictionaryRef result =+ CFDictionaryCreateMutable(kCFAllocatorDefault,+ 0,+ &kCFTypeDictionaryKeyCallBacks,+ &kCFTypeDictionaryValueCallBacks);++ if (result)+ {+ CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,+ kCFNumberLongType,+ &usagePage);+ if (pageRef)+ {+ CFDictionarySetValue(result,+ CFSTR(kIOHIDDeviceUsagePageKey),+ pageRef);+ CFRelease(pageRef);++ CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,+ kCFNumberLongType,+ &usage);+ if (usageRef)+ {+ CFDictionarySetValue(result,+ CFSTR(kIOHIDDeviceUsageKey),+ usageRef);+ CFRelease(usageRef);+ }+ }+ }++ return result;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++// Initialize joystick interface+//+void _glfwInitJoysticksNS(void)+{+ CFMutableArrayRef matchingCFArrayRef;++ _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,+ kIOHIDOptionsTypeNone);++ matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,+ 0,+ &kCFTypeArrayCallBacks);+ if (matchingCFArrayRef)+ {+ CFDictionaryRef matchingCFDictRef =+ createMatchingDictionary(kHIDPage_GenericDesktop,+ kHIDUsage_GD_Joystick);+ if (matchingCFDictRef)+ {+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);+ CFRelease(matchingCFDictRef);+ }++ matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,+ kHIDUsage_GD_GamePad);+ if (matchingCFDictRef)+ {+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);+ CFRelease(matchingCFDictRef);+ }++ matchingCFDictRef =+ createMatchingDictionary(kHIDPage_GenericDesktop,+ kHIDUsage_GD_MultiAxisController);+ if (matchingCFDictRef)+ {+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);+ CFRelease(matchingCFDictRef);+ }++ IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager,+ matchingCFArrayRef);+ CFRelease(matchingCFArrayRef);+ }++ IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,+ &matchCallback, NULL);+ IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,+ &removeCallback, NULL);++ IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,+ CFRunLoopGetMain(),+ kCFRunLoopDefaultMode);++ IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);++ // Execute the run loop once in order to register any initially-attached+ // joysticks+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);+}++// Close all opened joystick handles+//+void _glfwTerminateJoysticksNS(void)+{+ int joy;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ _GLFWjoystickNS* js = _glfw.ns_js + joy;+ removeJoystick(js);+ }++ CFRelease(_glfw.ns.hidManager);+ _glfw.ns.hidManager = NULL;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW platform API //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformJoystickPresent(int joy)+{+ _GLFWjoystickNS* js = _glfw.ns_js + joy;+ return js->present;+}++const float* _glfwPlatformGetJoystickAxes(int joy, int* count)+{+ _GLFWjoystickNS* js = _glfw.ns_js + joy;+ if (!pollJoystickAxisEvents(js))+ return NULL;++ *count = (int) CFArrayGetCount(js->axisElements);+ return js->axes;+}++const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)+{+ _GLFWjoystickNS* js = _glfw.ns_js + joy;+ if (!pollJoystickButtonEvents(js))+ return NULL;++ *count = (int) CFArrayGetCount(js->buttonElements) ++ (int) CFArrayGetCount(js->hatElements) * 4;+ return js->buttons;+}++const char* _glfwPlatformGetJoystickName(int joy)+{+ _GLFWjoystickNS* js = _glfw.ns_js + joy;+ if (!js->present)+ return NULL;++ return js->name;+}+
glfw/src/cocoa_monitor.m view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -28,11 +28,9 @@ #include "internal.h" #include <stdlib.h>-#include <stdlib.h> #include <limits.h> #include <IOKit/graphics/IOGraphicsLib.h>-#include <IOKit/graphics/IOGraphicsLib.h> #include <CoreVideo/CVBase.h> #include <CoreVideo/CVDisplayLink.h> #include <ApplicationServices/ApplicationServices.h>@@ -57,7 +55,8 @@ (const void**) &value)) { // This may happen if a desktop Mac is running headless- _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to retrieve display name");+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to retrieve display name"); CFRelease(info); return strdup("Unknown");@@ -65,7 +64,7 @@ size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value), kCFStringEncodingUTF8);- name = calloc(size + 1, sizeof(char));+ name = calloc(size + 1, 1); CFStringGetCString(value, name, size, kCFStringEncodingUTF8); CFRelease(info);@@ -75,28 +74,28 @@ // Check whether the display mode should be included in enumeration //-static GLboolean modeIsGood(CGDisplayModeRef mode)+static GLFWbool modeIsGood(CGDisplayModeRef mode) { uint32_t flags = CGDisplayModeGetIOFlags(mode); if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))- return GL_FALSE;+ return GLFW_FALSE; if (flags & kDisplayModeInterlacedFlag)- return GL_FALSE;+ return GLFW_FALSE; if (flags & kDisplayModeStretchedFlag)- return GL_FALSE;+ return GLFW_FALSE; CFStringRef format = CGDisplayModeCopyPixelEncoding(mode); if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) && CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0)) { CFRelease(format);- return GL_FALSE;+ return GLFW_FALSE; } CFRelease(format);- return GL_TRUE;+ return GLFW_TRUE; } // Convert Core Graphics display mode to GLFW video mode@@ -165,7 +164,7 @@ // Change the current video mode //-GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired)+GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) { CFArrayRef modes; CFIndex count, i;@@ -177,7 +176,7 @@ best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0)- return GL_TRUE;+ return GLFW_TRUE; CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); @@ -215,15 +214,15 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Monitor mode list changed");- return GL_FALSE;+ return GLFW_FALSE; } - return GL_TRUE;+ return GLFW_TRUE; } // Restore the previously saved (original) video mode //-void _glfwRestoreVideoMode(_GLFWmonitor* monitor)+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor) { if (monitor->ns.previousMode) {@@ -251,53 +250,29 @@ *count = 0; CGGetOnlineDisplayList(0, NULL, &displayCount);- displays = calloc(displayCount, sizeof(CGDirectDisplayID)); monitors = calloc(displayCount, sizeof(_GLFWmonitor*)); CGGetOnlineDisplayList(displayCount, displays, &displayCount); - NSArray* screens = [NSScreen screens];- for (i = 0; i < displayCount; i++) {- int j;+ _GLFWmonitor* monitor; if (CGDisplayIsAsleep(displays[i])) continue; - CGDirectDisplayID screenDisplayID = CGDisplayMirrorsDisplay(displays[i]);- if (screenDisplayID == kCGNullDirectDisplay)- screenDisplayID = displays[i];- const CGSize size = CGDisplayScreenSize(displays[i]); char* name = getDisplayName(displays[i]); - monitors[found] = _glfwAllocMonitor(name, size.width, size.height);- monitors[found]->ns.displayID = displays[i];+ monitor = _glfwAllocMonitor(name, size.width, size.height);+ monitor->ns.displayID = displays[i];+ monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]); free(name); - for (j = 0; j < [screens count]; j++)- {- NSScreen* screen = [screens objectAtIndex:j];- NSDictionary* dictionary = [screen deviceDescription];- NSNumber* number = [dictionary objectForKey:@"NSScreenNumber"];-- if ([number unsignedIntegerValue] == screenDisplayID)- {- monitors[found]->ns.screen = screen;- break;- }- }-- if (monitors[found]->ns.screen)- found++;- else- {- _glfwFreeMonitor(monitors[found]);- monitors[found] = NULL;- }+ found++;+ monitors[found - 1] = monitor; } free(displays);@@ -306,9 +281,11 @@ return monitors; } -GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) {- return first->ns.displayID == second->ns.displayID;+ // HACK: Compare unit numbers instead of display IDs to work around display+ // replacement on machines with automatic graphics switching+ return first->ns.unitNumber == second->ns.unitNumber; } void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)@@ -321,22 +298,22 @@ *ypos = (int) bounds.origin.y; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { CFArrayRef modes;- CFIndex count, i, j;+ CFIndex found, i, j; GLFWvidmode* result; CVDisplayLinkRef link; + *count = 0;+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);- count = CFArrayGetCount(modes);-- result = calloc(count, sizeof(GLFWvidmode));- *found = 0;+ found = CFArrayGetCount(modes);+ result = calloc(found, sizeof(GLFWvidmode)); - for (i = 0; i < count; i++)+ for (i = 0; i < found; i++) { CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); if (!modeIsGood(dm))@@ -344,24 +321,21 @@ const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); - for (j = 0; j < *found; j++)+ for (j = 0; j < *count; j++) { if (_glfwCompareVideoModes(result + j, &mode) == 0) break; } - if (i < *found)- {- // This is a duplicate, so skip it+ // Skip duplicate modes+ if (i < *count) continue;- } - result[*found] = mode;- (*found)++;+ (*count)++;+ result[*count - 1] = mode; } CFRelease(modes);- CVDisplayLinkRelease(link); return result; }
glfw/src/cocoa_platform.h view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -24,28 +24,28 @@ // //======================================================================== -#ifndef _cocoa_platform_h_-#define _cocoa_platform_h_-+#ifndef _glfw3_cocoa_platform_h_+#define _glfw3_cocoa_platform_h_ #include <stdint.h>+#include <dlfcn.h> #if defined(__OBJC__)+#import <Carbon/Carbon.h> #import <Cocoa/Cocoa.h> #else+#include <Carbon/Carbon.h> #include <ApplicationServices/ApplicationServices.h> typedef void* id; #endif #include "posix_tls.h"--#if defined(_GLFW_NSGL)- #include "nsgl_context.h"-#else- #error "No supported context creation API selected"-#endif+#include "cocoa_joystick.h"+#include "nsgl_context.h" -#include "iokit_joystick.h"+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)+#define _glfw_dlclose(handle) dlclose(handle)+#define _glfw_dlsym(handle, name) dlsym(handle, name) #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNS ns #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns@@ -53,38 +53,67 @@ #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns +#define _GLFW_EGL_CONTEXT_STATE+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE +// HIToolbox.framework pointer typedefs+#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData+#define kTISNotifySelectedKeyboardInputSourceChanged _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged+typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);+#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource+typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);+#define TISGetInputSourceProperty _glfw.ns.tis.GetInputSourceProperty+typedef UInt8 (*PFN_LMGetKbdType)(void);+#define LMGetKbdType _glfw.ns.tis.GetKbdType++ // Cocoa-specific per-window data // typedef struct _GLFWwindowNS { id object;- id delegate;+ id delegate; id view;- unsigned int modifierFlags; // The total sum of the distances the cursor has been warped // since the last cursor motion event was processed // This is kept to counteract Cocoa doing the same internally- double warpDeltaX, warpDeltaY;+ double cursorWarpDeltaX, cursorWarpDeltaY; } _GLFWwindowNS; - // Cocoa-specific global data // typedef struct _GLFWlibraryNS {- CGEventSourceRef eventSource;- id delegate;- id autoreleasePool;- id cursor;+ CGEventSourceRef eventSource;+ id delegate;+ id autoreleasePool;+ id cursor;+ TISInputSourceRef inputSource;+ IOHIDManagerRef hidManager;+ id unicodeData;+ id listener; - short int publicKeys[256];- char* clipboardString;+ char keyName[64];+ short int publicKeys[256];+ short int nativeKeys[GLFW_KEY_LAST + 1];+ char* clipboardString;+ // Where to place the cursor when re-enabled+ double restoreCursorPosX, restoreCursorPosY;+ // The window whose disabled cursor mode is active+ _GLFWwindow* disabledCursorWindow; -} _GLFWlibraryNS;+ struct {+ CFBundleRef bundle;+ PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;+ PFN_TISGetInputSourceProperty GetInputSourceProperty;+ PFN_LMGetKbdType GetKbdType;+ CFStringRef kPropertyUnicodeKeyLayoutData;+ CFStringRef kNotifySelectedKeyboardInputSourceChanged;+ } tis; +} _GLFWlibraryNS; // Cocoa-specific per-monitor data //@@ -92,11 +121,10 @@ { CGDirectDisplayID displayID; CGDisplayModeRef previousMode;- id screen;+ uint32_t unitNumber; } _GLFWmonitorNS; - // Cocoa-specific per-cursor data // typedef struct _GLFWcursorNS@@ -105,20 +133,18 @@ } _GLFWcursorNS; - // Cocoa-specific global timer data // typedef struct _GLFWtimeNS {- double base;- double resolution;+ uint64_t frequency; } _GLFWtimeNS; -void _glfwInitTimer(void);+void _glfwInitTimerNS(void); -GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);-void _glfwRestoreVideoMode(_GLFWmonitor* monitor);+GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); -#endif // _cocoa_platform_h_+#endif // _glfw3_cocoa_platform_h_
+ glfw/src/cocoa_time.c view
@@ -0,0 +1,60 @@+//========================================================================+// GLFW 3.2 OS X - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <mach/mach_time.h>+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++// Initialise timer+//+void _glfwInitTimerNS(void)+{+ mach_timebase_info_data_t info;+ mach_timebase_info(&info);++ _glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW platform API //////+//////////////////////////////////////////////////////////////////////////++uint64_t _glfwPlatformGetTimerValue(void)+{+ return mach_absolute_time();+}++uint64_t _glfwPlatformGetTimerFrequency(void)+{+ return _glfw.ns_time.frequency;+}+
glfw/src/cocoa_window.m view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -26,6 +26,7 @@ #include "internal.h" +#include <float.h> #include <string.h> // Needed for _NSGetProgname@@ -55,6 +56,26 @@ return nil; } +// Returns the style mask corresponding to the window settings+//+static NSUInteger getStyleMask(_GLFWwindow* window)+{+ NSUInteger styleMask = 0;++ if (window->monitor || !window->decorated)+ styleMask |= NSBorderlessWindowMask;+ else+ {+ styleMask |= NSTitledWindowMask | NSClosableWindowMask |+ NSMiniaturizableWindowMask;++ if (window->resizable)+ styleMask |= NSResizableWindowMask;+ }++ return styleMask;+}+ // Center the cursor in the view of the window // static void centerCursor(_GLFWwindow *window)@@ -64,10 +85,18 @@ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); } -// Update the cursor to match the specified cursor mode+// Returns whether the cursor is in the client area of the specified window //-static void updateModeCursor(_GLFWwindow* window)+static GLFWbool cursorInClientArea(_GLFWwindow* window) {+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];+ return [window->ns.view mouse:pos inRect:[window->ns.view frame]];+}++// Updates the cursor image according to its cursor mode+//+static void updateCursorImage(_GLFWwindow* window)+{ if (window->cursorMode == GLFW_CURSOR_NORMAL) { if (window->cursor)@@ -79,51 +108,98 @@ [(NSCursor*) _glfw.ns.cursor set]; } -// Enter full screen mode+// Transforms the specified y-coordinate between the CG display and NS screen+// coordinate systems //-static GLboolean enterFullscreenMode(_GLFWwindow* window)+static float transformY(float y) {- GLboolean status;+ return CGDisplayBounds(CGMainDisplayID()).size.height - y;+} - status = _glfwSetVideoMode(window->monitor, &window->videoMode);+// Make the specified window and its video mode active on its monitor+//+static GLFWbool acquireMonitor(_GLFWwindow* window)+{+ const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode);+ const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);+ const NSRect frame = NSMakeRect(bounds.origin.x,+ transformY(bounds.origin.y + bounds.size.height),+ bounds.size.width,+ bounds.size.height); - // NOTE: The window is resized despite mode setting failure to make- // glfwSetWindowSize more robust- [window->ns.object setFrame:[window->monitor->ns.screen frame]- display:YES];+ [window->ns.object setFrame:frame display:YES]; + _glfwInputMonitorWindowChange(window->monitor, window); return status; } -// Leave full screen mode+// Remove the window and restore the original video mode //-static void leaveFullscreenMode(_GLFWwindow* window)+static void releaseMonitor(_GLFWwindow* window) {- _glfwRestoreVideoMode(window->monitor);+ if (window->monitor->window != window)+ return;++ _glfwInputMonitorWindowChange(window->monitor, NULL);+ _glfwRestoreVideoModeNS(window->monitor); } -// Transforms the specified y-coordinate between the CG display and NS screen-// coordinate systems+// Translates OS X key modifiers into GLFW ones //-static float transformY(float y)+static int translateFlags(NSUInteger flags) {- const float height = CGDisplayBounds(CGMainDisplayID()).size.height;- return height - y;+ int mods = 0;++ if (flags & NSShiftKeyMask)+ mods |= GLFW_MOD_SHIFT;+ if (flags & NSControlKeyMask)+ mods |= GLFW_MOD_CONTROL;+ if (flags & NSAlternateKeyMask)+ mods |= GLFW_MOD_ALT;+ if (flags & NSCommandKeyMask)+ mods |= GLFW_MOD_SUPER;++ return mods; } -// Returns the backing rect of the specified window+// Translates a OS X keycode to a GLFW keycode //-static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect)+static int translateKey(unsigned int key) {-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- return [window->ns.view convertRectToBacking:contentRect];- else-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/- return contentRect;+ if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))+ return GLFW_KEY_UNKNOWN;++ return _glfw.ns.publicKeys[key]; } +// Translate a GLFW keycode to a Cocoa modifier flag+//+static NSUInteger translateKeyToModifierFlag(int key)+{+ switch (key)+ {+ case GLFW_KEY_LEFT_SHIFT:+ case GLFW_KEY_RIGHT_SHIFT:+ return NSShiftKeyMask;+ case GLFW_KEY_LEFT_CONTROL:+ case GLFW_KEY_RIGHT_CONTROL:+ return NSControlKeyMask;+ case GLFW_KEY_LEFT_ALT:+ case GLFW_KEY_RIGHT_ALT:+ return NSAlternateKeyMask;+ case GLFW_KEY_LEFT_SUPER:+ case GLFW_KEY_RIGHT_SUPER:+ return NSCommandKeyMask;+ } + return 0;+}++// Defines a constant for empty ranges in NSTextInputClient+//+static const NSRange kEmptyRange = { NSNotFound, 0 };++ //------------------------------------------------------------------------ // Delegate for window related notifications //------------------------------------------------------------------------@@ -156,27 +232,26 @@ - (void)windowDidResize:(NSNotification *)notification {- if (_glfw.focusedWindow == window &&- window->cursorMode == GLFW_CURSOR_DISABLED)- {+ if (window->context.client != GLFW_NO_API)+ [window->context.nsgl.object update];++ if (_glfw.ns.disabledCursorWindow == window) centerCursor(window);- } const NSRect contentRect = [window->ns.view frame];- const NSRect fbRect = convertRectToBacking(window, contentRect);+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height); _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);- _glfwInputWindowDamage(window); } - (void)windowDidMove:(NSNotification *)notification {- if (_glfw.focusedWindow == window &&- window->cursorMode == GLFW_CURSOR_DISABLED)- {+ if (window->context.client != GLFW_NO_API)+ [window->context.nsgl.object update];++ if (_glfw.ns.disabledCursorWindow == window) centerCursor(window);- } int x, y; _glfwPlatformGetWindowPos(window, &x, &y);@@ -185,35 +260,35 @@ - (void)windowDidMiniaturize:(NSNotification *)notification {- _glfwInputWindowIconify(window, GL_TRUE);+ if (window->monitor)+ releaseMonitor(window);++ _glfwInputWindowIconify(window, GLFW_TRUE); } - (void)windowDidDeminiaturize:(NSNotification *)notification {- _glfwInputWindowIconify(window, GL_FALSE);+ if (window->monitor)+ acquireMonitor(window);++ _glfwInputWindowIconify(window, GLFW_FALSE); } - (void)windowDidBecomeKey:(NSNotification *)notification {- if (window->monitor)- enterFullscreenMode(window);-- if (_glfw.focusedWindow == window &&- window->cursorMode == GLFW_CURSOR_DISABLED)- {+ if (_glfw.ns.disabledCursorWindow == window) centerCursor(window);- } - _glfwInputWindowFocus(window, GL_TRUE);- _glfwPlatformApplyCursorMode(window);+ _glfwInputWindowFocus(window, GLFW_TRUE);+ _glfwPlatformSetCursorMode(window, window->cursorMode); } - (void)windowDidResignKey:(NSNotification *)notification {- if (window->monitor)- leaveFullscreenMode(window);+ if (window->monitor && window->autoIconify)+ _glfwPlatformIconifyWindow(window); - _glfwInputWindowFocus(window, GL_FALSE);+ _glfwInputWindowFocus(window, GLFW_FALSE); } @end@@ -250,45 +325,26 @@ _glfwPlatformPostEmptyEvent(); } -@end--// Translates OS X key modifiers into GLFW ones-//-static int translateFlags(NSUInteger flags)+- (void)applicationDidHide:(NSNotification *)notification {- int mods = 0;-- if (flags & NSShiftKeyMask)- mods |= GLFW_MOD_SHIFT;- if (flags & NSControlKeyMask)- mods |= GLFW_MOD_CONTROL;- if (flags & NSAlternateKeyMask)- mods |= GLFW_MOD_ALT;- if (flags & NSCommandKeyMask)- mods |= GLFW_MOD_SUPER;+ int i; - return mods;+ for (i = 0; i < _glfw.monitorCount; i++)+ _glfwRestoreVideoModeNS(_glfw.monitors[i]); } -// Translates a OS X keycode to a GLFW keycode-//-static int translateKey(unsigned int key)-{- if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))- return GLFW_KEY_UNKNOWN;-- return _glfw.ns.publicKeys[key];-}+@end //------------------------------------------------------------------------ // Content view class for the GLFW window //------------------------------------------------------------------------ -@interface GLFWContentView : NSOpenGLView+@interface GLFWContentView : NSView <NSTextInputClient> { _GLFWwindow* window; NSTrackingArea* trackingArea;+ NSMutableAttributedString* markedText; } - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;@@ -313,12 +369,12 @@ - (id)initWithGlfwWindow:(_GLFWwindow *)initWindow {- self = [super initWithFrame:NSMakeRect(0, 0, 1, 1)- pixelFormat:nil];+ self = [super init]; if (self != nil) { window = initWindow; trackingArea = nil;+ markedText = [[NSMutableAttributedString alloc] init]; [self updateTrackingAreas]; [self registerForDraggedTypes:[NSArray arrayWithObjects:@@ -328,9 +384,10 @@ return self; } --(void)dealloc+- (void)dealloc { [trackingArea release];+ [markedText release]; [super dealloc]; } @@ -351,7 +408,7 @@ - (void)cursorUpdate:(NSEvent *)event {- updateModeCursor(window);+ updateCursorImage(window); } - (void)mouseDown:(NSEvent *)event@@ -379,20 +436,23 @@ { if (window->cursorMode == GLFW_CURSOR_DISABLED) {- _glfwInputCursorMotion(window,- [event deltaX] - window->ns.warpDeltaX,- [event deltaY] - window->ns.warpDeltaY);+ const double dx = [event deltaX] - window->ns.cursorWarpDeltaX;+ const double dy = [event deltaY] - window->ns.cursorWarpDeltaY;++ _glfwInputCursorPos(window,+ window->virtualCursorPosX + dx,+ window->virtualCursorPosY + dy); } else { const NSRect contentRect = [window->ns.view frame]; const NSPoint pos = [event locationInWindow]; - _glfwInputCursorMotion(window, pos.x, contentRect.size.height - pos.y);+ _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y); } - window->ns.warpDeltaX = 0;- window->ns.warpDeltaY = 0;+ window->ns.cursorWarpDeltaX = 0;+ window->ns.cursorWarpDeltaY = 0; } - (void)rightMouseDown:(NSEvent *)event@@ -439,20 +499,24 @@ - (void)mouseExited:(NSEvent *)event {- _glfwInputCursorEnter(window, GL_FALSE);+ _glfwInputCursorEnter(window, GLFW_FALSE); } - (void)mouseEntered:(NSEvent *)event {- _glfwInputCursorEnter(window, GL_TRUE);+ _glfwInputCursorEnter(window, GLFW_TRUE); } - (void)viewDidChangeBackingProperties { const NSRect contentRect = [window->ns.view frame];- const NSRect fbRect = convertRectToBacking(window, contentRect);+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);+}++- (void)drawRect:(NSRect)rect+{ _glfwInputWindowDamage(window); } @@ -487,18 +551,7 @@ _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods); - NSString* characters = [event characters];- NSUInteger i, length = [characters length];- const int plain = !(mods & GLFW_MOD_SUPER);-- for (i = 0; i < length; i++)- {- const unichar codepoint = [characters characterAtIndex:i];- if ((codepoint & 0xff00) == 0xf700)- continue;-- _glfwInputChar(window, codepoint, mods, plain);- }+ [self interpretKeyEvents:[NSArray arrayWithObject:event]]; } - (void)flagsChanged:(NSEvent *)event@@ -508,21 +561,18 @@ [event modifierFlags] & NSDeviceIndependentModifierFlagsMask; const int key = translateKey([event keyCode]); const int mods = translateFlags(modifierFlags);+ const NSUInteger keyFlag = translateKeyToModifierFlag(key); - if (modifierFlags == window->ns.modifierFlags)+ if (keyFlag & modifierFlags) { if (window->keys[key] == GLFW_PRESS) action = GLFW_RELEASE; else action = GLFW_PRESS; }- else if (modifierFlags > window->ns.modifierFlags)- action = GLFW_PRESS; else action = GLFW_RELEASE; - window->ns.modifierFlags = modifierFlags;- _glfwInputKey(window, key, [event keyCode], action, mods); } @@ -537,23 +587,13 @@ { double deltaX, deltaY; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- {- deltaX = [event scrollingDeltaX];- deltaY = [event scrollingDeltaY];+ deltaX = [event scrollingDeltaX];+ deltaY = [event scrollingDeltaY]; - if ([event hasPreciseScrollingDeltas])- {- deltaX *= 0.1;- deltaY *= 0.1;- }- }- else-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/+ if ([event hasPreciseScrollingDeltas]) {- deltaX = [event deltaX];- deltaY = [event deltaY];+ deltaX *= 0.1;+ deltaY *= 0.1; } if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0)@@ -584,9 +624,9 @@ NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType]; const NSRect contentRect = [window->ns.view frame];- _glfwInputCursorMotion(window,- [sender draggingLocation].x,- contentRect.size.height - [sender draggingLocation].y);+ _glfwInputCursorPos(window,+ [sender draggingLocation].x,+ contentRect.size.height - [sender draggingLocation].y); const int count = [files count]; if (count)@@ -613,6 +653,92 @@ [self setNeedsDisplay:YES]; } +- (BOOL)hasMarkedText+{+ return [markedText length] > 0;+}++- (NSRange)markedRange+{+ if ([markedText length] > 0)+ return NSMakeRange(0, [markedText length] - 1);+ else+ return kEmptyRange;+}++- (NSRange)selectedRange+{+ return kEmptyRange;+}++- (void)setMarkedText:(id)string+ selectedRange:(NSRange)selectedRange+ replacementRange:(NSRange)replacementRange+{+ if ([string isKindOfClass:[NSAttributedString class]])+ [markedText initWithAttributedString:string];+ else+ [markedText initWithString:string];+}++- (void)unmarkText+{+ [[markedText mutableString] setString:@""];+}++- (NSArray*)validAttributesForMarkedText+{+ return [NSArray array];+}++- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range+ actualRange:(NSRangePointer)actualRange+{+ return nil;+}++- (NSUInteger)characterIndexForPoint:(NSPoint)point+{+ return 0;+}++- (NSRect)firstRectForCharacterRange:(NSRange)range+ actualRange:(NSRangePointer)actualRange+{+ int xpos, ypos;+ _glfwPlatformGetWindowPos(window, &xpos, &ypos);+ const NSRect contentRect = [window->ns.view frame];+ return NSMakeRect(xpos, transformY(ypos + contentRect.size.height), 0.0, 0.0);+}++- (void)insertText:(id)string replacementRange:(NSRange)replacementRange+{+ NSString* characters;+ NSEvent* event = [NSApp currentEvent];+ const int mods = translateFlags([event modifierFlags]);+ const int plain = !(mods & GLFW_MOD_SUPER);++ if ([string isKindOfClass:[NSAttributedString class]])+ characters = [string string];+ else+ characters = (NSString*) string;++ NSUInteger i, length = [characters length];++ for (i = 0; i < length; i++)+ {+ const unichar codepoint = [characters characterAtIndex:i];+ if ((codepoint & 0xff00) == 0xf700)+ continue;++ _glfwInputChar(window, codepoint, mods, plain);+ }+}++- (void)doCommandBySelector:(SEL)selector+{+}+ @end @@ -654,6 +780,12 @@ [super sendEvent:event]; } ++// No-op thread entry point+//+- (void)doNothing:(id)object+{+} @end #if defined(_GLFW_USE_MENUBAR)@@ -719,6 +851,7 @@ [[appMenu addItemWithTitle:@"Services" action:NULL keyEquivalent:@""] setSubmenu:servicesMenu];+ [servicesMenu release]; [appMenu addItem:[NSMenuItem separatorItem]]; [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName] action:@selector(hide:)@@ -737,6 +870,7 @@ NSMenuItem* windowMenuItem = [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];+ [bar release]; NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; [NSApp setWindowsMenu:windowMenu]; [windowMenuItem setSubmenu:windowMenu];@@ -752,18 +886,12 @@ action:@selector(arrangeInFront:) keyEquivalent:@""]; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- {- // TODO: Make this appear at the bottom of the menu (for consistency)-- [windowMenu addItem:[NSMenuItem separatorItem]];- [[windowMenu addItemWithTitle:@"Enter Full Screen"- action:@selector(toggleFullScreen:)- keyEquivalent:@"f"]- setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask];- }-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/+ // TODO: Make this appear at the bottom of the menu (for consistency)+ [windowMenu addItem:[NSMenuItem separatorItem]];+ [[windowMenu addItemWithTitle:@"Enter Full Screen"+ action:@selector(toggleFullScreen:)+ keyEquivalent:@"f"]+ setKeyEquivalentModifierMask:NSControlKeyMask | NSCommandKeyMask]; // Prior to Snow Leopard, we need to use this oddly-named semi-private API // to get the application menu working properly.@@ -775,14 +903,19 @@ // Initialize the Cocoa Application Kit //-static GLboolean initializeAppKit(void)+static GLFWbool initializeAppKit(void) { if (NSApp)- return GL_TRUE;+ return GLFW_TRUE; // Implicitly create shared NSApplication instance [GLFWApplication sharedApplication]; + // Make Cocoa enter multi-threaded mode+ [NSThread detachNewThreadSelector:@selector(doNothing:)+ toTarget:NSApp+ withObject:nil];+ // In case we are unbundled, make us a proper UI application [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; @@ -800,91 +933,85 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create application delegate");- return GL_FALSE;+ return GLFW_FALSE; } [NSApp setDelegate:_glfw.ns.delegate]; [NSApp run]; - return GL_TRUE;+ return GLFW_TRUE; } // Create the Cocoa window //-static GLboolean createWindow(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig)+static GLFWbool createNativeWindow(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig) { window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window]; if (window->ns.delegate == nil) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window delegate");- return GL_FALSE;+ return GLFW_FALSE; } - unsigned int styleMask = 0;+ NSRect contentRect; - if (wndconfig->monitor || !wndconfig->decorated)- styleMask = NSBorderlessWindowMask;- else+ if (window->monitor) {- styleMask = NSTitledWindowMask | NSClosableWindowMask |- NSMiniaturizableWindowMask;-- if (wndconfig->resizable)- styleMask |= NSResizableWindowMask;- }+ GLFWvidmode mode;+ int xpos, ypos; - NSRect contentRect;+ _glfwPlatformGetVideoMode(window->monitor, &mode);+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos); - if (wndconfig->monitor)- contentRect = [wndconfig->monitor->ns.screen frame];+ contentRect = NSMakeRect(xpos, ypos, mode.width, mode.height);+ } else contentRect = NSMakeRect(0, 0, wndconfig->width, wndconfig->height); window->ns.object = [[GLFWWindow alloc] initWithContentRect:contentRect- styleMask:styleMask+ styleMask:getStyleMask(window) backing:NSBackingStoreBuffered defer:NO]; if (window->ns.object == nil) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window");- return GL_FALSE;+ return GLFW_FALSE; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- {- if (wndconfig->resizable)- [window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];- }-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/-- if (wndconfig->monitor)- {+ if (window->monitor) [window->ns.object setLevel:NSMainMenuWindowLevel + 1];- [window->ns.object setHidesOnDeactivate:YES];- } else { [window->ns.object center]; + if (wndconfig->resizable)+ [window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];+ if (wndconfig->floating) [window->ns.object setLevel:NSFloatingWindowLevel];++ if (wndconfig->maximized)+ [window->ns.object zoom:nil]; } + window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];++#if defined(_GLFW_USE_RETINA)+ [window->ns.view setWantsBestResolutionOpenGLSurface:YES];+#endif /*_GLFW_USE_RETINA*/++ [window->ns.object makeFirstResponder:window->ns.view]; [window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]]; [window->ns.object setDelegate:window->ns.delegate]; [window->ns.object setAcceptsMouseMovedEvents:YES];--#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- [window->ns.object setRestorable:NO];-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/+ [window->ns.object setContentView:window->ns.view];+ [window->ns.object setRestorable:NO]; - return GL_TRUE;+ return GLFW_TRUE; } @@ -898,50 +1025,52 @@ const _GLFWfbconfig* fbconfig) { if (!initializeAppKit())- return GL_FALSE;-- if (!createWindow(window, wndconfig))- return GL_FALSE;-- if (!_glfwCreateContext(window, ctxconfig, fbconfig))- return GL_FALSE;-- window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];+ return GLFW_FALSE; -#if defined(_GLFW_USE_RETINA)-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6)- [window->ns.view setWantsBestResolutionOpenGLSurface:YES];-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/-#endif /*_GLFW_USE_RETINA*/+ if (!createNativeWindow(window, wndconfig))+ return GLFW_FALSE; - [window->ns.object setContentView:window->ns.view];- // NOTE: If you set the pixel format before the context it creates another- // context, only to have it destroyed by the next line- // We cannot use the view to create the context because that interface- // does not support context resource sharing- [window->ns.view setOpenGLContext:window->nsgl.context];- [window->ns.view setPixelFormat:window->nsgl.pixelFormat];- [window->nsgl.context setView:window->ns.view];+ if (ctxconfig->client != GLFW_NO_API)+ {+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)+ {+ if (!_glfwInitNSGL())+ return GLFW_FALSE;+ if (!_glfwCreateContextNSGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }+ else+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");+ return GLFW_FALSE;+ }+ } - if (wndconfig->monitor)+ if (window->monitor) { _glfwPlatformShowWindow(window);- if (!enterFullscreenMode(window))- return GL_FALSE;+ _glfwPlatformFocusWindow(window);+ if (!acquireMonitor(window))+ return GLFW_FALSE;++ centerCursor(window); } - return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformDestroyWindow(_GLFWwindow* window) {+ if (_glfw.ns.disabledCursorWindow == window)+ _glfw.ns.disabledCursorWindow = NULL;+ [window->ns.object orderOut:nil]; if (window->monitor)- leaveFullscreenMode(window);+ releaseMonitor(window); - _glfwDestroyContext(window);+ if (window->context.destroy)+ window->context.destroy(window); [window->ns.object setDelegate:nil]; [window->ns.delegate release];@@ -952,6 +1081,9 @@ [window->ns.object close]; window->ns.object = nil;++ [_glfw.ns.autoreleasePool drain];+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init]; } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)@@ -959,6 +1091,12 @@ [window->ns.object setTitle:[NSString stringWithUTF8String:title]]; } +void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+ int count, const GLFWimage* images)+{+ // Regular windows do not have icons+}+ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) { const NSRect contentRect =@@ -991,15 +1129,41 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) { if (window->monitor)- enterFullscreenMode(window);+ {+ if (window->monitor->window == window)+ acquireMonitor(window);+ } else [window->ns.object setContentSize:NSMakeSize(width, height)]; } +void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)+ [window->ns.object setContentMinSize:NSMakeSize(0, 0)];+ else+ [window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)];++ if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)+ [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];+ else+ [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)+{+ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)+ [window->ns.object setContentAspectRatio:NSMakeSize(0, 0)];+ else+ [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];+}+ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { const NSRect contentRect = [window->ns.view frame];- const NSRect fbRect = convertRectToBacking(window, contentRect);+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect]; if (width) *width = (int) fbRect.size.width;@@ -1033,11 +1197,30 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) {- [window->ns.object deminiaturize:nil];+ if ([window->ns.object isMiniaturized])+ [window->ns.object deminiaturize:nil];+ else if ([window->ns.object isZoomed])+ [window->ns.object zoom:nil]; } +void _glfwPlatformMaximizeWindow(_GLFWwindow* window)+{+ if (![window->ns.object isZoomed])+ [window->ns.object zoom:nil];+}+ void _glfwPlatformShowWindow(_GLFWwindow* window) {+ [window->ns.object orderFront:nil];+}++void _glfwPlatformHideWindow(_GLFWwindow* window)+{+ [window->ns.object orderOut:nil];+}++void _glfwPlatformFocusWindow(_GLFWwindow* window)+{ // Make us the active application // HACK: This has been moved here from initializeAppKit to prevent // applications using only hidden windows from being activated, but@@ -1047,14 +1230,101 @@ [window->ns.object makeKeyAndOrderFront:nil]; } -void _glfwPlatformUnhideWindow(_GLFWwindow* window)+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+ _GLFWmonitor* monitor,+ int xpos, int ypos,+ int width, int height,+ int refreshRate) {- [window->ns.object orderFront:nil];-}+ if (window->monitor == monitor)+ {+ if (monitor)+ {+ if (monitor->window == window)+ acquireMonitor(window);+ }+ else+ {+ const NSRect contentRect =+ NSMakeRect(xpos, transformY(ypos + height), width, height);+ const NSRect frameRect =+ [window->ns.object frameRectForContentRect:contentRect+ styleMask:getStyleMask(window)]; -void _glfwPlatformHideWindow(_GLFWwindow* window)-{- [window->ns.object orderOut:nil];+ [window->ns.object setFrame:frameRect display:YES];+ }++ return;+ }++ if (window->monitor)+ releaseMonitor(window);++ _glfwInputWindowMonitorChange(window, monitor);++ const NSUInteger styleMask = getStyleMask(window);+ [window->ns.object setStyleMask:styleMask];+ [window->ns.object makeFirstResponder:window->ns.view];++ NSRect contentRect;++ if (monitor)+ {+ GLFWvidmode mode;++ _glfwPlatformGetVideoMode(window->monitor, &mode);+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);++ contentRect = NSMakeRect(xpos, transformY(ypos + mode.height),+ mode.width, mode.height);+ }+ else+ {+ contentRect = NSMakeRect(xpos, transformY(ypos + height),+ width, height);+ }++ NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect+ styleMask:styleMask];+ [window->ns.object setFrame:frameRect display:YES];++ if (monitor)+ {+ [window->ns.object setLevel:NSMainMenuWindowLevel + 1];+ [window->ns.object setHasShadow:NO];++ acquireMonitor(window);+ }+ else+ {+ if (window->numer != GLFW_DONT_CARE &&+ window->denom != GLFW_DONT_CARE)+ {+ [window->ns.object setContentAspectRatio:NSMakeSize(window->numer,+ window->denom)];+ }++ if (window->minwidth != GLFW_DONT_CARE &&+ window->minheight != GLFW_DONT_CARE)+ {+ [window->ns.object setContentMinSize:NSMakeSize(window->minwidth,+ window->minheight)];+ }++ if (window->maxwidth != GLFW_DONT_CARE &&+ window->maxheight != GLFW_DONT_CARE)+ {+ [window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,+ window->maxheight)];+ }++ if (window->floating)+ [window->ns.object setLevel:NSFloatingWindowLevel];+ else+ [window->ns.object setLevel:NSNormalWindowLevel];++ [window->ns.object setHasShadow:YES];+ } } int _glfwPlatformWindowFocused(_GLFWwindow* window)@@ -1072,6 +1342,11 @@ return [window->ns.object isVisible]; } +int _glfwPlatformWindowMaximized(_GLFWwindow* window)+{+ return [window->ns.object isZoomed];+}+ void _glfwPlatformPollEvents(void) { for (;;)@@ -1104,6 +1379,19 @@ _glfwPlatformPollEvents(); } +void _glfwPlatformWaitEventsTimeout(double timeout)+{+ NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask+ untilDate:date+ inMode:NSDefaultRunLoopMode+ dequeue:YES];+ if (event)+ [NSApp sendEvent:event];++ _glfwPlatformPollEvents();+}+ void _glfwPlatformPostEmptyEvent(void) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];@@ -1133,13 +1421,13 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) {- updateModeCursor(window);+ updateCursorImage(window); const NSRect contentRect = [window->ns.view frame]; const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream]; - window->ns.warpDeltaX += x - pos.x;- window->ns.warpDeltaY += y - contentRect.size.height + pos.y;+ window->ns.cursorWarpDeltaX += x - pos.x;+ window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y; if (window->monitor) {@@ -1148,24 +1436,81 @@ } else {- const NSPoint localPoint = NSMakePoint(x, contentRect.size.height - y - 1);- const NSPoint globalPoint = [window->ns.object convertBaseToScreen:localPoint];+ const NSRect localRect = NSMakeRect(x, contentRect.size.height - y - 1, 0, 0);+ const NSRect globalRect = [window->ns.object convertRectToScreen:localRect];+ const NSPoint globalPoint = globalRect.origin; CGWarpMouseCursorPosition(CGPointMake(globalPoint.x, transformY(globalPoint.y))); } } -void _glfwPlatformApplyCursorMode(_GLFWwindow* window)+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) {- updateModeCursor(window);-- if (window->cursorMode == GLFW_CURSOR_DISABLED)+ if (mode == GLFW_CURSOR_DISABLED)+ {+ _glfw.ns.disabledCursorWindow = window;+ _glfwPlatformGetCursorPos(window,+ &_glfw.ns.restoreCursorPosX,+ &_glfw.ns.restoreCursorPosY);+ centerCursor(window); CGAssociateMouseAndMouseCursorPosition(false);- else+ }+ else if (_glfw.ns.disabledCursorWindow == window)+ {+ _glfw.ns.disabledCursorWindow = NULL; CGAssociateMouseAndMouseCursorPosition(true);+ _glfwPlatformSetCursorPos(window,+ _glfw.ns.restoreCursorPosX,+ _glfw.ns.restoreCursorPosY);+ }++ if (cursorInClientArea(window))+ updateCursorImage(window); } +const char* _glfwPlatformGetKeyName(int key, int scancode)+{+ if (key != GLFW_KEY_UNKNOWN)+ scancode = _glfw.ns.nativeKeys[key];++ if (!_glfwIsPrintable(_glfw.ns.publicKeys[scancode]))+ return NULL;++ UInt32 deadKeyState = 0;+ UniChar characters[8];+ UniCharCount characterCount = 0;++ if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes],+ scancode,+ kUCKeyActionDisplay,+ 0,+ LMGetKbdType(),+ kUCKeyTranslateNoDeadKeysBit,+ &deadKeyState,+ sizeof(characters) / sizeof(characters[0]),+ &characterCount,+ characters) != noErr)+ {+ return NULL;+ }++ if (!characterCount)+ return NULL;++ CFStringRef string = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,+ characters,+ characterCount,+ kCFAllocatorNull);+ CFStringGetCString(string,+ _glfw.ns.keyName,+ sizeof(_glfw.ns.keyName),+ kCFStringEncodingUTF8);+ CFRelease(string);++ return _glfw.ns.keyName;+}+ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot)@@ -1173,6 +1518,9 @@ NSImage* native; NSBitmapImageRep* rep; + if (!initializeAppKit())+ return GLFW_FALSE;+ rep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:image->width@@ -1187,12 +1535,12 @@ bitsPerPixel:32]; if (rep == nil)- return GL_FALSE;+ return GLFW_FALSE; memcpy([rep bitmapData], image->pixels, image->width * image->height * 4); native = [[NSImage alloc] initWithSize:NSMakeSize(image->width, image->height)];- [native addRepresentation: rep];+ [native addRepresentation:rep]; cursor->ns.object = [[NSCursor alloc] initWithImage:native hotSpot:NSMakePoint(xhot, yhot)];@@ -1201,22 +1549,26 @@ [rep release]; if (cursor->ns.object == nil)- return GL_FALSE;+ return GLFW_FALSE; - return GL_TRUE;+ return GLFW_TRUE; } int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) {+ if (!initializeAppKit())+ return GLFW_FALSE;+ cursor->ns.object = getStandardCursor(shape); if (!cursor->ns.object) {- _glfwInputError(GLFW_INVALID_ENUM, "Cocoa: Invalid standard cursor");- return GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Cocoa: Failed to retrieve standard cursor");+ return GLFW_FALSE; } [cursor->ns.object retain];- return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)@@ -1227,16 +1579,8 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) {- const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];-- if (window->cursorMode == GLFW_CURSOR_NORMAL &&- [window->ns.view mouse:pos inRect:[window->ns.view frame]])- {- if (cursor)- [(NSCursor*) cursor->ns.object set];- else- [[NSCursor arrowCursor] set];- }+ if (cursorInClientArea(window))+ updateCursorImage(window); } void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)@@ -1255,7 +1599,8 @@ if (![[pasteboard types] containsObject:NSStringPboardType]) {- _glfwInputError(GLFW_FORMAT_UNAVAILABLE, NULL);+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "Cocoa: Failed to retrieve string from pasteboard"); return NULL; } @@ -1271,6 +1616,27 @@ _glfw.ns.clipboardString = strdup([object UTF8String]); return _glfw.ns.clipboardString;+}++char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)+{+ *count = 0;+ return NULL;+}++int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ return GLFW_FALSE;+}++VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,+ _GLFWwindow* window,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ return VK_ERROR_EXTENSION_NOT_PRESENT; }
glfw/src/context.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -27,74 +27,40 @@ #include "internal.h" +#include <assert.h> #include <stdio.h> #include <string.h> #include <limits.h> #include <stdio.h> -// Parses the client API version string and extracts the version number-//-static GLboolean parseVersionString(int* api, int* major, int* minor, int* rev)-{- int i;- const char* version;- const char* prefixes[] =- {- "OpenGL ES-CM ",- "OpenGL ES-CL ",- "OpenGL ES ",- NULL- };-- *api = GLFW_OPENGL_API;-- version = (const char*) glGetString(GL_VERSION);- if (!version)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Failed to retrieve context version string");- return GL_FALSE;- }-- for (i = 0; prefixes[i]; i++)- {- const size_t length = strlen(prefixes[i]);-- if (strncmp(version, prefixes[i], length) == 0)- {- version += length;- *api = GLFW_OPENGL_ES_API;- break;- }- }-- if (!sscanf(version, "%d.%d.%d", major, minor, rev))- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "No version found in context version string");- return GL_FALSE;- }-- return GL_TRUE;-}-- ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -GLboolean _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) {- if (ctxconfig->api != GLFW_OPENGL_API &&- ctxconfig->api != GLFW_OPENGL_ES_API)+ if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&+ ctxconfig->source != GLFW_EGL_CONTEXT_API) {- _glfwInputError(GLFW_INVALID_ENUM, "Invalid client API requested");- return GL_FALSE;+ _glfwInputError(GLFW_INVALID_ENUM,+ "Invalid context creation API %i",+ ctxconfig->source);+ return GLFW_FALSE; } - if (ctxconfig->api == GLFW_OPENGL_API)+ if (ctxconfig->client != GLFW_NO_API &&+ ctxconfig->client != GLFW_OPENGL_API &&+ ctxconfig->client != GLFW_OPENGL_ES_API) {+ _glfwInputError(GLFW_INVALID_ENUM,+ "Invalid client API %i",+ ctxconfig->client);+ return GLFW_FALSE;+ }++ if (ctxconfig->client == GLFW_OPENGL_API)+ { if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || (ctxconfig->major == 1 && ctxconfig->minor > 5) || (ctxconfig->major == 2 && ctxconfig->minor > 1) ||@@ -104,15 +70,12 @@ // OpenGL 1.x series ended with version 1.5 // OpenGL 2.x series ended with version 2.1 // OpenGL 3.x series ended with version 3.3+ // For now, let everything else through _glfwInputError(GLFW_INVALID_VALUE,- "Invalid OpenGL version %i.%i requested",+ "Invalid OpenGL version %i.%i", ctxconfig->major, ctxconfig->minor);- return GL_FALSE;- }- else- {- // For now, let everything else through+ return GLFW_FALSE; } if (ctxconfig->profile)@@ -121,33 +84,32 @@ ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE) { _glfwInputError(GLFW_INVALID_ENUM,- "Invalid OpenGL profile requested");- return GL_FALSE;+ "Invalid OpenGL profile %i",+ ctxconfig->profile);+ return GLFW_FALSE; } - if (ctxconfig->major < 3 ||+ if (ctxconfig->major <= 2 || (ctxconfig->major == 3 && ctxconfig->minor < 2)) { // Desktop OpenGL context profiles are only defined for version 3.2 // and above _glfwInputError(GLFW_INVALID_VALUE,- "Context profiles only exist for "- "OpenGL version 3.2 and above");- return GL_FALSE;+ "Context profiles are only defined for OpenGL version 3.2 and above");+ return GLFW_FALSE; } } - if (ctxconfig->forward && ctxconfig->major < 3)+ if (ctxconfig->forward && ctxconfig->major <= 2) { // Forward-compatible contexts are only defined for OpenGL version 3.0 and above _glfwInputError(GLFW_INVALID_VALUE,- "Forward compatibility only exist for OpenGL "- "version 3.0 and above");- return GL_FALSE;+ "Forward-compatibility is only defined for OpenGL version 3.0 and above");+ return GLFW_FALSE; } }- else if (ctxconfig->api == GLFW_OPENGL_ES_API)+ else if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major < 1 || ctxconfig->minor < 0 || (ctxconfig->major == 1 && ctxconfig->minor > 1) ||@@ -156,31 +118,12 @@ // OpenGL ES 1.0 is the smallest valid version // OpenGL ES 1.x series ended with version 1.1 // OpenGL ES 2.x series ended with version 2.0-- _glfwInputError(GLFW_INVALID_VALUE,- "Invalid OpenGL ES version %i.%i requested",- ctxconfig->major, ctxconfig->minor);- return GL_FALSE;- }- else- { // For now, let everything else through- } - if (ctxconfig->profile)- {- // OpenGL ES does not support profiles _glfwInputError(GLFW_INVALID_VALUE,- "Context profiles are not supported by OpenGL ES");- return GL_FALSE;- }-- if (ctxconfig->forward)- {- // OpenGL ES does not support forward-compatibility- _glfwInputError(GLFW_INVALID_VALUE,- "Forward compatibility is not supported by OpenGL ES");- return GL_FALSE;+ "Invalid OpenGL ES version %i.%i",+ ctxconfig->major, ctxconfig->minor);+ return GLFW_FALSE; } } @@ -189,9 +132,10 @@ if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION && ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET) {- _glfwInputError(GLFW_INVALID_VALUE,- "Invalid context robustness mode requested");- return GL_FALSE;+ _glfwInputError(GLFW_INVALID_ENUM,+ "Invalid context robustness mode %i",+ ctxconfig->robustness);+ return GLFW_FALSE; } } @@ -200,13 +144,14 @@ if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE && ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH) {- _glfwInputError(GLFW_INVALID_VALUE,- "Invalid context release behavior requested");- return GL_FALSE;+ _glfwInputError(GLFW_INVALID_ENUM,+ "Invalid context release behavior %i",+ ctxconfig->release);+ return GLFW_FALSE; } } - return GL_TRUE;+ return GLFW_TRUE; } const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,@@ -372,63 +317,159 @@ return closest; } -GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)+GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig) {- _GLFWwindow* window = _glfwPlatformGetCurrentContext();+ int i;+ _GLFWwindow* window;+ const char* version;+ const char* prefixes[] =+ {+ "OpenGL ES-CM ",+ "OpenGL ES-CL ",+ "OpenGL ES ",+ NULL+ }; - if (!parseVersionString(&window->context.api,- &window->context.major,- &window->context.minor,- &window->context.revision))+ window = _glfwPlatformGetCurrentContext();++ window->context.source = ctxconfig->source;+ window->context.client = GLFW_OPENGL_API;++ window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)+ window->context.getProcAddress("glGetIntegerv");+ window->context.GetString = (PFNGLGETSTRINGPROC)+ window->context.getProcAddress("glGetString");+ if (!window->context.GetIntegerv || !window->context.GetString) {- return GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");+ return GLFW_FALSE; } -#if defined(_GLFW_USE_OPENGL)- if (window->context.major > 2)+ version = (const char*) window->context.GetString(GL_VERSION);+ if (!version) {+ if (ctxconfig->client == GLFW_OPENGL_API)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "OpenGL version string retrieval is broken");+ }+ else+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "OpenGL ES version string retrieval is broken");+ }++ return GLFW_FALSE;+ }++ for (i = 0; prefixes[i]; i++)+ {+ const size_t length = strlen(prefixes[i]);++ if (strncmp(version, prefixes[i], length) == 0)+ {+ version += length;+ window->context.client = GLFW_OPENGL_ES_API;+ break;+ }+ }++ if (!sscanf(version, "%d.%d.%d",+ &window->context.major,+ &window->context.minor,+ &window->context.revision))+ {+ if (window->context.client == GLFW_OPENGL_API)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "No version found in OpenGL version string");+ }+ else+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "No version found in OpenGL ES version string");+ }++ return GLFW_FALSE;+ }++ if (window->context.major < ctxconfig->major ||+ (window->context.major == ctxconfig->major &&+ window->context.minor < ctxconfig->minor))+ {+ // The desired OpenGL version is greater than the actual version+ // This only happens if the machine lacks {GLX|WGL}_ARB_create_context+ // /and/ the user has requested an OpenGL version greater than 1.0++ // For API consistency, we emulate the behavior of the+ // {GLX|WGL}_ARB_create_context extension and fail here++ if (window->context.client == GLFW_OPENGL_API)+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "Requested OpenGL version %i.%i, got version %i.%i",+ ctxconfig->major, ctxconfig->minor,+ window->context.major, window->context.minor);+ }+ else+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "Requested OpenGL ES version %i.%i, got version %i.%i",+ ctxconfig->major, ctxconfig->minor,+ window->context.major, window->context.minor);+ }++ return GLFW_FALSE;+ }++ if (window->context.major >= 3)+ { // OpenGL 3.0+ uses a different function for extension string retrieval // We cache it here instead of in glfwExtensionSupported mostly to alert // users as early as possible that their build may be broken - window->GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");- if (!window->GetStringi)+ window->context.GetStringi = (PFNGLGETSTRINGIPROC)+ window->context.getProcAddress("glGetStringi");+ if (!window->context.GetStringi) { _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");- return GL_FALSE;+ return GLFW_FALSE; } } - if (window->context.api == GLFW_OPENGL_API)+ if (window->context.client == GLFW_OPENGL_API) { // Read back context flags (OpenGL 3.0 and above) if (window->context.major >= 3) { GLint flags;- glGetIntegerv(GL_CONTEXT_FLAGS, &flags);+ window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags); if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)- window->context.forward = GL_TRUE;+ window->context.forward = GLFW_TRUE; if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)- window->context.debug = GL_TRUE;+ window->context.debug = GLFW_TRUE; else if (glfwExtensionSupported("GL_ARB_debug_output") && ctxconfig->debug) { // HACK: This is a workaround for older drivers (pre KHR_debug) // not setting the debug bit in the context flags for // debug contexts- window->context.debug = GL_TRUE;+ window->context.debug = GLFW_TRUE; }++ if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)+ window->context.noerror = GLFW_TRUE; } // Read back OpenGL context profile (OpenGL 3.2 and above)- if (window->context.major > 3 ||+ if (window->context.major >= 4 || (window->context.major == 3 && window->context.minor >= 2)) { GLint mask;- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);+ window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;@@ -451,7 +492,8 @@ // only present from 3.0 while the extension applies from 1.1 GLint strategy;- glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);+ window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,+ &strategy); if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB) window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;@@ -468,7 +510,8 @@ // one, so we can reuse them here GLint strategy;- glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);+ window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,+ &strategy); if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB) window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;@@ -480,55 +523,38 @@ if (glfwExtensionSupported("GL_KHR_context_flush_control")) { GLint behavior;- glGetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);+ window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior); if (behavior == GL_NONE) window->context.release = GLFW_RELEASE_BEHAVIOR_NONE; else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH) window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH; }-#endif // _GLFW_USE_OPENGL - return GL_TRUE;-}--GLboolean _glfwIsValidContext(const _GLFWctxconfig* ctxconfig)-{- _GLFWwindow* window = _glfwPlatformGetCurrentContext();-- if (window->context.major < ctxconfig->major ||- (window->context.major == ctxconfig->major &&- window->context.minor < ctxconfig->minor))+ // Clearing the front buffer to black to avoid garbage pixels left over from+ // previous uses of our bit of VRAM {- // The desired OpenGL version is greater than the actual version- // This only happens if the machine lacks {GLX|WGL}_ARB_create_context- // /and/ the user has requested an OpenGL version greater than 1.0-- // For API consistency, we emulate the behavior of the- // {GLX|WGL}_ARB_create_context extension and fail here-- _glfwInputError(GLFW_VERSION_UNAVAILABLE, NULL);- return GL_FALSE;+ PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)+ window->context.getProcAddress("glClear");+ glClear(GL_COLOR_BUFFER_BIT);+ window->context.swapBuffers(window); } - return GL_TRUE;+ return GLFW_TRUE; } -int _glfwStringInExtensionString(const char* string, const GLubyte* extensions)+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions) {- const GLubyte* start;- GLubyte* where;- GLubyte* terminator;+ const char* start = extensions; - // It takes a bit of care to be fool-proof about parsing the- // OpenGL extensions string. Don't be fooled by sub-strings,- // etc.- start = extensions; for (;;) {- where = (GLubyte*) strstr((const char*) start, string);+ const char* where;+ const char* terminator;++ where = strstr(start, string); if (!where)- return GL_FALSE;+ return GLFW_FALSE; terminator = where + strlen(string); if (where == start || *(where - 1) == ' ')@@ -540,7 +566,7 @@ start = terminator; } - return GL_TRUE;+ return GLFW_TRUE; } @@ -551,13 +577,24 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); _GLFW_REQUIRE_INIT(); - if (_glfwPlatformGetCurrentContext() == window)+ if (window && window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); return;+ } - _glfwPlatformMakeContextCurrent(window);+ if (previous)+ {+ if (!window || window->context.source != previous->context.source)+ previous->context.makeCurrent(NULL);+ }++ if (window)+ window->context.makeCurrent(window); } GLFWAPI GLFWwindow* glfwGetCurrentContext(void)@@ -569,43 +606,56 @@ GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT();- _glfwPlatformSwapBuffers(window);++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return;+ }++ window->context.swapBuffers(window); } GLFWAPI void glfwSwapInterval(int interval) {+ _GLFWwindow* window;+ _GLFW_REQUIRE_INIT(); - if (!_glfwPlatformGetCurrentContext())+ window = _glfwPlatformGetCurrentContext();+ if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); return; } - _glfwPlatformSwapInterval(interval);+ window->context.swapInterval(interval); } GLFWAPI int glfwExtensionSupported(const char* extension) { _GLFWwindow* window; - _GLFW_REQUIRE_INIT_OR_RETURN(GL_FALSE);+ assert(extension != NULL); + _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);+ window = _glfwPlatformGetCurrentContext(); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);- return GL_FALSE;+ return GLFW_FALSE; } if (*extension == '\0') {- _glfwInputError(GLFW_INVALID_VALUE, NULL);- return GL_FALSE;+ _glfwInputError(GLFW_INVALID_VALUE, "Extension name is empty string");+ return GLFW_FALSE; } -#if defined(_GLFW_USE_OPENGL) if (window->context.major >= 3) { int i;@@ -613,53 +663,58 @@ // Check if extension is in the modern OpenGL extensions string list - glGetIntegerv(GL_NUM_EXTENSIONS, &count);+ window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count); for (i = 0; i < count; i++) {- const char* en = (const char*) window->GetStringi(GL_EXTENSIONS, i);+ const char* en = (const char*)+ window->context.GetStringi(GL_EXTENSIONS, i); if (!en) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Failed to retrieve extension string %i", i);- return GL_FALSE;+ "Extension string retrieval is broken");+ return GLFW_FALSE; } if (strcmp(en, extension) == 0)- return GL_TRUE;+ return GLFW_TRUE; } } else-#endif // _GLFW_USE_OPENGL { // Check if extension is in the old style OpenGL extensions string - const GLubyte* extensions = glGetString(GL_EXTENSIONS);+ const char* extensions = (const char*)+ window->context.GetString(GL_EXTENSIONS); if (!extensions) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Failed to retrieve extension string");- return GL_FALSE;+ "Extension string retrieval is broken");+ return GLFW_FALSE; } if (_glfwStringInExtensionString(extension, extensions))- return GL_TRUE;+ return GLFW_TRUE; } // Check if extension is in the platform-specific string- return _glfwPlatformExtensionSupported(extension);+ return window->context.extensionSupported(extension); } GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) {+ _GLFWwindow* window;+ assert(procname != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - if (!_glfwPlatformGetCurrentContext())+ window = _glfwPlatformGetCurrentContext();+ if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); return NULL; } - return _glfwPlatformGetProcAddress(procname);+ return window->context.getProcAddress(procname); }
glfw/src/egl_context.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 EGL - www.glfw.org+// GLFW 3.2 EGL - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -28,13 +28,14 @@ #include "internal.h" #include <stdio.h>+#include <string.h> #include <stdlib.h> #include <assert.h> // Return a description of the specified EGL error //-static const char* getErrorString(EGLint error)+static const char* getEGLErrorString(EGLint error) { switch (error) {@@ -47,54 +48,46 @@ case EGL_BAD_ALLOC: return "EGL failed to allocate resources for the requested operation"; case EGL_BAD_ATTRIBUTE:- return "An unrecognized attribute or attribute value was passed "- "in the attribute list";+ return "An unrecognized attribute or attribute value was passed in the attribute list"; case EGL_BAD_CONTEXT:- return "An EGLContext argument does not name a valid EGL "- "rendering context";+ return "An EGLContext argument does not name a valid EGL rendering context"; case EGL_BAD_CONFIG:- return "An EGLConfig argument does not name a valid EGL frame "- "buffer configuration";+ return "An EGLConfig argument does not name a valid EGL frame buffer configuration"; case EGL_BAD_CURRENT_SURFACE:- return "The current surface of the calling thread is a window, pixel "- "buffer or pixmap that is no longer valid";+ return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid"; case EGL_BAD_DISPLAY:- return "An EGLDisplay argument does not name a valid EGL display "- "connection";+ return "An EGLDisplay argument does not name a valid EGL display connection"; case EGL_BAD_SURFACE:- return "An EGLSurface argument does not name a valid surface "- "configured for GL rendering";+ return "An EGLSurface argument does not name a valid surface configured for GL rendering"; case EGL_BAD_MATCH: return "Arguments are inconsistent"; case EGL_BAD_PARAMETER: return "One or more argument values are invalid"; case EGL_BAD_NATIVE_PIXMAP:- return "A NativePixmapType argument does not refer to a valid "- "native pixmap";+ return "A NativePixmapType argument does not refer to a valid native pixmap"; case EGL_BAD_NATIVE_WINDOW:- return "A NativeWindowType argument does not refer to a valid "- "native window";+ return "A NativeWindowType argument does not refer to a valid native window"; case EGL_CONTEXT_LOST: return "The application must destroy all contexts and reinitialise";+ default:+ return "ERROR: UNKNOWN EGL ERROR"; }-- return "UNKNOWN EGL ERROR"; } // Returns the specified attribute of the specified EGLConfig //-static int getConfigAttrib(EGLConfig config, int attrib)+static int getEGLConfigAttrib(EGLConfig config, int attrib) { int value; eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value); return value; } -// Return a list of available and usable framebuffer configs+// Return the EGLConfig most closely matching the specified hints //-static GLboolean chooseFBConfigs(const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* desired,- EGLConfig* result)+static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* desired,+ EGLConfig* result) { EGLConfig* nativeConfigs; _GLFWfbconfig* usableConfigs;@@ -105,7 +98,7 @@ if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");- return GL_FALSE;+ return GLFW_FALSE; } nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));@@ -119,114 +112,312 @@ const EGLConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; -#if defined(_GLFW_X11)- if (!getConfigAttrib(n, EGL_NATIVE_VISUAL_ID))- {- // Only consider EGLConfigs with associated visuals+ // Only consider RGB(A) EGLConfigs+ if (!(getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) continue;- }-#endif // _GLFW_X11 - if (!(getConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER))- {- // Only consider RGB(A) EGLConfigs+ // Only consider window EGLConfigs+ if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) continue;- } - if (!(getConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))- {- // Only consider window EGLConfigs+#if defined(_GLFW_X11)+ // Only consider EGLConfigs with associated Visuals+ if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID)) continue;- }+#endif // _GLFW_X11 - if (ctxconfig->api == GLFW_OPENGL_ES_API)+ if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major == 1) {- if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) continue; } else {- if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) continue; } }- else if (ctxconfig->api == GLFW_OPENGL_API)+ else if (ctxconfig->client == GLFW_OPENGL_API) {- if (!(getConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))+ if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) continue; } - u->redBits = getConfigAttrib(n, EGL_RED_SIZE);- u->greenBits = getConfigAttrib(n, EGL_GREEN_SIZE);- u->blueBits = getConfigAttrib(n, EGL_BLUE_SIZE);+ u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);+ u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);+ u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE); - u->alphaBits = getConfigAttrib(n, EGL_ALPHA_SIZE);- u->depthBits = getConfigAttrib(n, EGL_DEPTH_SIZE);- u->stencilBits = getConfigAttrib(n, EGL_STENCIL_SIZE);+ u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);+ u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);+ u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); - u->samples = getConfigAttrib(n, EGL_SAMPLES);- u->doublebuffer = GL_TRUE;+ u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);+ u->doublebuffer = GLFW_TRUE; - u->egl = n;+ u->handle = (uintptr_t) n; usableCount++; } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest)- *result = closest->egl;+ *result = (EGLConfig) closest->handle; free(nativeConfigs); free(usableConfigs); - return closest ? GL_TRUE : GL_FALSE;+ return closest != NULL; } +static void makeContextCurrentEGL(_GLFWwindow* window)+{+ if (window)+ {+ if (!eglMakeCurrent(_glfw.egl.display,+ window->context.egl.surface,+ window->context.egl.surface,+ window->context.egl.handle))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: Failed to make context current: %s",+ getEGLErrorString(eglGetError()));+ return;+ }+ }+ else+ {+ if (!eglMakeCurrent(_glfw.egl.display,+ EGL_NO_SURFACE,+ EGL_NO_SURFACE,+ EGL_NO_CONTEXT))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: Failed to clear current context: %s",+ getEGLErrorString(eglGetError()));+ return;+ }+ } + _glfwPlatformSetCurrentContext(window);+}++static void swapBuffersEGL(_GLFWwindow* window)+{+ if (window != _glfwPlatformGetCurrentContext())+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: The context must be current on the calling thread when swapping buffers");+ return;+ }++ eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);+}++static void swapIntervalEGL(int interval)+{+ eglSwapInterval(_glfw.egl.display, interval);+}++static int extensionSupportedEGL(const char* extension)+{+ const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);+ if (extensions)+ {+ if (_glfwStringInExtensionString(extension, extensions))+ return GLFW_TRUE;+ }++ return GLFW_FALSE;+}++static GLFWglproc getProcAddressEGL(const char* procname)+{+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();++ if (window->context.egl.client)+ {+ GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,+ procname);+ if (proc)+ return proc;+ }++ return eglGetProcAddress(procname);+}++static void destroyContextEGL(_GLFWwindow* window)+{+#if defined(_GLFW_X11)+ // NOTE: Do not unload libGL.so.1 while the X11 display is still open,+ // as it will make XCloseDisplay segfault+ if (window->context.client != GLFW_OPENGL_API)+#endif // _GLFW_X11+ {+ if (window->context.egl.client)+ {+ _glfw_dlclose(window->context.egl.client);+ window->context.egl.client = NULL;+ }+ }++ if (window->context.egl.surface)+ {+ eglDestroySurface(_glfw.egl.display, window->context.egl.surface);+ window->context.egl.surface = EGL_NO_SURFACE;+ }++ if (window->context.egl.handle)+ {+ eglDestroyContext(_glfw.egl.display, window->context.egl.handle);+ window->context.egl.handle = EGL_NO_CONTEXT;+ }+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialize EGL //-int _glfwInitContextAPI(void)+GLFWbool _glfwInitEGL(void) {- if (!_glfwInitTLS())- return GL_FALSE;+ int i;+ const char* sonames[] =+ {+#if defined(_GLFW_WIN32)+ "libEGL.dll",+ "EGL.dll",+#elif defined(_GLFW_COCOA)+ "libEGL.dylib",+#else+ "libEGL.so.1",+#endif+ NULL+ }; - _glfw.egl.display = eglGetDisplay((EGLNativeDisplayType)_GLFW_EGL_NATIVE_DISPLAY);+ if (_glfw.egl.handle)+ return GLFW_TRUE;++ for (i = 0; sonames[i]; i++)+ {+ _glfw.egl.handle = _glfw_dlopen(sonames[i]);+ if (_glfw.egl.handle)+ break;+ }++ if (!_glfw.egl.handle)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");+ return GLFW_FALSE;+ }++ _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);++ _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");+ _glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");+ _glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");+ _glfw.egl.GetError = (PFNEGLGETERRORPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglGetError");+ _glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglInitialize");+ _glfw.egl.Terminate = (PFNEGLTERMINATEPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglTerminate");+ _glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");+ _glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");+ _glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");+ _glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");+ _glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");+ _glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");+ _glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");+ _glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");+ _glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglQueryString");+ _glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)+ _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");++ if (!_glfw.egl.GetConfigAttrib ||+ !_glfw.egl.GetConfigs ||+ !_glfw.egl.GetDisplay ||+ !_glfw.egl.GetError ||+ !_glfw.egl.Initialize ||+ !_glfw.egl.Terminate ||+ !_glfw.egl.BindAPI ||+ !_glfw.egl.CreateContext ||+ !_glfw.egl.DestroySurface ||+ !_glfw.egl.DestroyContext ||+ !_glfw.egl.CreateWindowSurface ||+ !_glfw.egl.MakeCurrent ||+ !_glfw.egl.SwapBuffers ||+ !_glfw.egl.SwapInterval ||+ !_glfw.egl.QueryString ||+ !_glfw.egl.GetProcAddress)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: Failed to load required entry points");++ _glfwTerminateEGL();+ return GLFW_FALSE;+ }++ _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); if (_glfw.egl.display == EGL_NO_DISPLAY) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to get EGL display: %s",- getErrorString(eglGetError()));- return GL_FALSE;+ getEGLErrorString(eglGetError()));++ _glfwTerminateEGL();+ return GLFW_FALSE; } - if (!eglInitialize(_glfw.egl.display,- &_glfw.egl.versionMajor,- &_glfw.egl.versionMinor))+ if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL: %s",- getErrorString(eglGetError()));- return GL_FALSE;+ getEGLErrorString(eglGetError()));++ _glfwTerminateEGL();+ return GLFW_FALSE; } - if (_glfwPlatformExtensionSupported("EGL_KHR_create_context"))- _glfw.egl.KHR_create_context = GL_TRUE;+ _glfw.egl.KHR_create_context =+ extensionSupportedEGL("EGL_KHR_create_context");+ _glfw.egl.KHR_create_context_no_error =+ extensionSupportedEGL("EGL_KHR_create_context_no_error");+ _glfw.egl.KHR_gl_colorspace =+ extensionSupportedEGL("EGL_KHR_gl_colorspace"); - return GL_TRUE;+ return GLFW_TRUE; } // Terminate EGL //-void _glfwTerminateContextAPI(void)+void _glfwTerminateEGL(void) {- eglTerminate(_glfw.egl.display);+ if (_glfw.egl.display)+ {+ eglTerminate(_glfw.egl.display);+ _glfw.egl.display = EGL_NO_DISPLAY;+ } - _glfwTerminateTLS();+ if (_glfw.egl.handle)+ {+ _glfw_dlclose(_glfw.egl.handle);+ _glfw.egl.handle = NULL;+ } } #define setEGLattrib(attribName, attribValue) \@@ -238,118 +429,87 @@ // Create the OpenGL or OpenGL ES context //-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig) {- int attribs[40];+ EGLint attribs[40]; EGLConfig config; EGLContext share = NULL; + if (!_glfw.egl.display)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");+ return GLFW_FALSE;+ }+ if (ctxconfig->share)- share = ctxconfig->share->egl.context;+ share = ctxconfig->share->context.egl.handle; - if (!chooseFBConfigs(ctxconfig, fbconfig, &config))+ if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Failed to find a suitable EGLConfig");- return GL_FALSE;+ return GLFW_FALSE; } -#if defined(_GLFW_X11)- // Retrieve the visual corresponding to the chosen EGL config- {- EGLint count = 0;- int mask;- EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0;- XVisualInfo info;-- eglGetConfigAttrib(_glfw.egl.display, config,- EGL_NATIVE_VISUAL_ID, &visualID);-- info.screen = _glfw.x11.screen;- mask = VisualScreenMask;-- if (visualID)- {- // The X window visual must match the EGL config- info.visualid = visualID;- mask |= VisualIDMask;- }- else- {- // some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID- // attribute, so attempt to find the closest match.-- eglGetConfigAttrib(_glfw.egl.display, config,- EGL_RED_SIZE, &redBits);- eglGetConfigAttrib(_glfw.egl.display, config,- EGL_GREEN_SIZE, &greenBits);- eglGetConfigAttrib(_glfw.egl.display, config,- EGL_BLUE_SIZE, &blueBits);- eglGetConfigAttrib(_glfw.egl.display, config,- EGL_ALPHA_SIZE, &alphaBits);-- info.depth = redBits + greenBits + blueBits + alphaBits;- mask |= VisualDepthMask;- }-- window->egl.visual = XGetVisualInfo(_glfw.x11.display,- mask, &info, &count);- if (!window->egl.visual)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "EGL: Failed to retrieve visual for EGLConfig");- return GL_FALSE;- }- }-#endif // _GLFW_X11-- if (ctxconfig->api == GLFW_OPENGL_ES_API)+ if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!eglBindAPI(EGL_OPENGL_ES_API)) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL ES: %s",- getErrorString(eglGetError()));- return GL_FALSE;+ getEGLErrorString(eglGetError()));+ return GLFW_FALSE; } } else { if (!eglBindAPI(EGL_OPENGL_API)) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL: %s",- getErrorString(eglGetError()));- return GL_FALSE;+ getEGLErrorString(eglGetError()));+ return GLFW_FALSE; } } if (_glfw.egl.KHR_create_context) {- int index = 0, mask = 0, flags = 0, strategy = 0;+ int index = 0, mask = 0, flags = 0; - if (ctxconfig->api == GLFW_OPENGL_API)+ if (ctxconfig->client == GLFW_OPENGL_API) {+ if (ctxconfig->forward)+ flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; - if (ctxconfig->forward)- flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;-- if (ctxconfig->debug)- flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;+ if (_glfw.egl.KHR_create_context_no_error)+ {+ if (ctxconfig->noerror)+ flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;+ } } + if (ctxconfig->debug)+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;+ if (ctxconfig->robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)- strategy = EGL_NO_RESET_NOTIFICATION_KHR;+ {+ setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,+ EGL_NO_RESET_NOTIFICATION_KHR);+ } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)- strategy = EGL_LOSE_CONTEXT_ON_RESET_KHR;+ {+ setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,+ EGL_LOSE_CONTEXT_ON_RESET_KHR);+ } flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; }@@ -366,16 +526,13 @@ if (flags) setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags); - if (strategy)- setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, strategy);- setEGLattrib(EGL_NONE, EGL_NONE); } else { int index = 0; - if (ctxconfig->api == GLFW_OPENGL_ES_API)+ if (ctxconfig->client == GLFW_OPENGL_ES_API) setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_NONE, EGL_NONE);@@ -384,127 +541,169 @@ // Context release behaviors (GL_KHR_context_flush_control) are not yet // supported on EGL but are not a hard constraint, so ignore and continue - window->egl.context = eglCreateContext(_glfw.egl.display,- config, share, attribs);+ window->context.egl.handle = eglCreateContext(_glfw.egl.display,+ config, share, attribs); - if (window->egl.context == EGL_NO_CONTEXT)+ if (window->context.egl.handle == EGL_NO_CONTEXT) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: Failed to create context: %s",- getErrorString(eglGetError()));- return GL_FALSE;+ getEGLErrorString(eglGetError()));+ return GLFW_FALSE; } - window->egl.config = config;-- return GL_TRUE;-}+ // Set up attributes for surface creation+ {+ int index = 0; -#undef setEGLattrib+ if (fbconfig->sRGB)+ {+ if (_glfw.egl.KHR_gl_colorspace)+ {+ setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);+ }+ } -// Destroy the OpenGL context-//-void _glfwDestroyContext(_GLFWwindow* window)-{-#if defined(_GLFW_X11)- if (window->egl.visual)- {- XFree(window->egl.visual);- window->egl.visual = NULL;+ setEGLattrib(EGL_NONE, EGL_NONE); }-#endif // _GLFW_X11 - if (window->egl.surface)+ window->context.egl.surface =+ eglCreateWindowSurface(_glfw.egl.display,+ config,+ _GLFW_EGL_NATIVE_WINDOW,+ attribs);+ if (window->context.egl.surface == EGL_NO_SURFACE) {- eglDestroySurface(_glfw.egl.display, window->egl.surface);- window->egl.surface = EGL_NO_SURFACE;+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: Failed to create window surface: %s",+ getEGLErrorString(eglGetError()));+ return GLFW_FALSE; } - if (window->egl.context)- {- eglDestroyContext(_glfw.egl.display, window->egl.context);- window->egl.context = EGL_NO_CONTEXT;- }-}+ window->context.egl.config = config; -// Analyzes the specified context for possible recreation-//-int _glfwAnalyzeContext(const _GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)-{+ // Load the appropriate client library+ {+ int i;+ const char** sonames;+ const char* es1sonames[] =+ { #if defined(_GLFW_WIN32)- return _GLFW_RECREATION_NOT_NEEDED;+ "GLESv1_CM.dll",+ "libGLES_CM.dll",+#elif defined(_GLFW_COCOA)+ "libGLESv1_CM.dylib", #else- return 0;+ "libGLESv1_CM.so.1",+ "libGLES_CM.so.1", #endif-}-+ NULL+ };+ const char* es2sonames[] =+ {+#if defined(_GLFW_WIN32)+ "GLESv2.dll",+ "libGLESv2.dll",+#elif defined(_GLFW_COCOA)+ "libGLESv2.dylib",+#else+ "libGLESv2.so.2",+#endif+ NULL+ };+ const char* glsonames[] =+ {+#if defined(_GLFW_WIN32)+#elif defined(_GLFW_COCOA)+#else+ "libGL.so.1",+#endif+ NULL+ }; -//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////+ if (ctxconfig->client == GLFW_OPENGL_ES_API)+ {+ if (ctxconfig->major == 1)+ sonames = es1sonames;+ else+ sonames = es2sonames;+ }+ else+ sonames = glsonames; -void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)-{- if (window)- {- if (window->egl.surface == EGL_NO_SURFACE)+ for (i = 0; sonames[i]; i++) {- window->egl.surface = eglCreateWindowSurface(_glfw.egl.display,- window->egl.config,- (EGLNativeWindowType)_GLFW_EGL_NATIVE_WINDOW,- NULL);- if (window->egl.surface == EGL_NO_SURFACE)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "EGL: Failed to create window surface: %s",- getErrorString(eglGetError()));- }+ // HACK: Match presence of lib prefix to increase chance of finding+ // a matching pair in the jungle that is Win32 EGL/GLES+ if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0))+ continue;++ window->context.egl.client = _glfw_dlopen(sonames[i]);+ if (window->context.egl.client)+ break; } - eglMakeCurrent(_glfw.egl.display,- window->egl.surface,- window->egl.surface,- window->egl.context);- }- else- {- eglMakeCurrent(_glfw.egl.display,- EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);+ if (!window->context.egl.client)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "EGL: Failed to load client library");+ return GLFW_FALSE;+ } } - _glfwSetCurrentContext(window);-}+ window->context.makeCurrent = makeContextCurrentEGL;+ window->context.swapBuffers = swapBuffersEGL;+ window->context.swapInterval = swapIntervalEGL;+ window->context.extensionSupported = extensionSupportedEGL;+ window->context.getProcAddress = getProcAddressEGL;+ window->context.destroy = destroyContextEGL; -void _glfwPlatformSwapBuffers(_GLFWwindow* window)-{- eglSwapBuffers(_glfw.egl.display, window->egl.surface);+ return GLFW_TRUE; } -void _glfwPlatformSwapInterval(int interval)-{- eglSwapInterval(_glfw.egl.display, interval);-}+#undef setEGLattrib -int _glfwPlatformExtensionSupported(const char* extension)+// Returns the Visual and depth of the chosen EGLConfig+//+#if defined(_GLFW_X11)+GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig,+ Visual** visual, int* depth) {- const char* extensions;+ XVisualInfo* result;+ XVisualInfo desired;+ EGLConfig native;+ EGLint visualID = 0, count = 0;+ const long vimask = VisualScreenMask | VisualIDMask; - extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);- if (extensions != NULL)+ if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) {- if (_glfwStringInExtensionString(extension, (unsigned char*) extensions))- return GL_TRUE;+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "EGL: Failed to find a suitable EGLConfig");+ return GLFW_FALSE; } - return GL_FALSE;-}+ eglGetConfigAttrib(_glfw.egl.display, native,+ EGL_NATIVE_VISUAL_ID, &visualID); -GLFWglproc _glfwPlatformGetProcAddress(const char* procname)-{- return eglGetProcAddress(procname);+ desired.screen = _glfw.x11.screen;+ desired.visualid = visualID;++ result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count);+ if (!result)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "EGL: Failed to retrieve Visual for EGLConfig");+ return GLFW_FALSE;+ }++ *visual = result->visual;+ *depth = result->depth;++ XFree(result);+ return GLFW_TRUE; }+#endif // _GLFW_X11 //////////////////////////////////////////////////////////////////////////@@ -521,13 +720,27 @@ { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_CONTEXT);- return window->egl.context;++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return EGL_NO_CONTEXT;+ }++ return window->context.egl.handle; } GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_SURFACE);- return window->egl.surface;++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return EGL_NO_SURFACE;+ }++ return window->context.egl.surface; }
glfw/src/egl_context.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 EGL - www.glfw.org+// GLFW 3.2 EGL - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,61 +25,189 @@ // //======================================================================== -#ifndef _egl_context_h_-#define _egl_context_h_+#ifndef _glfw3_egl_context_h_+#define _glfw3_egl_context_h_ -#include <EGL/egl.h>+#if defined(_GLFW_USE_EGLPLATFORM_H)+ #include <EGL/eglplatform.h>+#elif defined(_GLFW_WIN32)+ #define EGLAPIENTRY __stdcall+typedef HDC EGLNativeDisplayType;+typedef HWND EGLNativeWindowType;+#elif defined(_GLFW_X11)+ #define EGLAPIENTRY+typedef Display* EGLNativeDisplayType;+typedef Window EGLNativeWindowType;+#elif defined(_GLFW_WAYLAND)+ #define EGLAPIENTRY+typedef struct wl_display* EGLNativeDisplayType;+typedef struct wl_egl_window* EGLNativeWindowType;+#elif defined(_GLFW_MIR)+ #define EGLAPIENTRY+typedef MirEGLNativeDisplayType EGLNativeDisplayType;+typedef MirEGLNativeWindowType EGLNativeWindowType;+#else+ #error "No supported EGL platform selected"+#endif -// This path may need to be changed if you build GLFW using your own setup-// We ship and use our own copy of eglext.h since GLFW uses fairly new-// extensions and not all operating systems come with an up-to-date version-#include "../deps/EGL/eglext.h"+#define EGL_SUCCESS 0x3000+#define EGL_NOT_INITIALIZED 0x3001+#define EGL_BAD_ACCESS 0x3002+#define EGL_BAD_ALLOC 0x3003+#define EGL_BAD_ATTRIBUTE 0x3004+#define EGL_BAD_CONFIG 0x3005+#define EGL_BAD_CONTEXT 0x3006+#define EGL_BAD_CURRENT_SURFACE 0x3007+#define EGL_BAD_DISPLAY 0x3008+#define EGL_BAD_MATCH 0x3009+#define EGL_BAD_NATIVE_PIXMAP 0x300a+#define EGL_BAD_NATIVE_WINDOW 0x300b+#define EGL_BAD_PARAMETER 0x300c+#define EGL_BAD_SURFACE 0x300d+#define EGL_CONTEXT_LOST 0x300e+#define EGL_COLOR_BUFFER_TYPE 0x303f+#define EGL_RGB_BUFFER 0x308e+#define EGL_SURFACE_TYPE 0x3033+#define EGL_WINDOW_BIT 0x0004+#define EGL_RENDERABLE_TYPE 0x3040+#define EGL_OPENGL_ES_BIT 0x0001+#define EGL_OPENGL_ES2_BIT 0x0004+#define EGL_OPENGL_BIT 0x0008+#define EGL_ALPHA_SIZE 0x3021+#define EGL_BLUE_SIZE 0x3022+#define EGL_GREEN_SIZE 0x3023+#define EGL_RED_SIZE 0x3024+#define EGL_DEPTH_SIZE 0x3025+#define EGL_STENCIL_SIZE 0x3026+#define EGL_SAMPLES 0x3031+#define EGL_OPENGL_ES_API 0x30a0+#define EGL_OPENGL_API 0x30a2+#define EGL_NONE 0x3038+#define EGL_EXTENSIONS 0x3055+#define EGL_CONTEXT_CLIENT_VERSION 0x3098+#define EGL_NATIVE_VISUAL_ID 0x302e+#define EGL_NO_SURFACE ((EGLSurface) 0)+#define EGL_NO_DISPLAY ((EGLDisplay) 0)+#define EGL_NO_CONTEXT ((EGLContext) 0)+#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType) 0) -// Do we have support for dlopen/dlsym?-#if defined(_GLFW_HAS_DLOPEN)- #include <dlfcn.h>-#endif+#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002+#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001+#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002+#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001+#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31bd+#define EGL_NO_RESET_NOTIFICATION_KHR 0x31be+#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31bf+#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004+#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098+#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30fb+#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30fd+#define EGL_CONTEXT_FLAGS_KHR 0x30fc+#define EGL_CONTEXT_OPENGL_NO_ERROR_KHR 0x31b3+#define EGL_GL_COLORSPACE_KHR 0x309d+#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 -#define _GLFW_PLATFORM_FBCONFIG EGLConfig egl-#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL egl-#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl+typedef int EGLint;+typedef unsigned int EGLBoolean;+typedef unsigned int EGLenum;+typedef void* EGLConfig;+typedef void* EGLContext;+typedef void* EGLDisplay;+typedef void* EGLSurface; +// EGL function pointer typedefs+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);+typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);+typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);+typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);+typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);+typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);+typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);+#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib+#define eglGetConfigs _glfw.egl.GetConfigs+#define eglGetDisplay _glfw.egl.GetDisplay+#define eglGetError _glfw.egl.GetError+#define eglInitialize _glfw.egl.Initialize+#define eglTerminate _glfw.egl.Terminate+#define eglBindAPI _glfw.egl.BindAPI+#define eglCreateContext _glfw.egl.CreateContext+#define eglDestroySurface _glfw.egl.DestroySurface+#define eglDestroyContext _glfw.egl.DestroyContext+#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface+#define eglMakeCurrent _glfw.egl.MakeCurrent+#define eglSwapBuffers _glfw.egl.SwapBuffers+#define eglSwapInterval _glfw.egl.SwapInterval+#define eglQueryString _glfw.egl.QueryString+#define eglGetProcAddress _glfw.egl.GetProcAddress +#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl++ // EGL-specific per-context data // typedef struct _GLFWcontextEGL {- EGLConfig config;- EGLContext context;- EGLSurface surface;+ EGLConfig config;+ EGLContext handle;+ EGLSurface surface; -#if defined(_GLFW_X11)- XVisualInfo* visual;-#endif+ void* client; } _GLFWcontextEGL; - // EGL-specific global data // typedef struct _GLFWlibraryEGL { EGLDisplay display;- EGLint versionMajor, versionMinor;+ EGLint major, minor;+ GLFWbool prefix; - GLboolean KHR_create_context;+ GLFWbool KHR_create_context;+ GLFWbool KHR_create_context_no_error;+ GLFWbool KHR_gl_colorspace; + void* handle;++ PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;+ PFNEGLGETCONFIGSPROC GetConfigs;+ PFNEGLGETDISPLAYPROC GetDisplay;+ PFNEGLGETERRORPROC GetError;+ PFNEGLINITIALIZEPROC Initialize;+ PFNEGLTERMINATEPROC Terminate;+ PFNEGLBINDAPIPROC BindAPI;+ PFNEGLCREATECONTEXTPROC CreateContext;+ PFNEGLDESTROYSURFACEPROC DestroySurface;+ PFNEGLDESTROYCONTEXTPROC DestroyContext;+ PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;+ PFNEGLMAKECURRENTPROC MakeCurrent;+ PFNEGLSWAPBUFFERSPROC SwapBuffers;+ PFNEGLSWAPINTERVALPROC SwapInterval;+ PFNEGLQUERYSTRINGPROC QueryString;+ PFNEGLGETPROCADDRESSPROC GetProcAddress;+ } _GLFWlibraryEGL; -int _glfwInitContextAPI(void);-void _glfwTerminateContextAPI(void);-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);-void _glfwDestroyContext(_GLFWwindow* window);-int _glfwAnalyzeContext(const _GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);+GLFWbool _glfwInitEGL(void);+void _glfwTerminateEGL(void);+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig);+#if defined(_GLFW_X11)+GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig,+ Visual** visual, int* depth);+#endif /*_GLFW_X11*/ -#endif // _egl_context_h_+#endif // _glfw3_egl_context_h_
glfw/src/glx_context.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 GLX - www.glfw.org+// GLFW 3.2 GLX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -31,11 +31,6 @@ #include <stdlib.h> #include <assert.h> --// This is the only glXGetProcAddress variant not declared by glxext.h-void (*glXGetProcAddressEXT(const GLubyte* procName))();-- #ifndef GLXBadProfileARB #define GLXBadProfileARB 13 #endif@@ -43,38 +38,36 @@ // Returns the specified attribute of the specified GLXFBConfig //-static int getFBConfigAttrib(GLXFBConfig fbconfig, int attrib)+static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib) { int value; glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value); return value; } -// Return a list of available and usable framebuffer configs+// Return the GLXFBConfig most closely matching the specified hints //-static GLboolean chooseFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result)+static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired, GLXFBConfig* result) { GLXFBConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; int i, nativeCount, usableCount; const char* vendor;- GLboolean trustWindowBit = GL_TRUE;+ GLFWbool trustWindowBit = GLFW_TRUE; + // HACK: This is a (hopefully temporary) workaround for Chromium+ // (VirtualBox GL) not setting the window bit on any GLXFBConfigs vendor = glXGetClientString(_glfw.x11.display, GLX_VENDOR); if (strcmp(vendor, "Chromium") == 0)- {- // HACK: This is a (hopefully temporary) workaround for Chromium- // (VirtualBox GL) not setting the window bit on any GLXFBConfigs- trustWindowBit = GL_FALSE;- }+ trustWindowBit = GLFW_FALSE; - nativeConfigs = glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen,- &nativeCount);+ nativeConfigs =+ glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount); if (!nativeCount) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");- return GL_FALSE;+ return GLFW_FALSE; } usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));@@ -85,72 +78,62 @@ const GLXFBConfig n = nativeConfigs[i]; _GLFWfbconfig* u = usableConfigs + usableCount; - if (!getFBConfigAttrib(n, GLX_VISUAL_ID))- {- // Only consider GLXFBConfigs with associated visuals+ // Only consider RGBA GLXFBConfigs+ if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT)) continue;- } - if (!(getFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))- {- // Only consider RGBA GLXFBConfigs- continue;- }-- if (!(getFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))+ // Only consider window GLXFBConfigs+ if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT)) { if (trustWindowBit)- {- // Only consider window GLXFBConfigs continue;- } } - u->redBits = getFBConfigAttrib(n, GLX_RED_SIZE);- u->greenBits = getFBConfigAttrib(n, GLX_GREEN_SIZE);- u->blueBits = getFBConfigAttrib(n, GLX_BLUE_SIZE);+ u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);+ u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);+ u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE); - u->alphaBits = getFBConfigAttrib(n, GLX_ALPHA_SIZE);- u->depthBits = getFBConfigAttrib(n, GLX_DEPTH_SIZE);- u->stencilBits = getFBConfigAttrib(n, GLX_STENCIL_SIZE);+ u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);+ u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);+ u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_SIZE); - u->accumRedBits = getFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);- u->accumGreenBits = getFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);- u->accumBlueBits = getFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);- u->accumAlphaBits = getFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE);+ u->accumRedBits = getGLXFBConfigAttrib(n, GLX_ACCUM_RED_SIZE);+ u->accumGreenBits = getGLXFBConfigAttrib(n, GLX_ACCUM_GREEN_SIZE);+ u->accumBlueBits = getGLXFBConfigAttrib(n, GLX_ACCUM_BLUE_SIZE);+ u->accumAlphaBits = getGLXFBConfigAttrib(n, GLX_ACCUM_ALPHA_SIZE); - u->auxBuffers = getFBConfigAttrib(n, GLX_AUX_BUFFERS);+ u->auxBuffers = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS); - if (getFBConfigAttrib(n, GLX_STEREO))- u->stereo = GL_TRUE;- if (getFBConfigAttrib(n, GLX_DOUBLEBUFFER))- u->doublebuffer = GL_TRUE;+ if (getGLXFBConfigAttrib(n, GLX_STEREO))+ u->stereo = GLFW_TRUE;+ if (getGLXFBConfigAttrib(n, GLX_DOUBLEBUFFER))+ u->doublebuffer = GLFW_TRUE; if (_glfw.glx.ARB_multisample)- u->samples = getFBConfigAttrib(n, GLX_SAMPLES);+ u->samples = getGLXFBConfigAttrib(n, GLX_SAMPLES); - if (_glfw.glx.ARB_framebuffer_sRGB)- u->sRGB = getFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);+ if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)+ u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB); - u->glx = n;+ u->handle = (uintptr_t) n; usableCount++; } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (closest)- *result = closest->glx;+ *result = (GLXFBConfig) closest->handle; XFree(nativeConfigs); free(usableConfigs); - return closest ? GL_TRUE : GL_FALSE;+ return closest != NULL; } // Create the OpenGL context using legacy API //-static GLXContext createLegacyContext(_GLFWwindow* window,- GLXFBConfig fbconfig,- GLXContext share)+static GLXContext createLegacyContextGLX(_GLFWwindow* window,+ GLXFBConfig fbconfig,+ GLXContext share) { return glXCreateNewContext(_glfw.x11.display, fbconfig,@@ -159,122 +142,279 @@ True); } +static void makeContextCurrentGLX(_GLFWwindow* window)+{+ if (window)+ {+ if (!glXMakeCurrent(_glfw.x11.display,+ window->context.glx.window,+ window->context.glx.handle))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "GLX: Failed to make context current");+ return;+ }+ }+ else+ {+ if (!glXMakeCurrent(_glfw.x11.display, None, NULL))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "GLX: Failed to clear current context");+ return;+ }+ } + _glfwPlatformSetCurrentContext(window);+}++static void swapBuffersGLX(_GLFWwindow* window)+{+ glXSwapBuffers(_glfw.x11.display, window->context.glx.window);+}++static void swapIntervalGLX(int interval)+{+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();++ if (_glfw.glx.EXT_swap_control)+ {+ _glfw.glx.SwapIntervalEXT(_glfw.x11.display,+ window->context.glx.window,+ interval);+ }+ else if (_glfw.glx.MESA_swap_control)+ _glfw.glx.SwapIntervalMESA(interval);+ else if (_glfw.glx.SGI_swap_control)+ {+ if (interval > 0)+ _glfw.glx.SwapIntervalSGI(interval);+ }+}++static int extensionSupportedGLX(const char* extension)+{+ const char* extensions =+ glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);+ if (extensions)+ {+ if (_glfwStringInExtensionString(extension, extensions))+ return GLFW_TRUE;+ }++ return GLFW_FALSE;+}++static GLFWglproc getProcAddressGLX(const char* procname)+{+ if (_glfw.glx.GetProcAddress)+ return _glfw.glx.GetProcAddress((const GLubyte*) procname);+ else if (_glfw.glx.GetProcAddressARB)+ return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);+ else+ return dlsym(_glfw.glx.handle, procname);+}++// Destroy the OpenGL context+//+static void destroyContextGLX(_GLFWwindow* window)+{+ if (window->context.glx.window)+ {+ glXDestroyWindow(_glfw.x11.display, window->context.glx.window);+ window->context.glx.window = None;+ }++ if (window->context.glx.handle)+ {+ glXDestroyContext(_glfw.x11.display, window->context.glx.handle);+ window->context.glx.handle = NULL;+ }+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialize GLX //-int _glfwInitContextAPI(void)+GLFWbool _glfwInitGLX(void) {- if (!_glfwInitTLS())- return GL_FALSE;+ int i;+ const char* sonames[] =+ {+#if defined(__CYGWIN__)+ "libGL-1.so",+#else+ "libGL.so.1",+ "libGL.so",+#endif+ NULL+ }; -#ifdef _GLFW_DLOPEN_LIBGL- _glfw.glx.libGL = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL);- if (!_glfw.glx.libGL)+ if (_glfw.glx.handle)+ return GLFW_TRUE;++ for (i = 0; sonames[i]; i++) {- _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL");- return GL_FALSE;+ _glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);+ if (_glfw.glx.handle)+ break; }-#endif + if (!_glfw.glx.handle)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");+ return GLFW_FALSE;+ }++ _glfw.glx.GetFBConfigs =+ dlsym(_glfw.glx.handle, "glXGetFBConfigs");+ _glfw.glx.GetFBConfigAttrib =+ dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");+ _glfw.glx.GetClientString =+ dlsym(_glfw.glx.handle, "glXGetClientString");+ _glfw.glx.QueryExtension =+ dlsym(_glfw.glx.handle, "glXQueryExtension");+ _glfw.glx.QueryVersion =+ dlsym(_glfw.glx.handle, "glXQueryVersion");+ _glfw.glx.DestroyContext =+ dlsym(_glfw.glx.handle, "glXDestroyContext");+ _glfw.glx.MakeCurrent =+ dlsym(_glfw.glx.handle, "glXMakeCurrent");+ _glfw.glx.SwapBuffers =+ dlsym(_glfw.glx.handle, "glXSwapBuffers");+ _glfw.glx.QueryExtensionsString =+ dlsym(_glfw.glx.handle, "glXQueryExtensionsString");+ _glfw.glx.CreateNewContext =+ dlsym(_glfw.glx.handle, "glXCreateNewContext");+ _glfw.glx.CreateWindow =+ dlsym(_glfw.glx.handle, "glXCreateWindow");+ _glfw.glx.DestroyWindow =+ dlsym(_glfw.glx.handle, "glXDestroyWindow");+ _glfw.glx.GetProcAddress =+ dlsym(_glfw.glx.handle, "glXGetProcAddress");+ _glfw.glx.GetProcAddressARB =+ dlsym(_glfw.glx.handle, "glXGetProcAddressARB");+ _glfw.glx.GetVisualFromFBConfig =+ dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");++ if (!_glfw.glx.GetFBConfigs ||+ !_glfw.glx.GetFBConfigAttrib ||+ !_glfw.glx.GetClientString ||+ !_glfw.glx.QueryExtension ||+ !_glfw.glx.QueryVersion ||+ !_glfw.glx.DestroyContext ||+ !_glfw.glx.MakeCurrent ||+ !_glfw.glx.SwapBuffers ||+ !_glfw.glx.QueryExtensionsString ||+ !_glfw.glx.CreateNewContext ||+ !_glfw.glx.CreateWindow ||+ !_glfw.glx.DestroyWindow ||+ !_glfw.glx.GetProcAddress ||+ !_glfw.glx.GetProcAddressARB ||+ !_glfw.glx.GetVisualFromFBConfig)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "GLX: Failed to load required entry points");+ return GLFW_FALSE;+ }+ if (!glXQueryExtension(_glfw.x11.display, &_glfw.glx.errorBase, &_glfw.glx.eventBase)) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");- return GL_FALSE;+ return GLFW_FALSE; } - if (!glXQueryVersion(_glfw.x11.display,- &_glfw.glx.versionMajor,- &_glfw.glx.versionMinor))+ if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor)) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to query GLX version");- return GL_FALSE;+ return GLFW_FALSE; } - if (_glfw.glx.versionMajor == 1 && _glfw.glx.versionMinor < 3)+ if (_glfw.glx.major == 1 && _glfw.glx.minor < 3) { _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX version 1.3 is required");- return GL_FALSE;+ return GLFW_FALSE; } - if (_glfwPlatformExtensionSupported("GLX_EXT_swap_control"))+ if (extensionSupportedGLX("GLX_EXT_swap_control")) { _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)- _glfwPlatformGetProcAddress("glXSwapIntervalEXT");+ getProcAddressGLX("glXSwapIntervalEXT"); if (_glfw.glx.SwapIntervalEXT)- _glfw.glx.EXT_swap_control = GL_TRUE;+ _glfw.glx.EXT_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_SGI_swap_control"))+ if (extensionSupportedGLX("GLX_SGI_swap_control")) { _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)- _glfwPlatformGetProcAddress("glXSwapIntervalSGI");+ getProcAddressGLX("glXSwapIntervalSGI"); if (_glfw.glx.SwapIntervalSGI)- _glfw.glx.SGI_swap_control = GL_TRUE;+ _glfw.glx.SGI_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_MESA_swap_control"))+ if (extensionSupportedGLX("GLX_MESA_swap_control")) { _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)- _glfwPlatformGetProcAddress("glXSwapIntervalMESA");+ getProcAddressGLX("glXSwapIntervalMESA"); if (_glfw.glx.SwapIntervalMESA)- _glfw.glx.MESA_swap_control = GL_TRUE;+ _glfw.glx.MESA_swap_control = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_ARB_multisample"))- _glfw.glx.ARB_multisample = GL_TRUE;+ if (extensionSupportedGLX("GLX_ARB_multisample"))+ _glfw.glx.ARB_multisample = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_framebuffer_sRGB"))- _glfw.glx.ARB_framebuffer_sRGB = GL_TRUE;+ if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))+ _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context"))+ if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))+ _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;++ if (extensionSupportedGLX("GLX_ARB_create_context")) { _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)- _glfwPlatformGetProcAddress("glXCreateContextAttribsARB");+ getProcAddressGLX("glXCreateContextAttribsARB"); if (_glfw.glx.CreateContextAttribsARB)- _glfw.glx.ARB_create_context = GL_TRUE;+ _glfw.glx.ARB_create_context = GLFW_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_robustness"))- _glfw.glx.ARB_create_context_robustness = GL_TRUE;+ if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))+ _glfw.glx.ARB_create_context_robustness = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile"))- _glfw.glx.ARB_create_context_profile = GL_TRUE;+ if (extensionSupportedGLX("GLX_ARB_create_context_profile"))+ _glfw.glx.ARB_create_context_profile = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile"))- _glfw.glx.EXT_create_context_es2_profile = GL_TRUE;+ if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))+ _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE; - if (_glfwPlatformExtensionSupported("GLX_ARB_context_flush_control"))- _glfw.glx.ARB_context_flush_control = GL_TRUE;+ if (extensionSupportedGLX("GLX_ARB_context_flush_control"))+ _glfw.glx.ARB_context_flush_control = GLFW_TRUE; - return GL_TRUE;+ return GLFW_TRUE; } // Terminate GLX //-void _glfwTerminateContextAPI(void)+void _glfwTerminateGLX(void) {- // Unload libGL.so if necessary-#ifdef _GLFW_DLOPEN_LIBGL- if (_glfw.glx.libGL != NULL)+ // NOTE: This function must not call any X11 functions, as it is called+ // after XCloseDisplay (see _glfwPlatformTerminate for details)++ if (_glfw.glx.handle) {- dlclose(_glfw.glx.libGL);- _glfw.glx.libGL = NULL;+ dlclose(_glfw.glx.handle);+ _glfw.glx.handle = NULL; }-#endif-- _glfwTerminateTLS(); } #define setGLXattrib(attribName, attribValue) \@@ -286,43 +426,33 @@ // Create the OpenGL or OpenGL ES context //-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig) { int attribs[40];- GLXFBConfig native;+ GLXFBConfig native = NULL; GLXContext share = NULL; if (ctxconfig->share)- share = ctxconfig->share->glx.context;+ share = ctxconfig->share->context.glx.handle; - if (!chooseFBConfig(fbconfig, &native))+ if (!chooseGLXFBConfig(fbconfig, &native)) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "GLX: Failed to find a suitable GLXFBConfig");- return GL_FALSE;- }-- // Retrieve the corresponding visual- window->glx.visual = glXGetVisualFromFBConfig(_glfw.x11.display, native);- if (!window->glx.visual)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "GLX: Failed to retrieve visual for GLXFBConfig");- return GL_FALSE;+ return GLFW_FALSE; } - if (ctxconfig->api == GLFW_OPENGL_ES_API)+ if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!_glfw.glx.ARB_create_context || !_glfw.glx.ARB_create_context_profile || !_glfw.glx.EXT_create_context_es2_profile) { _glfwInputError(GLFW_API_UNAVAILABLE,- "GLX: OpenGL ES requested but "- "GLX_EXT_create_context_es2_profile is unavailable");- return GL_FALSE;+ "GLX: OpenGL ES requested but GLX_EXT_create_context_es2_profile is unavailable");+ return GLFW_FALSE; } } @@ -331,9 +461,8 @@ if (!_glfw.glx.ARB_create_context) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "GLX: Forward compatibility requested but "- "GLX_ARB_create_context_profile is unavailable");- return GL_FALSE;+ "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");+ return GLFW_FALSE; } } @@ -343,45 +472,49 @@ !_glfw.glx.ARB_create_context_profile) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "GLX: An OpenGL profile requested but "- "GLX_ARB_create_context_profile is unavailable");- return GL_FALSE;+ "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");+ return GLFW_FALSE; } } - _glfwGrabXErrorHandler();+ _glfwGrabErrorHandlerX11(); if (_glfw.glx.ARB_create_context) {- int index = 0, mask = 0, flags = 0, strategy = 0;+ int index = 0, mask = 0, flags = 0; - if (ctxconfig->api == GLFW_OPENGL_API)+ if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - if (ctxconfig->debug)- flags |= GLX_CONTEXT_DEBUG_BIT_ARB;-- if (ctxconfig->profile)- {- if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)- mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;- else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)- mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;- }+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)+ mask |= GLX_CONTEXT_CORE_PROFILE_BIT_ARB;+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)+ mask |= GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } else mask |= GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + if (ctxconfig->debug)+ flags |= GLX_CONTEXT_DEBUG_BIT_ARB;+ if (ctxconfig->noerror)+ flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;+ if (ctxconfig->robustness) { if (_glfw.glx.ARB_create_context_robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)- strategy = GLX_NO_RESET_NOTIFICATION_ARB;+ {+ setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,+ GLX_NO_RESET_NOTIFICATION_ARB);+ } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)- strategy = GLX_LOSE_CONTEXT_ON_RESET_ARB;+ {+ setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,+ GLX_LOSE_CONTEXT_ON_RESET_ARB);+ } flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; }@@ -404,12 +537,11 @@ } } + // NOTE: Only request an explicitly versioned context when necessary, as+ // explicitly requesting version 1.0 does not always return the+ // highest version supported by the driver if (ctxconfig->major != 1 || ctxconfig->minor != 0) {- // NOTE: Only request an explicitly versioned context when- // necessary, as explicitly requesting version 1.0 does not- // always return the highest available version- setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); }@@ -420,128 +552,94 @@ if (flags) setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags); - if (strategy)- setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);- setGLXattrib(None, None); - window->glx.context =+ window->context.glx.handle = _glfw.glx.CreateContextAttribsARB(_glfw.x11.display, native, share, True, attribs); - if (!window->glx.context)+ // HACK: This is a fallback for broken versions of the Mesa+ // implementation of GLX_ARB_create_context_profile that fail+ // default 1.0 context creation with a GLXBadProfileARB error in+ // violation of the extension spec+ if (!window->context.glx.handle) {- // HACK: This is a fallback for the broken Mesa implementation of- // GLX_ARB_create_context_profile, which fails default 1.0- // context creation with a GLXBadProfileARB error in violation- // of the extension spec if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&- ctxconfig->api == GLFW_OPENGL_API &&+ ctxconfig->client == GLFW_OPENGL_API && ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&- ctxconfig->forward == GL_FALSE)+ ctxconfig->forward == GLFW_FALSE) {- window->glx.context = createLegacyContext(window, native, share);+ window->context.glx.handle =+ createLegacyContextGLX(window, native, share); } } } else- window->glx.context = createLegacyContext(window, native, share);-- _glfwReleaseXErrorHandler();-- if (!window->glx.context) {- _glfwInputXError(GLFW_PLATFORM_ERROR, "GLX: Failed to create context");- return GL_FALSE;+ window->context.glx.handle =+ createLegacyContextGLX(window, native, share); } - return GL_TRUE;-}--#undef setGLXattrib+ _glfwReleaseErrorHandlerX11(); -// Destroy the OpenGL context-//-void _glfwDestroyContext(_GLFWwindow* window)-{- if (window->glx.visual)+ if (!window->context.glx.handle) {- XFree(window->glx.visual);- window->glx.visual = NULL;+ _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");+ return GLFW_FALSE; } - if (window->glx.context)+ window->context.glx.window =+ glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);+ if (!window->context.glx.window) {- glXDestroyContext(_glfw.x11.display, window->glx.context);- window->glx.context = NULL;+ _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");+ return GLFW_FALSE; }-} --//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)-{- if (window)- {- glXMakeCurrent(_glfw.x11.display,- window->x11.handle,- window->glx.context);- }- else- glXMakeCurrent(_glfw.x11.display, None, NULL);+ window->context.makeCurrent = makeContextCurrentGLX;+ window->context.swapBuffers = swapBuffersGLX;+ window->context.swapInterval = swapIntervalGLX;+ window->context.extensionSupported = extensionSupportedGLX;+ window->context.getProcAddress = getProcAddressGLX;+ window->context.destroy = destroyContextGLX; - _glfwSetCurrentContext(window);+ return GLFW_TRUE; } -void _glfwPlatformSwapBuffers(_GLFWwindow* window)-{- glXSwapBuffers(_glfw.x11.display, window->x11.handle);-}+#undef setGLXattrib -void _glfwPlatformSwapInterval(int interval)+// Returns the Visual and depth of the chosen GLXFBConfig+//+GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig,+ Visual** visual, int* depth) {- _GLFWwindow* window = _glfwPlatformGetCurrentContext();+ GLXFBConfig native;+ XVisualInfo* result; - if (_glfw.glx.EXT_swap_control)- {- _glfw.glx.SwapIntervalEXT(_glfw.x11.display,- window->x11.handle,- interval);- }- else if (_glfw.glx.MESA_swap_control)- _glfw.glx.SwapIntervalMESA(interval);- else if (_glfw.glx.SGI_swap_control)+ if (!chooseGLXFBConfig(fbconfig, &native)) {- if (interval > 0)- _glfw.glx.SwapIntervalSGI(interval);+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "GLX: Failed to find a suitable GLXFBConfig");+ return GLFW_FALSE; }-} -int _glfwPlatformExtensionSupported(const char* extension)-{- const GLubyte* extensions;-- // Get list of GLX extensions- extensions = (const GLubyte*) glXQueryExtensionsString(_glfw.x11.display,- _glfw.x11.screen);- if (extensions != NULL)+ result = glXGetVisualFromFBConfig(_glfw.x11.display, native);+ if (!result) {- if (_glfwStringInExtensionString(extension, extensions))- return GL_TRUE;+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "GLX: Failed to retrieve Visual for GLXFBConfig");+ return GLFW_FALSE; } - return GL_FALSE;-}+ *visual = result->visual;+ *depth = result->depth; -GLFWglproc _glfwPlatformGetProcAddress(const char* procname)-{- return _glfw_glXGetProcAddress((const GLubyte*) procname);+ XFree(result);+ return GLFW_TRUE; } @@ -553,6 +651,27 @@ { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL);- return window->glx.context;++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return NULL;+ }++ return window->context.glx.handle;+}++GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* handle)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ _GLFW_REQUIRE_INIT_OR_RETURN(None);++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return None;+ }++ return window->context.glx.window; }
glfw/src/glx_context.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 GLX - www.glfw.org+// GLFW 3.2 GLX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,96 +25,158 @@ // //======================================================================== -#ifndef _glx_context_h_-#define _glx_context_h_+#ifndef _glfw3_glx_context_h_+#define _glfw3_glx_context_h_ -#define GLX_GLXEXT_LEGACY-#include <GL/glx.h>+#define GLX_VENDOR 1+#define GLX_RGBA_BIT 0x00000001+#define GLX_WINDOW_BIT 0x00000001+#define GLX_DRAWABLE_TYPE 0x8010+#define GLX_RENDER_TYPE 0x8011+#define GLX_RGBA_TYPE 0x8014+#define GLX_DOUBLEBUFFER 5+#define GLX_STEREO 6+#define GLX_AUX_BUFFERS 7+#define GLX_RED_SIZE 8+#define GLX_GREEN_SIZE 9+#define GLX_BLUE_SIZE 10+#define GLX_ALPHA_SIZE 11+#define GLX_DEPTH_SIZE 12+#define GLX_STENCIL_SIZE 13+#define GLX_ACCUM_RED_SIZE 14+#define GLX_ACCUM_GREEN_SIZE 15+#define GLX_ACCUM_BLUE_SIZE 16+#define GLX_ACCUM_ALPHA_SIZE 17+#define GLX_SAMPLES 0x186a1+#define GLX_VISUAL_ID 0x800b -// This path may need to be changed if you build GLFW using your own setup-// We ship and use our own copy of glxext.h since GLFW uses fairly new-// extensions and not all operating systems come with an up-to-date version-#include "../deps/GL/glxext.h"+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20b2+#define GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001+#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001+#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126+#define GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002+#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091+#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092+#define GLX_CONTEXT_FLAGS_ARB 0x2094+#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004+#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004+#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252+#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256+#define GLX_NO_RESET_NOTIFICATION_ARB 0x8261+#define GLX_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097+#define GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0+#define GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098 -// Do we have support for dlopen/dlsym?-#if defined(_GLFW_HAS_DLOPEN)- #include <dlfcn.h>-#endif+typedef XID GLXWindow;+typedef XID GLXDrawable;+typedef struct __GLXFBConfig* GLXFBConfig;+typedef struct __GLXcontext* GLXContext;+typedef void (*__GLXextproc)(void); -// We support four different ways for getting addresses for GL/GLX-// extension functions: glXGetProcAddress, glXGetProcAddressARB,-// glXGetProcAddressEXT, and dlsym-#if defined(_GLFW_HAS_GLXGETPROCADDRESSARB)- #define _glfw_glXGetProcAddress(x) glXGetProcAddressARB(x)-#elif defined(_GLFW_HAS_GLXGETPROCADDRESS)- #define _glfw_glXGetProcAddress(x) glXGetProcAddress(x)-#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)- #define _glfw_glXGetProcAddress(x) glXGetProcAddressEXT(x)-#elif defined(_GLFW_HAS_DLOPEN)- #define _glfw_glXGetProcAddress(x) dlsym(_glfw.glx.libGL, x)- #define _GLFW_DLOPEN_LIBGL-#else- #error "No OpenGL entry point retrieval mechanism was enabled"-#endif+typedef int (*PFNGLXGETFBCONFIGATTRIBPROC)(Display*,GLXFBConfig,int,int*);+typedef const char* (*PFNGLXGETCLIENTSTRINGPROC)(Display*,int);+typedef Bool (*PFNGLXQUERYEXTENSIONPROC)(Display*,int*,int*);+typedef Bool (*PFNGLXQUERYVERSIONPROC)(Display*,int*,int*);+typedef void (*PFNGLXDESTROYCONTEXTPROC)(Display*,GLXContext);+typedef Bool (*PFNGLXMAKECURRENTPROC)(Display*,GLXDrawable,GLXContext);+typedef void (*PFNGLXSWAPBUFFERSPROC)(Display*,GLXDrawable);+typedef const char* (*PFNGLXQUERYEXTENSIONSSTRINGPROC)(Display*,int);+typedef GLXFBConfig* (*PFNGLXGETFBCONFIGSPROC)(Display*,int,int*);+typedef GLXContext (*PFNGLXCREATENEWCONTEXTPROC)(Display*,GLXFBConfig,int,GLXContext,Bool);+typedef __GLXextproc (* PFNGLXGETPROCADDRESSPROC)(const GLubyte *procName);+typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);+typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);+typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);+typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);+typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);+typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow); -#define _GLFW_PLATFORM_FBCONFIG GLXFBConfig glx+// libGL.so function pointer typedefs+#define glXGetFBConfigs _glfw.glx.GetFBConfigs+#define glXGetFBConfigAttrib _glfw.glx.GetFBConfigAttrib+#define glXGetClientString _glfw.glx.GetClientString+#define glXQueryExtension _glfw.glx.QueryExtension+#define glXQueryVersion _glfw.glx.QueryVersion+#define glXDestroyContext _glfw.glx.DestroyContext+#define glXMakeCurrent _glfw.glx.MakeCurrent+#define glXSwapBuffers _glfw.glx.SwapBuffers+#define glXQueryExtensionsString _glfw.glx.QueryExtensionsString+#define glXCreateNewContext _glfw.glx.CreateNewContext+#define glXGetVisualFromFBConfig _glfw.glx.GetVisualFromFBConfig+#define glXCreateWindow _glfw.glx.CreateWindow+#define glXDestroyWindow _glfw.glx.DestroyWindow+ #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx -#ifndef GLX_MESA_swap_control-typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);-#endif - // GLX-specific per-context data // typedef struct _GLFWcontextGLX {- // Rendering context- GLXContext context;- // Visual of selected GLXFBConfig- XVisualInfo* visual;+ GLXContext handle;+ GLXWindow window; } _GLFWcontextGLX; - // GLX-specific global data // typedef struct _GLFWlibraryGLX {- int versionMajor, versionMinor;+ int major, minor; int eventBase; int errorBase; - // GLX extensions- PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;- PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;- PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;- PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;- GLboolean SGI_swap_control;- GLboolean EXT_swap_control;- GLboolean MESA_swap_control;- GLboolean ARB_multisample;- GLboolean ARB_framebuffer_sRGB;- GLboolean ARB_create_context;- GLboolean ARB_create_context_profile;- GLboolean ARB_create_context_robustness;- GLboolean EXT_create_context_es2_profile;- GLboolean ARB_context_flush_control;+ // dlopen handle for libGL.so.1+ void* handle; -#if defined(_GLFW_DLOPEN_LIBGL)- // dlopen handle for libGL.so (for glfwGetProcAddress)- void* libGL;-#endif+ // GLX 1.3 functions+ PFNGLXGETFBCONFIGSPROC GetFBConfigs;+ PFNGLXGETFBCONFIGATTRIBPROC GetFBConfigAttrib;+ PFNGLXGETCLIENTSTRINGPROC GetClientString;+ PFNGLXQUERYEXTENSIONPROC QueryExtension;+ PFNGLXQUERYVERSIONPROC QueryVersion;+ PFNGLXDESTROYCONTEXTPROC DestroyContext;+ PFNGLXMAKECURRENTPROC MakeCurrent;+ PFNGLXSWAPBUFFERSPROC SwapBuffers;+ PFNGLXQUERYEXTENSIONSSTRINGPROC QueryExtensionsString;+ PFNGLXCREATENEWCONTEXTPROC CreateNewContext;+ PFNGLXGETVISUALFROMFBCONFIGPROC GetVisualFromFBConfig;+ PFNGLXCREATEWINDOWPROC CreateWindow;+ PFNGLXDESTROYWINDOWPROC DestroyWindow; + // GLX 1.4 and extension functions+ PFNGLXGETPROCADDRESSPROC GetProcAddress;+ PFNGLXGETPROCADDRESSPROC GetProcAddressARB;+ PFNGLXSWAPINTERVALSGIPROC SwapIntervalSGI;+ PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;+ PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;+ PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;+ GLFWbool SGI_swap_control;+ GLFWbool EXT_swap_control;+ GLFWbool MESA_swap_control;+ GLFWbool ARB_multisample;+ GLFWbool ARB_framebuffer_sRGB;+ GLFWbool EXT_framebuffer_sRGB;+ GLFWbool ARB_create_context;+ GLFWbool ARB_create_context_profile;+ GLFWbool ARB_create_context_robustness;+ GLFWbool EXT_create_context_es2_profile;+ GLFWbool ARB_context_flush_control;+ } _GLFWlibraryGLX; -int _glfwInitContextAPI(void);-void _glfwTerminateContextAPI(void);-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);-void _glfwDestroyContext(_GLFWwindow* window);+GLFWbool _glfwInitGLX(void);+void _glfwTerminateGLX(void);+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig);+void _glfwDestroyContextGLX(_GLFWwindow* window);+GLFWbool _glfwChooseVisualGLX(const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig,+ Visual** visual, int* depth); -#endif // _glx_context_h_+#endif // _glfw3_glx_context_h_
glfw/src/init.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -33,13 +33,13 @@ #include <stdarg.h> -// The three global variables below comprise all global data in GLFW, except for-// various static const translation tables. Any other global variable is a bug.+// The three global variables below comprise all global data in GLFW.+// Any other global variable is a bug. // Global state shared between compilation units of GLFW // These are documented in internal.h //-GLboolean _glfwInitialized = GL_FALSE;+GLFWbool _glfwInitialized = GLFW_FALSE; _GLFWlibrary _glfw; // This is outside of _glfw so it can be initialized and usable before@@ -65,16 +65,18 @@ case GLFW_OUT_OF_MEMORY: return "Out of memory"; case GLFW_API_UNAVAILABLE:- return "The requested client API is unavailable";+ return "The requested API is unavailable"; case GLFW_VERSION_UNAVAILABLE:- return "The requested client API version is unavailable";+ return "The requested API version is unavailable"; case GLFW_PLATFORM_ERROR: return "A platform-specific error occurred"; case GLFW_FORMAT_UNAVAILABLE: return "The requested format is unavailable";+ case GLFW_NO_WINDOW_CONTEXT:+ return "The specified window has no context";+ default:+ return "ERROR: UNKNOWN GLFW ERROR"; }-- return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; } @@ -86,7 +88,7 @@ { if (_glfwErrorCallback) {- char buffer[16384];+ char buffer[8192]; const char* description; if (format)@@ -118,30 +120,25 @@ GLFWAPI int glfwInit(void) { if (_glfwInitialized)- return GL_TRUE;+ return GLFW_TRUE; memset(&_glfw, 0, sizeof(_glfw)); if (!_glfwPlatformInit()) { _glfwPlatformTerminate();- return GL_FALSE;+ return GLFW_FALSE; } _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);- if (!_glfw.monitorCount)- {- _glfwInputError(GLFW_PLATFORM_ERROR, "No monitors found");- _glfwPlatformTerminate();- return GL_FALSE;- }+ _glfwInitialized = GLFW_TRUE; - _glfwInitialized = GL_TRUE;+ _glfw.timerOffset = _glfwPlatformGetTimerValue(); // Not all window hints have zero as their default value glfwDefaultWindowHints(); - return GL_TRUE;+ return GLFW_TRUE; } GLFWAPI void glfwTerminate(void)@@ -166,6 +163,8 @@ _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp); } + _glfwTerminateVulkan();+ _glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount); _glfw.monitors = NULL; _glfw.monitorCount = 0;@@ -173,7 +172,7 @@ _glfwPlatformTerminate(); memset(&_glfw, 0, sizeof(_glfw));- _glfwInitialized = GL_FALSE;+ _glfwInitialized = GLFW_FALSE; } GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
glfw/src/input.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -27,107 +27,14 @@ #include "internal.h" -#include <stdlib.h>+#include <assert.h> #include <float.h>-#if defined(_MSC_VER)- #include <malloc.h>-#endif+#include <stdlib.h> // Internal key state used for sticky keys #define _GLFW_STICK 3 -// Sets the cursor mode for the specified window-//-static void setCursorMode(_GLFWwindow* window, int newMode)-{- const int oldMode = window->cursorMode;-- if (newMode != GLFW_CURSOR_NORMAL &&- newMode != GLFW_CURSOR_HIDDEN &&- newMode != GLFW_CURSOR_DISABLED)- {- _glfwInputError(GLFW_INVALID_ENUM, NULL);- return;- }-- if (oldMode == newMode)- return;-- window->cursorMode = newMode;-- if (_glfw.focusedWindow == window)- {- if (oldMode == GLFW_CURSOR_DISABLED)- {- _glfwPlatformSetCursorPos(window,- _glfw.cursorPosX,- _glfw.cursorPosY);- }- else if (newMode == GLFW_CURSOR_DISABLED)- {- int width, height;-- _glfwPlatformGetCursorPos(window,- &_glfw.cursorPosX,- &_glfw.cursorPosY);-- window->cursorPosX = _glfw.cursorPosX;- window->cursorPosY = _glfw.cursorPosY;-- _glfwPlatformGetWindowSize(window, &width, &height);- _glfwPlatformSetCursorPos(window, width / 2, height / 2);- }-- _glfwPlatformApplyCursorMode(window);- }-}--// Set sticky keys mode for the specified window-//-static void setStickyKeys(_GLFWwindow* window, int enabled)-{- if (window->stickyKeys == enabled)- return;-- if (!enabled)- {- int i;-- // Release all sticky keys- for (i = 0; i <= GLFW_KEY_LAST; i++)- {- if (window->keys[i] == _GLFW_STICK)- window->keys[i] = GLFW_RELEASE;- }- }-- window->stickyKeys = enabled;-}--// Set sticky mouse buttons mode for the specified window-//-static void setStickyMouseButtons(_GLFWwindow* window, int enabled)-{- if (window->stickyMouseButtons == enabled)- return;-- if (!enabled)- {- int i;-- // Release all sticky mouse buttons- for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)- {- if (window->mouseButtons[i] == _GLFW_STICK)- window->mouseButtons[i] = GLFW_RELEASE;- }- }-- window->stickyMouseButtons = enabled;-}-- ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// //////////////////////////////////////////////////////////////////////////@@ -136,13 +43,13 @@ { if (key >= 0 && key <= GLFW_KEY_LAST) {- GLboolean repeated = GL_FALSE;+ GLFWbool repeated = GLFW_FALSE; if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE) return; if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)- repeated = GL_TRUE;+ repeated = GLFW_TRUE; if (action == GLFW_RELEASE && window->stickyKeys) window->keys[key] = _GLFW_STICK;@@ -157,7 +64,7 @@ window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); } -void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, int plain)+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) { if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) return;@@ -193,25 +100,19 @@ window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); } -void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y)+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) {- if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- if (x == 0.0 && y == 0.0)- return;-- window->cursorPosX += x;- window->cursorPosY += y;+ if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)+ return; - x = window->cursorPosX;- y = window->cursorPosY;- }+ window->virtualCursorPosX = xpos;+ window->virtualCursorPosY = ypos; if (window->callbacks.cursorPos)- window->callbacks.cursorPos((GLFWwindow*) window, x, y);+ window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); } -void _glfwInputCursorEnter(_GLFWwindow* window, int entered)+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) { if (window->callbacks.cursorEnter) window->callbacks.cursorEnter((GLFWwindow*) window, entered);@@ -223,14 +124,33 @@ window->callbacks.drop((GLFWwindow*) window, count, paths); } +void _glfwInputJoystickChange(int joy, int event)+{+ if (_glfw.callbacks.joystick)+ _glfw.callbacks.joystick(joy, event);+} + //////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++GLFWbool _glfwIsPrintable(int key)+{+ return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||+ (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||+ key == GLFW_KEY_KP_EQUAL;+}+++////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(0); @@ -243,7 +163,7 @@ case GLFW_STICKY_MOUSE_BUTTONS: return window->stickyMouseButtons; default:- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode); return 0; } }@@ -251,35 +171,101 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); switch (mode) { case GLFW_CURSOR:- setCursorMode(window, value);- break;+ {+ if (value != GLFW_CURSOR_NORMAL &&+ value != GLFW_CURSOR_HIDDEN &&+ value != GLFW_CURSOR_DISABLED)+ {+ _glfwInputError(GLFW_INVALID_ENUM,+ "Invalid cursor mode %i",+ value);+ return;+ }++ if (window->cursorMode == value)+ return;++ window->cursorMode = value;++ _glfwPlatformGetCursorPos(window,+ &window->virtualCursorPosX,+ &window->virtualCursorPosY);++ if (_glfwPlatformWindowFocused(window))+ _glfwPlatformSetCursorMode(window, value);++ return;+ }+ case GLFW_STICKY_KEYS:- setStickyKeys(window, value ? GL_TRUE : GL_FALSE);- break;+ {+ if (window->stickyKeys == value)+ return;++ if (!value)+ {+ int i;++ // Release all sticky keys+ for (i = 0; i <= GLFW_KEY_LAST; i++)+ {+ if (window->keys[i] == _GLFW_STICK)+ window->keys[i] = GLFW_RELEASE;+ }+ }++ window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;+ return;+ }+ case GLFW_STICKY_MOUSE_BUTTONS:- setStickyMouseButtons(window, value ? GL_TRUE : GL_FALSE);- break;- default:- _glfwInputError(GLFW_INVALID_ENUM, NULL);- break;+ {+ if (window->stickyMouseButtons == value)+ return;++ if (!value)+ {+ int i;++ // Release all sticky mouse buttons+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)+ {+ if (window->mouseButtons[i] == _GLFW_STICK)+ window->mouseButtons[i] = GLFW_RELEASE;+ }+ }++ window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;+ return;+ } }++ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode); } +GLFWAPI const char* glfwGetKeyName(int key, int scancode)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return _glfwPlatformGetKeyName(key, scancode);+}+ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (key < 0 || key > GLFW_KEY_LAST)+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) {- _glfwInputError(GLFW_INVALID_ENUM, "The specified key is invalid");+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); return GLFW_RELEASE; } @@ -296,13 +282,13 @@ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE); - if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)+ if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST) {- _glfwInputError(GLFW_INVALID_ENUM,- "The specified mouse button is invalid");+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button); return GLFW_RELEASE; } @@ -319,6 +305,7 @@ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); if (xpos) *xpos = 0;@@ -330,9 +317,9 @@ if (window->cursorMode == GLFW_CURSOR_DISABLED) { if (xpos)- *xpos = window->cursorPosX;+ *xpos = window->virtualCursorPosX; if (ypos)- *ypos = window->cursorPosY;+ *ypos = window->virtualCursorPosY; } else _glfwPlatformGetCursorPos(window, xpos, ypos);@@ -341,17 +328,27 @@ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); - if (_glfw.focusedWindow != window)+ if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||+ ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid cursor position %f %f",+ xpos, ypos); return;+ } + if (!_glfwPlatformWindowFocused(window))+ return;+ if (window->cursorMode == GLFW_CURSOR_DISABLED) { // Only update the accumulated position if the cursor is disabled- window->cursorPosX = xpos;- window->cursorPosY = ypos;+ window->virtualCursorPosX = xpos;+ window->virtualCursorPosY = ypos; } else {@@ -364,6 +361,8 @@ { _GLFWcursor* cursor; + assert(image != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); cursor = calloc(1, sizeof(_GLFWcursor));@@ -385,6 +384,17 @@ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + if (shape != GLFW_ARROW_CURSOR &&+ shape != GLFW_IBEAM_CURSOR &&+ shape != GLFW_CROSSHAIR_CURSOR &&+ shape != GLFW_HAND_CURSOR &&+ shape != GLFW_HRESIZE_CURSOR &&+ shape != GLFW_VRESIZE_CURSOR)+ {+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor %i", shape);+ return NULL;+ }+ cursor = calloc(1, sizeof(_GLFWcursor)); cursor->next = _glfw.cursorListHead; _glfw.cursorListHead = cursor;@@ -437,17 +447,20 @@ { _GLFWwindow* window = (_GLFWwindow*) windowHandle; _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); - _glfwPlatformSetCursor(window, cursor);- window->cursor = cursor;++ _glfwPlatformSetCursor(window, cursor); } GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.key, cbfun); return cbfun;@@ -456,6 +469,8 @@ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.character, cbfun); return cbfun;@@ -464,6 +479,8 @@ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.charmods, cbfun); return cbfun;@@ -473,6 +490,8 @@ GLFWmousebuttonfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun); return cbfun;@@ -482,6 +501,8 @@ GLFWcursorposfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun); return cbfun;@@ -491,6 +512,8 @@ GLFWcursorenterfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun); return cbfun;@@ -500,6 +523,8 @@ GLFWscrollfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun); return cbfun;@@ -508,6 +533,8 @@ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.drop, cbfun); return cbfun;@@ -519,7 +546,7 @@ if (joy < 0 || joy > GLFW_JOYSTICK_LAST) {- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy); return 0; } @@ -528,13 +555,14 @@ GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count) {+ assert(count != NULL); *count = 0; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (joy < 0 || joy > GLFW_JOYSTICK_LAST) {- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy); return NULL; } @@ -543,13 +571,14 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count) {+ assert(count != NULL); *count = 0; _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (joy < 0 || joy > GLFW_JOYSTICK_LAST) {- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy); return NULL; } @@ -562,16 +591,26 @@ if (joy < 0 || joy > GLFW_JOYSTICK_LAST) {- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy); return NULL; } return _glfwPlatformGetJoystickName(joy); } +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);+ return cbfun;+}+ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ assert(string != NULL);+ _GLFW_REQUIRE_INIT(); _glfwPlatformSetClipboardString(window, string); }@@ -579,6 +618,8 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return _glfwPlatformGetClipboardString(window); }@@ -586,19 +627,33 @@ GLFWAPI double glfwGetTime(void) { _GLFW_REQUIRE_INIT_OR_RETURN(0.0);- return _glfwPlatformGetTime();+ return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /+ _glfwPlatformGetTimerFrequency(); } GLFWAPI void glfwSetTime(double time) { _GLFW_REQUIRE_INIT(); - if (time != time || time - DBL_MAX == time || time < 0.0)+ if (time != time || time < 0.0 || time > 18446744073.0) {- _glfwInputError(GLFW_INVALID_VALUE, "Invalid time");+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time); return; } - _glfwPlatformSetTime(time);+ _glfw.timerOffset = _glfwPlatformGetTimerValue() -+ (uint64_t) (time * _glfwPlatformGetTimerFrequency());+}++GLFWAPI uint64_t glfwGetTimerValue(void)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(0);+ return _glfwPlatformGetTimerValue();+}++GLFWAPI uint64_t glfwGetTimerFrequency(void)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(0);+ return _glfwPlatformGetTimerFrequency(); }
glfw/src/internal.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,47 +25,142 @@ // //======================================================================== -#ifndef _internal_h_-#define _internal_h_+#ifndef _glfw3_internal_h_+#define _glfw3_internal_h_ #if defined(_GLFW_USE_CONFIG_H) #include "glfw_config.h" #endif -#define _GLFW_VERSION_NUMBER "3.1.1"--#if defined(_GLFW_USE_OPENGL)- // This is the default for glfw3.h-#elif defined(_GLFW_USE_GLESV1)- #define GLFW_INCLUDE_ES1-#elif defined(_GLFW_USE_GLESV2)- #define GLFW_INCLUDE_ES2-#else- #error "No supported client library selected"+#if defined(GLFW_INCLUDE_GLCOREARB) || \+ defined(GLFW_INCLUDE_ES1) || \+ defined(GLFW_INCLUDE_ES2) || \+ defined(GLFW_INCLUDE_ES3) || \+ defined(GLFW_INCLUDE_NONE) || \+ defined(GLFW_INCLUDE_GLEXT) || \+ defined(GLFW_INCLUDE_GLU) || \+ defined(GLFW_INCLUDE_VULKAN) || \+ defined(GLFW_DLL)+ #error "You must not define any header option macros when compiling GLFW" #endif -// Disable the inclusion of the platform glext.h by gl.h to allow proper-// inclusion of our own, newer glext.h below-#define GL_GLEXT_LEGACY-+#define GLFW_INCLUDE_NONE #include "../include/GLFW/glfw3.h" -#if defined(_GLFW_USE_OPENGL)- // This path may need to be changed if you build GLFW using your own setup- // GLFW comes with its own copy of glext.h since it uses fairly new extensions- // and not all development environments come with an up-to-date version- #include "../deps/GL/glext.h"-#endif+typedef int GLFWbool; typedef struct _GLFWwndconfig _GLFWwndconfig; typedef struct _GLFWctxconfig _GLFWctxconfig; typedef struct _GLFWfbconfig _GLFWfbconfig;+typedef struct _GLFWcontext _GLFWcontext; typedef struct _GLFWwindow _GLFWwindow; typedef struct _GLFWlibrary _GLFWlibrary; typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWcursor _GLFWcursor; +typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);+typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);+typedef void (* _GLFWswapintervalfun)(int);+typedef int (* _GLFWextensionsupportedfun)(const char*);+typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);+typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);++#define GL_VERSION 0x1f02+#define GL_NONE 0+#define GL_COLOR_BUFFER_BIT 0x00004000+#define GL_EXTENSIONS 0x1f03+#define GL_NUM_EXTENSIONS 0x821d+#define GL_CONTEXT_FLAGS 0x821e+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002+#define GL_CONTEXT_PROFILE_MASK 0x9126+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82fb+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008++typedef int GLint;+typedef unsigned int GLuint;+typedef unsigned int GLenum;+typedef unsigned int GLbitfield;+typedef unsigned char GLubyte;++typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);+typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);++#define VK_NULL_HANDLE 0++typedef void* VkInstance;+typedef void* VkPhysicalDevice;+typedef uint64_t VkSurfaceKHR;+typedef uint32_t VkFlags;+typedef uint32_t VkBool32;++typedef enum VkStructureType+{+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,+ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,+ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,+ VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,+ VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF+} VkStructureType;++typedef enum VkResult+{+ VK_SUCCESS = 0,+ VK_NOT_READY = 1,+ VK_TIMEOUT = 2,+ VK_EVENT_SET = 3,+ VK_EVENT_RESET = 4,+ VK_INCOMPLETE = 5,+ VK_ERROR_OUT_OF_HOST_MEMORY = -1,+ VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,+ VK_ERROR_INITIALIZATION_FAILED = -3,+ VK_ERROR_DEVICE_LOST = -4,+ VK_ERROR_MEMORY_MAP_FAILED = -5,+ VK_ERROR_LAYER_NOT_PRESENT = -6,+ VK_ERROR_EXTENSION_NOT_PRESENT = -7,+ VK_ERROR_FEATURE_NOT_PRESENT = -8,+ VK_ERROR_INCOMPATIBLE_DRIVER = -9,+ VK_ERROR_TOO_MANY_OBJECTS = -10,+ VK_ERROR_FORMAT_NOT_SUPPORTED = -11,+ VK_ERROR_SURFACE_LOST_KHR = -1000000000,+ VK_SUBOPTIMAL_KHR = 1000001003,+ VK_ERROR_OUT_OF_DATE_KHR = -1000001004,+ VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,+ VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,+ VK_RESULT_MAX_ENUM = 0x7FFFFFFF+} VkResult;++typedef struct VkAllocationCallbacks VkAllocationCallbacks;++typedef struct VkExtensionProperties+{+ char extensionName[256];+ uint32_t specVersion;+} VkExtensionProperties;++typedef void (APIENTRY * PFN_vkVoidFunction)(void);++#if defined(_GLFW_VULKAN_STATIC)+ PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);+ VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);+#else+ typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);+ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);+ #define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties+ #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr+#endif+ #if defined(_GLFW_COCOA) #include "cocoa_platform.h" #elif defined(_GLFW_WIN32)@@ -103,7 +198,7 @@ * @brief Various utility functions for internal use. * * These functions are shared code and may be used by any part of GLFW- * Each platform may add its own utility functions, but those may only be+ * Each platform may add its own utility functions, but those must only be * called by the platform-specific code */ @@ -112,6 +207,13 @@ // Helper macros //======================================================================== +// Constructs a version number string from the public header macros+#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r+#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)+#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \+ GLFW_VERSION_MINOR, \+ GLFW_VERSION_REVISION)+ // Checks for whether the library has been initialized #define _GLFW_REQUIRE_INIT() \ if (!_glfwInitialized) \@@ -151,16 +253,15 @@ int width; int height; const char* title;- GLboolean resizable;- GLboolean visible;- GLboolean decorated;- GLboolean focused;- GLboolean autoIconify;- GLboolean floating;- _GLFWmonitor* monitor;+ GLFWbool resizable;+ GLFWbool visible;+ GLFWbool decorated;+ GLFWbool focused;+ GLFWbool autoIconify;+ GLFWbool floating;+ GLFWbool maximized; }; - /*! @brief Context configuration. * * Parameters relating to the creation of the context but not directly related@@ -169,18 +270,19 @@ */ struct _GLFWctxconfig {- int api;+ int client;+ int source; int major; int minor;- GLboolean forward;- GLboolean debug;+ GLFWbool forward;+ GLFWbool debug;+ GLFWbool noerror; int profile; int robustness; int release; _GLFWwindow* share; }; - /*! @brief Framebuffer configuration. * * This describes buffers and their sizes. It also contains@@ -202,16 +304,42 @@ int accumBlueBits; int accumAlphaBits; int auxBuffers;- int stereo;+ GLFWbool stereo; int samples;- int sRGB;- int doublebuffer;+ GLFWbool sRGB;+ GLFWbool doublebuffer;+ uintptr_t handle;+}; +/*! @brief Context structure.+ */+struct _GLFWcontext+{+ int client;+ int source;+ int major, minor, revision;+ GLFWbool forward, debug, noerror;+ int profile;+ int robustness;+ int release;++ PFNGLGETSTRINGIPROC GetStringi;+ PFNGLGETINTEGERVPROC GetIntegerv;+ PFNGLGETSTRINGPROC GetString;++ _GLFWmakecontextcurrentfun makeCurrent;+ _GLFWswapbuffersfun swapBuffers;+ _GLFWswapintervalfun swapInterval;+ _GLFWextensionsupportedfun extensionSupported;+ _GLFWgetprocaddressfun getProcAddress;+ _GLFWdestroycontextfun destroy;+ // This is defined in the context API's context.h- _GLFW_PLATFORM_FBCONFIG;+ _GLFW_PLATFORM_CONTEXT_STATE;+ // This is defined in egl_context.h+ _GLFW_EGL_CONTEXT_STATE; }; - /*! @brief Window and context structure. */ struct _GLFWwindow@@ -219,37 +347,29 @@ struct _GLFWwindow* next; // Window settings and state- GLboolean resizable;- GLboolean decorated;- GLboolean autoIconify;- GLboolean floating;- GLboolean closed;+ GLFWbool resizable;+ GLFWbool decorated;+ GLFWbool autoIconify;+ GLFWbool floating;+ GLFWbool closed; void* userPointer; GLFWvidmode videoMode; _GLFWmonitor* monitor; _GLFWcursor* cursor; - // Window input state- GLboolean stickyKeys;- GLboolean stickyMouseButtons;- double cursorPosX, cursorPosY;+ int minwidth, minheight;+ int maxwidth, maxheight;+ int numer, denom;++ GLFWbool stickyKeys;+ GLFWbool stickyMouseButtons; int cursorMode; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char keys[GLFW_KEY_LAST + 1];-- // OpenGL extensions and context attributes- struct {- int api;- int major, minor, revision;- GLboolean forward, debug;- int profile;- int robustness;- int release;- } context;+ // Virtual cursor position when cursor is disabled+ double virtualCursorPosX, virtualCursorPosY; -#if defined(_GLFW_USE_OPENGL)- PFNGLGETSTRINGIPROC GetStringi;-#endif+ _GLFWcontext context; struct { GLFWwindowposfun pos;@@ -271,11 +391,8 @@ // This is defined in the window API's platform.h _GLFW_PLATFORM_WINDOW_STATE;- // This is defined in the context API's context.h- _GLFW_PLATFORM_CONTEXT_STATE; }; - /*! @brief Monitor structure. */ struct _GLFWmonitor@@ -285,6 +402,9 @@ // Physical dimensions in millimeters. int widthMM, heightMM; + // The window whose video mode is current on this monitor+ _GLFWwindow* window;+ GLFWvidmode* modes; int modeCount; GLFWvidmode currentMode;@@ -296,7 +416,6 @@ _GLFW_PLATFORM_MONITOR_STATE; }; - /*! @brief Cursor structure */ struct _GLFWcursor@@ -312,50 +431,41 @@ struct _GLFWlibrary { struct {- int redBits;- int greenBits;- int blueBits;- int alphaBits;- int depthBits;- int stencilBits;- int accumRedBits;- int accumGreenBits;- int accumBlueBits;- int accumAlphaBits;- int auxBuffers;- int stereo;- int resizable;- int visible;- int decorated;- int focused;- int autoIconify;- int floating;- int samples;- int sRGB;- int refreshRate;- int doublebuffer;- int api;- int major;- int minor;- int forward;- int debug;- int profile;- int robustness;- int release;+ _GLFWfbconfig framebuffer;+ _GLFWwndconfig window;+ _GLFWctxconfig context;+ int refreshRate; } hints; - double cursorPosX, cursorPosY;+ _GLFWcursor* cursorListHead; - _GLFWcursor* cursorListHead;+ _GLFWwindow* windowListHead; - _GLFWwindow* windowListHead;- _GLFWwindow* focusedWindow;+ _GLFWmonitor** monitors;+ int monitorCount; - _GLFWmonitor** monitors;- int monitorCount;+ uint64_t timerOffset; struct {+ GLFWbool available;+ void* handle;+ char** extensions;+ uint32_t extensionCount;+#if !defined(_GLFW_VULKAN_STATIC)+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;+#endif+ GLFWbool KHR_surface;+ GLFWbool KHR_win32_surface;+ GLFWbool KHR_xlib_surface;+ GLFWbool KHR_xcb_surface;+ GLFWbool KHR_wayland_surface;+ GLFWbool KHR_mir_surface;+ } vk;++ struct { GLFWmonitorfun monitor;+ GLFWjoystickfun joystick; } callbacks; // This is defined in the window API's platform.h@@ -368,6 +478,8 @@ _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; // This is defined in the platform's tls.h _GLFW_PLATFORM_LIBRARY_TLS_STATE;+ // This is defined in egl_context.h+ _GLFW_EGL_LIBRARY_CONTEXT_STATE; }; @@ -377,7 +489,7 @@ /*! @brief Flag indicating whether GLFW has been successfully initialized. */-extern GLboolean _glfwInitialized;+extern GLFWbool _glfwInitialized; /*! @brief All global data protected by @ref _glfwInitialized. * This should only be touched after a call to @ref glfwInit that has not been@@ -391,7 +503,7 @@ //======================================================================== /*! @brief Initializes the platform-specific part of the library.- * @return `GL_TRUE` if successful, or `GL_FALSE` if an error occurred.+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an error occurred. * @ingroup platform */ int _glfwPlatformInit(void);@@ -420,12 +532,17 @@ */ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos); -/*! @brief Applies the cursor mode of the specified window to the system.- * @param[in] window The window whose cursor mode to apply.+/*! @brief Sets the specified cursor mode of the specified window.+ * @param[in] window The window whose cursor mode to set. * @ingroup platform */-void _glfwPlatformApplyCursorMode(_GLFWwindow* window);+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); +/*! @copydoc glfwGetKeyName+ * @ingroup platform+ */+const char* _glfwPlatformGetKeyName(int key, int scancode);+ /*! @copydoc glfwGetMonitors * @ingroup platform */@@ -435,11 +552,11 @@ * * @param[in] first The first monitor. * @param[in] second The second monitor.- * @return @c GL_TRUE if the monitor objects represent the same monitor, or @c- * GL_FALSE otherwise.+ * @return @c GLFW_TRUE if the monitor objects represent the same monitor, or+ * @c GLFW_FALSE otherwise. * @ingroup platform */-GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second);+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second); /*! @copydoc glfwGetMonitorPos * @ingroup platform@@ -498,15 +615,15 @@ */ const char* _glfwPlatformGetJoystickName(int joy); -/*! @copydoc glfwGetTime+/*! @copydoc glfwGetTimerValue * @ingroup platform */-double _glfwPlatformGetTime(void);+uint64_t _glfwPlatformGetTimerValue(void); -/*! @copydoc glfwSetTime+/*! @copydoc glfwGetTimerFrequency * @ingroup platform */-void _glfwPlatformSetTime(double time);+uint64_t _glfwPlatformGetTimerFrequency(void); /*! @ingroup platform */@@ -524,6 +641,11 @@ */ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); +/*! @copydoc glfwSetWindowIcon+ * @ingroup platform+ */+void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images);+ /*! @copydoc glfwGetWindowPos * @ingroup platform */@@ -544,6 +666,16 @@ */ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); +/*! @copydoc glfwSetWindowSizeLimits+ * @ingroup platform+ */+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);++/*! @copydoc glfwSetWindowAspectRatio+ * @ingroup platform+ */+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);+ /*! @copydoc glfwGetFramebufferSize * @ingroup platform */@@ -564,20 +696,31 @@ */ void _glfwPlatformRestoreWindow(_GLFWwindow* window); -/*! @copydoc glfwShowWindow+/*! @copydoc glfwMaximizeWindow * @ingroup platform */-void _glfwPlatformShowWindow(_GLFWwindow* window);+void _glfwPlatformMaximizeWindow(_GLFWwindow* window); -/*! @ingroup platform+/*! @copydoc glfwShowWindow+ * @ingroup platform */-void _glfwPlatformUnhideWindow(_GLFWwindow* window);+void _glfwPlatformShowWindow(_GLFWwindow* window); /*! @copydoc glfwHideWindow * @ingroup platform */ void _glfwPlatformHideWindow(_GLFWwindow* window); +/*! @copydoc glfwFocusWindow+ * @ingroup platform+ */+void _glfwPlatformFocusWindow(_GLFWwindow* window);++/*! @copydoc glfwSetWindowMonitor+ * @ingroup platform+ */+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);+ /*! @brief Returns whether the window is focused. * @ingroup platform */@@ -593,6 +736,11 @@ */ int _glfwPlatformWindowVisible(_GLFWwindow* window); +/*! @brief Returns whether the window is maximized.+ * @ingroup platform+ */+int _glfwPlatformWindowMaximized(_GLFWwindow* window);+ /*! @copydoc glfwPollEvents * @ingroup platform */@@ -603,41 +751,25 @@ */ void _glfwPlatformWaitEvents(void); +/*! @copydoc glfwWaitEventsTimeout+ * @ingroup platform+ */+void _glfwPlatformWaitEventsTimeout(double timeout);+ /*! @copydoc glfwPostEmptyEvent * @ingroup platform */ void _glfwPlatformPostEmptyEvent(void); -/*! @copydoc glfwMakeContextCurrent- * @ingroup platform+/*! @ingroup platform */-void _glfwPlatformMakeContextCurrent(_GLFWwindow* window);+void _glfwPlatformSetCurrentContext(_GLFWwindow* context); /*! @copydoc glfwGetCurrentContext * @ingroup platform */ _GLFWwindow* _glfwPlatformGetCurrentContext(void); -/*! @copydoc glfwSwapBuffers- * @ingroup platform- */-void _glfwPlatformSwapBuffers(_GLFWwindow* window);--/*! @copydoc glfwSwapInterval- * @ingroup platform- */-void _glfwPlatformSwapInterval(int interval);--/*! @copydoc glfwExtensionSupported- * @ingroup platform- */-int _glfwPlatformExtensionSupported(const char* extension);--/*! @copydoc glfwGetProcAddress- * @ingroup platform- */-GLFWglproc _glfwPlatformGetProcAddress(const char* procname);- /*! @copydoc glfwCreateCursor * @ingroup platform */@@ -658,18 +790,30 @@ */ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor); +/*! @ingroup platform+ */+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count); +/*! @ingroup platform+ */+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);++/*! @ingroup platform+ */+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);++ //======================================================================== // Event API functions //======================================================================== /*! @brief Notifies shared code of a window focus event. * @param[in] window The window that received the event.- * @param[in] focused `GL_TRUE` if the window received focus, or `GL_FALSE`+ * @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE` * if it lost focus. * @ingroup event */-void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused);+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); /*! @brief Notifies shared code of a window movement event. * @param[in] window The window that received the event.@@ -697,11 +841,11 @@ /*! @brief Notifies shared code of a window iconification event. * @param[in] window The window that received the event.- * @param[in] iconified `GL_TRUE` if the window was iconified, or `GL_FALSE`- * if it was restored.+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or+ * `GLFW_FALSE` if it was restored. * @ingroup event */-void _glfwInputWindowIconify(_GLFWwindow* window, int iconified);+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified); /*! @brief Notifies shared code of a window damage event. * @param[in] window The window that received the event.@@ -714,6 +858,8 @@ */ void _glfwInputWindowCloseRequest(_GLFWwindow* window); +void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);+ /*! @brief Notifies shared code of a physical key event. * @param[in] window The window that received the event. * @param[in] key The key that was pressed or released.@@ -728,19 +874,19 @@ * @param[in] window The window that received the event. * @param[in] codepoint The Unicode code point of the input character. * @param[in] mods Bit field describing which modifier keys were held down.- * @param[in] plain `GL_TRUE` if the character is regular text input, or- * `GL_FALSE` otherwise.+ * @param[in] plain `GLFW_TRUE` if the character is regular text input, or+ * `GLFW_FALSE` otherwise. * @ingroup event */-void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, int plain);+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain); /*! @brief Notifies shared code of a scroll event. * @param[in] window The window that received the event.- * @param[in] x The scroll offset along the x-axis.- * @param[in] y The scroll offset along the y-axis.+ * @param[in] xoffset The scroll offset along the x-axis.+ * @param[in] yoffset The scroll offset along the y-axis. * @ingroup event */-void _glfwInputScroll(_GLFWwindow* window, double x, double y);+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); /*! @brief Notifies shared code of a mouse button click event. * @param[in] window The window that received the event.@@ -752,33 +898,41 @@ /*! @brief Notifies shared code of a cursor motion event. * @param[in] window The window that received the event.- * @param[in] x The new x-coordinate of the cursor, relative to the left edge- * of the client area of the window.- * @param[in] y The new y-coordinate of the cursor, relative to the top edge+ * @param[in] xpos The new x-coordinate of the cursor, relative to the left+ * edge of the client area of the window.+ * @param[in] ypos The new y-coordinate of the cursor, relative to the top edge * of the client area of the window. * @ingroup event */-void _glfwInputCursorMotion(_GLFWwindow* window, double x, double y);+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); /*! @brief Notifies shared code of a cursor enter/leave event. * @param[in] window The window that received the event.- * @param[in] entered `GL_TRUE` if the cursor entered the client area of the- * window, or `GL_FALSE` if it left it.+ * @param[in] entered `GLFW_TRUE` if the cursor entered the client area of the+ * window, or `GLFW_FALSE` if it left it. * @ingroup event */-void _glfwInputCursorEnter(_GLFWwindow* window, int entered);+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered); /*! @ingroup event */ void _glfwInputMonitorChange(void); +/*! @ingroup event+ */+void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window);+ /*! @brief Notifies shared code of an error. * @param[in] error The error code most suitable for the error. * @param[in] format The `printf` style format string of the error * description. * @ingroup event */+#if defined(__GNUC__)+void _glfwInputError(int error, const char* format, ...) __attribute__((format(printf, 2, 3)));+#else void _glfwInputError(int error, const char* format, ...);+#endif /*! @brief Notifies dropped object over window. * @param[in] window The window that received the event.@@ -788,7 +942,14 @@ */ void _glfwInputDrop(_GLFWwindow* window, int count, const char** names); +/*! @brief Notifies shared code of a joystick connection/disconnection event.+ * @param[in] joy The joystick that was connected or disconnected.+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.+ * @ingroup event+ */+void _glfwInputJoystickChange(int joy, int event); + //======================================================================== // Utility functions //========================================================================@@ -811,10 +972,10 @@ /*! @brief Searches an extension string for the specified extension. * @param[in] string The extension string to search. * @param[in] extensions The extension to search for.- * @return `GL_TRUE` if the extension was found, or `GL_FALSE` otherwise.+ * @return `GLFW_TRUE` if the extension was found, or `GLFW_FALSE` otherwise. * @ingroup utility */-int _glfwStringInExtensionString(const char* string, const GLubyte* extensions);+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions); /*! @brief Chooses the framebuffer config that best matches the desired one. * @param[in] desired The desired framebuffer config.@@ -830,14 +991,15 @@ /*! @brief Retrieves the attributes of the current context. * @param[in] ctxconfig The desired context attributes.- * @return `GL_TRUE` if successful, or `GL_FALSE` if the context is unusable.+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if the context is+ * unusable. * @ingroup utility */-GLboolean _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);+GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig); /*! @brief Checks whether the desired context attributes are valid. * @param[in] ctxconfig The context attributes to check.- * @return `GL_TRUE` if the context attributes are valid, or `GL_FALSE`+ * @return `GLFW_TRUE` if the context attributes are valid, or `GLFW_FALSE` * otherwise. * @ingroup utility *@@ -845,16 +1007,7 @@ * exists and whether all relevant options have supported and non-conflicting * values. */-GLboolean _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);--/*! @brief Checks whether the current context fulfils the specified hard- * constraints.- * @param[in] ctxconfig The desired context attributes.- * @return `GL_TRUE` if the context fulfils the hard constraints, or `GL_FALSE`- * otherwise.- * @ingroup utility- */-GLboolean _glfwIsValidContext(const _GLFWctxconfig* ctxconfig);+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig); /*! @ingroup utility */@@ -883,4 +1036,20 @@ */ void _glfwFreeMonitors(_GLFWmonitor** monitors, int count); -#endif // _internal_h_+/*! @ingroup utility+ */+GLFWbool _glfwIsPrintable(int key);++/*! @ingroup utility+ */+GLFWbool _glfwInitVulkan(void);++/*! @ingroup utility+ */+void _glfwTerminateVulkan(void);++/*! @ingroup utility+ */+const char* _glfwGetVulkanResultString(VkResult result);++#endif // _glfw3_internal_h_
− glfw/src/iokit_joystick.h
@@ -1,61 +0,0 @@-//========================================================================-// GLFW 3.1 IOKit - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2006-2014 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#ifndef _iokit_joystick_h_-#define _iokit_joystick_h_--#include <IOKit/IOKitLib.h>-#include <IOKit/IOCFPlugIn.h>-#include <IOKit/hid/IOHIDLib.h>-#include <IOKit/hid/IOHIDKeys.h>--#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \- _GLFWjoystickIOKit iokit_js[GLFW_JOYSTICK_LAST + 1]---// IOKit-specific per-joystick data-//-typedef struct _GLFWjoystickIOKit-{- int present;- char name[256];-- IOHIDDeviceInterface** interface;-- CFMutableArrayRef axisElements;- CFMutableArrayRef buttonElements;- CFMutableArrayRef hatElements;-- float* axes;- unsigned char* buttons;--} _GLFWjoystickIOKit;---void _glfwInitJoysticks(void);-void _glfwTerminateJoysticks(void);--#endif // _iokit_joystick_h_
− glfw/src/iokit_joystick.m
@@ -1,506 +0,0 @@-//========================================================================-// GLFW 3.1 IOKit - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>-// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#include "internal.h"--#include <unistd.h>-#include <ctype.h>--#include <mach/mach.h>-#include <mach/mach_error.h>--#include <CoreFoundation/CoreFoundation.h>-#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>---//-------------------------------------------------------------------------// Joystick element information-//-------------------------------------------------------------------------typedef struct-{- IOHIDElementCookie cookie;-- long min;- long max;-- long minReport;- long maxReport;--} _GLFWjoyelement;---static void getElementsCFArrayHandler(const void* value, void* parameter);---// Adds an element to the specified joystick-//-static void addJoystickElement(_GLFWjoystickIOKit* joystick, CFTypeRef elementRef)-{- long elementType, usagePage, usage;- CFMutableArrayRef elementsArray = NULL;-- CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementTypeKey)),- kCFNumberLongType, &elementType);- CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsagePageKey)),- kCFNumberLongType, &usagePage);- CFNumberGetValue(CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementUsageKey)),- kCFNumberLongType, &usage);-- if ((elementType == kIOHIDElementTypeInput_Axis) ||- (elementType == kIOHIDElementTypeInput_Button) ||- (elementType == kIOHIDElementTypeInput_Misc))- {- switch (usagePage)- {- case kHIDPage_GenericDesktop:- {- switch (usage)- {- case kHIDUsage_GD_X:- case kHIDUsage_GD_Y:- case kHIDUsage_GD_Z:- case kHIDUsage_GD_Rx:- case kHIDUsage_GD_Ry:- case kHIDUsage_GD_Rz:- case kHIDUsage_GD_Slider:- case kHIDUsage_GD_Dial:- case kHIDUsage_GD_Wheel:- elementsArray = joystick->axisElements;- break;- case kHIDUsage_GD_Hatswitch:- elementsArray = joystick->hatElements;- break;- }-- break;- }-- case kHIDPage_Button:- elementsArray = joystick->buttonElements;- break;- default:- break;- }-- if (elementsArray)- {- long number;- CFTypeRef numberRef;- _GLFWjoyelement* element = calloc(1, sizeof(_GLFWjoyelement));-- CFArrayAppendValue(elementsArray, element);-- numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementCookieKey));- if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))- element->cookie = (IOHIDElementCookie) number;-- numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMinKey));- if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))- element->minReport = element->min = number;-- numberRef = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementMaxKey));- if (numberRef && CFNumberGetValue(numberRef, kCFNumberLongType, &number))- element->maxReport = element->max = number;- }- }- else- {- CFTypeRef array = CFDictionaryGetValue(elementRef, CFSTR(kIOHIDElementKey));- if (array)- {- if (CFGetTypeID(array) == CFArrayGetTypeID())- {- CFRange range = { 0, CFArrayGetCount(array) };- CFArrayApplyFunction(array, range, getElementsCFArrayHandler, joystick);- }- }- }-}--// Adds an element to the specified joystick-//-static void getElementsCFArrayHandler(const void* value, void* parameter)-{- if (CFGetTypeID(value) == CFDictionaryGetTypeID())- addJoystickElement((_GLFWjoystickIOKit*) parameter, (CFTypeRef) value);-}--// Returns the value of the specified element of the specified joystick-//-static long getElementValue(_GLFWjoystickIOKit* joystick, _GLFWjoyelement* element)-{- IOReturn result = kIOReturnSuccess;- IOHIDEventStruct hidEvent;- hidEvent.value = 0;-- if (joystick && element && joystick->interface)- {- result = (*(joystick->interface))->getElementValue(joystick->interface,- element->cookie,- &hidEvent);- if (kIOReturnSuccess == result)- {- // Record min and max for auto calibration- if (hidEvent.value < element->minReport)- element->minReport = hidEvent.value;- if (hidEvent.value > element->maxReport)- element->maxReport = hidEvent.value;- }- }-- // Auto user scale- return (long) hidEvent.value;-}--// Removes the specified joystick-//-static void removeJoystick(_GLFWjoystickIOKit* joystick)-{- int i;-- if (!joystick->present)- return;-- for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)- free((void*) CFArrayGetValueAtIndex(joystick->axisElements, i));- CFArrayRemoveAllValues(joystick->axisElements);-- for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)- free((void*) CFArrayGetValueAtIndex(joystick->buttonElements, i));- CFArrayRemoveAllValues(joystick->buttonElements);-- for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)- free((void*) CFArrayGetValueAtIndex(joystick->hatElements, i));- CFArrayRemoveAllValues(joystick->hatElements);-- free(joystick->axes);- free(joystick->buttons);-- (*(joystick->interface))->close(joystick->interface);- (*(joystick->interface))->Release(joystick->interface);-- memset(joystick, 0, sizeof(_GLFWjoystickIOKit));-}--// Callback for user-initiated joystick removal-//-static void removalCallback(void* target, IOReturn result, void* refcon, void* sender)-{- removeJoystick((_GLFWjoystickIOKit*) refcon);-}--// Polls for joystick events and updates GLFW state-//-static void pollJoystickEvents(void)-{- int joy;-- for (joy = 0; joy <= GLFW_JOYSTICK_LAST; joy++)- {- CFIndex i;- int buttonIndex = 0;- _GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;-- if (!joystick->present)- continue;-- for (i = 0; i < CFArrayGetCount(joystick->buttonElements); i++)- {- _GLFWjoyelement* button =- (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->buttonElements, i);-- if (getElementValue(joystick, button))- joystick->buttons[buttonIndex++] = GLFW_PRESS;- else- joystick->buttons[buttonIndex++] = GLFW_RELEASE;- }-- for (i = 0; i < CFArrayGetCount(joystick->axisElements); i++)- {- _GLFWjoyelement* axis =- (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->axisElements, i);-- long value = getElementValue(joystick, axis);- long readScale = axis->maxReport - axis->minReport;-- if (readScale == 0)- joystick->axes[i] = value;- else- joystick->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;- }-- for (i = 0; i < CFArrayGetCount(joystick->hatElements); i++)- {- _GLFWjoyelement* hat =- (_GLFWjoyelement*) CFArrayGetValueAtIndex(joystick->hatElements, i);-- // Bit fields of button presses for each direction, including nil- const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };-- long j, value = getElementValue(joystick, hat);- if (value < 0 || value > 8)- value = 8;-- for (j = 0; j < 4; j++)- {- if (directions[value] & (1 << j))- joystick->buttons[buttonIndex++] = GLFW_PRESS;- else- joystick->buttons[buttonIndex++] = GLFW_RELEASE;- }- }- }-}---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Initialize joystick interface-//-void _glfwInitJoysticks(void)-{- int joy = 0;- IOReturn result = kIOReturnSuccess;- mach_port_t masterPort = 0;- io_iterator_t objectIterator = 0;- CFMutableDictionaryRef hidMatchDictionary = NULL;- io_object_t ioHIDDeviceObject = 0;-- result = IOMasterPort(bootstrap_port, &masterPort);- hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey);- if (kIOReturnSuccess != result || !hidMatchDictionary)- {- if (hidMatchDictionary)- CFRelease(hidMatchDictionary);-- return;- }-- result = IOServiceGetMatchingServices(masterPort,- hidMatchDictionary,- &objectIterator);- if (result != kIOReturnSuccess)- return;-- if (!objectIterator)- {- // There are no joysticks- return;- }-- while ((ioHIDDeviceObject = IOIteratorNext(objectIterator)))- {- CFMutableDictionaryRef propsRef = NULL;- CFTypeRef valueRef = NULL;- kern_return_t result;-- IOCFPlugInInterface** ppPlugInInterface = NULL;- HRESULT plugInResult = S_OK;- SInt32 score = 0;-- long usagePage = 0;- long usage = 0;-- valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,- CFSTR(kIOHIDPrimaryUsagePageKey),- kCFAllocatorDefault, kNilOptions);- if (valueRef)- {- CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage);- CFRelease(valueRef);- }-- valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject,- CFSTR(kIOHIDPrimaryUsageKey),- kCFAllocatorDefault, kNilOptions);- if (valueRef)- {- CFNumberGetValue(valueRef, kCFNumberLongType, &usage);- CFRelease(valueRef);- }-- if (usagePage != kHIDPage_GenericDesktop)- {- // This device is not relevant to GLFW- continue;- }-- if ((usage != kHIDUsage_GD_Joystick &&- usage != kHIDUsage_GD_GamePad &&- usage != kHIDUsage_GD_MultiAxisController))- {- // This device is not relevant to GLFW- continue;- }- - result = IORegistryEntryCreateCFProperties(ioHIDDeviceObject,- &propsRef,- kCFAllocatorDefault,- kNilOptions);- - if (result != kIOReturnSuccess)- continue;-- _GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;- joystick->present = GL_TRUE;-- result = IOCreatePlugInInterfaceForService(ioHIDDeviceObject,- kIOHIDDeviceUserClientTypeID,- kIOCFPlugInInterfaceID,- &ppPlugInInterface,- &score);-- if (kIOReturnSuccess != result)- {- CFRelease(propsRef);- return;- }-- plugInResult = (*ppPlugInInterface)->QueryInterface(- ppPlugInInterface,- CFUUIDGetUUIDBytes(kIOHIDDeviceInterfaceID),- (void *) &(joystick->interface));-- if (plugInResult != S_OK)- {- CFRelease(propsRef);- return;- }-- (*ppPlugInInterface)->Release(ppPlugInInterface);-- (*(joystick->interface))->open(joystick->interface, 0);- (*(joystick->interface))->setRemovalCallback(joystick->interface,- removalCallback,- joystick,- joystick);-- // Get product string- valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDProductKey));- if (valueRef)- {- CFStringGetCString(valueRef,- joystick->name,- sizeof(joystick->name),- kCFStringEncodingUTF8);- }-- joystick->axisElements = CFArrayCreateMutable(NULL, 0, NULL);- joystick->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);- joystick->hatElements = CFArrayCreateMutable(NULL, 0, NULL);-- valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDElementKey));- if (CFGetTypeID(valueRef) == CFArrayGetTypeID())- {- CFRange range = { 0, CFArrayGetCount(valueRef) };- CFArrayApplyFunction(valueRef,- range,- getElementsCFArrayHandler,- (void*) joystick);- }-- CFRelease(propsRef);-- joystick->axes = calloc(CFArrayGetCount(joystick->axisElements),- sizeof(float));- joystick->buttons = calloc(CFArrayGetCount(joystick->buttonElements) +- CFArrayGetCount(joystick->hatElements) * 4, 1);-- joy++;- if (joy > GLFW_JOYSTICK_LAST)- break;- }-}--// Close all opened joystick handles-//-void _glfwTerminateJoysticks(void)-{- int i;-- for (i = 0; i < GLFW_JOYSTICK_LAST + 1; i++)- {- _GLFWjoystickIOKit* joystick = &_glfw.iokit_js[i];- removeJoystick(joystick);-- if (joystick->axisElements)- CFRelease(joystick->axisElements);- if (joystick->buttonElements)- CFRelease(joystick->buttonElements);- if (joystick->hatElements)- CFRelease(joystick->hatElements);- }-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformJoystickPresent(int joy)-{- pollJoystickEvents();-- return _glfw.iokit_js[joy].present;-}--const float* _glfwPlatformGetJoystickAxes(int joy, int* count)-{- _GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;-- pollJoystickEvents();-- if (!joystick->present)- return NULL;-- *count = (int) CFArrayGetCount(joystick->axisElements);- return joystick->axes;-}--const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)-{- _GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy;-- pollJoystickEvents();-- if (!joystick->present)- return NULL;-- *count = (int) CFArrayGetCount(joystick->buttonElements) +- (int) CFArrayGetCount(joystick->hatElements) * 4;- return joystick->buttons;-}--const char* _glfwPlatformGetJoystickName(int joy)-{- pollJoystickEvents();-- return _glfw.iokit_js[joy].name;-}-
glfw/src/linux_joystick.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Linux - www.glfw.org+// GLFW 3.2 Linux - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -45,12 +45,13 @@ // Attempt to open the specified joystick device //-static void openJoystickDevice(const char* path)-{ #if defined(__linux__)+static GLFWbool openJoystickDevice(const char* path)+{ char axisCount, buttonCount;- char name[256];+ char name[256] = ""; int joy, fd, version;+ _GLFWjoystickLinux* js; for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++) {@@ -58,7 +59,7 @@ continue; if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)- return;+ return GLFW_FALSE; } for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)@@ -68,13 +69,11 @@ } if (joy > GLFW_JOYSTICK_LAST)- return;+ return GLFW_FALSE; fd = open(path, O_RDONLY | O_NONBLOCK); if (fd == -1)- return;-- _glfw.linux_js.js[joy].fd = fd;+ return GLFW_FALSE; // Verify that the joystick driver version is at least 1.0 ioctl(fd, JSIOCGVERSION, &version);@@ -82,116 +81,102 @@ { // It's an old 0.x interface (we don't support it) close(fd);- return;+ return GLFW_FALSE; } if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0) strncpy(name, "Unknown", sizeof(name)); - _glfw.linux_js.js[joy].name = strdup(name);- _glfw.linux_js.js[joy].path = strdup(path);+ js = _glfw.linux_js.js + joy;+ js->present = GLFW_TRUE;+ js->name = strdup(name);+ js->path = strdup(path);+ js->fd = fd; ioctl(fd, JSIOCGAXES, &axisCount);- _glfw.linux_js.js[joy].axisCount = (int) axisCount;+ js->axisCount = (int) axisCount;+ js->axes = calloc(axisCount, sizeof(float)); ioctl(fd, JSIOCGBUTTONS, &buttonCount);- _glfw.linux_js.js[joy].buttonCount = (int) buttonCount;-- _glfw.linux_js.js[joy].axes = calloc(axisCount, sizeof(float));- _glfw.linux_js.js[joy].buttons = calloc(buttonCount, 1);+ js->buttonCount = (int) buttonCount;+ js->buttons = calloc(buttonCount, 1); - _glfw.linux_js.js[joy].present = GL_TRUE;-#endif // __linux__+ _glfwInputJoystickChange(joy, GLFW_CONNECTED);+ return GLFW_TRUE; }+#endif // __linux__ -// Polls for and processes events for all present joysticks+// Polls for and processes events the specified joystick //-static void pollJoystickEvents(void)+static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js) { #if defined(__linux__)- int i;- struct js_event e;- ssize_t offset = 0;- char buffer[16384];-- const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));-- while (size > offset)- {- regmatch_t match;- const struct inotify_event* e = (struct inotify_event*) (buffer + offset);-- if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)- {- char path[20];- snprintf(path, sizeof(path), "/dev/input/%s", e->name);- openJoystickDevice(path);- }+ _glfwPollJoystickEvents(); - offset += sizeof(struct inotify_event) + e->len;- }+ if (!js->present)+ return GLFW_FALSE; - for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)+ // Read all queued events (non-blocking)+ for (;;) {- if (!_glfw.linux_js.js[i].present)- continue;+ struct js_event e; - // Read all queued events (non-blocking)- for (;;)+ errno = 0;+ if (read(js->fd, &e, sizeof(e)) < 0) {- errno = 0;- if (read(_glfw.linux_js.js[i].fd, &e, sizeof(e)) < 0)+ // Reset the joystick slot if the device was disconnected+ if (errno == ENODEV) {- if (errno == ENODEV)- {- // The joystick was disconnected-- free(_glfw.linux_js.js[i].axes);- free(_glfw.linux_js.js[i].buttons);- free(_glfw.linux_js.js[i].name);- free(_glfw.linux_js.js[i].path);+ free(js->axes);+ free(js->buttons);+ free(js->name);+ free(js->path); - memset(&_glfw.linux_js.js[i], 0, sizeof(_glfw.linux_js.js[i]));- }+ memset(js, 0, sizeof(_GLFWjoystickLinux)); - break;+ _glfwInputJoystickChange(js - _glfw.linux_js.js,+ GLFW_DISCONNECTED); } - // We don't care if it's an init event or not- e.type &= ~JS_EVENT_INIT;-- switch (e.type)- {- case JS_EVENT_AXIS:- _glfw.linux_js.js[i].axes[e.number] =- (float) e.value / 32767.0f;- break;+ break;+ } - case JS_EVENT_BUTTON:- _glfw.linux_js.js[i].buttons[e.number] =- e.value ? GLFW_PRESS : GLFW_RELEASE;- break;+ // Clear the initial-state bit+ e.type &= ~JS_EVENT_INIT; - default:- break;- }- }+ if (e.type == JS_EVENT_AXIS)+ js->axes[e.number] = (float) e.value / 32767.0f;+ else if (e.type == JS_EVENT_BUTTON)+ js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE; } #endif // __linux__+ return js->present; } +// Lexically compare joysticks by name; used by qsort+//+#if defined(__linux__)+static int compareJoysticks(const void* fp, const void* sp)+{+ const _GLFWjoystickLinux* fj = fp;+ const _GLFWjoystickLinux* sj = sp;+ return strcmp(fj->path, sj->path);+}+#endif // __linux__ + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialize joystick interface //-int _glfwInitJoysticks(void)+GLFWbool _glfwInitJoysticksLinux(void) { #if defined(__linux__)- const char* dirname = "/dev/input"; DIR* dir;+ int count = 0;+ const char* dirname = "/dev/input"; _glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); if (_glfw.linux_js.inotify == -1)@@ -199,7 +184,7 @@ _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to initialize inotify: %s", strerror(errno));- return GL_FALSE;+ return GLFW_FALSE; } // HACK: Register for IN_ATTRIB as well to get notified when udev is done@@ -220,7 +205,7 @@ if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0) { _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");- return GL_FALSE;+ return GLFW_FALSE; } dir = opendir(dirname);@@ -237,7 +222,8 @@ continue; snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);- openJoystickDevice(path);+ if (openJoystickDevice(path))+ count++; } closedir(dir);@@ -251,14 +237,15 @@ // Continue with no joysticks detected } + qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks); #endif // __linux__ - return GL_TRUE;+ return GLFW_TRUE; } // Close all opened joystick handles //-void _glfwTerminateJoysticks(void)+void _glfwTerminateJoysticksLinux(void) { #if defined(__linux__) int i;@@ -287,38 +274,68 @@ #endif // __linux__ } +void _glfwPollJoystickEvents(void)+{+#if defined(__linux__)+ ssize_t offset = 0;+ char buffer[16384]; + const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));++ while (size > offset)+ {+ regmatch_t match;+ const struct inotify_event* e = (struct inotify_event*) (buffer + offset);++ if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)+ {+ char path[20];+ snprintf(path, sizeof(path), "/dev/input/%s", e->name);+ openJoystickDevice(path);+ }++ offset += sizeof(struct inotify_event) + e->len;+ }+#endif+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// int _glfwPlatformJoystickPresent(int joy) {- pollJoystickEvents();-- return _glfw.linux_js.js[joy].present;+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;+ return pollJoystickEvents(js); } const float* _glfwPlatformGetJoystickAxes(int joy, int* count) {- pollJoystickEvents();+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;+ if (!pollJoystickEvents(js))+ return NULL; - *count = _glfw.linux_js.js[joy].axisCount;- return _glfw.linux_js.js[joy].axes;+ *count = js->axisCount;+ return js->axes; } const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count) {- pollJoystickEvents();+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;+ if (!pollJoystickEvents(js))+ return NULL; - *count = _glfw.linux_js.js[joy].buttonCount;- return _glfw.linux_js.js[joy].buttons;+ *count = js->buttonCount;+ return js->buttons; } const char* _glfwPlatformGetJoystickName(int joy) {- pollJoystickEvents();+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;+ if (!pollJoystickEvents(js))+ return NULL; - return _glfw.linux_js.js[joy].name;+ return js->name; }
glfw/src/linux_joystick.h view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Linux - www.glfw.org+// GLFW 3.2 Linux - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -24,40 +24,45 @@ // //======================================================================== -#ifndef _linux_joystick_h_-#define _linux_joystick_h_+#ifndef _glfw3_linux_joystick_h_+#define _glfw3_linux_joystick_h_ #include <regex.h> -#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \- _GLFWjoystickLinux linux_js+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js -// Linux-specific joystick API data+// Linux-specific joystick data // typedef struct _GLFWjoystickLinux {- struct- {- int present;- int fd;- float* axes;- int axisCount;- unsigned char* buttons;- int buttonCount;- char* name;- char* path;- } js[GLFW_JOYSTICK_LAST + 1];+ GLFWbool present;+ int fd;+ float* axes;+ int axisCount;+ unsigned char* buttons;+ int buttonCount;+ char* name;+ char* path;+} _GLFWjoystickLinux; +// Linux-specific joystick API data+//+typedef struct _GLFWjoylistLinux+{+ _GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];+ #if defined(__linux__) int inotify; int watch; regex_t regex; #endif /*__linux__*/-} _GLFWjoystickLinux;+} _GLFWjoylistLinux; -int _glfwInitJoysticks(void);-void _glfwTerminateJoysticks(void);+GLFWbool _glfwInitJoysticksLinux(void);+void _glfwTerminateJoysticksLinux(void); -#endif // _linux_joystick_h_+void _glfwPollJoystickEvents(void);++#endif // _glfw3_linux_joystick_h_
− glfw/src/mach_time.c
@@ -1,71 +0,0 @@-//========================================================================-// GLFW 3.1 OS X - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#include "internal.h"--#include <mach/mach_time.h>---// Return raw time-//-static uint64_t getRawTime(void)-{- return mach_absolute_time();-}---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Initialise timer-//-void _glfwInitTimer(void)-{- mach_timebase_info_data_t info;- mach_timebase_info(&info);-- _glfw.ns_time.resolution = (double) info.numer / (info.denom * 1.0e9);- _glfw.ns_time.base = getRawTime();-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--double _glfwPlatformGetTime(void)-{- return (double) (getRawTime() - _glfw.ns_time.base) *- _glfw.ns_time.resolution;-}--void _glfwPlatformSetTime(double time)-{- _glfw.ns_time.base = getRawTime() -- (uint64_t) (time / _glfw.ns_time.resolution);-}-
glfw/src/mir_init.c view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 Mir - www.glfw.org+// GLFW 3.2 Mir - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -26,10 +26,136 @@ #include "internal.h" +#include <linux/input.h> #include <stdlib.h> #include <string.h> +// Create key code translation tables+//+static void createKeyTables(void)+{+ memset(_glfw.mir.publicKeys, -1, sizeof(_glfw.mir.publicKeys));++ _glfw.mir.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;+ _glfw.mir.publicKeys[KEY_1] = GLFW_KEY_1;+ _glfw.mir.publicKeys[KEY_2] = GLFW_KEY_2;+ _glfw.mir.publicKeys[KEY_3] = GLFW_KEY_3;+ _glfw.mir.publicKeys[KEY_4] = GLFW_KEY_4;+ _glfw.mir.publicKeys[KEY_5] = GLFW_KEY_5;+ _glfw.mir.publicKeys[KEY_6] = GLFW_KEY_6;+ _glfw.mir.publicKeys[KEY_7] = GLFW_KEY_7;+ _glfw.mir.publicKeys[KEY_8] = GLFW_KEY_8;+ _glfw.mir.publicKeys[KEY_9] = GLFW_KEY_9;+ _glfw.mir.publicKeys[KEY_0] = GLFW_KEY_0;+ _glfw.mir.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;+ _glfw.mir.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;+ _glfw.mir.publicKeys[KEY_Q] = GLFW_KEY_Q;+ _glfw.mir.publicKeys[KEY_W] = GLFW_KEY_W;+ _glfw.mir.publicKeys[KEY_E] = GLFW_KEY_E;+ _glfw.mir.publicKeys[KEY_R] = GLFW_KEY_R;+ _glfw.mir.publicKeys[KEY_T] = GLFW_KEY_T;+ _glfw.mir.publicKeys[KEY_Y] = GLFW_KEY_Y;+ _glfw.mir.publicKeys[KEY_U] = GLFW_KEY_U;+ _glfw.mir.publicKeys[KEY_I] = GLFW_KEY_I;+ _glfw.mir.publicKeys[KEY_O] = GLFW_KEY_O;+ _glfw.mir.publicKeys[KEY_P] = GLFW_KEY_P;+ _glfw.mir.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;+ _glfw.mir.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;+ _glfw.mir.publicKeys[KEY_A] = GLFW_KEY_A;+ _glfw.mir.publicKeys[KEY_S] = GLFW_KEY_S;+ _glfw.mir.publicKeys[KEY_D] = GLFW_KEY_D;+ _glfw.mir.publicKeys[KEY_F] = GLFW_KEY_F;+ _glfw.mir.publicKeys[KEY_G] = GLFW_KEY_G;+ _glfw.mir.publicKeys[KEY_H] = GLFW_KEY_H;+ _glfw.mir.publicKeys[KEY_J] = GLFW_KEY_J;+ _glfw.mir.publicKeys[KEY_K] = GLFW_KEY_K;+ _glfw.mir.publicKeys[KEY_L] = GLFW_KEY_L;+ _glfw.mir.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;+ _glfw.mir.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;+ _glfw.mir.publicKeys[KEY_Z] = GLFW_KEY_Z;+ _glfw.mir.publicKeys[KEY_X] = GLFW_KEY_X;+ _glfw.mir.publicKeys[KEY_C] = GLFW_KEY_C;+ _glfw.mir.publicKeys[KEY_V] = GLFW_KEY_V;+ _glfw.mir.publicKeys[KEY_B] = GLFW_KEY_B;+ _glfw.mir.publicKeys[KEY_N] = GLFW_KEY_N;+ _glfw.mir.publicKeys[KEY_M] = GLFW_KEY_M;+ _glfw.mir.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;+ _glfw.mir.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;+ _glfw.mir.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;+ _glfw.mir.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;+ _glfw.mir.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;+ _glfw.mir.publicKeys[KEY_TAB] = GLFW_KEY_TAB;+ _glfw.mir.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;+ _glfw.mir.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;+ _glfw.mir.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;+ _glfw.mir.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;+ _glfw.mir.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;+ _glfw.mir.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;+ _glfw.mir.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;+ _glfw.mir.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;+ _glfw.mir.publicKeys[KEY_MENU] = GLFW_KEY_MENU;+ _glfw.mir.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;+ _glfw.mir.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;+ _glfw.mir.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;+ _glfw.mir.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;+ _glfw.mir.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;+ _glfw.mir.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;+ _glfw.mir.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;+ _glfw.mir.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;+ _glfw.mir.publicKeys[KEY_HOME] = GLFW_KEY_HOME;+ _glfw.mir.publicKeys[KEY_END] = GLFW_KEY_END;+ _glfw.mir.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;+ _glfw.mir.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;+ _glfw.mir.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;+ _glfw.mir.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;+ _glfw.mir.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;+ _glfw.mir.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;+ _glfw.mir.publicKeys[KEY_UP] = GLFW_KEY_UP;+ _glfw.mir.publicKeys[KEY_F1] = GLFW_KEY_F1;+ _glfw.mir.publicKeys[KEY_F2] = GLFW_KEY_F2;+ _glfw.mir.publicKeys[KEY_F3] = GLFW_KEY_F3;+ _glfw.mir.publicKeys[KEY_F4] = GLFW_KEY_F4;+ _glfw.mir.publicKeys[KEY_F5] = GLFW_KEY_F5;+ _glfw.mir.publicKeys[KEY_F6] = GLFW_KEY_F6;+ _glfw.mir.publicKeys[KEY_F7] = GLFW_KEY_F7;+ _glfw.mir.publicKeys[KEY_F8] = GLFW_KEY_F8;+ _glfw.mir.publicKeys[KEY_F9] = GLFW_KEY_F9;+ _glfw.mir.publicKeys[KEY_F10] = GLFW_KEY_F10;+ _glfw.mir.publicKeys[KEY_F11] = GLFW_KEY_F11;+ _glfw.mir.publicKeys[KEY_F12] = GLFW_KEY_F12;+ _glfw.mir.publicKeys[KEY_F13] = GLFW_KEY_F13;+ _glfw.mir.publicKeys[KEY_F14] = GLFW_KEY_F14;+ _glfw.mir.publicKeys[KEY_F15] = GLFW_KEY_F15;+ _glfw.mir.publicKeys[KEY_F16] = GLFW_KEY_F16;+ _glfw.mir.publicKeys[KEY_F17] = GLFW_KEY_F17;+ _glfw.mir.publicKeys[KEY_F18] = GLFW_KEY_F18;+ _glfw.mir.publicKeys[KEY_F19] = GLFW_KEY_F19;+ _glfw.mir.publicKeys[KEY_F20] = GLFW_KEY_F20;+ _glfw.mir.publicKeys[KEY_F21] = GLFW_KEY_F21;+ _glfw.mir.publicKeys[KEY_F22] = GLFW_KEY_F22;+ _glfw.mir.publicKeys[KEY_F23] = GLFW_KEY_F23;+ _glfw.mir.publicKeys[KEY_F24] = GLFW_KEY_F24;+ _glfw.mir.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;+ _glfw.mir.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;+ _glfw.mir.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;+ _glfw.mir.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;+ _glfw.mir.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;+ _glfw.mir.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;+ _glfw.mir.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;+ _glfw.mir.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;+ _glfw.mir.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;+ _glfw.mir.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;+ _glfw.mir.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;+ _glfw.mir.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;+ _glfw.mir.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;+ _glfw.mir.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;+ _glfw.mir.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;+ _glfw.mir.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;+ _glfw.mir.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// //////////////////////////////////////////////////////////////////////////@@ -46,39 +172,47 @@ "Mir: Unable to connect to server: %s", mir_connection_get_error_message(_glfw.mir.connection)); - return GL_FALSE;+ return GLFW_FALSE; } _glfw.mir.display = mir_connection_get_egl_native_display(_glfw.mir.connection); - if (!_glfwInitContextAPI())- return GL_FALSE;+ createKeyTables(); - _glfwInitTimer();- _glfwInitJoysticks();+ if (!_glfwInitThreadLocalStoragePOSIX())+ return GLFW_FALSE; + if (!_glfwInitJoysticksLinux())+ return GLFW_FALSE;++ _glfwInitTimerPOSIX();++ // Need the default conf for when we set a NULL cursor+ _glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);+ _glfw.mir.event_queue = calloc(1, sizeof(EventQueue));- _glfwInitEventQueue(_glfw.mir.event_queue);+ _glfwInitEventQueueMir(_glfw.mir.event_queue); error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL); if (error) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Failed to create event mutex: %s\n",+ "Mir: Failed to create event mutex: %s", strerror(error));- return GL_FALSE;+ return GLFW_FALSE; } - return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformTerminate(void) {- _glfwTerminateContextAPI();- _glfwTerminateJoysticks();+ _glfwTerminateEGL();+ _glfwTerminateJoysticksLinux();+ _glfwTerminateThreadLocalStoragePOSIX(); - _glfwDeleteEventQueue(_glfw.mir.event_queue);+ _glfwDeleteEventQueueMir(_glfw.mir.event_queue); pthread_mutex_destroy(&_glfw.mir.event_mutex); @@ -87,15 +221,18 @@ const char* _glfwPlatformGetVersionString(void) {- const char* version = _GLFW_VERSION_NUMBER " Mir EGL"+ return _GLFW_VERSION_NUMBER " Mir EGL" #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) " clock_gettime"+#else+ " gettimeofday" #endif+#if defined(__linux__)+ " /dev/js"+#endif #if defined(_GLFW_BUILD_DLL) " shared" #endif ;-- return version; }
glfw/src/mir_monitor.c view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 Mir - www.glfw.org+// GLFW 3.2 Mir - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -73,7 +73,7 @@ return monitors; } -GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) { return first->mir.output_id == second->mir.output_id; }@@ -86,6 +86,39 @@ *ypos = monitor->mir.y; } +void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)+{+ switch (pf)+ {+ case mir_pixel_format_rgb_565:+ mode->redBits = 5;+ mode->greenBits = 6;+ mode->blueBits = 5;+ break;+ case mir_pixel_format_rgba_5551:+ mode->redBits = 5;+ mode->greenBits = 5;+ mode->blueBits = 5;+ break;+ case mir_pixel_format_rgba_4444:+ mode->redBits = 4;+ mode->greenBits = 4;+ mode->blueBits = 4;+ break;+ case mir_pixel_format_abgr_8888:+ case mir_pixel_format_xbgr_8888:+ case mir_pixel_format_argb_8888:+ case mir_pixel_format_xrgb_8888:+ case mir_pixel_format_bgr_888:+ case mir_pixel_format_rgb_888:+ default:+ mode->redBits = 8;+ mode->greenBits = 8;+ mode->blueBits = 8;+ break;+ }+}+ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found) { int i;@@ -106,9 +139,8 @@ modes[*found].width = out->modes[*found].horizontal_resolution; modes[*found].height = out->modes[*found].vertical_resolution; modes[*found].refreshRate = out->modes[*found].refresh_rate;- modes[*found].redBits = 8;- modes[*found].greenBits = 8;- modes[*found].blueBits = 8;++ FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]); } break;@@ -127,12 +159,24 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW native API //////+//////////////////////////////////////////////////////////////////////////++GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)+{+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ _GLFW_REQUIRE_INIT_OR_RETURN(0);+ return monitor->mir.output_id; }
glfw/src/mir_platform.h view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 Mir - www.glfw.org+// GLFW 3.2 Mir - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -24,33 +24,51 @@ // //======================================================================== -#ifndef _mir_platform_h_-#define _mir_platform_h_+#ifndef _glfw3_mir_platform_h_+#define _glfw3_mir_platform_h_ +#include <sys/queue.h>+#include <pthread.h>+#include <dlfcn.h>+ #include <mir_toolkit/mir_client_library.h> +typedef VkFlags VkMirSurfaceCreateFlagsKHR;++typedef struct VkMirSurfaceCreateInfoKHR+{+ VkStructureType sType;+ const void* pNext;+ VkMirSurfaceCreateFlagsKHR flags;+ MirConnection* connection;+ MirSurface* mirSurface;+} VkMirSurfaceCreateInfoKHR;++typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);+ #include "posix_tls.h" #include "posix_time.h" #include "linux_joystick.h"--#include <sys/queue.h>--#include <pthread.h>+#include "xkb_unicode.h"+#include "egl_context.h" -#if defined(_GLFW_EGL)- #include "egl_context.h"-#else- #error "The Mir backend depends on EGL platform support"-#endif+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)+#define _glfw_dlclose(handle) dlclose(handle)+#define _glfw_dlsym(handle, name) dlsym(handle, name) -#define _GLFW_EGL_NATIVE_WINDOW window->mir.window-#define _GLFW_EGL_NATIVE_DISPLAY _glfw.mir.display+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.window)+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display) #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir +#define _GLFW_PLATFORM_CONTEXT_STATE+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE++ // Mir-specific Event Queue // typedef struct EventQueue@@ -69,7 +87,6 @@ } _GLFWwindowMir; - // Mir-specific per-monitor data // typedef struct _GLFWmonitorMir@@ -81,30 +98,33 @@ } _GLFWmonitorMir; - // Mir-specific global data // typedef struct _GLFWlibraryMir { MirConnection* connection; MirEGLNativeDisplayType display;+ MirCursorConfiguration* default_conf; EventQueue* event_queue; + short int publicKeys[256];+ pthread_mutex_t event_mutex; pthread_cond_t event_cond; } _GLFWlibraryMir; - // Mir-specific per-cursor data // TODO: Only system cursors are implemented in Mir atm. Need to wait for support. // typedef struct _GLFWcursorMir {+ MirCursorConfiguration* conf;+ MirBufferStream* custom_cursor; } _GLFWcursorMir; -extern void _glfwInitEventQueue(EventQueue* queue);-extern void _glfwDeleteEventQueue(EventQueue* queue);+extern void _glfwInitEventQueueMir(EventQueue* queue);+extern void _glfwDeleteEventQueueMir(EventQueue* queue); -#endif // _mir_platform_h_+#endif // _glfw3_mir_platform_h_
glfw/src/mir_window.c view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 Mir - www.glfw.org+// GLFW 3.2 Mir - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2014 Brandon Schaefer <brandon.schaefer@canonical.com>+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,7 +25,6 @@ //======================================================================== #include "internal.h"-#include "xkb_unicode.h" #include <linux/input.h> #include <stdlib.h>@@ -35,32 +34,34 @@ typedef struct EventNode { TAILQ_ENTRY(EventNode) entries;- MirEvent* event;+ const MirEvent* event; _GLFWwindow* window; } EventNode; static void deleteNode(EventQueue* queue, EventNode* node) {- free(node->event);+ mir_event_unref(node->event); free(node); } -static int emptyEventQueue(EventQueue* queue)+static GLFWbool emptyEventQueue(EventQueue* queue) {- return queue->head.tqh_first == NULL ? GL_TRUE : GL_FALSE;+ return queue->head.tqh_first == NULL; } -static EventNode* newEventNode(MirEvent const* event, _GLFWwindow* context)+// TODO The mir_event_ref is not supposed to be used but ... its needed+// in this case. Need to wait until we can read from an FD set up by mir+// for single threaded event handling.+static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context) { EventNode* new_node = calloc(1, sizeof(EventNode));- new_node->event = calloc(1, sizeof(MirEvent));+ new_node->event = mir_event_ref(event); new_node->window = context; - memcpy(new_node->event, event, sizeof(MirEvent)); return new_node; } -static void enqueueEvent(MirEvent const* event, _GLFWwindow* context)+static void enqueueEvent(const MirEvent* event, _GLFWwindow* context) { pthread_mutex_lock(&_glfw.mir.event_mutex); @@ -88,6 +89,9 @@ return node; } +/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out+ the best pixel format!+*/ static MirPixelFormat findValidPixelFormat(void) { unsigned int i, validFormats, mirPixelFormats = 32;@@ -114,234 +118,119 @@ { int publicMods = 0x0; - if (mods & mir_key_modifier_alt)+ if (mods & mir_input_event_modifier_alt) publicMods |= GLFW_MOD_ALT;- else if (mods & mir_key_modifier_shift)+ else if (mods & mir_input_event_modifier_shift) publicMods |= GLFW_MOD_SHIFT;- else if (mods & mir_key_modifier_ctrl)+ else if (mods & mir_input_event_modifier_ctrl) publicMods |= GLFW_MOD_CONTROL;- else if (mods & mir_key_modifier_meta)+ else if (mods & mir_input_event_modifier_meta) publicMods |= GLFW_MOD_SUPER; return publicMods; } -// Taken from wl_init.c static int toGLFWKeyCode(uint32_t key) {- switch (key)- {- case KEY_GRAVE: return GLFW_KEY_GRAVE_ACCENT;- case KEY_1: return GLFW_KEY_1;- case KEY_2: return GLFW_KEY_2;- case KEY_3: return GLFW_KEY_3;- case KEY_4: return GLFW_KEY_4;- case KEY_5: return GLFW_KEY_5;- case KEY_6: return GLFW_KEY_6;- case KEY_7: return GLFW_KEY_7;- case KEY_8: return GLFW_KEY_8;- case KEY_9: return GLFW_KEY_9;- case KEY_0: return GLFW_KEY_0;- case KEY_MINUS: return GLFW_KEY_MINUS;- case KEY_EQUAL: return GLFW_KEY_EQUAL;- case KEY_Q: return GLFW_KEY_Q;- case KEY_W: return GLFW_KEY_W;- case KEY_E: return GLFW_KEY_E;- case KEY_R: return GLFW_KEY_R;- case KEY_T: return GLFW_KEY_T;- case KEY_Y: return GLFW_KEY_Y;- case KEY_U: return GLFW_KEY_U;- case KEY_I: return GLFW_KEY_I;- case KEY_O: return GLFW_KEY_O;- case KEY_P: return GLFW_KEY_P;- case KEY_LEFTBRACE: return GLFW_KEY_LEFT_BRACKET;- case KEY_RIGHTBRACE: return GLFW_KEY_RIGHT_BRACKET;- case KEY_A: return GLFW_KEY_A;- case KEY_S: return GLFW_KEY_S;- case KEY_D: return GLFW_KEY_D;- case KEY_F: return GLFW_KEY_F;- case KEY_G: return GLFW_KEY_G;- case KEY_H: return GLFW_KEY_H;- case KEY_J: return GLFW_KEY_J;- case KEY_K: return GLFW_KEY_K;- case KEY_L: return GLFW_KEY_L;- case KEY_SEMICOLON: return GLFW_KEY_SEMICOLON;- case KEY_APOSTROPHE: return GLFW_KEY_APOSTROPHE;- case KEY_Z: return GLFW_KEY_Z;- case KEY_X: return GLFW_KEY_X;- case KEY_C: return GLFW_KEY_C;- case KEY_V: return GLFW_KEY_V;- case KEY_B: return GLFW_KEY_B;- case KEY_N: return GLFW_KEY_N;- case KEY_M: return GLFW_KEY_M;- case KEY_COMMA: return GLFW_KEY_COMMA;- case KEY_DOT: return GLFW_KEY_PERIOD;- case KEY_SLASH: return GLFW_KEY_SLASH;- case KEY_BACKSLASH: return GLFW_KEY_BACKSLASH;- case KEY_ESC: return GLFW_KEY_ESCAPE;- case KEY_TAB: return GLFW_KEY_TAB;- case KEY_LEFTSHIFT: return GLFW_KEY_LEFT_SHIFT;- case KEY_RIGHTSHIFT: return GLFW_KEY_RIGHT_SHIFT;- case KEY_LEFTCTRL: return GLFW_KEY_LEFT_CONTROL;- case KEY_RIGHTCTRL: return GLFW_KEY_RIGHT_CONTROL;- case KEY_LEFTALT: return GLFW_KEY_LEFT_ALT;- case KEY_RIGHTALT: return GLFW_KEY_RIGHT_ALT;- case KEY_LEFTMETA: return GLFW_KEY_LEFT_SUPER;- case KEY_RIGHTMETA: return GLFW_KEY_RIGHT_SUPER;- case KEY_MENU: return GLFW_KEY_MENU;- case KEY_NUMLOCK: return GLFW_KEY_NUM_LOCK;- case KEY_CAPSLOCK: return GLFW_KEY_CAPS_LOCK;- case KEY_PRINT: return GLFW_KEY_PRINT_SCREEN;- case KEY_SCROLLLOCK: return GLFW_KEY_SCROLL_LOCK;- case KEY_PAUSE: return GLFW_KEY_PAUSE;- case KEY_DELETE: return GLFW_KEY_DELETE;- case KEY_BACKSPACE: return GLFW_KEY_BACKSPACE;- case KEY_ENTER: return GLFW_KEY_ENTER;- case KEY_HOME: return GLFW_KEY_HOME;- case KEY_END: return GLFW_KEY_END;- case KEY_PAGEUP: return GLFW_KEY_PAGE_UP;- case KEY_PAGEDOWN: return GLFW_KEY_PAGE_DOWN;- case KEY_INSERT: return GLFW_KEY_INSERT;- case KEY_LEFT: return GLFW_KEY_LEFT;- case KEY_RIGHT: return GLFW_KEY_RIGHT;- case KEY_DOWN: return GLFW_KEY_DOWN;- case KEY_UP: return GLFW_KEY_UP;- case KEY_F1: return GLFW_KEY_F1;- case KEY_F2: return GLFW_KEY_F2;- case KEY_F3: return GLFW_KEY_F3;- case KEY_F4: return GLFW_KEY_F4;- case KEY_F5: return GLFW_KEY_F5;- case KEY_F6: return GLFW_KEY_F6;- case KEY_F7: return GLFW_KEY_F7;- case KEY_F8: return GLFW_KEY_F8;- case KEY_F9: return GLFW_KEY_F9;- case KEY_F10: return GLFW_KEY_F10;- case KEY_F11: return GLFW_KEY_F11;- case KEY_F12: return GLFW_KEY_F12;- case KEY_F13: return GLFW_KEY_F13;- case KEY_F14: return GLFW_KEY_F14;- case KEY_F15: return GLFW_KEY_F15;- case KEY_F16: return GLFW_KEY_F16;- case KEY_F17: return GLFW_KEY_F17;- case KEY_F18: return GLFW_KEY_F18;- case KEY_F19: return GLFW_KEY_F19;- case KEY_F20: return GLFW_KEY_F20;- case KEY_F21: return GLFW_KEY_F21;- case KEY_F22: return GLFW_KEY_F22;- case KEY_F23: return GLFW_KEY_F23;- case KEY_F24: return GLFW_KEY_F24;- case KEY_KPSLASH: return GLFW_KEY_KP_DIVIDE;- case KEY_KPDOT: return GLFW_KEY_KP_MULTIPLY;- case KEY_KPMINUS: return GLFW_KEY_KP_SUBTRACT;- case KEY_KPPLUS: return GLFW_KEY_KP_ADD;- case KEY_KP0: return GLFW_KEY_KP_0;- case KEY_KP1: return GLFW_KEY_KP_1;- case KEY_KP2: return GLFW_KEY_KP_2;- case KEY_KP3: return GLFW_KEY_KP_3;- case KEY_KP4: return GLFW_KEY_KP_4;- case KEY_KP5: return GLFW_KEY_KP_5;- case KEY_KP6: return GLFW_KEY_KP_6;- case KEY_KP7: return GLFW_KEY_KP_7;- case KEY_KP8: return GLFW_KEY_KP_8;- case KEY_KP9: return GLFW_KEY_KP_9;- case KEY_KPCOMMA: return GLFW_KEY_KP_DECIMAL;- case KEY_KPEQUAL: return GLFW_KEY_KP_EQUAL;- case KEY_KPENTER: return GLFW_KEY_KP_ENTER;- default: return GLFW_KEY_UNKNOWN;- }+ if (key < sizeof(_glfw.mir.publicKeys) / sizeof(_glfw.mir.publicKeys[0]))+ return _glfw.mir.publicKeys[key];++ return GLFW_KEY_UNKNOWN; } -static void handleKeyEvent(const MirKeyEvent key, _GLFWwindow* window)+static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window) {- const int pressed = key.action == mir_key_action_up ? GLFW_RELEASE : GLFW_PRESS;- const int mods = mirModToGLFWMod(key.modifiers);- const long text = _glfwKeySym2Unicode(key.key_code);- const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));+ const int action = mir_keyboard_event_action (key_event);+ const int scan_code = mir_keyboard_event_scan_code(key_event);+ const int key_code = mir_keyboard_event_key_code (key_event);+ const int modifiers = mir_keyboard_event_modifiers(key_event); - _glfwInputKey(window, toGLFWKeyCode(key.scan_code), key.scan_code, pressed, mods);+ const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;+ const int mods = mirModToGLFWMod(modifiers);+ const long text = _glfwKeySym2Unicode(key_code);+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);+ if (text != -1) _glfwInputChar(window, text, mods, plain); } -static void handleMouseButton(_GLFWwindow* window,- int pressed, int mods, MirMotionButton button)+static void handlePointerButton(_GLFWwindow* window,+ int pressed,+ const MirPointerEvent* pointer_event) {- static int lastButton;- int publicButton;- const int publicMods = mirModToGLFWMod(mods);+ int mods = mir_pointer_event_modifiers(pointer_event);+ const int publicMods = mirModToGLFWMod(mods);+ MirPointerButton button = mir_pointer_button_primary;+ static uint32_t oldButtonStates = 0;+ uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);+ int publicButton = GLFW_MOUSE_BUTTON_LEFT; + // XOR our old button states our new states to figure out what was added or removed+ button = newButtonStates ^ oldButtonStates;+ switch (button) {- case mir_motion_button_primary:+ case mir_pointer_button_primary: publicButton = GLFW_MOUSE_BUTTON_LEFT; break;- case mir_motion_button_secondary:+ case mir_pointer_button_secondary: publicButton = GLFW_MOUSE_BUTTON_RIGHT; break;- case mir_motion_button_tertiary:+ case mir_pointer_button_tertiary: publicButton = GLFW_MOUSE_BUTTON_MIDDLE; break;- case mir_motion_button_forward:+ case mir_pointer_button_forward: // FIXME What is the forward button? publicButton = GLFW_MOUSE_BUTTON_4; break;- case mir_motion_button_back:+ case mir_pointer_button_back: // FIXME What is the back button? publicButton = GLFW_MOUSE_BUTTON_5; break; default:- publicButton = lastButton; break; } - lastButton = publicButton;+ oldButtonStates = newButtonStates; _glfwInputMouseClick(window, publicButton, pressed, publicMods); } -static void handleMouseMotion(_GLFWwindow* window, int x, int y)+static void handlePointerMotion(_GLFWwindow* window,+ const MirPointerEvent* pointer_event) {- _glfwInputCursorMotion(window, x, y);-}+ int current_x = window->virtualCursorPosX;+ int current_y = window->virtualCursorPosY;+ int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);+ int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);+ int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);+ int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll); -static void handleMouseScroll(_GLFWwindow* window, int dx, int dy)-{- _glfwInputScroll(window, dx, dy);+ _glfwInputCursorPos(window, x, y);+ if (dx != 0 || dy != 0)+ _glfwInputScroll(window, dx, dy); } -static void handleMouseEvent(const MirMotionEvent motion,- int cord_index,+static void handlePointerEvent(const MirPointerEvent* pointer_event, _GLFWwindow* window) {- switch (motion.action)+ int action = mir_pointer_event_action(pointer_event);++ switch (action) {- case mir_motion_action_down:- case mir_motion_action_pointer_down:- handleMouseButton(window, GLFW_PRESS,- motion.modifiers, motion.button_state);- break;- case mir_motion_action_up:- case mir_motion_action_pointer_up:- handleMouseButton(window, GLFW_RELEASE,- motion.modifiers, motion.button_state);- break;- case mir_motion_action_hover_move:- case mir_motion_action_move:- handleMouseMotion(window,- motion.pointer_coordinates[cord_index].x,- motion.pointer_coordinates[cord_index].y);+ case mir_pointer_action_button_down:+ handlePointerButton(window, GLFW_PRESS, pointer_event); break;- case mir_motion_action_outside:+ case mir_pointer_action_button_up:+ handlePointerButton(window, GLFW_RELEASE, pointer_event); break;- case mir_motion_action_scroll:- handleMouseScroll(window,- motion.pointer_coordinates[cord_index].hscroll,- motion.pointer_coordinates[cord_index].vscroll);+ case mir_pointer_action_motion:+ handlePointerMotion(window, pointer_event); break;- case mir_motion_action_cancel:- case mir_motion_action_hover_enter:- case mir_motion_action_hover_exit:+ case mir_pointer_action_enter:+ case mir_pointer_action_leave: break; default: break;@@ -349,85 +238,90 @@ } } -static void handleMotionEvent(const MirMotionEvent motion, _GLFWwindow* window)+static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window) {- int i;- for (i = 0; i < motion.pointer_count; i++)- handleMouseEvent(motion, i, window);+ int type = mir_input_event_get_type(input_event);++ switch (type)+ {+ case mir_input_event_type_key:+ handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);+ break;+ case mir_input_event_type_pointer:+ handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);+ break;+ default:+ break;+ } } -static void handleInput(MirEvent const* event, _GLFWwindow* window)+static void handleEvent(const MirEvent* event, _GLFWwindow* window) {- switch (event->type)+ int type = mir_event_get_type(event);++ switch (type) {- case mir_event_type_key:- handleKeyEvent(event->key, window);- break;- case mir_event_type_motion:- handleMotionEvent(event->motion, window);+ case mir_event_type_input:+ handleInput(mir_event_get_input_event(event), window); break; default: break; } } -static void addNewEvent(MirSurface* surface, MirEvent const* event, void* context)+static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context) { enqueueEvent(event, context); } -static int createSurface(_GLFWwindow* window)+static GLFWbool createSurface(_GLFWwindow* window) {- MirSurfaceParameters params =- {- .name = "MirSurface",- .width = window->mir.width,- .height = window->mir.height,- .pixel_format = mir_pixel_format_invalid,- .buffer_usage = mir_buffer_usage_hardware,- .output_id = mir_display_output_id_invalid- };-- MirEventDelegate delegate =- {- addNewEvent,- window- };+ MirSurfaceSpec* spec;+ MirBufferUsage buffer_usage = mir_buffer_usage_hardware;+ MirPixelFormat pixel_format = findValidPixelFormat(); - params.pixel_format = findValidPixelFormat();- if (params.pixel_format == mir_pixel_format_invalid)+ if (pixel_format == mir_pixel_format_invalid) { _glfwInputError(GLFW_PLATFORM_ERROR, "Mir: Unable to find a correct pixel format");- return GL_FALSE;+ return GLFW_FALSE; }+ + spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,+ window->mir.width,+ window->mir.height,+ pixel_format); - window->mir.surface =- mir_connection_create_surface_sync(_glfw.mir.connection, ¶ms);+ mir_surface_spec_set_buffer_usage(spec, buffer_usage);+ mir_surface_spec_set_name(spec, "MirSurface");++ window->mir.surface = mir_surface_create_sync(spec);+ mir_surface_spec_release(spec);+ if (!mir_surface_is_valid(window->mir.surface)) { _glfwInputError(GLFW_PLATFORM_ERROR, "Mir: Unable to create surface: %s", mir_surface_get_error_message(window->mir.surface)); - return GL_FALSE;+ return GLFW_FALSE; } - mir_surface_set_event_handler(window->mir.surface, &delegate);+ mir_surface_set_event_handler(window->mir.surface, addNewEvent, window); - return GL_TRUE;+ return GLFW_TRUE; } ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwInitEventQueue(EventQueue* queue)+void _glfwInitEventQueueMir(EventQueue* queue) { TAILQ_INIT(&queue->head); } -void _glfwDeleteEventQueue(EventQueue* queue)+void _glfwDeleteEventQueueMir(EventQueue* queue) { if (queue) {@@ -457,23 +351,20 @@ const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) {- if (!_glfwCreateContext(window, ctxconfig, fbconfig))- return GL_FALSE;-- if (wndconfig->monitor)+ if (window->monitor) { GLFWvidmode mode;- _glfwPlatformGetVideoMode(wndconfig->monitor, &mode);+ _glfwPlatformGetVideoMode(window->monitor, &mode); mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen); if (wndconfig->width > mode.width || wndconfig->height > mode.height) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Requested surface size is to large (%i %i)",- wndconfig->width, wndconfig->height);+ "Mir: Requested surface size too large: %ix%i",+ wndconfig->width, wndconfig->height); - return GL_FALSE;+ return GLFW_FALSE; } } @@ -481,11 +372,20 @@ window->mir.height = wndconfig->height; if (!createSurface(window))- return GL_FALSE;+ return GLFW_FALSE; - window->mir.window = mir_surface_get_egl_native_window(window->mir.surface);+ window->mir.window = mir_buffer_stream_get_egl_native_window(+ mir_surface_get_buffer_stream(window->mir.surface)); - return GL_TRUE;+ if (ctxconfig->client != GLFW_NO_API)+ {+ if (!_glfwInitEGL())+ return GLFW_FALSE;+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }++ return GLFW_TRUE; } void _glfwPlatformDestroyWindow(_GLFWwindow* window)@@ -496,19 +396,59 @@ window->mir.surface = NULL; } - _glfwDestroyContext(window);+ if (window->context.destroy)+ window->context.destroy(window); } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) {+ MirSurfaceSpec* spec;+ const char* e_title = title ? title : "";++ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);+ mir_surface_spec_set_name(spec, e_title);++ mir_surface_apply_spec(window->mir.surface, spec);+ mir_surface_spec_release(spec);+}++void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+ int count, const GLFWimage* images)+{ _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)+{+ MirSurfaceSpec* spec;++ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);+ mir_surface_spec_set_width (spec, width);+ mir_surface_spec_set_height(spec, height);++ mir_surface_apply_spec(window->mir.surface, spec);+ mir_surface_spec_release(spec);+}++void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)+{+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+}+ void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,@@ -516,19 +456,13 @@ int* right, int* bottom) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);-}--void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)-{- _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)@@ -549,43 +483,74 @@ mir_surface_set_state(window->mir.surface, mir_surface_state_restored); } -void _glfwPlatformHideWindow(_GLFWwindow* window)+void _glfwPlatformMaximizeWindow(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +void _glfwPlatformHideWindow(_GLFWwindow* window)+{+ MirSurfaceSpec* spec;++ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);+ mir_surface_spec_set_state(spec, mir_surface_state_hidden);++ mir_surface_apply_spec(window->mir.surface, spec);+ mir_surface_spec_release(spec);+}+ void _glfwPlatformShowWindow(_GLFWwindow* window) {+ MirSurfaceSpec* spec;++ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);+ mir_surface_spec_set_state(spec, mir_surface_state_restored);++ mir_surface_apply_spec(window->mir.surface, spec);+ mir_surface_spec_release(spec);+}++void _glfwPlatformFocusWindow(_GLFWwindow* window)+{ _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } -void _glfwPlatformUnhideWindow(_GLFWwindow* window)+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+ _GLFWmonitor* monitor,+ int xpos, int ypos,+ int width, int height,+ int refreshRate) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } int _glfwPlatformWindowFocused(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);- return GL_FALSE;+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+ return GLFW_FALSE; } int _glfwPlatformWindowIconified(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);- return GL_FALSE;+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+ return GLFW_FALSE; } int _glfwPlatformWindowVisible(_GLFWwindow* window) {+ return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;+}++int _glfwPlatformWindowMaximized(_GLFWwindow* window)+{ _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);- return GL_FALSE;+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+ return GLFW_FALSE; } void _glfwPlatformPollEvents(void)@@ -594,7 +559,7 @@ while ((node = dequeueEvent(_glfw.mir.event_queue))) {- handleInput(node->event, node->window);+ handleEvent(node->event, node->window); deleteNode(_glfw.mir.event_queue, node); } }@@ -611,6 +576,24 @@ _glfwPlatformPollEvents(); } +void _glfwPlatformWaitEventsTimeout(double timeout)+{+ pthread_mutex_lock(&_glfw.mir.event_mutex);++ if (emptyEventQueue(_glfw.mir.event_queue))+ {+ struct timespec time;+ clock_gettime(CLOCK_REALTIME, &time);+ time.tv_sec += (long) timeout;+ time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);+ pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);+ }++ pthread_mutex_unlock(&_glfw.mir.event_mutex);++ _glfwPlatformPollEvents();+}+ void _glfwPlatformPostEmptyEvent(void) { }@@ -623,65 +606,243 @@ *height = window->mir.height; } +// FIXME implement int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ MirBufferStream* stream;+ MirPixelFormat pixel_format = findValidPixelFormat(); - return GL_FALSE;+ int i_w = image->width;+ int i_h = image->height;++ if (pixel_format == mir_pixel_format_invalid)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Mir: Unable to find a correct pixel format");+ return GLFW_FALSE;+ }++ stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,+ i_w, i_h,+ pixel_format,+ mir_buffer_usage_software);++ cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);++ char* dest;+ unsigned char *pixels;+ int i, r_stride, bytes_per_pixel, bytes_per_row;++ MirGraphicsRegion region;+ mir_buffer_stream_get_graphics_region(stream, ®ion);++ // FIXME Figure this out based on the current_pf+ bytes_per_pixel = 4;+ bytes_per_row = bytes_per_pixel * i_w;++ dest = region.vaddr;+ pixels = image->pixels;++ r_stride = region.stride;++ for (i = 0; i < i_h; i++)+ {+ memcpy(dest, pixels, bytes_per_row);+ dest += r_stride;+ pixels += r_stride;+ }++ cursor->mir.custom_cursor = stream;++ return GLFW_TRUE; } +const char* getSystemCursorName(int shape)+{+ switch (shape)+ {+ case GLFW_ARROW_CURSOR:+ return mir_arrow_cursor_name;+ case GLFW_IBEAM_CURSOR:+ return mir_caret_cursor_name;+ case GLFW_CROSSHAIR_CURSOR:+ return mir_crosshair_cursor_name;+ case GLFW_HAND_CURSOR:+ return mir_open_hand_cursor_name;+ case GLFW_HRESIZE_CURSOR:+ return mir_horizontal_resize_cursor_name;+ case GLFW_VRESIZE_CURSOR:+ return mir_vertical_resize_cursor_name;+ }++ return NULL;+}+ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ const char* cursor_name = getSystemCursorName(shape); - return GL_FALSE;+ if (cursor_name)+ {+ cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);+ cursor->mir.custom_cursor = NULL;++ return GLFW_TRUE;+ }++ return GLFW_FALSE; } void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ if (cursor->mir.conf)+ mir_cursor_configuration_destroy(cursor->mir.conf);+ if (cursor->mir.custom_cursor)+ mir_buffer_stream_release_sync(cursor->mir.custom_cursor); } void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ if (cursor && cursor->mir.conf)+ {+ mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));+ if (cursor->mir.custom_cursor)+ {+ mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);+ }+ }+ else+ {+ mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));+ } } void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } -void _glfwPlatformApplyCursorMode(_GLFWwindow* window)+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } +const char* _glfwPlatformGetKeyName(int key, int scancode)+{+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);+ return NULL;+}+ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); } const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Mir: Unsupported function %s!", __PRETTY_FUNCTION__);+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__); return NULL;+}++char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)+{+ char** extensions;++ *count = 0;++ if (!_glfw.vk.KHR_mir_surface)+ return NULL;++ extensions = calloc(2, sizeof(char*));+ extensions[0] = strdup("VK_KHR_surface");+ extensions[1] = strdup("VK_KHR_mir_surface");++ *count = 2;+ return extensions;+}++int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =+ (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");+ if (!vkGetPhysicalDeviceMirPresentationSupportKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Mir: Vulkan instance missing VK_KHR_mir_surface extension");+ return GLFW_FALSE;+ }++ return vkGetPhysicalDeviceMirPresentationSupportKHR(device,+ queuefamily,+ _glfw.mir.connection);+}++VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,+ _GLFWwindow* window,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ VkResult err;+ VkMirSurfaceCreateInfoKHR sci;+ PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;++ vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)+ vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");+ if (!vkCreateMirSurfaceKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Mir: Vulkan instance missing VK_KHR_mir_surface extension");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ memset(&sci, 0, sizeof(sci));+ sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;+ sci.connection = _glfw.mir.connection;+ sci.mirSurface = window->mir.surface;++ err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Mir: Failed to create Vulkan surface: %s",+ _glfwGetVulkanResultString(err));+ }++ return err;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW native API //////+//////////////////////////////////////////////////////////////////////////++GLFWAPI MirConnection* glfwGetMirDisplay(void)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return _glfw.mir.connection;+}++GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return window->mir.surface; }
glfw/src/monitor.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -27,7 +27,9 @@ #include "internal.h" +#include <assert.h> #include <math.h>+#include <float.h> #include <string.h> #include <stdlib.h> #include <limits.h>@@ -37,43 +39,42 @@ #define strdup _strdup #endif -// Lexical comparison function for GLFW video modes, used by qsort+// Lexically compare video modes, used by qsort //-static int compareVideoModes(const void* firstPtr, const void* secondPtr)+static int compareVideoModes(const void* fp, const void* sp) {- int firstBPP, secondBPP, firstSize, secondSize;- const GLFWvidmode* first = firstPtr;- const GLFWvidmode* second = secondPtr;+ const GLFWvidmode* fm = fp;+ const GLFWvidmode* sm = sp;+ const int fbpp = fm->redBits + fm->greenBits + fm->blueBits;+ const int sbpp = sm->redBits + sm->greenBits + sm->blueBits;+ const int farea = fm->width * fm->height;+ const int sarea = sm->width * sm->height; // First sort on color bits per pixel- firstBPP = first->redBits + first->greenBits + first->blueBits;- secondBPP = second->redBits + second->greenBits + second->blueBits;- if (firstBPP != secondBPP)- return firstBPP - secondBPP;+ if (fbpp != sbpp)+ return fbpp - sbpp; - // Then sort on screen area, in pixels- firstSize = first->width * first->height;- secondSize = second->width * second->height;- if (firstSize != secondSize)- return firstSize - secondSize;+ // Then sort on screen area+ if (farea != sarea)+ return farea - sarea; // Lastly sort on refresh rate- return first->refreshRate - second->refreshRate;+ return fm->refreshRate - sm->refreshRate; } // Retrieves the available modes for the specified monitor //-static int refreshVideoModes(_GLFWmonitor* monitor)+static GLFWbool refreshVideoModes(_GLFWmonitor* monitor) { int modeCount; GLFWvidmode* modes; if (monitor->modes)- return GL_TRUE;+ return GLFW_TRUE; modes = _glfwPlatformGetVideoModes(monitor, &modeCount); if (!modes)- return GL_FALSE;+ return GLFW_FALSE; qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes); @@ -81,7 +82,7 @@ monitor->modes = modes; monitor->modeCount = modeCount; - return GL_TRUE;+ return GLFW_TRUE; } @@ -129,7 +130,11 @@ for (window = _glfw.windowListHead; window; window = window->next) { if (window->monitor == monitors[i])- window->monitor = NULL;+ {+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);+ _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);+ } } if (_glfw.callbacks.monitor)@@ -161,7 +166,12 @@ _glfwFreeMonitors(monitors, monitorCount); } +void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)+{+ monitor->window = window;+} + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// //////////////////////////////////////////////////////////////////////////@@ -266,9 +276,9 @@ return closest; } -int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second)+int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm) {- return compareVideoModes(first, second);+ return compareVideoModes(fm, sm); } void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)@@ -297,6 +307,7 @@ GLFWAPI GLFWmonitor** glfwGetMonitors(int* count) {+ assert(count != NULL); *count = 0; _GLFW_REQUIRE_INIT_OR_RETURN(NULL);@@ -308,12 +319,17 @@ GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL);++ if (!_glfw.monitorCount)+ return NULL;+ return (GLFWmonitor*) _glfw.monitors[0]; } GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL); if (xpos) *xpos = 0;@@ -328,6 +344,7 @@ GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL); if (widthMM) *widthMM = 0;@@ -345,6 +362,8 @@ GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return monitor->name; }@@ -359,6 +378,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL);+ assert(count != NULL); *count = 0; @@ -374,6 +395,7 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -389,10 +411,9 @@ _GLFW_REQUIRE_INIT(); - if (gamma <= 0.f)+ if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX) {- _glfwInputError(GLFW_INVALID_VALUE,- "Gamma value must be greater than zero");+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma); return; } @@ -423,6 +444,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL); @@ -435,6 +457,19 @@ GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp) { _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ assert(monitor != NULL);+ assert(ramp != NULL);+ assert(ramp->red != NULL);+ assert(ramp->green != NULL);+ assert(ramp->blue != NULL);++ if (ramp->size <= 0)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid gamma ramp size %i",+ ramp->size);+ return;+ } _GLFW_REQUIRE_INIT();
glfw/src/nsgl_context.h view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -24,10 +24,9 @@ // //======================================================================== -#ifndef _nsgl_context_h_-#define _nsgl_context_h_+#ifndef _glfw3_nsgl_context_h_+#define _glfw3_nsgl_context_h_ -#define _GLFW_PLATFORM_FBCONFIG #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl @@ -37,26 +36,25 @@ typedef struct _GLFWcontextNSGL { id pixelFormat;- id context;+ id object; } _GLFWcontextNSGL; - // NSGL-specific global data // typedef struct _GLFWlibraryNSGL { // dlopen handle for OpenGL.framework (for glfwGetProcAddress)- void* framework;+ CFBundleRef framework; } _GLFWlibraryNSGL; -int _glfwInitContextAPI(void);-void _glfwTerminateContextAPI(void);-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);-void _glfwDestroyContext(_GLFWwindow* window);+GLFWbool _glfwInitNSGL(void);+void _glfwTerminateNSGL(void);+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig);+void _glfwDestroyContextNSGL(_GLFWwindow* window); -#endif // _nsgl_context_h_+#endif // _glfw3_nsgl_context_h_
glfw/src/nsgl_context.m view
@@ -1,7 +1,7 @@ //========================================================================-// GLFW 3.1 OS X - www.glfw.org+// GLFW 3.2 OS X - www.glfw.org //-------------------------------------------------------------------------// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -27,58 +27,112 @@ #include "internal.h" +static void makeContextCurrentNSGL(_GLFWwindow* window)+{+ if (window)+ [window->context.nsgl.object makeCurrentContext];+ else+ [NSOpenGLContext clearCurrentContext];++ _glfwPlatformSetCurrentContext(window);+}++static void swapBuffersNSGL(_GLFWwindow* window)+{+ // ARP appears to be unnecessary, but this is future-proof+ [window->context.nsgl.object flushBuffer];+}++static void swapIntervalNSGL(int interval)+{+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();++ GLint sync = interval;+ [window->context.nsgl.object setValues:&sync+ forParameter:NSOpenGLCPSwapInterval];+}++static int extensionSupportedNSGL(const char* extension)+{+ // There are no NSGL extensions+ return GLFW_FALSE;+}++static GLFWglproc getProcAddressNSGL(const char* procname)+{+ CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,+ procname,+ kCFStringEncodingASCII);++ GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,+ symbolName);++ CFRelease(symbolName);++ return symbol;+}++// Destroy the OpenGL context+//+static void destroyContextNSGL(_GLFWwindow* window)+{+ [window->context.nsgl.pixelFormat release];+ window->context.nsgl.pixelFormat = nil;++ [window->context.nsgl.object release];+ window->context.nsgl.object = nil;+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialize OpenGL support //-int _glfwInitContextAPI(void)+GLFWbool _glfwInitNSGL(void) {- if (!_glfwInitTLS())- return GL_FALSE;+ if (_glfw.nsgl.framework)+ return GLFW_TRUE; _glfw.nsgl.framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (_glfw.nsgl.framework == NULL) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_API_UNAVAILABLE, "NSGL: Failed to locate OpenGL framework");- return GL_FALSE;+ return GLFW_FALSE; } - return GL_TRUE;+ return GLFW_TRUE; } // Terminate OpenGL support //-void _glfwTerminateContextAPI(void)+void _glfwTerminateNSGL(void) {- _glfwTerminateTLS(); } // Create the OpenGL context //-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig) { unsigned int attributeCount = 0; - if (ctxconfig->api == GLFW_OPENGL_ES_API)+ if (ctxconfig->client == GLFW_OPENGL_ES_API) {- _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "NSGL: This API does not support OpenGL ES");- return GL_FALSE;+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "NSGL: OpenGL ES is not available on OS X");+ return GLFW_FALSE; } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (ctxconfig->major == 3 && ctxconfig->minor < 2) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "NSGL: The targeted version of OS X does not "- "support OpenGL 3.0 or 3.1");- return GL_FALSE;+ "NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");+ return GLFW_FALSE; } if (ctxconfig->major > 2)@@ -86,31 +140,17 @@ if (!ctxconfig->forward) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "NSGL: The targeted version of OS X only "- "supports OpenGL 3.2 and later versions if they "- "are forward-compatible");- return GL_FALSE;+ "NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");+ return GLFW_FALSE; } if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "NSGL: The targeted version of OS X only "- "supports OpenGL 3.2 and later versions if they "- "use the core profile");- return GL_FALSE;+ "NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");+ return GLFW_FALSE; } }-#else- // Fail if OpenGL 3.0 or above was requested- if (ctxconfig->major > 2)- {- _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "NSGL: The targeted version of OS X does not "- "support OpenGL version 3.0 or above");- return GL_FALSE;- }-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ // Context robustness modes (GL_KHR_robustness) are not yet supported on // OS X but are not a hard constraint, so ignore and continue@@ -127,7 +167,6 @@ ADD_ATTR(NSOpenGLPFAAccelerated); ADD_ATTR(NSOpenGLPFAClosestPolicy); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 if (ctxconfig->major >= 4) {@@ -139,7 +178,6 @@ { ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core); }-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ if (ctxconfig->major <= 2) {@@ -213,91 +251,40 @@ #undef ADD_ATTR #undef ADD_ATTR2 - window->nsgl.pixelFormat =+ window->context.nsgl.pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];- if (window->nsgl.pixelFormat == nil)+ if (window->context.nsgl.pixelFormat == nil) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "NSGL: Failed to create OpenGL pixel format");- return GL_FALSE;+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "NSGL: Failed to find a suitable pixel format");+ return GLFW_FALSE; } NSOpenGLContext* share = NULL; if (ctxconfig->share)- share = ctxconfig->share->nsgl.context;+ share = ctxconfig->share->context.nsgl.object; - window->nsgl.context =- [[NSOpenGLContext alloc] initWithFormat:window->nsgl.pixelFormat+ window->context.nsgl.object =+ [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat shareContext:share];- if (window->nsgl.context == nil)+ if (window->context.nsgl.object == nil) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_VERSION_UNAVAILABLE, "NSGL: Failed to create OpenGL context");- return GL_FALSE;+ return GLFW_FALSE; } - return GL_TRUE;-}--// Destroy the OpenGL context-//-void _glfwDestroyContext(_GLFWwindow* window)-{- [window->nsgl.pixelFormat release];- window->nsgl.pixelFormat = nil;-- [window->nsgl.context release];- window->nsgl.context = nil;-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)-{- if (window)- [window->nsgl.context makeCurrentContext];- else- [NSOpenGLContext clearCurrentContext];-- _glfwSetCurrentContext(window);-}--void _glfwPlatformSwapBuffers(_GLFWwindow* window)-{- // ARP appears to be unnecessary, but this is future-proof- [window->nsgl.context flushBuffer];-}--void _glfwPlatformSwapInterval(int interval)-{- _GLFWwindow* window = _glfwPlatformGetCurrentContext();-- GLint sync = interval;- [window->nsgl.context setValues:&sync forParameter:NSOpenGLCPSwapInterval];-}--int _glfwPlatformExtensionSupported(const char* extension)-{- // There are no NSGL extensions- return GL_FALSE;-}--GLFWglproc _glfwPlatformGetProcAddress(const char* procname)-{- CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,- procname,- kCFStringEncodingASCII);-- GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,- symbolName);+ [window->context.nsgl.object setView:window->ns.view]; - CFRelease(symbolName);+ window->context.makeCurrent = makeContextCurrentNSGL;+ window->context.swapBuffers = swapBuffersNSGL;+ window->context.swapInterval = swapIntervalNSGL;+ window->context.extensionSupported = extensionSupportedNSGL;+ window->context.getProcAddress = getProcAddressNSGL;+ window->context.destroy = destroyContextNSGL; - return symbol;+ return GLFW_TRUE; } @@ -309,6 +296,13 @@ { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(nil);- return window->nsgl.context;++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return NULL;+ }++ return window->context.nsgl.object; }
glfw/src/posix_time.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 POSIX - www.glfw.org+// GLFW 3.2 POSIX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -30,52 +30,29 @@ #include <sys/time.h> #include <time.h> -// Return raw time-//-static uint64_t getRawTime(void)-{-#if defined(CLOCK_MONOTONIC)- if (_glfw.posix_time.monotonic)- {- struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts);- return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;- }- else-#endif- {- struct timeval tv;-- gettimeofday(&tv, NULL);- return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;- }-}-- ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialise timer //-void _glfwInitTimer(void)+void _glfwInitTimerPOSIX(void) { #if defined(CLOCK_MONOTONIC) struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {- _glfw.posix_time.monotonic = GL_TRUE;- _glfw.posix_time.resolution = 1e-9;+ _glfw.posix_time.monotonic = GLFW_TRUE;+ _glfw.posix_time.frequency = 1000000000; } else #endif {- _glfw.posix_time.resolution = 1e-6;+ _glfw.posix_time.monotonic = GLFW_FALSE;+ _glfw.posix_time.frequency = 1000000; }-- _glfw.posix_time.base = getRawTime(); } @@ -83,15 +60,26 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -double _glfwPlatformGetTime(void)+uint64_t _glfwPlatformGetTimerValue(void) {- return (double) (getRawTime() - _glfw.posix_time.base) *- _glfw.posix_time.resolution;+#if defined(CLOCK_MONOTONIC)+ if (_glfw.posix_time.monotonic)+ {+ struct timespec ts;+ clock_gettime(CLOCK_MONOTONIC, &ts);+ return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;+ }+ else+#endif+ {+ struct timeval tv;+ gettimeofday(&tv, NULL);+ return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;+ } } -void _glfwPlatformSetTime(double time)+uint64_t _glfwPlatformGetTimerFrequency(void) {- _glfw.posix_time.base = getRawTime() -- (uint64_t) (time / _glfw.posix_time.resolution);+ return _glfw.posix_time.frequency; }
glfw/src/posix_time.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 POSIX - www.glfw.org+// GLFW 3.2 POSIX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,8 +25,8 @@ // //======================================================================== -#ifndef _posix_time_h_-#define _posix_time_h_+#ifndef _glfw3_posix_time_h_+#define _glfw3_posix_time_h_ #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time @@ -37,13 +37,12 @@ // typedef struct _GLFWtimePOSIX {- GLboolean monotonic;- double resolution;- uint64_t base;+ GLFWbool monotonic;+ uint64_t frequency; } _GLFWtimePOSIX; -void _glfwInitTimer(void);+void _glfwInitTimerPOSIX(void); -#endif // _posix_time_h_+#endif // _glfw3_posix_time_h_
glfw/src/posix_tls.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 POSIX - www.glfw.org+// GLFW 3.2 POSIX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -32,32 +32,34 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwInitTLS(void)+GLFWbool _glfwInitThreadLocalStoragePOSIX(void) { if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0) { _glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create context TLS");- return GL_FALSE;+ return GLFW_FALSE; } - return GL_TRUE;-}--void _glfwTerminateTLS(void)-{- pthread_key_delete(_glfw.posix_tls.context);+ _glfw.posix_tls.allocated = GLFW_TRUE;+ return GLFW_TRUE; } -void _glfwSetCurrentContext(_GLFWwindow* context)+void _glfwTerminateThreadLocalStoragePOSIX(void) {- pthread_setspecific(_glfw.posix_tls.context, context);+ if (_glfw.posix_tls.allocated)+ pthread_key_delete(_glfw.posix_tls.context); } ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////++void _glfwPlatformSetCurrentContext(_GLFWwindow* context)+{+ pthread_setspecific(_glfw.posix_tls.context, context);+} _GLFWwindow* _glfwPlatformGetCurrentContext(void) {
glfw/src/posix_tls.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 POSIX - www.glfw.org+// GLFW 3.2 POSIX - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,8 +25,8 @@ // //======================================================================== -#ifndef _posix_tls_h_-#define _posix_tls_h_+#ifndef _glfw3_posix_tls_h_+#define _glfw3_posix_tls_h_ #include <pthread.h> @@ -37,13 +37,13 @@ // typedef struct _GLFWtlsPOSIX {+ GLFWbool allocated; pthread_key_t context; } _GLFWtlsPOSIX; -int _glfwInitTLS(void);-void _glfwTerminateTLS(void);-void _glfwSetCurrentContext(_GLFWwindow* context);+GLFWbool _glfwInitThreadLocalStoragePOSIX(void);+void _glfwTerminateThreadLocalStoragePOSIX(void); -#endif // _posix_tls_h_+#endif // _glfw3_posix_tls_h_
+ glfw/src/vulkan.c view
@@ -0,0 +1,302 @@+//========================================================================+// GLFW 3.2 - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2002-2006 Marcus Geelnard+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <assert.h>+#include <string.h>+#include <stdlib.h>+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++GLFWbool _glfwInitVulkan(void)+{+ VkResult err;+ VkExtensionProperties* ep;+ uint32_t i, count;++#if !defined(_GLFW_VULKAN_STATIC)+#if defined(_GLFW_WIN32)+ const char* name = "vulkan-1.dll";+#else+ const char* name = "libvulkan.so.1";+#endif++ if (_glfw.vk.available)+ return GLFW_TRUE;++ _glfw.vk.handle = _glfw_dlopen(name);+ if (!_glfw.vk.handle)+ return GLFW_FALSE;++ _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)+ _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");+ if (!_glfw.vk.GetInstanceProcAddr)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Vulkan: Loader does not export vkGetInstanceProcAddr");++ _glfwTerminateVulkan();+ return GLFW_FALSE;+ }++ _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)+ vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");+ if (!_glfw.vk.EnumerateInstanceExtensionProperties)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");++ _glfwTerminateVulkan();+ return GLFW_FALSE;+ }+#endif // _GLFW_VULKAN_STATIC++ err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Vulkan: Failed to query instance extension count: %s",+ _glfwGetVulkanResultString(err));++ _glfwTerminateVulkan();+ return GLFW_FALSE;+ }++ ep = calloc(count, sizeof(VkExtensionProperties));++ err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Vulkan: Failed to query instance extensions: %s",+ _glfwGetVulkanResultString(err));++ free(ep);+ _glfwTerminateVulkan();+ return GLFW_FALSE;+ }++ for (i = 0; i < count; i++)+ {+ if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)+ _glfw.vk.KHR_surface = GLFW_TRUE;+ if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)+ _glfw.vk.KHR_win32_surface = GLFW_TRUE;+ if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)+ _glfw.vk.KHR_xlib_surface = GLFW_TRUE;+ if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)+ _glfw.vk.KHR_xcb_surface = GLFW_TRUE;+ if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)+ _glfw.vk.KHR_wayland_surface = GLFW_TRUE;+ if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)+ _glfw.vk.KHR_mir_surface = GLFW_TRUE;+ }++ free(ep);++ _glfw.vk.available = GLFW_TRUE;++ if (_glfw.vk.KHR_surface)+ {+ _glfw.vk.extensions =+ _glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);+ }++ return GLFW_TRUE;+}++void _glfwTerminateVulkan(void)+{+ uint32_t i;++ for (i = 0; i < _glfw.vk.extensionCount; i++)+ free(_glfw.vk.extensions[i]);+ free(_glfw.vk.extensions);++ if (_glfw.vk.handle)+ _glfw_dlclose(_glfw.vk.handle);+}++const char* _glfwGetVulkanResultString(VkResult result)+{+ switch (result)+ {+ case VK_SUCCESS:+ return "Success";+ case VK_NOT_READY:+ return "A fence or query has not yet completed";+ case VK_TIMEOUT:+ return "A wait operation has not completed in the specified time";+ case VK_EVENT_SET:+ return "An event is signaled";+ case VK_EVENT_RESET:+ return "An event is unsignaled";+ case VK_INCOMPLETE:+ return "A return array was too small for the result";+ case VK_ERROR_OUT_OF_HOST_MEMORY:+ return "A host memory allocation has failed";+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:+ return "A device memory allocation has failed";+ case VK_ERROR_INITIALIZATION_FAILED:+ return "Initialization of an object could not be completed for implementation-specific reasons";+ case VK_ERROR_DEVICE_LOST:+ return "The logical or physical device has been lost";+ case VK_ERROR_MEMORY_MAP_FAILED:+ return "Mapping of a memory object has failed";+ case VK_ERROR_LAYER_NOT_PRESENT:+ return "A requested layer is not present or could not be loaded";+ case VK_ERROR_EXTENSION_NOT_PRESENT:+ return "A requested extension is not supported";+ case VK_ERROR_FEATURE_NOT_PRESENT:+ return "A requested feature is not supported";+ case VK_ERROR_INCOMPATIBLE_DRIVER:+ return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";+ case VK_ERROR_TOO_MANY_OBJECTS:+ return "Too many objects of the type have already been created";+ case VK_ERROR_FORMAT_NOT_SUPPORTED:+ return "A requested format is not supported on this device";+ case VK_ERROR_SURFACE_LOST_KHR:+ return "A surface is no longer available";+ case VK_SUBOPTIMAL_KHR:+ return "A swapchain no longer matches the surface properties exactly, but can still be used";+ case VK_ERROR_OUT_OF_DATE_KHR:+ return "A surface has changed in such a way that it is no longer compatible with the swapchain";+ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:+ return "The display used by a swapchain does not use the same presentable image layout";+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:+ return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";+ case VK_ERROR_VALIDATION_FAILED_EXT:+ return "A validation layer found an error";+ default:+ return "ERROR: UNKNOWN VULKAN ERROR";+ }+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW public API //////+//////////////////////////////////////////////////////////////////////////++GLFWAPI int glfwVulkanSupported(void)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);+ return _glfwInitVulkan();+}++GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)+{+ *count = 0;++ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);++ if (!_glfwInitVulkan())+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");+ return NULL;+ }++ *count = _glfw.vk.extensionCount;+ return (const char**) _glfw.vk.extensions;+}++GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,+ const char* procname)+{+ GLFWvkproc proc;++ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);++ if (!_glfwInitVulkan())+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");+ return NULL;+ }++ proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);+ if (!proc)+ proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);++ return proc;+}++GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);++ if (!_glfwInitVulkan())+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");+ return GLFW_FALSE;+ }++ if (!_glfw.vk.extensions)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Vulkan: Window surface creation extensions not found");+ return GLFW_FALSE;+ }++ return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,+ device,+ queuefamily);+}++GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,+ GLFWwindow* handle,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ assert(surface != NULL);++ *surface = VK_NULL_HANDLE;++ _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);++ if (!_glfwInitVulkan())+ {+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");+ return VK_ERROR_INITIALIZATION_FAILED;+ }++ if (!_glfw.vk.extensions)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Vulkan: Window surface creation extensions not found");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);+}+
glfw/src/wgl_context.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 WGL - www.glfw.org+// GLFW 3.2 WGL - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -32,111 +32,21 @@ #include <assert.h> -// Initialize WGL-specific extensions-// This function is called once before initial context creation, i.e. before-// any WGL extensions could be present. This is done in order to have both-// extension variable clearing and loading in the same place, hopefully-// decreasing the possibility of forgetting to add one without the other.-//-static void initWGLExtensions(_GLFWwindow* window)-{- // This needs to include every function pointer loaded below- window->wgl.SwapIntervalEXT = NULL;- window->wgl.GetPixelFormatAttribivARB = NULL;- window->wgl.GetExtensionsStringARB = NULL;- window->wgl.GetExtensionsStringEXT = NULL;- window->wgl.CreateContextAttribsARB = NULL;-- // This needs to include every extension used below except for- // WGL_ARB_extensions_string and WGL_EXT_extensions_string- window->wgl.ARB_multisample = GL_FALSE;- window->wgl.ARB_framebuffer_sRGB = GL_FALSE;- window->wgl.ARB_create_context = GL_FALSE;- window->wgl.ARB_create_context_profile = GL_FALSE;- window->wgl.EXT_create_context_es2_profile = GL_FALSE;- window->wgl.ARB_create_context_robustness = GL_FALSE;- window->wgl.EXT_swap_control = GL_FALSE;- window->wgl.ARB_pixel_format = GL_FALSE;- window->wgl.ARB_context_flush_control = GL_FALSE;-- window->wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)- wglGetProcAddress("wglGetExtensionsStringEXT");- if (!window->wgl.GetExtensionsStringEXT)- {- window->wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)- wglGetProcAddress("wglGetExtensionsStringARB");- if (!window->wgl.GetExtensionsStringARB)- return;- }-- if (_glfwPlatformExtensionSupported("WGL_ARB_multisample"))- window->wgl.ARB_multisample = GL_TRUE;-- if (_glfwPlatformExtensionSupported("WGL_ARB_framebuffer_sRGB"))- window->wgl.ARB_framebuffer_sRGB = GL_TRUE;-- if (_glfwPlatformExtensionSupported("WGL_ARB_create_context"))- {- window->wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)- wglGetProcAddress("wglCreateContextAttribsARB");-- if (window->wgl.CreateContextAttribsARB)- window->wgl.ARB_create_context = GL_TRUE;- }-- if (window->wgl.ARB_create_context)- {- if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile"))- window->wgl.ARB_create_context_profile = GL_TRUE;- }-- if (window->wgl.ARB_create_context &&- window->wgl.ARB_create_context_profile)- {- if (_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile"))- window->wgl.EXT_create_context_es2_profile = GL_TRUE;- }-- if (window->wgl.ARB_create_context)- {- if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_robustness"))- window->wgl.ARB_create_context_robustness = GL_TRUE;- }-- if (_glfwPlatformExtensionSupported("WGL_EXT_swap_control"))- {- window->wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)- wglGetProcAddress("wglSwapIntervalEXT");-- if (window->wgl.SwapIntervalEXT)- window->wgl.EXT_swap_control = GL_TRUE;- }-- if (_glfwPlatformExtensionSupported("WGL_ARB_pixel_format"))- {- window->wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)- wglGetProcAddress("wglGetPixelFormatAttribivARB");-- if (window->wgl.GetPixelFormatAttribivARB)- window->wgl.ARB_pixel_format = GL_TRUE;- }-- if (_glfwPlatformExtensionSupported("WGL_ARB_context_flush_control"))- window->wgl.ARB_context_flush_control = GL_TRUE;-}- // Returns the specified attribute of the specified pixel format-// NOTE: Do not call this unless we have found WGL_ARB_pixel_format // static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib) { int value = 0; - if (!window->wgl.GetPixelFormatAttribivARB(window->wgl.dc,- pixelFormat,- 0, 1, &attrib, &value))+ assert(_glfw.wgl.ARB_pixel_format);++ if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,+ pixelFormat,+ 0, 1, &attrib, &value)) {- // NOTE: We should probably handle this error somehow+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to retrieve pixel format attribute %i",+ attrib); return 0; } @@ -145,34 +55,26 @@ // Return a list of available and usable framebuffer configs //-static GLboolean choosePixelFormat(_GLFWwindow* window,- const _GLFWfbconfig* desired,- int* result)+static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired) { _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest;- int i, nativeCount, usableCount;+ int i, pixelFormat, nativeCount, usableCount; - if (window->wgl.ARB_pixel_format)+ if (_glfw.wgl.ARB_pixel_format) { nativeCount = getPixelFormatAttrib(window,- 1,- WGL_NUMBER_PIXEL_FORMATS_ARB);+ 1,+ WGL_NUMBER_PIXEL_FORMATS_ARB); } else {- nativeCount = DescribePixelFormat(window->wgl.dc,+ nativeCount = DescribePixelFormat(window->context.wgl.dc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL); } - if (!nativeCount)- {- _glfwInputError(GLFW_API_UNAVAILABLE, "WGL: No pixel formats found");- return GL_FALSE;- }- usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig)); usableCount = 0; @@ -181,9 +83,10 @@ const int n = i + 1; _GLFWfbconfig* u = usableConfigs + usableCount; - if (window->wgl.ARB_pixel_format)+ if (_glfw.wgl.ARB_pixel_format) {- // Get pixel format attributes through WGL_ARB_pixel_format+ // Get pixel format attributes through "modern" extension+ if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) || !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB)) {@@ -218,26 +121,27 @@ u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB); if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))- u->stereo = GL_TRUE;+ u->stereo = GLFW_TRUE; if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))- u->doublebuffer = GL_TRUE;+ u->doublebuffer = GLFW_TRUE; - if (window->wgl.ARB_multisample)+ if (_glfw.wgl.ARB_multisample) u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB); - if (window->wgl.ARB_framebuffer_sRGB)+ if (_glfw.wgl.ARB_framebuffer_sRGB ||+ _glfw.wgl.EXT_framebuffer_sRGB) { if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))- u->sRGB = GL_TRUE;+ u->sRGB = GLFW_TRUE; } } else { PIXELFORMATDESCRIPTOR pfd; - // Get pixel format attributes through old-fashioned PFDs+ // Get pixel format attributes through legacy PFDs - if (!DescribePixelFormat(window->wgl.dc,+ if (!DescribePixelFormat(window->context.wgl.dc, n, sizeof(PIXELFORMATDESCRIPTOR), &pfd))@@ -276,12 +180,12 @@ u->auxBuffers = pfd.cAuxBuffers; if (pfd.dwFlags & PFD_STEREO)- u->stereo = GL_TRUE;+ u->stereo = GLFW_TRUE; if (pfd.dwFlags & PFD_DOUBLEBUFFER)- u->doublebuffer = GL_TRUE;+ u->doublebuffer = GLFW_TRUE; } - u->wgl = n;+ u->handle = n; usableCount++; } @@ -291,55 +195,267 @@ "WGL: The driver does not appear to support OpenGL"); free(usableConfigs);- return GL_FALSE;+ return 0; } closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); if (!closest) {- _glfwInputError(GLFW_PLATFORM_ERROR,+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "WGL: Failed to find a suitable pixel format"); free(usableConfigs);- return GL_FALSE;+ return 0; } - *result = closest->wgl;+ pixelFormat = (int) closest->handle; free(usableConfigs); - return GL_TRUE;+ return pixelFormat; } +// Returns whether desktop compositing is enabled+//+static GLFWbool isCompositionEnabled(void)+{+ BOOL enabled; + if (!_glfw_DwmIsCompositionEnabled)+ return FALSE;++ if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)+ return FALSE;++ return enabled;+}++static void makeContextCurrentWGL(_GLFWwindow* window)+{+ if (window)+ {+ if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))+ _glfwPlatformSetCurrentContext(window);+ else+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to make context current");+ _glfwPlatformSetCurrentContext(NULL);+ }+ }+ else+ {+ if (!wglMakeCurrent(NULL, NULL))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to clear current context");+ }++ _glfwPlatformSetCurrentContext(NULL);+ }+}++static void swapBuffersWGL(_GLFWwindow* window)+{+ // HACK: Use DwmFlush when desktop composition is enabled+ if (isCompositionEnabled() && !window->monitor)+ {+ int count = abs(window->context.wgl.interval);+ while (count--)+ _glfw_DwmFlush();+ }++ SwapBuffers(window->context.wgl.dc);+}++static void swapIntervalWGL(int interval)+{+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();++ window->context.wgl.interval = interval;++ // HACK: Disable WGL swap interval when desktop composition is enabled to+ // avoid interfering with DWM vsync+ if (isCompositionEnabled() && !window->monitor)+ interval = 0;++ if (_glfw.wgl.EXT_swap_control)+ _glfw.wgl.SwapIntervalEXT(interval);+}++static int extensionSupportedWGL(const char* extension)+{+ const char* extensions;++ if (_glfw.wgl.GetExtensionsStringEXT)+ {+ extensions = _glfw.wgl.GetExtensionsStringEXT();+ if (extensions)+ {+ if (_glfwStringInExtensionString(extension, extensions))+ return GLFW_TRUE;+ }+ }++ if (_glfw.wgl.GetExtensionsStringARB)+ {+ extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());+ if (extensions)+ {+ if (_glfwStringInExtensionString(extension, extensions))+ return GLFW_TRUE;+ }+ }++ return GLFW_FALSE;+}++static GLFWglproc getProcAddressWGL(const char* procname)+{+ const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);+ if (proc)+ return proc;++ return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);+}++// Destroy the OpenGL context+//+static void destroyContextWGL(_GLFWwindow* window)+{+ if (window->context.wgl.handle)+ {+ wglDeleteContext(window->context.wgl.handle);+ window->context.wgl.handle = NULL;+ }+}++// Initialize WGL-specific extensions+//+static void loadWGLExtensions(void)+{+ PIXELFORMATDESCRIPTOR pfd;+ HGLRC rc;+ HDC dc = GetDC(_glfw.win32.helperWindowHandle);;++ _glfw.wgl.extensionsLoaded = GLFW_TRUE;++ // NOTE: A dummy context has to be created for opengl32.dll to load the+ // OpenGL ICD, from which we can then query WGL extensions+ // NOTE: This code will accept the Microsoft GDI ICD; accelerated context+ // creation failure occurs during manual pixel format enumeration++ ZeroMemory(&pfd, sizeof(pfd));+ pfd.nSize = sizeof(pfd);+ pfd.nVersion = 1;+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;+ pfd.iPixelType = PFD_TYPE_RGBA;+ pfd.cColorBits = 24;++ if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to set pixel format for dummy context");+ return;+ }++ rc = wglCreateContext(dc);+ if (!rc)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to create dummy context");+ return;+ }++ if (!wglMakeCurrent(dc, rc))+ {+ wglDeleteContext(rc);++ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to make dummy context current");+ return;+ }++ // NOTE: Functions must be loaded first as they're needed to retrieve the+ // extension string that tells us whether the functions are supported+ _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)+ wglGetProcAddress("wglGetExtensionsStringEXT");+ _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)+ wglGetProcAddress("wglGetExtensionsStringARB");+ _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)+ wglGetProcAddress("wglCreateContextAttribsARB");+ _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)+ wglGetProcAddress("wglSwapIntervalEXT");+ _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)+ wglGetProcAddress("wglGetPixelFormatAttribivARB");++ // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not+ // checked below as we are already using them+ _glfw.wgl.ARB_multisample =+ extensionSupportedWGL("WGL_ARB_multisample");+ _glfw.wgl.ARB_framebuffer_sRGB =+ extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");+ _glfw.wgl.EXT_framebuffer_sRGB =+ extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");+ _glfw.wgl.ARB_create_context =+ extensionSupportedWGL("WGL_ARB_create_context");+ _glfw.wgl.ARB_create_context_profile =+ extensionSupportedWGL("WGL_ARB_create_context_profile");+ _glfw.wgl.EXT_create_context_es2_profile =+ extensionSupportedWGL("WGL_EXT_create_context_es2_profile");+ _glfw.wgl.ARB_create_context_robustness =+ extensionSupportedWGL("WGL_ARB_create_context_robustness");+ _glfw.wgl.EXT_swap_control =+ extensionSupportedWGL("WGL_EXT_swap_control");+ _glfw.wgl.ARB_pixel_format =+ extensionSupportedWGL("WGL_ARB_pixel_format");+ _glfw.wgl.ARB_context_flush_control =+ extensionSupportedWGL("WGL_ARB_context_flush_control");++ wglMakeCurrent(dc, NULL);+ wglDeleteContext(rc);+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialize WGL //-int _glfwInitContextAPI(void)+GLFWbool _glfwInitWGL(void) {- if (!_glfwInitTLS())- return GL_FALSE;+ if (_glfw.wgl.instance)+ return GLFW_TRUE; - _glfw.wgl.opengl32.instance = LoadLibraryW(L"opengl32.dll");- if (!_glfw.wgl.opengl32.instance)+ _glfw.wgl.instance = LoadLibraryA("opengl32.dll");+ if (!_glfw.wgl.instance) {- _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to load opengl32.dll");- return GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");+ return GLFW_FALSE; } - return GL_TRUE;+ _glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)+ GetProcAddress(_glfw.wgl.instance, "wglCreateContext");+ _glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)+ GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");+ _glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)+ GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");+ _glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T)+ GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");+ _glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)+ GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");+ _glfw.wgl.ShareLists = (WGLSHARELISTS_T)+ GetProcAddress(_glfw.wgl.instance, "wglShareLists");++ return GLFW_TRUE; } // Terminate WGL //-void _glfwTerminateContextAPI(void)+void _glfwTerminateWGL(void) {- if (_glfw.wgl.opengl32.instance)- FreeLibrary(_glfw.wgl.opengl32.instance);-- _glfwTerminateTLS();+ if (_glfw.wgl.instance)+ FreeLibrary(_glfw.wgl.instance); } #define setWGLattrib(attribName, attribValue) \@@ -351,75 +467,118 @@ // Create the OpenGL or OpenGL ES context //-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig) { int attribs[40];- int pixelFormat = 0;+ int pixelFormat; PIXELFORMATDESCRIPTOR pfd; HGLRC share = NULL; + if (!_glfw.wgl.extensionsLoaded)+ loadWGLExtensions();+ if (ctxconfig->share)- share = ctxconfig->share->wgl.context;+ share = ctxconfig->share->context.wgl.handle; - window->wgl.dc = GetDC(window->win32.handle);- if (!window->wgl.dc)+ window->context.wgl.dc = GetDC(window->win32.handle);+ if (!window->context.wgl.dc) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to retrieve DC for window");- return GL_FALSE;+ "WGL: Failed to retrieve DC for window");+ return GLFW_FALSE; } - if (!choosePixelFormat(window, fbconfig, &pixelFormat))- return GL_FALSE;+ pixelFormat = choosePixelFormat(window, fbconfig);+ if (!pixelFormat)+ return GLFW_FALSE; - if (!DescribePixelFormat(window->wgl.dc, pixelFormat, sizeof(pfd), &pfd))+ if (!DescribePixelFormat(window->context.wgl.dc,+ pixelFormat, sizeof(pfd), &pfd)) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to retrieve PFD for selected pixel "- "format");- return GL_FALSE;+ "WGL: Failed to retrieve PFD for selected pixel format");+ return GLFW_FALSE; } - if (!SetPixelFormat(window->wgl.dc, pixelFormat, &pfd))+ if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd)) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to set selected pixel format");- return GL_FALSE;+ "WGL: Failed to set selected pixel format");+ return GLFW_FALSE; } - if (window->wgl.ARB_create_context)+ if (ctxconfig->client == GLFW_OPENGL_API) {- int index = 0, mask = 0, flags = 0, strategy = 0;+ if (ctxconfig->forward)+ {+ if (!_glfw.wgl.ARB_create_context)+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");+ return GLFW_FALSE;+ }+ } - if (ctxconfig->api == GLFW_OPENGL_API)+ if (ctxconfig->profile) {+ if (!_glfw.wgl.ARB_create_context_profile)+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");+ return GLFW_FALSE;+ }+ }+ }+ else+ {+ if (!_glfw.wgl.ARB_create_context ||+ !_glfw.wgl.ARB_create_context_profile ||+ !_glfw.wgl.EXT_create_context_es2_profile)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");+ return GLFW_FALSE;+ }+ }++ if (_glfw.wgl.ARB_create_context)+ {+ int index = 0, mask = 0, flags = 0;++ if (ctxconfig->client == GLFW_OPENGL_API)+ { if (ctxconfig->forward) flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; - if (ctxconfig->debug)- flags |= WGL_CONTEXT_DEBUG_BIT_ARB;-- if (ctxconfig->profile)- {- if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)- mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;- else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)- mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;- }+ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)+ mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;+ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)+ mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; } else mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT; + if (ctxconfig->debug)+ flags |= WGL_CONTEXT_DEBUG_BIT_ARB;+ if (ctxconfig->noerror)+ flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;+ if (ctxconfig->robustness) {- if (window->wgl.ARB_create_context_robustness)+ if (_glfw.wgl.ARB_create_context_robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)- strategy = WGL_NO_RESET_NOTIFICATION_ARB;+ {+ setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,+ WGL_NO_RESET_NOTIFICATION_ARB);+ } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)- strategy = WGL_LOSE_CONTEXT_ON_RESET_ARB;+ {+ setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,+ WGL_LOSE_CONTEXT_ON_RESET_ARB);+ } flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB; }@@ -427,7 +586,7 @@ if (ctxconfig->release) {- if (window->wgl.ARB_context_flush_control)+ if (_glfw.wgl.ARB_context_flush_control) { if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE) {@@ -442,12 +601,11 @@ } } + // NOTE: Only request an explicitly versioned context when necessary, as+ // explicitly requesting version 1.0 does not always return the+ // highest version supported by the driver if (ctxconfig->major != 1 || ctxconfig->minor != 0) {- // NOTE: Only request an explicitly versioned context when- // necessary, as explicitly requesting version 1.0 does not- // always return the highest available version- setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major); setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor); }@@ -458,242 +616,86 @@ if (mask) setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask); - if (strategy)- setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, strategy);- setWGLattrib(0, 0); - window->wgl.context = window->wgl.CreateContextAttribsARB(window->wgl.dc,- share,- attribs);- if (!window->wgl.context)- {- _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "WGL: Failed to create OpenGL context");- return GL_FALSE;- }- }- else- {- window->wgl.context = wglCreateContext(window->wgl.dc);- if (!window->wgl.context)+ window->context.wgl.handle =+ _glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,+ share, attribs);+ if (!window->context.wgl.handle) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "WGL: Failed to create OpenGL context");- return GL_FALSE;- }+ const DWORD error = GetLastError(); - if (share)- {- if (!wglShareLists(share, window->wgl.context))+ if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB)) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "WGL: Failed to enable sharing with specified "- "OpenGL context");- return GL_FALSE;+ if (ctxconfig->client == GLFW_OPENGL_API)+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: Driver does not support OpenGL version %i.%i",+ ctxconfig->major,+ ctxconfig->minor);+ }+ else+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: Driver does not support OpenGL ES version %i.%i",+ ctxconfig->major,+ ctxconfig->minor);+ } }- }- }-- _glfwPlatformMakeContextCurrent(window);- initWGLExtensions(window);-- return GL_TRUE;-}--#undef setWGLattrib--// Destroy the OpenGL context-//-void _glfwDestroyContext(_GLFWwindow* window)-{- if (window->wgl.context)- {- wglDeleteContext(window->wgl.context);- window->wgl.context = NULL;- }-- if (window->wgl.dc)- {- ReleaseDC(window->win32.handle, window->wgl.dc);- window->wgl.dc = NULL;- }-}--// Analyzes the specified context for possible recreation-//-int _glfwAnalyzeContext(const _GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)-{- GLboolean required = GL_FALSE;-- if (ctxconfig->api == GLFW_OPENGL_API)- {- if (ctxconfig->forward)- {- if (!window->wgl.ARB_create_context)+ else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB)) { _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "WGL: A forward compatible OpenGL context "- "requested but WGL_ARB_create_context is "- "unavailable");- return _GLFW_RECREATION_IMPOSSIBLE;+ "WGL: Driver does not support the requested OpenGL profile"); }-- required = GL_TRUE;- }-- if (ctxconfig->profile)- {- if (!window->wgl.ARB_create_context_profile)+ else {- _glfwInputError(GLFW_VERSION_UNAVAILABLE,- "WGL: OpenGL profile requested but "- "WGL_ARB_create_context_profile is unavailable");- return _GLFW_RECREATION_IMPOSSIBLE;+ if (ctxconfig->client == GLFW_OPENGL_API)+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: Failed to create OpenGL context");+ }+ else+ {+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: Failed to create OpenGL ES context");+ } } - required = GL_TRUE;- }-- if (ctxconfig->release)- {- if (window->wgl.ARB_context_flush_control)- required = GL_TRUE;+ return GLFW_FALSE; } } else {- if (!window->wgl.ARB_create_context ||- !window->wgl.ARB_create_context_profile ||- !window->wgl.EXT_create_context_es2_profile)+ window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);+ if (!window->context.wgl.handle) {- _glfwInputError(GLFW_API_UNAVAILABLE,- "WGL: OpenGL ES requested but "- "WGL_ARB_create_context_es2_profile is unavailable");- return _GLFW_RECREATION_IMPOSSIBLE;+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,+ "WGL: Failed to create OpenGL context");+ return GLFW_FALSE; } - required = GL_TRUE;- }-- if (ctxconfig->major != 1 || ctxconfig->minor != 0)- {- if (window->wgl.ARB_create_context)- required = GL_TRUE;- }-- if (ctxconfig->debug)- {- if (window->wgl.ARB_create_context)- required = GL_TRUE;- }-- if (fbconfig->samples > 0)- {- // We want FSAA, but can we get it?- // FSAA is not a hard constraint, so otherwise we just don't care-- if (window->wgl.ARB_multisample && window->wgl.ARB_pixel_format)- {- // We appear to have both the extension and the means to ask for it- required = GL_TRUE;- }- }-- if (fbconfig->sRGB)- {- // We want sRGB, but can we get it?- // sRGB is not a hard constraint, so otherwise we just don't care-- if (window->wgl.ARB_framebuffer_sRGB && window->wgl.ARB_pixel_format)- {- // We appear to have both the extension and the means to ask for it- required = GL_TRUE;- }- }-- if (required)- return _GLFW_RECREATION_REQUIRED;-- return _GLFW_RECREATION_NOT_NEEDED;-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)-{- if (window)- wglMakeCurrent(window->wgl.dc, window->wgl.context);- else- wglMakeCurrent(NULL, NULL);-- _glfwSetCurrentContext(window);-}--void _glfwPlatformSwapBuffers(_GLFWwindow* window)-{- SwapBuffers(window->wgl.dc);-}--void _glfwPlatformSwapInterval(int interval)-{- _GLFWwindow* window = _glfwPlatformGetCurrentContext();--#if !defined(_GLFW_USE_DWM_SWAP_INTERVAL)- if (_glfwIsCompositionEnabled() && interval)- {- // Don't enabled vsync when desktop compositing is enabled, as it leads- // to frame jitter- return;- }-#endif-- if (window->wgl.EXT_swap_control)- window->wgl.SwapIntervalEXT(interval);-}--int _glfwPlatformExtensionSupported(const char* extension)-{- const GLubyte* extensions;-- _GLFWwindow* window = _glfwPlatformGetCurrentContext();-- if (window->wgl.GetExtensionsStringEXT != NULL)- {- extensions = (GLubyte*) window->wgl.GetExtensionsStringEXT();- if (extensions != NULL)+ if (share) {- if (_glfwStringInExtensionString(extension, extensions))- return GL_TRUE;+ if (!wglShareLists(share, window->context.wgl.handle))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "WGL: Failed to enable sharing with specified OpenGL context");+ return GLFW_FALSE;+ } } } - if (window->wgl.GetExtensionsStringARB != NULL)- {- extensions = (GLubyte*) window->wgl.GetExtensionsStringARB(window->wgl.dc);- if (extensions != NULL)- {- if (_glfwStringInExtensionString(extension, extensions))- return GL_TRUE;- }- }+ window->context.makeCurrent = makeContextCurrentWGL;+ window->context.swapBuffers = swapBuffersWGL;+ window->context.swapInterval = swapIntervalWGL;+ window->context.extensionSupported = extensionSupportedWGL;+ window->context.getProcAddress = getProcAddressWGL;+ window->context.destroy = destroyContextWGL; - return GL_FALSE;+ return GLFW_TRUE; } -GLFWglproc _glfwPlatformGetProcAddress(const char* procname)-{- const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);- if (proc)- return proc;-- return (GLFWglproc) GetProcAddress(_glfw.wgl.opengl32.instance, procname);-}+#undef setWGLattrib //////////////////////////////////////////////////////////////////////////@@ -704,6 +706,13 @@ { _GLFWwindow* window = (_GLFWwindow*) handle; _GLFW_REQUIRE_INIT_OR_RETURN(NULL);- return window->wgl.context;++ if (window->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return NULL;+ }++ return window->context.wgl.handle; }
glfw/src/wgl_context.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 WGL - www.glfw.org+// GLFW 3.2 WGL - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,15 +25,82 @@ // //======================================================================== -#ifndef _wgl_context_h_-#define _wgl_context_h_+#ifndef _glfw3_wgl_context_h_+#define _glfw3_wgl_context_h_ -// This path may need to be changed if you build GLFW using your own setup-// We ship and use our own copy of wglext.h since GLFW uses fairly new-// extensions and not all operating systems come with an up-to-date version-#include "../deps/GL/wglext.h" -#define _GLFW_PLATFORM_FBCONFIG int wgl+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000+#define WGL_SUPPORT_OPENGL_ARB 0x2010+#define WGL_DRAW_TO_WINDOW_ARB 0x2001+#define WGL_PIXEL_TYPE_ARB 0x2013+#define WGL_TYPE_RGBA_ARB 0x202b+#define WGL_ACCELERATION_ARB 0x2003+#define WGL_NO_ACCELERATION_ARB 0x2025+#define WGL_RED_BITS_ARB 0x2015+#define WGL_RED_SHIFT_ARB 0x2016+#define WGL_GREEN_BITS_ARB 0x2017+#define WGL_GREEN_SHIFT_ARB 0x2018+#define WGL_BLUE_BITS_ARB 0x2019+#define WGL_BLUE_SHIFT_ARB 0x201a+#define WGL_ALPHA_BITS_ARB 0x201b+#define WGL_ALPHA_SHIFT_ARB 0x201c+#define WGL_ACCUM_BITS_ARB 0x201d+#define WGL_ACCUM_RED_BITS_ARB 0x201e+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021+#define WGL_DEPTH_BITS_ARB 0x2022+#define WGL_STENCIL_BITS_ARB 0x2023+#define WGL_AUX_BUFFERS_ARB 0x2024+#define WGL_STEREO_ARB 0x2012+#define WGL_DOUBLE_BUFFER_ARB 0x2011+#define WGL_SAMPLES_ARB 0x2042+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092+#define WGL_CONTEXT_FLAGS_ARB 0x2094+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098++#define ERROR_INVALID_VERSION_ARB 0x2095+#define ERROR_INVALID_PROFILE_ARB 0x2096++typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);++typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);+typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);+typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);+typedef HDC (WINAPI * WGLGETCURRENTDC_T)(void);+typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);+typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);++// opengl32.dll function pointer typedefs+#define wglCreateContext _glfw.wgl.CreateContext+#define wglDeleteContext _glfw.wgl.DeleteContext+#define wglGetProcAddress _glfw.wgl.GetProcAddress+#define wglGetCurrentDC _glfw.wgl.GetCurrentDC+#define wglMakeCurrent _glfw.wgl.MakeCurrent+#define wglShareLists _glfw.wgl.ShareLists++#define _GLFW_RECREATION_NOT_NEEDED 0+#define _GLFW_RECREATION_REQUIRED 1+#define _GLFW_RECREATION_IMPOSSIBLE 2+ #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl @@ -42,48 +109,49 @@ // typedef struct _GLFWcontextWGL {- HDC dc; // Private GDI device context- HGLRC context; // Permanent rendering context-- // WGL extensions (context specific)- PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;- PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;- PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;- PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;- PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;- GLboolean EXT_swap_control;- GLboolean ARB_multisample;- GLboolean ARB_framebuffer_sRGB;- GLboolean ARB_pixel_format;- GLboolean ARB_create_context;- GLboolean ARB_create_context_profile;- GLboolean EXT_create_context_es2_profile;- GLboolean ARB_create_context_robustness;- GLboolean ARB_context_flush_control;+ HDC dc;+ HGLRC handle;+ int interval; } _GLFWcontextWGL; - // WGL-specific global data // typedef struct _GLFWlibraryWGL {- // opengl32.dll (for glfwGetProcAddress)- struct {- HINSTANCE instance;- } opengl32;+ HINSTANCE instance;+ WGLCREATECONTEXT_T CreateContext;+ WGLDELETECONTEXT_T DeleteContext;+ WGLGETPROCADDRESS_T GetProcAddress;+ WGLGETCURRENTDC_T GetCurrentDC;+ WGLMAKECURRENT_T MakeCurrent;+ WGLSHARELISTS_T ShareLists; + GLFWbool extensionsLoaded;++ PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;+ PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;+ PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;+ PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;+ GLFWbool EXT_swap_control;+ GLFWbool ARB_multisample;+ GLFWbool ARB_framebuffer_sRGB;+ GLFWbool EXT_framebuffer_sRGB;+ GLFWbool ARB_pixel_format;+ GLFWbool ARB_create_context;+ GLFWbool ARB_create_context_profile;+ GLFWbool EXT_create_context_es2_profile;+ GLFWbool ARB_create_context_robustness;+ GLFWbool ARB_context_flush_control;+ } _GLFWlibraryWGL; -int _glfwInitContextAPI(void);-void _glfwTerminateContextAPI(void);-int _glfwCreateContext(_GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);-void _glfwDestroyContext(_GLFWwindow* window);-int _glfwAnalyzeContext(const _GLFWwindow* window,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig);+GLFWbool _glfwInitWGL(void);+void _glfwTerminateWGL(void);+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig); -#endif // _wgl_context_h_+#endif // _glfw3_wgl_context_h_
glfw/src/win32_init.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org+// GLFW 3.2 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -30,20 +30,24 @@ #include <stdlib.h> #include <malloc.h> -#ifdef __BORLANDC__-// With the Borland C++ compiler, we want to disable FPU exceptions-#include <float.h>-#endif // __BORLANDC__+#include <initguid.h>+DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30); +#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) -#if defined(_GLFW_USE_OPTIMUS_HPG)+// Applications exporting this symbol with this value will be automatically+// directed to the high-performance GPU on Nvidia Optimus systems with+// up-to-date drivers+//+__declspec(dllexport) DWORD NvOptimusEnablement = 1; // Applications exporting this symbol with this value will be automatically-// directed to the high-performance GPU on Nvidia Optimus systems+// directed to the high-performance GPU on AMD PowerXpress systems with+// up-to-date drivers //-__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;+__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; -#endif // _GLFW_USE_OPTIMUS_HPG+#endif // _GLFW_USE_HYBRID_HPG #if defined(_GLFW_BUILD_DLL) @@ -58,58 +62,93 @@ // Load necessary libraries (DLLs) //-static GLboolean initLibraries(void)+static GLFWbool loadLibraries(void) {- _glfw.win32.winmm.instance = LoadLibraryW(L"winmm.dll");+ _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); if (!_glfw.win32.winmm.instance) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to load winmm.dll");- return GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");+ return GLFW_FALSE; } - _glfw.win32.winmm.joyGetDevCaps = (JOYGETDEVCAPS_T)- GetProcAddress(_glfw.win32.winmm.instance, "joyGetDevCapsW");- _glfw.win32.winmm.joyGetPos = (JOYGETPOS_T)- GetProcAddress(_glfw.win32.winmm.instance, "joyGetPos");- _glfw.win32.winmm.joyGetPosEx = (JOYGETPOSEX_T)- GetProcAddress(_glfw.win32.winmm.instance, "joyGetPosEx"); _glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T) GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); - if (!_glfw.win32.winmm.joyGetDevCaps ||- !_glfw.win32.winmm.joyGetPos ||- !_glfw.win32.winmm.joyGetPosEx ||- !_glfw.win32.winmm.timeGetTime)+ _glfw.win32.user32.instance = LoadLibraryA("user32.dll");+ if (!_glfw.win32.user32.instance) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to load winmm functions");- return GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");+ return GLFW_FALSE; } - _glfw.win32.user32.instance = LoadLibraryW(L"user32.dll");- if (_glfw.win32.user32.instance)+ _glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)+ GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");+ _glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)+ GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");++ _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");+ if (_glfw.win32.dinput8.instance) {- _glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)- GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");- _glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)- GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");+ _glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)+ GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create"); } - _glfw.win32.dwmapi.instance = LoadLibraryW(L"dwmapi.dll");+ {+ int i;+ const char* names[] =+ {+ "xinput1_4.dll",+ "xinput1_3.dll",+ "xinput9_1_0.dll",+ "xinput1_2.dll",+ "xinput1_1.dll",+ NULL+ };++ for (i = 0; names[i]; i++)+ {+ _glfw.win32.xinput.instance = LoadLibraryA(names[i]);+ if (_glfw.win32.xinput.instance)+ {+ _glfw.win32.xinput.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");+ _glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");++ break;+ }+ }+ }++ _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); if (_glfw.win32.dwmapi.instance) { _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");+ _glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); } - return GL_TRUE;+ _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");+ if (_glfw.win32.shcore.instance)+ {+ _glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)+ GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");+ }++ return GLFW_TRUE; } // Unload used libraries (DLLs) //-static void terminateLibraries(void)+static void freeLibraries(void) {+ if (_glfw.win32.xinput.instance)+ FreeLibrary(_glfw.win32.xinput.instance);++ if (_glfw.win32.dinput8.instance)+ FreeLibrary(_glfw.win32.dinput8.instance);+ if (_glfw.win32.winmm.instance) FreeLibrary(_glfw.win32.winmm.instance); @@ -118,13 +157,19 @@ if (_glfw.win32.dwmapi.instance) FreeLibrary(_glfw.win32.dwmapi.instance);++ if (_glfw.win32.shcore.instance)+ FreeLibrary(_glfw.win32.shcore.instance); } // Create key code translation tables // static void createKeyTables(void) {+ int scancode;+ memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));+ memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys)); _glfw.win32.publicKeys[0x00B] = GLFW_KEY_0; _glfw.win32.publicKeys[0x002] = GLFW_KEY_1;@@ -187,6 +232,7 @@ _glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN; _glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP; _glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;+ _glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE; _glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE; _glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB; _glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;@@ -246,31 +292,61 @@ _glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER; _glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY; _glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;-} --//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////+ for (scancode = 0; scancode < 512; scancode++)+ {+ if (_glfw.win32.publicKeys[scancode] > 0)+ _glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;+ }+} -// Returns whether desktop compositing is enabled+// Creates a dummy window for behind-the-scenes work //-BOOL _glfwIsCompositionEnabled(void)+static HWND createHelperWindow(void) {- BOOL enabled;+ HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,+ _GLFW_WNDCLASSNAME,+ L"GLFW helper window",+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN,+ 0, 0, 1, 1,+ HWND_MESSAGE, NULL,+ GetModuleHandleW(NULL),+ NULL);+ if (!window)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to create helper window");+ return NULL;+ } - if (!_glfw_DwmIsCompositionEnabled)- return FALSE;+ // HACK: The first call to ShowWindow is ignored if the parent process+ // passed along a STARTUPINFO, so clear that flag with a no-op call+ ShowWindow(window, SW_HIDE); - if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)- return FALSE;+ // Register for HID device notifications+ {+ DEV_BROADCAST_DEVICEINTERFACE_W dbi;+ ZeroMemory(&dbi, sizeof(dbi));+ dbi.dbcc_size = sizeof(dbi);+ dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;+ dbi.dbcc_classguid = GUID_DEVINTERFACE_HID; - return enabled;+ RegisterDeviceNotificationW(window,+ (DEV_BROADCAST_HDR*) &dbi,+ DEVICE_NOTIFY_WINDOW_HANDLE);+ }++ return window; } ++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////+ // Returns a wide string version of the specified UTF-8 string //-WCHAR* _glfwCreateWideStringFromUTF8(const char* source)+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source) { WCHAR* target; int length;@@ -292,7 +368,7 @@ // Returns a UTF-8 string version of the specified wide string //-char* _glfwCreateUTF8FromWideString(const WCHAR* source)+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) { char* target; int length;@@ -301,7 +377,7 @@ if (!length) return NULL; - target = calloc(length, sizeof(char));+ target = calloc(length, 1); if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL)) {@@ -319,6 +395,9 @@ int _glfwPlatformInit(void) {+ if (!_glfwInitThreadLocalStorageWin32())+ return GLFW_FALSE;+ // To make SetForegroundWindow work as we want, we need to fiddle // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early // as possible in the hope of still being the foreground process)@@ -327,36 +406,38 @@ SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0), SPIF_SENDCHANGE); - if (!initLibraries())- return GL_FALSE;+ if (!loadLibraries())+ return GLFW_FALSE; createKeyTables(); - if (_glfw_SetProcessDPIAware)+ if (_glfw_SetProcessDpiAwareness)+ _glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);+ else if (_glfw_SetProcessDPIAware) _glfw_SetProcessDPIAware(); -#ifdef __BORLANDC__- // With the Borland C++ compiler, we want to disable FPU exceptions- // (this is recommended for OpenGL applications under Windows)- _control87(MCW_EM, MCW_EM);-#endif+ if (!_glfwRegisterWindowClassWin32())+ return GLFW_FALSE; - if (!_glfwRegisterWindowClass())- return GL_FALSE;+ _glfw.win32.helperWindowHandle = createHelperWindow();+ if (!_glfw.win32.helperWindowHandle)+ return GLFW_FALSE; - if (!_glfwInitContextAPI())- return GL_FALSE;+ _glfwPlatformPollEvents(); - _glfwInitTimer();- _glfwInitJoysticks();+ _glfwInitTimerWin32();+ _glfwInitJoysticksWin32(); - return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformTerminate(void) {- _glfwUnregisterWindowClass();+ if (_glfw.win32.helperWindowHandle)+ DestroyWindow(_glfw.win32.helperWindowHandle); + _glfwUnregisterWindowClassWin32();+ // Restore previous foreground lock timeout system setting SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(_glfw.win32.foregroundLockTimeout),@@ -364,31 +445,29 @@ free(_glfw.win32.clipboardString); - _glfwTerminateJoysticks();- _glfwTerminateContextAPI();- terminateLibraries();+ _glfwTerminateWGL();+ _glfwTerminateEGL();++ _glfwTerminateJoysticksWin32();+ _glfwTerminateThreadLocalStorageWin32();++ freeLibraries(); } const char* _glfwPlatformGetVersionString(void) {- const char* version = _GLFW_VERSION_NUMBER " Win32"-#if defined(_GLFW_WGL)- " WGL"-#elif defined(_GLFW_EGL)- " EGL"-#endif+ return _GLFW_VERSION_NUMBER " Win32 WGL EGL" #if defined(__MINGW32__) " MinGW" #elif defined(_MSC_VER) " VisualC"-#elif defined(__BORLANDC__)- " BorlandC" #endif+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)+ " hybrid-GPU"+#endif #if defined(_GLFW_BUILD_DLL) " DLL" #endif ;-- return version; }
+ glfw/src/win32_joystick.c view
@@ -0,0 +1,763 @@+//========================================================================+// GLFW 3.1 Win32 - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2002-2006 Marcus Geelnard+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <math.h>++#include <initguid.h>++#define _GLFW_PRESENCE_ONLY 1+#define _GLFW_UPDATE_STATE 2++#define _GLFW_TYPE_AXIS 0+#define _GLFW_TYPE_SLIDER 1+#define _GLFW_TYPE_BUTTON 2+#define _GLFW_TYPE_POV 3++// Data produced with DirectInput device object enumeration+//+typedef struct _GLFWobjenumWin32+{+ IDirectInputDevice8W* device;+ _GLFWjoyobjectWin32* objects;+ int objectCount;+ int axisCount;+ int sliderCount;+ int buttonCount;+ int povCount;+} _GLFWobjenumWin32;++// Define only the necessary GUIDs (it's bad enough that we're exporting these)+//+DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);+DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);+DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);++// Object data array for our clone of c_dfDIJoystick+// Generated with https://github.com/elmindreda/c_dfDIJoystick2+//+static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =+{+ { &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },+ { &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+ { NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },+};++// Our clone of c_dfDIJoystick+//+static const DIDATAFORMAT _glfwDataFormat =+{+ sizeof(DIDATAFORMAT),+ sizeof(DIOBJECTDATAFORMAT),+ DIDFT_ABSAXIS,+ sizeof(DIJOYSTATE),+ sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),+ _glfwObjectDataFormats+};++// Returns a description fitting the specified XInput capabilities+//+static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)+{+ switch (xic->SubType)+ {+ case XINPUT_DEVSUBTYPE_WHEEL:+ return "XInput Wheel";+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:+ return "XInput Arcade Stick";+ case XINPUT_DEVSUBTYPE_FLIGHT_STICK:+ return "XInput Flight Stick";+ case XINPUT_DEVSUBTYPE_DANCE_PAD:+ return "XInput Dance Pad";+ case XINPUT_DEVSUBTYPE_GUITAR:+ return "XInput Guitar";+ case XINPUT_DEVSUBTYPE_DRUM_KIT:+ return "XInput Drum Kit";+ case XINPUT_DEVSUBTYPE_GAMEPAD:+ {+ if (xic->Flags & XINPUT_CAPS_WIRELESS)+ return "Wireless Xbox 360 Controller";+ else+ return "Xbox 360 Controller";+ }+ }++ return "Unknown XInput Device";+}++// Lexically compare device objects+//+static int compareJoystickObjects(const void* first, const void* second)+{+ const _GLFWjoyobjectWin32* fo = first;+ const _GLFWjoyobjectWin32* so = second;++ if (fo->type != so->type)+ return fo->type - so->type;++ return fo->offset - so->offset;+}++// Checks whether the specified device supports XInput+// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom+//+static GLFWbool supportsXInput(const GUID* guid)+{+ UINT i, count = 0;+ RAWINPUTDEVICELIST* ridl;+ GLFWbool result = GLFW_FALSE;++ if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)+ return GLFW_FALSE;++ ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));++ if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)+ {+ free(ridl);+ return GLFW_FALSE;+ }++ for (i = 0; i < count; i++)+ {+ RID_DEVICE_INFO rdi;+ char name[256];+ UINT size;++ if (ridl[i].dwType != RIM_TYPEHID)+ continue;++ ZeroMemory(&rdi, sizeof(rdi));+ rdi.cbSize = sizeof(rdi);+ size = sizeof(rdi);++ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,+ RIDI_DEVICEINFO,+ &rdi, &size) == -1)+ {+ continue;+ }++ if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)+ continue;++ memset(name, 0, sizeof(name));+ size = sizeof(name);++ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,+ RIDI_DEVICENAME,+ name, &size) == -1)+ {+ break;+ }++ name[sizeof(name) - 1] = '\0';+ if (strstr(name, "IG_"))+ {+ result = GLFW_TRUE;+ break;+ }+ }++ free(ridl);+ return result;+}++// Frees all resources associated with the specified joystick+//+static void closeJoystick(_GLFWjoystickWin32* js)+{+ if (js->device)+ {+ IDirectInputDevice8_Unacquire(js->device);+ IDirectInputDevice8_Release(js->device);+ }++ free(js->name);+ free(js->axes);+ free(js->buttons);+ free(js->objects);+ memset(js, 0, sizeof(_GLFWjoystickWin32));++ _glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);+}++// DirectInput device object enumeration callback+// Insights gleaned from SDL2+//+static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,+ void* user)+{+ _GLFWobjenumWin32* data = user;+ _GLFWjoyobjectWin32* object = data->objects + data->objectCount;++ if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)+ {+ DIPROPRANGE dipr;++ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)+ object->offset = DIJOFS_SLIDER(data->sliderCount);+ else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_X;+ else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_Y;+ else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_Z;+ else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_RX;+ else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_RY;+ else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)+ object->offset = DIJOFS_RZ;+ else+ return DIENUM_CONTINUE;++ ZeroMemory(&dipr, sizeof(dipr));+ dipr.diph.dwSize = sizeof(dipr);+ dipr.diph.dwHeaderSize = sizeof(dipr.diph);+ dipr.diph.dwObj = doi->dwType;+ dipr.diph.dwHow = DIPH_BYID;+ dipr.lMin = -32768;+ dipr.lMax = 32767;++ if (FAILED(IDirectInputDevice8_SetProperty(data->device,+ DIPROP_RANGE,+ &dipr.diph)))+ {+ return DIENUM_CONTINUE;+ }++ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)+ {+ object->type = _GLFW_TYPE_SLIDER;+ data->sliderCount++;+ }+ else+ {+ object->type = _GLFW_TYPE_AXIS;+ data->axisCount++;+ }+ }+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)+ {+ object->offset = DIJOFS_BUTTON(data->buttonCount);+ object->type = _GLFW_TYPE_BUTTON;+ data->buttonCount++;+ }+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)+ {+ object->offset = DIJOFS_POV(data->povCount);+ object->type = _GLFW_TYPE_POV;+ data->povCount++;+ }++ data->objectCount++;+ return DIENUM_CONTINUE;+}++// DirectInput device enumeration callback+//+static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)+{+ int joy = 0;+ DIDEVCAPS dc;+ DIPROPDWORD dipd;+ IDirectInputDevice8* device;+ _GLFWobjenumWin32 data;+ _GLFWjoystickWin32* js;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)+ return DIENUM_CONTINUE;+ }++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (!_glfw.win32_js[joy].present)+ break;+ }++ if (joy > GLFW_JOYSTICK_LAST)+ return DIENUM_STOP;++ if (supportsXInput(&di->guidProduct))+ return DIENUM_CONTINUE;++ if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,+ &di->guidInstance,+ &device,+ NULL)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");+ return DIENUM_CONTINUE;+ }++ if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "DI: Failed to set device data format");++ IDirectInputDevice8_Release(device);+ return DIENUM_CONTINUE;+ }++ ZeroMemory(&dc, sizeof(dc));+ dc.dwSize = sizeof(dc);++ if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "DI: Failed to query device capabilities");++ IDirectInputDevice8_Release(device);+ return DIENUM_CONTINUE;+ }++ ZeroMemory(&dipd, sizeof(dipd));+ dipd.diph.dwSize = sizeof(dipd);+ dipd.diph.dwHeaderSize = sizeof(dipd.diph);+ dipd.diph.dwHow = DIPH_DEVICE;+ dipd.dwData = DIPROPAXISMODE_ABS;++ if (FAILED(IDirectInputDevice8_SetProperty(device,+ DIPROP_AXISMODE,+ &dipd.diph)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "DI: Failed to set device axis mode");++ IDirectInputDevice8_Release(device);+ return DIENUM_CONTINUE;+ }++ memset(&data, 0, sizeof(data));+ data.device = device;+ data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,+ sizeof(_GLFWjoyobjectWin32));++ if (FAILED(IDirectInputDevice8_EnumObjects(device,+ deviceObjectCallback,+ &data,+ DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "DI: Failed to enumerate device objects");++ IDirectInputDevice8_Release(device);+ free(data.objects);+ return DIENUM_CONTINUE;+ }++ qsort(data.objects, data.objectCount,+ sizeof(_GLFWjoyobjectWin32),+ compareJoystickObjects);++ js = _glfw.win32_js + joy;+ js->device = device;+ js->guid = di->guidInstance;+ js->axisCount = data.axisCount + data.sliderCount;+ js->axes = calloc(js->axisCount, sizeof(float));+ js->buttonCount += data.buttonCount + data.povCount * 4;+ js->buttons = calloc(js->buttonCount, 1);+ js->objects = data.objects;+ js->objectCount = data.objectCount;+ js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);+ js->present = GLFW_TRUE;++ _glfwInputJoystickChange(joy, GLFW_CONNECTED);+ return DIENUM_CONTINUE;+}++// Attempt to open the specified joystick device+// TODO: Pack state arrays for non-gamepad devices+//+static GLFWbool openXinputDevice(DWORD index)+{+ int joy;+ XINPUT_CAPABILITIES xic;+ _GLFWjoystickWin32* js;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (_glfw.win32_js[joy].present &&+ _glfw.win32_js[joy].device == NULL &&+ _glfw.win32_js[joy].index == index)+ {+ return GLFW_FALSE;+ }+ }++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ {+ if (!_glfw.win32_js[joy].present)+ break;+ }++ if (joy > GLFW_JOYSTICK_LAST)+ return GLFW_FALSE;++ if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)+ return GLFW_FALSE;++ js = _glfw.win32_js + joy;+ js->axisCount = 6;+ js->axes = calloc(js->axisCount, sizeof(float));+ js->buttonCount = 14;+ js->buttons = calloc(js->buttonCount, 1);+ js->present = GLFW_TRUE;+ js->name = strdup(getDeviceDescription(&xic));+ js->index = index;++ _glfwInputJoystickChange(joy, GLFW_CONNECTED);++ return GLFW_TRUE;+}++// Polls for and processes events the specified joystick+//+static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)+{+ if (!js->present)+ return GLFW_FALSE;++ if (js->device)+ {+ int i, j, ai = 0, bi = 0;+ HRESULT result;+ DIJOYSTATE state;++ IDirectInputDevice8_Poll(js->device);+ result = IDirectInputDevice8_GetDeviceState(js->device,+ sizeof(state),+ &state);+ if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)+ {+ IDirectInputDevice8_Acquire(js->device);+ IDirectInputDevice8_Poll(js->device);+ result = IDirectInputDevice8_GetDeviceState(js->device,+ sizeof(state),+ &state);+ }++ if (FAILED(result))+ {+ closeJoystick(js);+ return GLFW_FALSE;+ }++ if (mode == _GLFW_PRESENCE_ONLY)+ return GLFW_TRUE;++ for (i = 0; i < js->objectCount; i++)+ {+ const void* data = (char*) &state + js->objects[i].offset;++ switch (js->objects[i].type)+ {+ case _GLFW_TYPE_AXIS:+ case _GLFW_TYPE_SLIDER:+ {+ js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;+ break;+ }++ case _GLFW_TYPE_BUTTON:+ {+ if (*((BYTE*) data) & 0x80)+ js->buttons[bi++] = GLFW_PRESS;+ else+ js->buttons[bi++] = GLFW_RELEASE;++ break;+ }++ case _GLFW_TYPE_POV:+ {+ const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };+ // Screams of horror are appropriate at this point+ int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);+ if (value < 0 || value > 8)+ value = 8;++ for (j = 0; j < 4; j++)+ {+ if (directions[value] & (1 << j))+ js->buttons[bi++] = GLFW_PRESS;+ else+ js->buttons[bi++] = GLFW_RELEASE;+ }++ break;+ }+ }+ }++ return GLFW_TRUE;+ }+ else+ {+ int i;+ DWORD result;+ XINPUT_STATE xis;+ const WORD buttons[14] =+ {+ XINPUT_GAMEPAD_A,+ XINPUT_GAMEPAD_B,+ XINPUT_GAMEPAD_X,+ XINPUT_GAMEPAD_Y,+ XINPUT_GAMEPAD_LEFT_SHOULDER,+ XINPUT_GAMEPAD_RIGHT_SHOULDER,+ XINPUT_GAMEPAD_BACK,+ XINPUT_GAMEPAD_START,+ XINPUT_GAMEPAD_LEFT_THUMB,+ XINPUT_GAMEPAD_RIGHT_THUMB,+ XINPUT_GAMEPAD_DPAD_UP,+ XINPUT_GAMEPAD_DPAD_RIGHT,+ XINPUT_GAMEPAD_DPAD_DOWN,+ XINPUT_GAMEPAD_DPAD_LEFT+ };++ result = _glfw_XInputGetState(js->index, &xis);+ if (result != ERROR_SUCCESS)+ {+ if (result == ERROR_DEVICE_NOT_CONNECTED)+ closeJoystick(js);++ return GLFW_FALSE;+ }++ if (mode == _GLFW_PRESENCE_ONLY)+ return GLFW_TRUE;++ if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX ++ xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >+ (double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)+ {+ js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;+ js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;+ }+ else+ {+ js->axes[0] = 0.f;+ js->axes[1] = 0.f;+ }++ if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX ++ xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >+ (double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)+ {+ js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;+ js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;+ }+ else+ {+ js->axes[2] = 0.f;+ js->axes[3] = 0.f;+ }++ if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)+ js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;+ else+ js->axes[4] = -1.f;++ if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)+ js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;+ else+ js->axes[5] = -1.f;++ for (i = 0; i < 14; i++)+ js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;++ return GLFW_TRUE;+ }+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++// Initialize joystick interface+//+void _glfwInitJoysticksWin32(void)+{+ if (_glfw.win32.dinput8.instance)+ {+ if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),+ DIRECTINPUT_VERSION,+ &IID_IDirectInput8W,+ (void**) &_glfw.win32.dinput8.api,+ NULL)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "DI: Failed to create interface");+ }+ }++ _glfwDetectJoystickConnectionWin32();+}++// Close all opened joystick handles+//+void _glfwTerminateJoysticksWin32(void)+{+ int joy;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ closeJoystick(_glfw.win32_js + joy);++ if (_glfw.win32.dinput8.api)+ IDirectInput8_Release(_glfw.win32.dinput8.api);+}++// Checks for new joysticks after DBT_DEVICEARRIVAL+//+void _glfwDetectJoystickConnectionWin32(void)+{+ if (_glfw.win32.xinput.instance)+ {+ DWORD i;++ for (i = 0; i < XUSER_MAX_COUNT; i++)+ openXinputDevice(i);+ }++ if (_glfw.win32.dinput8.api)+ {+ if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,+ DI8DEVCLASS_GAMECTRL,+ deviceCallback,+ NULL,+ DIEDFL_ALLDEVICES)))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Failed to enumerate DirectInput8 devices");+ return;+ }+ }+}++// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE+//+void _glfwDetectJoystickDisconnectionWin32(void)+{+ int joy;++ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)+ pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW platform API //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformJoystickPresent(int joy)+{+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;+ return pollJoystickState(js, _GLFW_PRESENCE_ONLY);+}++const float* _glfwPlatformGetJoystickAxes(int joy, int* count)+{+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;+ if (!pollJoystickState(js, _GLFW_UPDATE_STATE))+ return NULL;++ *count = js->axisCount;+ return js->axes;+}++const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)+{+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;+ if (!pollJoystickState(js, _GLFW_UPDATE_STATE))+ return NULL;++ *count = js->buttonCount;+ return js->buttons;+}++const char* _glfwPlatformGetJoystickName(int joy)+{+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;+ if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))+ return NULL;++ return js->name;+}+
+ glfw/src/win32_joystick.h view
@@ -0,0 +1,64 @@+//========================================================================+// GLFW 3.2 Win32 - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#ifndef _glfw3_win32_joystick_h_+#define _glfw3_win32_joystick_h_++#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \+ _GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]++// Joystick element (axis, button or slider)+//+typedef struct _GLFWjoyobjectWin32+{+ int offset;+ int type;+} _GLFWjoyobjectWin32;++// Win32-specific per-joystick data+//+typedef struct _GLFWjoystickWin32+{+ GLFWbool present;+ float* axes;+ int axisCount;+ unsigned char* buttons;+ int buttonCount;+ _GLFWjoyobjectWin32* objects;+ int objectCount;+ char* name;+ IDirectInputDevice8W* device;+ DWORD index;+ GUID guid;+} _GLFWjoystickWin32;+++void _glfwInitJoysticksWin32(void);+void _glfwTerminateJoysticksWin32(void);+void _glfwDetectJoystickConnectionWin32(void);+void _glfwDetectJoystickDisconnectionWin32(void);++#endif // _glfw3_win32_joystick_h_
glfw/src/win32_monitor.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org+// GLFW 3.2 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -32,22 +32,67 @@ #include <limits.h> #include <malloc.h> -// These constants are missing on MinGW-#ifndef EDS_ROTATEDMODE- #define EDS_ROTATEDMODE 0x00000004-#endif-#ifndef DISPLAY_DEVICE_ACTIVE- #define DISPLAY_DEVICE_ACTIVE 0x00000001-#endif +// Create monitor from an adapter and (optionally) a display+//+static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,+ DISPLAY_DEVICEW* display)+{+ _GLFWmonitor* monitor;+ char* name;+ HDC dc; + if (display)+ name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);+ else+ name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);+ if (!name)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to convert string to UTF-8");+ return NULL;+ }++ dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);++ monitor = _glfwAllocMonitor(name,+ GetDeviceCaps(dc, HORZSIZE),+ GetDeviceCaps(dc, VERTSIZE));++ DeleteDC(dc);+ free(name);++ if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)+ monitor->win32.modesPruned = GLFW_TRUE;++ wcscpy(monitor->win32.adapterName, adapter->DeviceName);+ WideCharToMultiByte(CP_UTF8, 0,+ adapter->DeviceName, -1,+ monitor->win32.publicAdapterName,+ sizeof(monitor->win32.publicAdapterName),+ NULL, NULL);++ if (display)+ {+ wcscpy(monitor->win32.displayName, display->DeviceName);+ WideCharToMultiByte(CP_UTF8, 0,+ display->DeviceName, -1,+ monitor->win32.publicDisplayName,+ sizeof(monitor->win32.publicDisplayName),+ NULL, NULL);+ }++ return monitor;+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Change the current video mode //-GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired)+GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired) { GLFWvidmode current; const GLFWvidmode* best;@@ -56,7 +101,7 @@ best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0)- return GL_TRUE;+ return GLFW_TRUE; ZeroMemory(&dm, sizeof(dm)); dm.dmSize = sizeof(DEVMODEW);@@ -77,22 +122,22 @@ NULL) != DISP_CHANGE_SUCCESSFUL) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");- return GL_FALSE;+ return GLFW_FALSE; } - monitor->win32.modeChanged = GL_TRUE;- return GL_TRUE;+ monitor->win32.modeChanged = GLFW_TRUE;+ return GLFW_TRUE; } // Restore the previously saved (original) video mode //-void _glfwRestoreVideoMode(_GLFWmonitor* monitor)+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor) { if (monitor->win32.modeChanged) { ChangeDisplaySettingsExW(monitor->win32.adapterName, NULL, NULL, CDS_FULLSCREEN, NULL);- monitor->win32.modeChanged = GL_FALSE;+ monitor->win32.modeChanged = GLFW_FALSE; } } @@ -103,16 +148,19 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) {- int size = 0, found = 0;+ int found = 0;+ DWORD adapterIndex, displayIndex, primaryIndex = 0;+ DISPLAY_DEVICEW adapter, display;+ GLFWbool hasDisplays = GLFW_FALSE; _GLFWmonitor** monitors = NULL;- DWORD adapterIndex, displayIndex; *count = 0; + // HACK: Check if any active adapters have connected displays+ // If not, this is a headless system or a VMware guest+ for (adapterIndex = 0; ; adapterIndex++) {- DISPLAY_DEVICEW adapter;- ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW)); adapter.cb = sizeof(DISPLAY_DEVICEW); @@ -122,73 +170,65 @@ if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE)) continue; - for (displayIndex = 0; ; displayIndex++)- {- DISPLAY_DEVICEW display;- char* name;- HDC dc;-- ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));- display.cb = sizeof(DISPLAY_DEVICEW);-- if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))- break;-- if (found == size)- {- size += 4;- monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);- }+ ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));+ display.cb = sizeof(DISPLAY_DEVICEW); - name = _glfwCreateUTF8FromWideString(display.DeviceString);- if (!name)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Failed to convert string to UTF-8");- continue;- }+ if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))+ {+ hasDisplays = GLFW_TRUE;+ break;+ }+ } - dc = CreateDCW(L"DISPLAY", adapter.DeviceName, NULL, NULL);+ for (adapterIndex = 0; ; adapterIndex++)+ {+ ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));+ adapter.cb = sizeof(DISPLAY_DEVICEW); - monitors[found] = _glfwAllocMonitor(name,- GetDeviceCaps(dc, HORZSIZE),- GetDeviceCaps(dc, VERTSIZE));+ if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))+ break; - DeleteDC(dc);- free(name);+ if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))+ continue; - wcscpy(monitors[found]->win32.adapterName, adapter.DeviceName);- wcscpy(monitors[found]->win32.displayName, display.DeviceName);+ if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)+ primaryIndex = found; - WideCharToMultiByte(CP_UTF8, 0,- adapter.DeviceName, -1,- monitors[found]->win32.publicAdapterName,- sizeof(monitors[found]->win32.publicAdapterName),- NULL, NULL);+ if (hasDisplays)+ {+ for (displayIndex = 0; ; displayIndex++)+ {+ ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));+ display.cb = sizeof(DISPLAY_DEVICEW); - WideCharToMultiByte(CP_UTF8, 0,- display.DeviceName, -1,- monitors[found]->win32.publicDisplayName,- sizeof(monitors[found]->win32.publicDisplayName),- NULL, NULL);+ if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))+ break; - if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE &&- displayIndex == 0)- {- _GLFW_SWAP_POINTERS(monitors[0], monitors[found]);+ found++;+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);+ monitors[found - 1] = createMonitor(&adapter, &display); }-+ }+ else+ { found++;+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);+ monitors[found - 1] = createMonitor(&adapter, NULL); } } + _GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);+ *count = found; return monitors; } -GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) {- return wcscmp(first->win32.displayName, second->win32.displayName) == 0;+ if (wcslen(first->win32.displayName))+ return wcscmp(first->win32.displayName, second->win32.displayName) == 0;+ else+ return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0; } void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)@@ -208,12 +248,12 @@ *ypos = settings.dmPosition.y; } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) {- int modeIndex = 0, count = 0;+ int modeIndex = 0, size = 0; GLFWvidmode* result = NULL; - *found = 0;+ *count = 0; for (;;) {@@ -229,11 +269,9 @@ modeIndex++; + // Skip modes with less than 15 BPP if (dm.dmBitsPerPel < 15)- {- // Skip modes with less than 15 BPP continue;- } mode.width = dm.dmPelsWidth; mode.height = dm.dmPelsHeight;@@ -243,30 +281,45 @@ &mode.greenBits, &mode.blueBits); - for (i = 0; i < *found; i++)+ for (i = 0; i < *count; i++) { if (_glfwCompareVideoModes(result + i, &mode) == 0) break; } - if (i < *found)- {- // This is a duplicate, so skip it+ // Skip duplicate modes+ if (i < *count) continue;- } - if (*found == count)+ if (monitor->win32.modesPruned) {- if (count)- count *= 2;- else- count = 128;+ // Skip modes not supported by the connected displays+ if (ChangeDisplaySettingsExW(monitor->win32.adapterName,+ &dm,+ NULL,+ CDS_TEST,+ NULL) != DISP_CHANGE_SUCCESSFUL)+ {+ continue;+ }+ } - result = (GLFWvidmode*) realloc(result, count * sizeof(GLFWvidmode));+ if (*count == size)+ {+ size += 128;+ result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode)); } - result[*found] = mode;- (*found)++;+ (*count)++;+ result[*count - 1] = mode;+ }++ if (!*count)+ {+ // HACK: Report the current mode if no valid modes were found+ result = calloc(1, sizeof(GLFWvidmode));+ _glfwPlatformGetVideoMode(monitor, result);+ *count = 1; } return result;
glfw/src/win32_platform.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org+// GLFW 3.2 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,9 +25,8 @@ // //======================================================================== -#ifndef _win32_platform_h_-#define _win32_platform_h_-+#ifndef _glfw3_win32_platform_h_+#define _glfw3_win32_platform_h_ // We don't need all the fancy stuff #ifndef NOMINMAX@@ -62,8 +61,14 @@ #define _WIN32_WINNT 0x0501 #endif +// GLFW uses DirectInput8 interfaces+#define DIRECTINPUT_VERSION 0x0800++#include <wctype.h> #include <windows.h> #include <mmsystem.h>+#include <dinput.h>+#include <xinput.h> #include <dbt.h> #if defined(_MSC_VER)@@ -71,9 +76,7 @@ #define strdup _strdup #endif --// HACK: Define macros that some older windows.h variants don't-+// HACK: Define macros that some windows.h variants don't #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif@@ -89,6 +92,18 @@ #ifndef UNICODE_NOCHAR #define UNICODE_NOCHAR 0xFFFF #endif+#ifndef WM_DPICHANGED+ #define WM_DPICHANGED 0x02E0+#endif+#ifndef GET_XBUTTON_WPARAM+ #define GET_XBUTTON_WPARAM(w) (HIWORD(w))+#endif+#ifndef EDS_ROTATEDMODE+ #define EDS_ROTATEDMODE 0x00000004+#endif+#ifndef DISPLAY_DEVICE_ACTIVE+ #define DISPLAY_DEVICE_ACTIVE 0x00000001+#endif #if WINVER < 0x0601 typedef struct tagCHANGEFILTERSTRUCT@@ -102,17 +117,63 @@ #endif #endif /*Windows 7*/ +#ifndef DPI_ENUMS_DECLARED+typedef enum PROCESS_DPI_AWARENESS+{+ PROCESS_DPI_UNAWARE = 0,+ PROCESS_SYSTEM_DPI_AWARE = 1,+ PROCESS_PER_MONITOR_DPI_AWARE = 2+} PROCESS_DPI_AWARENESS;+#endif /*DPI_ENUMS_DECLARED*/ +// HACK: Define macros that some xinput.h variants don't+#ifndef XINPUT_CAPS_WIRELESS+ #define XINPUT_CAPS_WIRELESS 0x0002+#endif+#ifndef XINPUT_DEVSUBTYPE_WHEEL+ #define XINPUT_DEVSUBTYPE_WHEEL 0x02+#endif+#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK+ #define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03+#endif+#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK+ #define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04+#endif+#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD+ #define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05+#endif+#ifndef XINPUT_DEVSUBTYPE_GUITAR+ #define XINPUT_DEVSUBTYPE_GUITAR 0x06+#endif+#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT+ #define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08+#endif+#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD+ #define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13+#endif+#ifndef XUSER_MAX_COUNT+ #define XUSER_MAX_COUNT 4+#endif++// HACK: Define macros that some dinput.h variants don't+#ifndef DIDFT_OPTIONAL+ #define DIDFT_OPTIONAL 0x80000000+#endif+ // winmm.dll function pointer typedefs-typedef MMRESULT (WINAPI * JOYGETDEVCAPS_T)(UINT,LPJOYCAPS,UINT);-typedef MMRESULT (WINAPI * JOYGETPOS_T)(UINT,LPJOYINFO);-typedef MMRESULT (WINAPI * JOYGETPOSEX_T)(UINT,LPJOYINFOEX); typedef DWORD (WINAPI * TIMEGETTIME_T)(void);-#define _glfw_joyGetDevCaps _glfw.win32.winmm.joyGetDevCaps-#define _glfw_joyGetPos _glfw.win32.winmm.joyGetPos-#define _glfw_joyGetPosEx _glfw.win32.winmm.joyGetPosEx #define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime +// xinput.dll function pointer typedefs+typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);+typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);+#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities+#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState++// dinput8.dll function pointer typedefs+typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);+#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create+ // user32.dll function pointer typedefs typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void); typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);@@ -121,31 +182,45 @@ // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);+typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID); #define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled+#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush +// shcore.dll function pointer typedefs+typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);+#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness -#define _GLFW_RECREATION_NOT_NEEDED 0-#define _GLFW_RECREATION_REQUIRED 1-#define _GLFW_RECREATION_IMPOSSIBLE 2+typedef VkFlags VkWin32SurfaceCreateFlagsKHR; +typedef struct VkWin32SurfaceCreateInfoKHR+{+ VkStructureType sType;+ const void* pNext;+ VkWin32SurfaceCreateFlagsKHR flags;+ HINSTANCE hinstance;+ HWND hwnd;+} VkWin32SurfaceCreateInfoKHR; -#include "win32_tls.h"+typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t); -#if defined(_GLFW_WGL)- #include "wgl_context.h"-#elif defined(_GLFW_EGL)- #define _GLFW_EGL_NATIVE_WINDOW window->win32.handle- #define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY- #include "egl_context.h"-#else- #error "No supported context creation API selected"-#endif+#include "win32_joystick.h"+#include "wgl_context.h"+#include "egl_context.h" -#include "winmm_joystick.h"+#define _GLFW_WNDCLASSNAME L"GLFW30" +#define _glfw_dlopen(name) LoadLibraryA(name)+#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)+#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)++#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)+#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY+ #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time+#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32 #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32 @@ -155,50 +230,67 @@ typedef struct _GLFWwindowWin32 { HWND handle;- DWORD dwStyle;- DWORD dwExStyle;+ HICON bigIcon;+ HICON smallIcon; - GLboolean cursorInside;- GLboolean iconified;+ GLFWbool cursorTracked;+ GLFWbool iconified; // The last received cursor position, regardless of source- int cursorPosX, cursorPosY;+ int lastCursorPosX, lastCursorPosY; } _GLFWwindowWin32; - // Win32-specific global data // typedef struct _GLFWlibraryWin32 {+ HWND helperWindowHandle; DWORD foregroundLockTimeout; char* clipboardString;+ char keyName[64]; short int publicKeys[512];+ short int nativeKeys[GLFW_KEY_LAST + 1];+ // Where to place the cursor when re-enabled+ double restoreCursorPosX, restoreCursorPosY;+ // The window whose disabled cursor mode is active+ _GLFWwindow* disabledCursorWindow; - // winmm.dll struct { HINSTANCE instance;- JOYGETDEVCAPS_T joyGetDevCaps;- JOYGETPOS_T joyGetPos;- JOYGETPOSEX_T joyGetPosEx; TIMEGETTIME_T timeGetTime; } winmm; - // user32.dll struct {- HINSTANCE instance;- SETPROCESSDPIAWARE_T SetProcessDPIAware;+ HINSTANCE instance;+ DIRECTINPUT8CREATE_T DirectInput8Create;+ IDirectInput8W* api;+ } dinput8;++ struct {+ HINSTANCE instance;+ XINPUTGETCAPABILITIES_T XInputGetCapabilities;+ XINPUTGETSTATE_T XInputGetState;+ } xinput;++ struct {+ HINSTANCE instance;+ SETPROCESSDPIAWARE_T SetProcessDPIAware; CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx; } user32; - // dwmapi.dll struct { HINSTANCE instance; DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;+ DWMFLUSH_T DwmFlush; } dwmapi; -} _GLFWlibraryWin32;+ struct {+ HINSTANCE instance;+ SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;+ } shcore; +} _GLFWlibraryWin32; // Win32-specific per-monitor data //@@ -209,11 +301,11 @@ WCHAR displayName[32]; char publicAdapterName[64]; char publicDisplayName[64];- GLboolean modeChanged;+ GLFWbool modesPruned;+ GLFWbool modeChanged; } _GLFWmonitorWin32; - // Win32-specific per-cursor data // typedef struct _GLFWcursorWin32@@ -222,29 +314,37 @@ } _GLFWcursorWin32; - // Win32-specific global timer data // typedef struct _GLFWtimeWin32 {- GLboolean hasPC;- double resolution;- unsigned __int64 base;+ GLFWbool hasPC;+ uint64_t frequency; } _GLFWtimeWin32; +// Win32-specific global TLS data+//+typedef struct _GLFWtlsWin32+{+ GLFWbool allocated;+ DWORD context; -GLboolean _glfwRegisterWindowClass(void);-void _glfwUnregisterWindowClass(void);+} _GLFWtlsWin32; -BOOL _glfwIsCompositionEnabled(void); -WCHAR* _glfwCreateWideStringFromUTF8(const char* source);-char* _glfwCreateUTF8FromWideString(const WCHAR* source);+GLFWbool _glfwRegisterWindowClassWin32(void);+void _glfwUnregisterWindowClassWin32(void); -void _glfwInitTimer(void);+GLFWbool _glfwInitThreadLocalStorageWin32(void);+void _glfwTerminateThreadLocalStorageWin32(void); -GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);-void _glfwRestoreVideoMode(_GLFWmonitor* monitor);+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); -#endif // _win32_platform_h_+void _glfwInitTimerWin32(void);++GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);++#endif // _glfw3_win32_platform_h_
glfw/src/win32_time.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org+// GLFW 3.2 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -28,43 +28,26 @@ #include "internal.h" -// Return raw time-//-static unsigned __int64 getRawTime(void)-{- if (_glfw.win32_time.hasPC)- {- unsigned __int64 time;- QueryPerformanceCounter((LARGE_INTEGER*) &time);- return time;- }- else- return (unsigned __int64) _glfw_timeGetTime();-}-- ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// // Initialise timer //-void _glfwInitTimer(void)+void _glfwInitTimerWin32(void) {- unsigned __int64 frequency;+ uint64_t frequency; if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency)) {- _glfw.win32_time.hasPC = GL_TRUE;- _glfw.win32_time.resolution = 1.0 / (double) frequency;+ _glfw.win32_time.hasPC = GLFW_TRUE;+ _glfw.win32_time.frequency = frequency; } else {- _glfw.win32_time.hasPC = GL_FALSE;- _glfw.win32_time.resolution = 0.001; // winmm resolution is 1 ms+ _glfw.win32_time.hasPC = GLFW_FALSE;+ _glfw.win32_time.frequency = 1000; }-- _glfw.win32_time.base = getRawTime(); } @@ -72,15 +55,20 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -double _glfwPlatformGetTime(void)+uint64_t _glfwPlatformGetTimerValue(void) {- return (double) (getRawTime() - _glfw.win32_time.base) *- _glfw.win32_time.resolution;+ if (_glfw.win32_time.hasPC)+ {+ uint64_t value;+ QueryPerformanceCounter((LARGE_INTEGER*) &value);+ return value;+ }+ else+ return (uint64_t) _glfw_timeGetTime(); } -void _glfwPlatformSetTime(double time)+uint64_t _glfwPlatformGetTimerFrequency(void) {- _glfw.win32_time.base = getRawTime() -- (unsigned __int64) (time / _glfw.win32_time.resolution);+ return _glfw.win32_time.frequency; }
glfw/src/win32_tls.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org+// GLFW 3.2 Win32 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -32,35 +32,35 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -int _glfwInitTLS(void)+GLFWbool _glfwInitThreadLocalStorageWin32(void) { _glfw.win32_tls.context = TlsAlloc(); if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES) { _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to allocate TLS index");- return GL_FALSE;+ return GLFW_FALSE; } - _glfw.win32_tls.allocated = GL_TRUE;- return GL_TRUE;+ _glfw.win32_tls.allocated = GLFW_TRUE;+ return GLFW_TRUE; } -void _glfwTerminateTLS(void)+void _glfwTerminateThreadLocalStorageWin32(void) { if (_glfw.win32_tls.allocated) TlsFree(_glfw.win32_tls.context); } -void _glfwSetCurrentContext(_GLFWwindow* context)-{- TlsSetValue(_glfw.win32_tls.context, context);-} - ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////++void _glfwPlatformSetCurrentContext(_GLFWwindow* context)+{+ TlsSetValue(_glfw.win32_tls.context, context);+} _GLFWwindow* _glfwPlatformGetCurrentContext(void) {
− glfw/src/win32_tls.h
@@ -1,48 +0,0 @@-//========================================================================-// GLFW 3.1 Win32 - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#ifndef _win32_tls_h_-#define _win32_tls_h_--#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls---// Win32-specific global TLS data-//-typedef struct _GLFWtlsWin32-{- GLboolean allocated;- DWORD context;--} _GLFWtlsWin32;---int _glfwInitTLS(void);-void _glfwTerminateTLS(void);-void _glfwSetCurrentContext(_GLFWwindow* context);--#endif // _win32_tls_h_
glfw/src/win32_window.c view
@@ -1,1301 +1,1713 @@ //========================================================================-// GLFW 3.1 Win32 - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#include "internal.h"--#include <stdlib.h>-#include <malloc.h>-#include <string.h>-#include <windowsx.h>-#include <shellapi.h>--#define _GLFW_KEY_INVALID -2--#define _GLFW_WNDCLASSNAME L"GLFW30"---// Updates the cursor clip rect-//-static void updateClipRect(_GLFWwindow* window)-{- RECT clipRect;- GetClientRect(window->win32.handle, &clipRect);- ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);- ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);- ClipCursor(&clipRect);-}--// Hide the mouse cursor-//-static void hideCursor(_GLFWwindow* window)-{- POINT pos;-- ClipCursor(NULL);-- if (GetCursorPos(&pos))- {- if (WindowFromPoint(pos) == window->win32.handle)- SetCursor(NULL);- }-}--// Disable the mouse cursor-//-static void disableCursor(_GLFWwindow* window)-{- POINT pos;-- updateClipRect(window);-- if (GetCursorPos(&pos))- {- if (WindowFromPoint(pos) == window->win32.handle)- SetCursor(NULL);- }-}--// Restores the mouse cursor-//-static void restoreCursor(_GLFWwindow* window)-{- POINT pos;-- ClipCursor(NULL);-- if (GetCursorPos(&pos))- {- if (WindowFromPoint(pos) == window->win32.handle)- {- if (window->cursor)- SetCursor(window->cursor->win32.handle);- else- SetCursor(LoadCursorW(NULL, IDC_ARROW));- }- }-}--// Translates a GLFW standard cursor to a resource ID-//-static LPWSTR translateCursorShape(int shape)-{- switch (shape)- {- case GLFW_ARROW_CURSOR:- return IDC_ARROW;- case GLFW_IBEAM_CURSOR:- return IDC_IBEAM;- case GLFW_CROSSHAIR_CURSOR:- return IDC_CROSS;- case GLFW_HAND_CURSOR:- return IDC_HAND;- case GLFW_HRESIZE_CURSOR:- return IDC_SIZEWE;- case GLFW_VRESIZE_CURSOR:- return IDC_SIZENS;- }-- return NULL;-}--// Retrieves and translates modifier keys-//-static int getKeyMods(void)-{- int mods = 0;-- if (GetKeyState(VK_SHIFT) & (1 << 31))- mods |= GLFW_MOD_SHIFT;- if (GetKeyState(VK_CONTROL) & (1 << 31))- mods |= GLFW_MOD_CONTROL;- if (GetKeyState(VK_MENU) & (1 << 31))- mods |= GLFW_MOD_ALT;- if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1 << 31))- mods |= GLFW_MOD_SUPER;-- return mods;-}--// Retrieves and translates modifier keys-//-static int getAsyncKeyMods(void)-{- int mods = 0;-- if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))- mods |= GLFW_MOD_SHIFT;- if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))- mods |= GLFW_MOD_CONTROL;- if (GetAsyncKeyState(VK_MENU) & (1 << 31))- mods |= GLFW_MOD_ALT;- if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & (1 << 31))- mods |= GLFW_MOD_SUPER;-- return mods;-}--// Translates a Windows key to the corresponding GLFW key-//-static int translateKey(WPARAM wParam, LPARAM lParam)-{- if (wParam == VK_CONTROL)- {- // The CTRL keys require special handling-- MSG next;- DWORD time;-- // Is this an extended key (i.e. right key)?- if (lParam & 0x01000000)- return GLFW_KEY_RIGHT_CONTROL;-- // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only- // want the RALT message, so we try to see if the next message- // is a RALT message. In that case, this is a false LCTRL!- time = GetMessageTime();-- if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))- {- if (next.message == WM_KEYDOWN ||- next.message == WM_SYSKEYDOWN ||- next.message == WM_KEYUP ||- next.message == WM_SYSKEYUP)- {- if (next.wParam == VK_MENU &&- (next.lParam & 0x01000000) &&- next.time == time)- {- // Next message is a RALT down message, which- // means that this is not a proper LCTRL message- return _GLFW_KEY_INVALID;- }- }- }-- return GLFW_KEY_LEFT_CONTROL;- }-- return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];-}--// Enter full screen mode-//-static GLboolean enterFullscreenMode(_GLFWwindow* window)-{- GLFWvidmode mode;- GLboolean status;- int xpos, ypos;-- status = _glfwSetVideoMode(window->monitor, &window->videoMode);-- _glfwPlatformGetVideoMode(window->monitor, &mode);- _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);-- SetWindowPos(window->win32.handle, HWND_TOPMOST,- xpos, ypos, mode.width, mode.height, SWP_NOCOPYBITS);-- return status;-}--// Leave full screen mode-//-static void leaveFullscreenMode(_GLFWwindow* window)-{- _glfwRestoreVideoMode(window->monitor);-}--// Window callback function (handles window events)-//-static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,- WPARAM wParam, LPARAM lParam)-{- _GLFWwindow* window = (_GLFWwindow*) GetWindowLongPtrW(hWnd, 0);-- switch (uMsg)- {- case WM_NCCREATE:- {- CREATESTRUCTW* cs = (CREATESTRUCTW*) lParam;- SetWindowLongPtrW(hWnd, 0, (LONG_PTR) cs->lpCreateParams);- break;- }-- case WM_SETFOCUS:- {- if (window->cursorMode != GLFW_CURSOR_NORMAL)- _glfwPlatformApplyCursorMode(window);-- if (window->monitor && window->autoIconify)- enterFullscreenMode(window);-- _glfwInputWindowFocus(window, GL_TRUE);- return 0;- }-- case WM_KILLFOCUS:- {- if (window->cursorMode != GLFW_CURSOR_NORMAL)- restoreCursor(window);-- if (window->monitor && window->autoIconify)- {- _glfwPlatformIconifyWindow(window);- leaveFullscreenMode(window);- }-- _glfwInputWindowFocus(window, GL_FALSE);- return 0;- }-- case WM_SYSCOMMAND:- {- switch (wParam & 0xfff0)- {- case SC_SCREENSAVE:- case SC_MONITORPOWER:- {- if (window->monitor)- {- // We are running in full screen mode, so disallow- // screen saver and screen blanking- return 0;- }- else- break;- }-- // User trying to access application menu using ALT?- case SC_KEYMENU:- return 0;- }- break;- }-- case WM_CLOSE:- {- _glfwInputWindowCloseRequest(window);- return 0;- }-- case WM_KEYDOWN:- case WM_SYSKEYDOWN:- {- const int scancode = (lParam >> 16) & 0x1ff;- const int key = translateKey(wParam, lParam);- if (key == _GLFW_KEY_INVALID)- break;-- _glfwInputKey(window, key, scancode, GLFW_PRESS, getKeyMods());- break;- }-- case WM_CHAR:- {- _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);- return 0;- }-- case WM_SYSCHAR:- {- _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_FALSE);- return 0;- }-- case WM_UNICHAR:- {- // This message is not sent by Windows, but is sent by some- // third-party input method engines-- if (wParam == UNICODE_NOCHAR)- {- // Returning TRUE here announces support for this message- return TRUE;- }-- _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GL_TRUE);- return FALSE;- }-- case WM_KEYUP:- case WM_SYSKEYUP:- {- const int mods = getKeyMods();- const int scancode = (lParam >> 16) & 0x1ff;- const int key = translateKey(wParam, lParam);- if (key == _GLFW_KEY_INVALID)- break;-- if (wParam == VK_SHIFT)- {- // Release both Shift keys on Shift up event, as only one event- // is sent even if both keys are released- _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);- _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, GLFW_RELEASE, mods);- }- else if (wParam == VK_SNAPSHOT)- {- // Key down is not reported for the print screen key- _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);- _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);- }- else- _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);-- break;- }-- case WM_LBUTTONDOWN:- case WM_RBUTTONDOWN:- case WM_MBUTTONDOWN:- case WM_XBUTTONDOWN:- {- const int mods = getKeyMods();-- SetCapture(hWnd);-- if (uMsg == WM_LBUTTONDOWN)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);- else if (uMsg == WM_RBUTTONDOWN)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);- else if (uMsg == WM_MBUTTONDOWN)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);- else- {- if (HIWORD(wParam) == XBUTTON1)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_PRESS, mods);- else if (HIWORD(wParam) == XBUTTON2)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_PRESS, mods);-- return TRUE;- }-- return 0;- }-- case WM_LBUTTONUP:- case WM_RBUTTONUP:- case WM_MBUTTONUP:- case WM_XBUTTONUP:- {- const int mods = getKeyMods();-- ReleaseCapture();-- if (uMsg == WM_LBUTTONUP)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_RELEASE, mods);- else if (uMsg == WM_RBUTTONUP)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_RELEASE, mods);- else if (uMsg == WM_MBUTTONUP)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_RELEASE, mods);- else- {- if (HIWORD(wParam) == XBUTTON1)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_4, GLFW_RELEASE, mods);- else if (HIWORD(wParam) == XBUTTON2)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_5, GLFW_RELEASE, mods);-- return TRUE;- }-- return 0;- }-- case WM_MOUSEMOVE:- {- const int x = GET_X_LPARAM(lParam);- const int y = GET_Y_LPARAM(lParam);-- if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- if (_glfw.focusedWindow != window)- break;-- _glfwInputCursorMotion(window,- x - window->win32.cursorPosX,- y - window->win32.cursorPosY);- }- else- _glfwInputCursorMotion(window, x, y);-- window->win32.cursorPosX = x;- window->win32.cursorPosY = y;-- if (!window->win32.cursorInside)- {- TRACKMOUSEEVENT tme;- ZeroMemory(&tme, sizeof(tme));- tme.cbSize = sizeof(tme);- tme.dwFlags = TME_LEAVE;- tme.hwndTrack = window->win32.handle;- TrackMouseEvent(&tme);-- window->win32.cursorInside = GL_TRUE;- _glfwInputCursorEnter(window, GL_TRUE);- }-- return 0;- }-- case WM_MOUSELEAVE:- {- window->win32.cursorInside = GL_FALSE;- _glfwInputCursorEnter(window, GL_FALSE);- return 0;- }-- case WM_MOUSEWHEEL:- {- _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);- return 0;- }-- case WM_MOUSEHWHEEL:- {- // This message is only sent on Windows Vista and later- // NOTE: The X-axis is inverted for consistency with OS X and X11.- _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);- return 0;- }-- case WM_SIZE:- {- if (_glfw.focusedWindow == window)- {- if (window->cursorMode == GLFW_CURSOR_DISABLED)- updateClipRect(window);- }-- if (!window->win32.iconified && wParam == SIZE_MINIMIZED)- {- window->win32.iconified = GL_TRUE;- _glfwInputWindowIconify(window, GL_TRUE);- }- else if (window->win32.iconified &&- (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED))- {- window->win32.iconified = GL_FALSE;- _glfwInputWindowIconify(window, GL_FALSE);- }-- _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));- _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));- return 0;- }-- case WM_MOVE:- {- if (_glfw.focusedWindow == window)- {- if (window->cursorMode == GLFW_CURSOR_DISABLED)- updateClipRect(window);- }-- // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as- // those macros do not handle negative window positions correctly- _glfwInputWindowPos(window,- GET_X_LPARAM(lParam),- GET_Y_LPARAM(lParam));- return 0;- }-- case WM_PAINT:- {- _glfwInputWindowDamage(window);- break;- }-- case WM_ERASEBKGND:- {- return TRUE;- }-- case WM_SETCURSOR:- {- if (_glfw.focusedWindow == window && LOWORD(lParam) == HTCLIENT)- {- if (window->cursorMode == GLFW_CURSOR_HIDDEN ||- window->cursorMode == GLFW_CURSOR_DISABLED)- {- SetCursor(NULL);- return TRUE;- }- else if (window->cursor)- {- SetCursor(window->cursor->win32.handle);- return TRUE;- }- }-- break;- }-- case WM_DEVICECHANGE:- {- if (DBT_DEVNODES_CHANGED == wParam)- {- _glfwInputMonitorChange();- return TRUE;- }- break;- }-- case WM_DWMCOMPOSITIONCHANGED:- {- if (_glfwIsCompositionEnabled())- {- _GLFWwindow* previous = _glfwPlatformGetCurrentContext();- _glfwPlatformMakeContextCurrent(window);- _glfwPlatformSwapInterval(0);- _glfwPlatformMakeContextCurrent(previous);- }-- // TODO: Restore vsync if compositing was disabled- break;- }-- case WM_DROPFILES:- {- HDROP hDrop = (HDROP) wParam;- POINT pt;- int i;-- const int count = DragQueryFileW(hDrop, 0xffffffff, NULL, 0);- char** paths = calloc(count, sizeof(char*));-- // Move the mouse to the position of the drop- DragQueryPoint(hDrop, &pt);- _glfwInputCursorMotion(window, pt.x, pt.y);-- for (i = 0; i < count; i++)- {- const UINT length = DragQueryFileW(hDrop, i, NULL, 0);- WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));-- DragQueryFileW(hDrop, i, buffer, length + 1);- paths[i] = _glfwCreateUTF8FromWideString(buffer);-- free(buffer);- }-- _glfwInputDrop(window, count, (const char**) paths);-- for (i = 0; i < count; i++)- free(paths[i]);- free(paths);-- DragFinish(hDrop);- return 0;- }- }-- return DefWindowProc(hWnd, uMsg, wParam, lParam);-}--// Translate client window size to full window size (including window borders)-//-static void getFullWindowSize(_GLFWwindow* window,- int clientWidth, int clientHeight,- int* fullWidth, int* fullHeight)-{- RECT rect = { 0, 0, clientWidth, clientHeight };- AdjustWindowRectEx(&rect, window->win32.dwStyle,- FALSE, window->win32.dwExStyle);- *fullWidth = rect.right - rect.left;- *fullHeight = rect.bottom - rect.top;-}--// Creates the GLFW window and rendering context-//-static int createWindow(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)-{- int xpos, ypos, fullWidth, fullHeight;- WCHAR* wideTitle;-- window->win32.dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;- window->win32.dwExStyle = WS_EX_APPWINDOW;-- if (window->monitor)- {- window->win32.dwStyle |= WS_POPUP;-- // NOTE: This window placement is temporary and approximate, as the- // correct position and size cannot be known until the monitor- // video mode has been set- _glfwPlatformGetMonitorPos(wndconfig->monitor, &xpos, &ypos);- fullWidth = wndconfig->width;- fullHeight = wndconfig->height;- }- else- {- if (wndconfig->decorated)- {- window->win32.dwStyle |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;-- if (wndconfig->resizable)- {- window->win32.dwStyle |= WS_MAXIMIZEBOX | WS_SIZEBOX;- window->win32.dwExStyle |= WS_EX_WINDOWEDGE;- }- }- else- window->win32.dwStyle |= WS_POPUP;-- xpos = CW_USEDEFAULT;- ypos = CW_USEDEFAULT;-- getFullWindowSize(window,- wndconfig->width, wndconfig->height,- &fullWidth, &fullHeight);- }-- wideTitle = _glfwCreateWideStringFromUTF8(wndconfig->title);- if (!wideTitle)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to convert title to wide string");- return GL_FALSE;- }-- window->win32.handle = CreateWindowExW(window->win32.dwExStyle,- _GLFW_WNDCLASSNAME,- wideTitle,- window->win32.dwStyle,- xpos, ypos,- fullWidth, fullHeight,- NULL, // No parent window- NULL, // No window menu- GetModuleHandleW(NULL),- window); // Pass object to WM_CREATE-- free(wideTitle);-- if (!window->win32.handle)- {- _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");- return GL_FALSE;- }-- if (_glfw_ChangeWindowMessageFilterEx)- {- _glfw_ChangeWindowMessageFilterEx(window->win32.handle,- WM_DROPFILES, MSGFLT_ALLOW, NULL);- _glfw_ChangeWindowMessageFilterEx(window->win32.handle,- WM_COPYDATA, MSGFLT_ALLOW, NULL);- _glfw_ChangeWindowMessageFilterEx(window->win32.handle,- WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);- }-- if (wndconfig->floating && !wndconfig->monitor)- {- SetWindowPos(window->win32.handle,- HWND_TOPMOST,- 0, 0, 0, 0,- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);- }-- DragAcceptFiles(window->win32.handle, TRUE);-- if (!_glfwCreateContext(window, ctxconfig, fbconfig))- return GL_FALSE;-- return GL_TRUE;-}--// Destroys the GLFW window and rendering context-//-static void destroyWindow(_GLFWwindow* window)-{- _glfwDestroyContext(window);-- if (window->win32.handle)- {- DestroyWindow(window->win32.handle);- window->win32.handle = NULL;- }-}---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Registers the GLFW window class-//-GLboolean _glfwRegisterWindowClass(void)-{- WNDCLASSW wc;-- wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;- wc.lpfnWndProc = (WNDPROC) windowProc;- wc.cbClsExtra = 0; // No extra class data- wc.cbWndExtra = sizeof(void*) + sizeof(int); // Make room for one pointer- wc.hInstance = GetModuleHandleW(NULL);- wc.hCursor = LoadCursorW(NULL, IDC_ARROW);- wc.hbrBackground = NULL; // No background- wc.lpszMenuName = NULL; // No menu- wc.lpszClassName = _GLFW_WNDCLASSNAME;-- // Load user-provided icon if available- wc.hIcon = LoadIconW(GetModuleHandleW(NULL), L"GLFW_ICON");- if (!wc.hIcon)- {- // No user-provided icon found, load default icon- wc.hIcon = LoadIconW(NULL, IDI_WINLOGO);- }-- if (!RegisterClassW(&wc))- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to register window class");- return GL_FALSE;- }-- return GL_TRUE;-}--// Unregisters the GLFW window class-//-void _glfwUnregisterWindowClass(void)-{- UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformCreateWindow(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)-{- int status;-- if (!createWindow(window, wndconfig, ctxconfig, fbconfig))- return GL_FALSE;-- status = _glfwAnalyzeContext(window, ctxconfig, fbconfig);-- if (status == _GLFW_RECREATION_IMPOSSIBLE)- return GL_FALSE;-- if (status == _GLFW_RECREATION_REQUIRED)- {- // Some window hints require us to re-create the context using WGL- // extensions retrieved through the current context, as we cannot check- // for WGL extensions or retrieve WGL entry points before we have a- // current context (actually until we have implicitly loaded the ICD)-- // Yes, this is strange, and yes, this is the proper way on Win32-- // As Windows only allows you to set the pixel format once for a- // window, we need to destroy the current window and create a new one- // to be able to use the new pixel format-- // Technically, it may be possible to keep the old window around if- // we're just creating an OpenGL 3.0+ context with the same pixel- // format, but it's not worth the added code complexity-- // First we clear the current context (the one we just created)- // This is usually done by glfwDestroyWindow, but as we're not doing- // full GLFW window destruction, it's duplicated here- _glfwPlatformMakeContextCurrent(NULL);-- // Next destroy the Win32 window and WGL context (without resetting or- // destroying the GLFW window object)- destroyWindow(window);-- // ...and then create them again, this time with better APIs- if (!createWindow(window, wndconfig, ctxconfig, fbconfig))- return GL_FALSE;- }-- if (window->monitor)- {- _glfwPlatformShowWindow(window);- if (!enterFullscreenMode(window))- return GL_FALSE;- }-- return GL_TRUE;-}--void _glfwPlatformDestroyWindow(_GLFWwindow* window)-{- if (window->monitor)- leaveFullscreenMode(window);-- destroyWindow(window);-}--void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)-{- WCHAR* wideTitle = _glfwCreateWideStringFromUTF8(title);- if (!wideTitle)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to convert title to wide string");- return;- }-- SetWindowTextW(window->win32.handle, wideTitle);- free(wideTitle);-}--void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)-{- POINT pos = { 0, 0 };- ClientToScreen(window->win32.handle, &pos);-- if (xpos)- *xpos = pos.x;- if (ypos)- *ypos = pos.y;-}--void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)-{- RECT rect = { xpos, ypos, xpos, ypos };- AdjustWindowRectEx(&rect, window->win32.dwStyle,- FALSE, window->win32.dwExStyle);- SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,- SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);-}--void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)-{- RECT area;- GetClientRect(window->win32.handle, &area);-- if (width)- *width = area.right;- if (height)- *height = area.bottom;-}--void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)-{- if (window->monitor)- enterFullscreenMode(window);- else- {- int fullWidth, fullHeight;- getFullWindowSize(window, width, height, &fullWidth, &fullHeight);-- SetWindowPos(window->win32.handle, HWND_TOP,- 0, 0, fullWidth, fullHeight,- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);- }-}--void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)-{- _glfwPlatformGetWindowSize(window, width, height);-}--void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,- int* left, int* top,- int* right, int* bottom)-{- RECT rect;- int width, height;-- _glfwPlatformGetWindowSize(window, &width, &height);- SetRect(&rect, 0, 0, width, height);- AdjustWindowRectEx(&rect, window->win32.dwStyle,- FALSE, window->win32.dwExStyle);-- if (left)- *left = -rect.left;- if (top)- *top = -rect.top;- if (right)- *right = rect.right - width;- if (bottom)- *bottom = rect.bottom - height;-}--void _glfwPlatformIconifyWindow(_GLFWwindow* window)-{- ShowWindow(window->win32.handle, SW_MINIMIZE);-}--void _glfwPlatformRestoreWindow(_GLFWwindow* window)-{- ShowWindow(window->win32.handle, SW_RESTORE);-}--void _glfwPlatformShowWindow(_GLFWwindow* window)-{- ShowWindow(window->win32.handle, SW_SHOW);- BringWindowToTop(window->win32.handle);- SetForegroundWindow(window->win32.handle);- SetFocus(window->win32.handle);-}--void _glfwPlatformUnhideWindow(_GLFWwindow* window)-{- ShowWindow(window->win32.handle, SW_SHOW);-}--void _glfwPlatformHideWindow(_GLFWwindow* window)-{- ShowWindow(window->win32.handle, SW_HIDE);-}--int _glfwPlatformWindowFocused(_GLFWwindow* window)-{- return window->win32.handle == GetActiveWindow();-}--int _glfwPlatformWindowIconified(_GLFWwindow* window)-{- return IsIconic(window->win32.handle);-}--int _glfwPlatformWindowVisible(_GLFWwindow* window)-{- return IsWindowVisible(window->win32.handle);-}--void _glfwPlatformPollEvents(void)-{- MSG msg;- _GLFWwindow* window;-- while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))- {- if (msg.message == WM_QUIT)- {- // Treat WM_QUIT as a close on all windows- // While GLFW does not itself post WM_QUIT, other processes may post- // it to this one, for example Task Manager-- window = _glfw.windowListHead;- while (window)- {- _glfwInputWindowCloseRequest(window);- window = window->next;- }- }- else- {- TranslateMessage(&msg);- DispatchMessageW(&msg);- }- }-- window = _glfw.focusedWindow;- if (window)- {- // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)- // This is the only async event handling in GLFW, but it solves some- // nasty problems- {- const int mods = getAsyncKeyMods();-- // Get current state of left and right shift keys- const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;- const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;-- // See if this differs from our belief of what has happened- // (we only have to check for lost key up events)- if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)- _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);-- if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)- _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);- }-- // Did the cursor move in an focused window that has disabled the cursor- if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- int width, height;- _glfwPlatformGetWindowSize(window, &width, &height);- _glfwPlatformSetCursorPos(window, width / 2, height / 2);- }- }-}--void _glfwPlatformWaitEvents(void)-{- WaitMessage();-- _glfwPlatformPollEvents();-}--void _glfwPlatformPostEmptyEvent(void)-{- _GLFWwindow* window = _glfw.windowListHead;- PostMessage(window->win32.handle, WM_NULL, 0, 0);-}--void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)-{- POINT pos;-- if (GetCursorPos(&pos))- {- ScreenToClient(window->win32.handle, &pos);-- if (xpos)- *xpos = pos.x;- if (ypos)- *ypos = pos.y;- }-}--void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)-{- POINT pos = { (int) xpos, (int) ypos };-- // Store the new position so it can be recognized later- window->win32.cursorPosX = pos.x;- window->win32.cursorPosY = pos.y;-- ClientToScreen(window->win32.handle, &pos);- SetCursorPos(pos.x, pos.y);-}--void _glfwPlatformApplyCursorMode(_GLFWwindow* window)-{- switch (window->cursorMode)- {- case GLFW_CURSOR_NORMAL:- restoreCursor(window);- break;- case GLFW_CURSOR_HIDDEN:- hideCursor(window);- break;- case GLFW_CURSOR_DISABLED:- disableCursor(window);- break;- }-}--int _glfwPlatformCreateCursor(_GLFWcursor* cursor,- const GLFWimage* image,- int xhot, int yhot)-{- HDC dc;- HBITMAP bitmap, mask;- BITMAPV5HEADER bi;- ICONINFO ii;- DWORD* target = 0;- BYTE* source = (BYTE*) image->pixels;- int i;-- ZeroMemory(&bi, sizeof(bi));- bi.bV5Size = sizeof(BITMAPV5HEADER);- bi.bV5Width = image->width;- bi.bV5Height = -image->height;- bi.bV5Planes = 1;- bi.bV5BitCount = 32;- bi.bV5Compression = BI_BITFIELDS;- bi.bV5RedMask = 0x00ff0000;- bi.bV5GreenMask = 0x0000ff00;- bi.bV5BlueMask = 0x000000ff;- bi.bV5AlphaMask = 0xff000000;-- dc = GetDC(NULL);- bitmap = CreateDIBSection(dc, (BITMAPINFO*) &bi, DIB_RGB_COLORS,- (void**) &target, NULL, (DWORD) 0);- ReleaseDC(NULL, dc);-- if (!bitmap)- return GL_FALSE;-- mask = CreateBitmap(image->width, image->height, 1, 1, NULL);- if (!mask)- {- DeleteObject(bitmap);- return GL_FALSE;- }-- for (i = 0; i < image->width * image->height; i++, target++, source += 4)- {- *target = (source[3] << 24) |- (source[0] << 16) |- (source[1] << 8) |- source[2];- }-- ZeroMemory(&ii, sizeof(ii));- ii.fIcon = FALSE;- ii.xHotspot = xhot;- ii.yHotspot = yhot;- ii.hbmMask = mask;- ii.hbmColor = bitmap;-- cursor->win32.handle = (HCURSOR) CreateIconIndirect(&ii);-- DeleteObject(bitmap);- DeleteObject(mask);-- if (!cursor->win32.handle)- return GL_FALSE;-- return GL_TRUE;-}--int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)-{- LPCWSTR native = translateCursorShape(shape);- if (!native)- {- _glfwInputError(GLFW_INVALID_ENUM, "Win32: Invalid standard cursor");- return GL_FALSE;- }-- cursor->win32.handle = CopyCursor(LoadCursorW(NULL, native));- if (!cursor->win32.handle)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to retrieve shared cursor");- return GL_FALSE;- }-- return GL_TRUE;-}--void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)-{- if (cursor->win32.handle)- DestroyIcon((HICON) cursor->win32.handle);-}--void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)-{- // It should be guaranteed that the cursor is not being used by this window if- // the following condition is not met. That way it should be safe to destroy the- // cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor.-- if (_glfw.focusedWindow == window &&- window->cursorMode == GLFW_CURSOR_NORMAL &&- window->win32.cursorInside)- {- if (cursor)- SetCursor(cursor->win32.handle);- else- SetCursor(LoadCursorW(NULL, IDC_ARROW));- }-}--void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)-{- WCHAR* wideString;- HANDLE stringHandle;- size_t wideSize;-- wideString = _glfwCreateWideStringFromUTF8(string);- if (!wideString)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to convert clipboard string to "- "wide string");- return;- }-- wideSize = (wcslen(wideString) + 1) * sizeof(WCHAR);-- stringHandle = GlobalAlloc(GMEM_MOVEABLE, wideSize);- if (!stringHandle)- {- free(wideString);-- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to allocate global handle for clipboard");- return;- }-- memcpy(GlobalLock(stringHandle), wideString, wideSize);- GlobalUnlock(stringHandle);-- if (!OpenClipboard(window->win32.handle))- {- GlobalFree(stringHandle);- free(wideString);-- _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");- return;- }-- EmptyClipboard();- SetClipboardData(CF_UNICODETEXT, stringHandle);- CloseClipboard();-- free(wideString);-}--const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)-{- HANDLE stringHandle;-- if (!IsClipboardFormatAvailable(CF_UNICODETEXT))- {- _glfwInputError(GLFW_FORMAT_UNAVAILABLE, NULL);- return NULL;- }-- if (!OpenClipboard(window->win32.handle))- {- _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");- return NULL;- }-- stringHandle = GetClipboardData(CF_UNICODETEXT);- if (!stringHandle)- {- CloseClipboard();-- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to retrieve clipboard data");- return NULL;- }-- free(_glfw.win32.clipboardString);- _glfw.win32.clipboardString =- _glfwCreateUTF8FromWideString(GlobalLock(stringHandle));-- GlobalUnlock(stringHandle);- CloseClipboard();-- if (!_glfw.win32.clipboardString)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Win32: Failed to convert wide string to UTF-8");- return NULL;- }-- return _glfw.win32.clipboardString;+// GLFW 3.2 Win32 - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2002-2006 Marcus Geelnard+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <limits.h>+#include <stdlib.h>+#include <malloc.h>+#include <string.h>+#include <windowsx.h>+#include <shellapi.h>++#define _GLFW_KEY_INVALID -2++// Returns the window style for the specified window+//+static DWORD getWindowStyle(const _GLFWwindow* window)+{+ DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;++ if (window->monitor)+ style |= WS_POPUP;+ else+ {+ if (window->decorated)+ {+ style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;++ if (window->resizable)+ style |= WS_MAXIMIZEBOX | WS_THICKFRAME;+ }+ else+ style |= WS_POPUP;+ }++ return style;+}++// Returns the extended window style for the specified window+//+static DWORD getWindowExStyle(const _GLFWwindow* window)+{+ DWORD style = WS_EX_APPWINDOW;++ if (window->monitor || window->floating)+ style |= WS_EX_TOPMOST;++ return style;+}++// Returns the image whose area most closely matches the desired one+//+static const GLFWimage* chooseImage(int count, const GLFWimage* images,+ int width, int height)+{+ int i, leastDiff = INT_MAX;+ const GLFWimage* closest = NULL;++ for (i = 0; i < count; i++)+ {+ const int currDiff = abs(images[i].width * images[i].height -+ width * height);+ if (currDiff < leastDiff)+ {+ closest = images + i;+ leastDiff = currDiff;+ }+ }++ return closest;+}++// Creates an RGBA icon or cursor+//+static HICON createIcon(const GLFWimage* image,+ int xhot, int yhot, GLFWbool icon)+{+ int i;+ HDC dc;+ HICON handle;+ HBITMAP color, mask;+ BITMAPV5HEADER bi;+ ICONINFO ii;+ unsigned char* target = NULL;+ unsigned char* source = image->pixels;++ ZeroMemory(&bi, sizeof(bi));+ bi.bV5Size = sizeof(BITMAPV5HEADER);+ bi.bV5Width = image->width;+ bi.bV5Height = -image->height;+ bi.bV5Planes = 1;+ bi.bV5BitCount = 32;+ bi.bV5Compression = BI_BITFIELDS;+ bi.bV5RedMask = 0x00ff0000;+ bi.bV5GreenMask = 0x0000ff00;+ bi.bV5BlueMask = 0x000000ff;+ bi.bV5AlphaMask = 0xff000000;++ dc = GetDC(NULL);+ color = CreateDIBSection(dc,+ (BITMAPINFO*) &bi,+ DIB_RGB_COLORS,+ (void**) &target,+ NULL,+ (DWORD) 0);+ ReleaseDC(NULL, dc);++ if (!color)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to create RGBA bitmap");+ return NULL;+ }++ mask = CreateBitmap(image->width, image->height, 1, 1, NULL);+ if (!mask)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to create mask bitmap");+ DeleteObject(color);+ return NULL;+ }++ for (i = 0; i < image->width * image->height; i++)+ {+ target[0] = source[2];+ target[1] = source[1];+ target[2] = source[0];+ target[3] = source[3];+ target += 4;+ source += 4;+ }++ ZeroMemory(&ii, sizeof(ii));+ ii.fIcon = icon;+ ii.xHotspot = xhot;+ ii.yHotspot = yhot;+ ii.hbmMask = mask;+ ii.hbmColor = color;++ handle = CreateIconIndirect(&ii);++ DeleteObject(color);+ DeleteObject(mask);++ if (!handle)+ {+ if (icon)+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");+ else+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");+ }++ return handle;+}++// Translate client window size to full window size according to styles+//+static void getFullWindowSize(DWORD style, DWORD exStyle,+ int clientWidth, int clientHeight,+ int* fullWidth, int* fullHeight)+{+ RECT rect = { 0, 0, clientWidth, clientHeight };+ AdjustWindowRectEx(&rect, style, FALSE, exStyle);+ *fullWidth = rect.right - rect.left;+ *fullHeight = rect.bottom - rect.top;+}++// Enforce the client rect aspect ratio based on which edge is being dragged+//+static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)+{+ int xoff, yoff;+ const float ratio = (float) window->numer / (float) window->denom;++ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),+ 0, 0, &xoff, &yoff);++ if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||+ edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)+ {+ area->bottom = area->top + yoff ++ (int) ((area->right - area->left - xoff) / ratio);+ }+ else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)+ {+ area->top = area->bottom - yoff -+ (int) ((area->right - area->left - xoff) / ratio);+ }+ else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)+ {+ area->right = area->left + xoff ++ (int) ((area->bottom - area->top - yoff) * ratio);+ }+}++// Centers the cursor over the window client area+//+static void centerCursor(_GLFWwindow* window)+{+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);+}++// Returns whether the cursor is in the client area of the specified window+//+static GLFWbool cursorInClientArea(_GLFWwindow* window)+{+ RECT area;+ POINT pos;++ if (!GetCursorPos(&pos))+ return GLFW_FALSE;++ if (WindowFromPoint(pos) != window->win32.handle)+ return GLFW_FALSE;++ GetClientRect(window->win32.handle, &area);+ ClientToScreen(window->win32.handle, (POINT*) &area.left);+ ClientToScreen(window->win32.handle, (POINT*) &area.right);++ return PtInRect(&area, pos);+}++// Updates the cursor image according to its cursor mode+//+static void updateCursorImage(_GLFWwindow* window)+{+ if (window->cursorMode == GLFW_CURSOR_NORMAL)+ {+ if (window->cursor)+ SetCursor(window->cursor->win32.handle);+ else+ SetCursor(LoadCursorW(NULL, IDC_ARROW));+ }+ else+ SetCursor(NULL);+}++// Updates the cursor clip rect+//+static void updateClipRect(_GLFWwindow* window)+{+ if (window)+ {+ RECT clipRect;+ GetClientRect(window->win32.handle, &clipRect);+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);+ ClipCursor(&clipRect);+ }+ else+ ClipCursor(NULL);+}++// Translates a GLFW standard cursor to a resource ID+//+static LPWSTR translateCursorShape(int shape)+{+ switch (shape)+ {+ case GLFW_ARROW_CURSOR:+ return IDC_ARROW;+ case GLFW_IBEAM_CURSOR:+ return IDC_IBEAM;+ case GLFW_CROSSHAIR_CURSOR:+ return IDC_CROSS;+ case GLFW_HAND_CURSOR:+ return IDC_HAND;+ case GLFW_HRESIZE_CURSOR:+ return IDC_SIZEWE;+ case GLFW_VRESIZE_CURSOR:+ return IDC_SIZENS;+ }++ return NULL;+}++// Retrieves and translates modifier keys+//+static int getKeyMods(void)+{+ int mods = 0;++ if (GetKeyState(VK_SHIFT) & (1 << 31))+ mods |= GLFW_MOD_SHIFT;+ if (GetKeyState(VK_CONTROL) & (1 << 31))+ mods |= GLFW_MOD_CONTROL;+ if (GetKeyState(VK_MENU) & (1 << 31))+ mods |= GLFW_MOD_ALT;+ if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1 << 31))+ mods |= GLFW_MOD_SUPER;++ return mods;+}++// Retrieves and translates modifier keys+//+static int getAsyncKeyMods(void)+{+ int mods = 0;++ if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))+ mods |= GLFW_MOD_SHIFT;+ if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))+ mods |= GLFW_MOD_CONTROL;+ if (GetAsyncKeyState(VK_MENU) & (1 << 31))+ mods |= GLFW_MOD_ALT;+ if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & (1 << 31))+ mods |= GLFW_MOD_SUPER;++ return mods;+}++// Translates a Windows key to the corresponding GLFW key+//+static int translateKey(WPARAM wParam, LPARAM lParam)+{+ if (wParam == VK_CONTROL)+ {+ // The CTRL keys require special handling++ MSG next;+ DWORD time;++ // Is this an extended key (i.e. right key)?+ if (lParam & 0x01000000)+ return GLFW_KEY_RIGHT_CONTROL;++ // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only+ // want the RALT message, so we try to see if the next message+ // is a RALT message. In that case, this is a false LCTRL!+ time = GetMessageTime();++ if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))+ {+ if (next.message == WM_KEYDOWN ||+ next.message == WM_SYSKEYDOWN ||+ next.message == WM_KEYUP ||+ next.message == WM_SYSKEYUP)+ {+ if (next.wParam == VK_MENU &&+ (next.lParam & 0x01000000) &&+ next.time == time)+ {+ // Next message is a RALT down message, which+ // means that this is not a proper LCTRL message+ return _GLFW_KEY_INVALID;+ }+ }+ }++ return GLFW_KEY_LEFT_CONTROL;+ }++ if (wParam == VK_PROCESSKEY)+ {+ // IME notifies that keys have been filtered by setting the virtual+ // key-code to VK_PROCESSKEY+ return _GLFW_KEY_INVALID;+ }++ return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];+}++// Make the specified window and its video mode active on its monitor+//+static GLFWbool acquireMonitor(_GLFWwindow* window)+{+ GLFWvidmode mode;+ GLFWbool status;+ int xpos, ypos;++ status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode);++ _glfwPlatformGetVideoMode(window->monitor, &mode);+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);++ SetWindowPos(window->win32.handle, HWND_TOPMOST,+ xpos, ypos, mode.width, mode.height,+ SWP_NOACTIVATE | SWP_NOCOPYBITS);++ _glfwInputMonitorWindowChange(window->monitor, window);+ return status;+}++// Remove the window and restore the original video mode+//+static void releaseMonitor(_GLFWwindow* window)+{+ if (window->monitor->window != window)+ return;++ _glfwInputMonitorWindowChange(window->monitor, NULL);+ _glfwRestoreVideoModeWin32(window->monitor);+}++// Window callback function (handles window messages)+//+static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,+ WPARAM wParam, LPARAM lParam)+{+ _GLFWwindow* window = GetPropW(hWnd, L"GLFW");+ if (!window)+ {+ // This is the message handling for the hidden helper window++ switch (uMsg)+ {+ case WM_DEVICECHANGE:+ {+ if (wParam == DBT_DEVNODES_CHANGED)+ {+ _glfwInputMonitorChange();+ return TRUE;+ }+ else if (wParam == DBT_DEVICEARRIVAL)+ {+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;+ if (dbh)+ {+ if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)+ _glfwDetectJoystickConnectionWin32();+ }+ }+ else if (wParam == DBT_DEVICEREMOVECOMPLETE)+ {+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;+ if (dbh)+ {+ if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)+ _glfwDetectJoystickDisconnectionWin32();+ }+ }++ break;+ }+ }++ return DefWindowProcW(hWnd, uMsg, wParam, lParam);+ }++ switch (uMsg)+ {+ case WM_SETFOCUS:+ {+ _glfwInputWindowFocus(window, GLFW_TRUE);++ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);++ return 0;+ }++ case WM_KILLFOCUS:+ {+ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);++ if (window->monitor && window->autoIconify)+ _glfwPlatformIconifyWindow(window);++ _glfwInputWindowFocus(window, GLFW_FALSE);+ return 0;+ }++ case WM_SYSCOMMAND:+ {+ switch (wParam & 0xfff0)+ {+ case SC_SCREENSAVE:+ case SC_MONITORPOWER:+ {+ if (window->monitor)+ {+ // We are running in full screen mode, so disallow+ // screen saver and screen blanking+ return 0;+ }+ else+ break;+ }++ // User trying to access application menu using ALT?+ case SC_KEYMENU:+ return 0;+ }+ break;+ }++ case WM_CLOSE:+ {+ _glfwInputWindowCloseRequest(window);+ return 0;+ }++ case WM_CHAR:+ case WM_SYSCHAR:+ case WM_UNICHAR:+ {+ const GLFWbool plain = (uMsg != WM_SYSCHAR);++ if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)+ {+ // WM_UNICHAR is not sent by Windows, but is sent by some+ // third-party input method engine+ // Returning TRUE here announces support for this message+ return TRUE;+ }++ _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);+ return 0;+ }++ case WM_KEYDOWN:+ case WM_SYSKEYDOWN:+ case WM_KEYUP:+ case WM_SYSKEYUP:+ {+ const int key = translateKey(wParam, lParam);+ const int scancode = (lParam >> 16) & 0x1ff;+ const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;+ const int mods = getKeyMods();++ if (key == _GLFW_KEY_INVALID)+ break;++ if (action == GLFW_RELEASE && wParam == VK_SHIFT)+ {+ // Release both Shift keys on Shift up event, as only one event+ // is sent even if both keys are released+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);+ }+ else if (wParam == VK_SNAPSHOT)+ {+ // Key down is not reported for the Print Screen key+ _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);+ _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);+ }+ else+ _glfwInputKey(window, key, scancode, action, mods);++ break;+ }++ case WM_LBUTTONDOWN:+ case WM_RBUTTONDOWN:+ case WM_MBUTTONDOWN:+ case WM_XBUTTONDOWN:+ case WM_LBUTTONUP:+ case WM_RBUTTONUP:+ case WM_MBUTTONUP:+ case WM_XBUTTONUP:+ {+ int button, action;++ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)+ button = GLFW_MOUSE_BUTTON_LEFT;+ else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)+ button = GLFW_MOUSE_BUTTON_RIGHT;+ else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)+ button = GLFW_MOUSE_BUTTON_MIDDLE;+ else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)+ button = GLFW_MOUSE_BUTTON_4;+ else+ button = GLFW_MOUSE_BUTTON_5;++ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||+ uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)+ {+ action = GLFW_PRESS;+ SetCapture(hWnd);+ }+ else+ {+ action = GLFW_RELEASE;+ ReleaseCapture();+ }++ _glfwInputMouseClick(window, button, action, getKeyMods());++ if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)+ return TRUE;++ return 0;+ }++ case WM_MOUSEMOVE:+ {+ const int x = GET_X_LPARAM(lParam);+ const int y = GET_Y_LPARAM(lParam);++ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ {+ const int dx = x - window->win32.lastCursorPosX;+ const int dy = y - window->win32.lastCursorPosY;++ if (_glfw.win32.disabledCursorWindow != window)+ break;++ _glfwInputCursorPos(window,+ window->virtualCursorPosX + dx,+ window->virtualCursorPosY + dy);+ }+ else+ _glfwInputCursorPos(window, x, y);++ window->win32.lastCursorPosX = x;+ window->win32.lastCursorPosY = y;++ if (!window->win32.cursorTracked)+ {+ TRACKMOUSEEVENT tme;+ ZeroMemory(&tme, sizeof(tme));+ tme.cbSize = sizeof(tme);+ tme.dwFlags = TME_LEAVE;+ tme.hwndTrack = window->win32.handle;+ TrackMouseEvent(&tme);++ window->win32.cursorTracked = GLFW_TRUE;+ _glfwInputCursorEnter(window, GLFW_TRUE);+ }++ return 0;+ }++ case WM_MOUSELEAVE:+ {+ window->win32.cursorTracked = GLFW_FALSE;+ _glfwInputCursorEnter(window, GLFW_FALSE);+ return 0;+ }++ case WM_MOUSEWHEEL:+ {+ _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);+ return 0;+ }++ case WM_MOUSEHWHEEL:+ {+ // This message is only sent on Windows Vista and later+ // NOTE: The X-axis is inverted for consistency with OS X and X11.+ _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);+ return 0;+ }++ case WM_ENTERSIZEMOVE:+ case WM_ENTERMENULOOP:+ {+ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);++ break;+ }++ case WM_EXITSIZEMOVE:+ case WM_EXITMENULOOP:+ {+ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);++ break;+ }++ case WM_SIZE:+ {+ const GLFWbool iconified =+ !window->win32.iconified && wParam == SIZE_MINIMIZED;+ const GLFWbool restored =+ window->win32.iconified &&+ (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);++ if (_glfw.win32.disabledCursorWindow == window)+ updateClipRect(window);++ if (iconified)+ _glfwInputWindowIconify(window, GLFW_TRUE);+ else if (restored)+ _glfwInputWindowIconify(window, GLFW_FALSE);++ _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));+ _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));++ if (iconified)+ {+ window->win32.iconified = GLFW_TRUE;+ if (window->monitor)+ releaseMonitor(window);+ }+ else if (restored)+ {+ window->win32.iconified = GLFW_FALSE;+ if (window->monitor)+ acquireMonitor(window);+ }++ return 0;+ }++ case WM_MOVE:+ {+ if (_glfw.win32.disabledCursorWindow == window)+ updateClipRect(window);++ // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as+ // those macros do not handle negative window positions correctly+ _glfwInputWindowPos(window,+ GET_X_LPARAM(lParam),+ GET_Y_LPARAM(lParam));+ return 0;+ }++ case WM_SIZING:+ {+ if (window->numer == GLFW_DONT_CARE ||+ window->denom == GLFW_DONT_CARE)+ {+ break;+ }++ applyAspectRatio(window, (int) wParam, (RECT*) lParam);+ return TRUE;+ }++ case WM_GETMINMAXINFO:+ {+ int xoff, yoff;+ MINMAXINFO* mmi = (MINMAXINFO*) lParam;++ if (window->monitor)+ break;++ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),+ 0, 0, &xoff, &yoff);++ if (window->minwidth != GLFW_DONT_CARE &&+ window->minheight != GLFW_DONT_CARE)+ {+ mmi->ptMinTrackSize.x = window->minwidth + xoff;+ mmi->ptMinTrackSize.y = window->minheight + yoff;+ }++ if (window->maxwidth != GLFW_DONT_CARE &&+ window->maxheight != GLFW_DONT_CARE)+ {+ mmi->ptMaxTrackSize.x = window->maxwidth + xoff;+ mmi->ptMaxTrackSize.y = window->maxheight + yoff;+ }++ return 0;+ }++ case WM_PAINT:+ {+ _glfwInputWindowDamage(window);+ break;+ }++ case WM_ERASEBKGND:+ {+ return TRUE;+ }++ case WM_SETCURSOR:+ {+ if (LOWORD(lParam) == HTCLIENT)+ {+ updateCursorImage(window);+ return TRUE;+ }++ break;+ }++ case WM_DPICHANGED:+ {+ RECT* rect = (RECT*) lParam;+ SetWindowPos(window->win32.handle,+ HWND_TOP,+ rect->left,+ rect->top,+ rect->right - rect->left,+ rect->bottom - rect->top,+ SWP_NOACTIVATE | SWP_NOZORDER);+ break;+ }++ case WM_DROPFILES:+ {+ HDROP drop = (HDROP) wParam;+ POINT pt;+ int i;++ const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);+ char** paths = calloc(count, sizeof(char*));++ // Move the mouse to the position of the drop+ DragQueryPoint(drop, &pt);+ _glfwInputCursorPos(window, pt.x, pt.y);++ for (i = 0; i < count; i++)+ {+ const UINT length = DragQueryFileW(drop, i, NULL, 0);+ WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));++ DragQueryFileW(drop, i, buffer, length + 1);+ paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);++ free(buffer);+ }++ _glfwInputDrop(window, count, (const char**) paths);++ for (i = 0; i < count; i++)+ free(paths[i]);+ free(paths);++ DragFinish(drop);+ return 0;+ }+ }++ return DefWindowProcW(hWnd, uMsg, wParam, lParam);+}++// Creates the GLFW window+//+static int createNativeWindow(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig)+{+ int xpos, ypos, fullWidth, fullHeight;+ WCHAR* wideTitle;+ DWORD style = getWindowStyle(window);+ DWORD exStyle = getWindowExStyle(window);++ if (window->monitor)+ {+ GLFWvidmode mode;++ // NOTE: This window placement is temporary and approximate, as the+ // correct position and size cannot be known until the monitor+ // video mode has been set+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);+ _glfwPlatformGetVideoMode(window->monitor, &mode);+ fullWidth = mode.width;+ fullHeight = mode.height;+ }+ else+ {+ xpos = CW_USEDEFAULT;+ ypos = CW_USEDEFAULT;++ if (wndconfig->maximized)+ style |= WS_MAXIMIZE;++ getFullWindowSize(style, exStyle,+ wndconfig->width, wndconfig->height,+ &fullWidth, &fullHeight);+ }++ wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);+ if (!wideTitle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to convert window title to UTF-16");+ return GLFW_FALSE;+ }++ window->win32.handle = CreateWindowExW(exStyle,+ _GLFW_WNDCLASSNAME,+ wideTitle,+ style,+ xpos, ypos,+ fullWidth, fullHeight,+ NULL, // No parent window+ NULL, // No window menu+ GetModuleHandleW(NULL),+ NULL);++ free(wideTitle);++ if (!window->win32.handle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");+ return GLFW_FALSE;+ }++ SetPropW(window->win32.handle, L"GLFW", window);++ if (_glfw_ChangeWindowMessageFilterEx)+ {+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,+ WM_DROPFILES, MSGFLT_ALLOW, NULL);+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,+ WM_COPYDATA, MSGFLT_ALLOW, NULL);+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,+ WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);+ }++ DragAcceptFiles(window->win32.handle, TRUE);++ return GLFW_TRUE;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++// Registers the GLFW window class+//+GLFWbool _glfwRegisterWindowClassWin32(void)+{+ WNDCLASSEXW wc;++ ZeroMemory(&wc, sizeof(wc));+ wc.cbSize = sizeof(wc);+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;+ wc.lpfnWndProc = (WNDPROC) windowProc;+ wc.hInstance = GetModuleHandleW(NULL);+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);+ wc.lpszClassName = _GLFW_WNDCLASSNAME;++ // Load user-provided icon if available+ wc.hIcon = LoadImageW(GetModuleHandleW(NULL),+ L"GLFW_ICON", IMAGE_ICON,+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);+ if (!wc.hIcon)+ {+ // No user-provided icon found, load default icon+ wc.hIcon = LoadImageW(NULL,+ IDI_APPLICATION, IMAGE_ICON,+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);+ }++ if (!RegisterClassExW(&wc))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to register window class");+ return GLFW_FALSE;+ }++ return GLFW_TRUE;+}++// Unregisters the GLFW window class+//+void _glfwUnregisterWindowClassWin32(void)+{+ UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW platform API //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformCreateWindow(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig)+{+ if (!createNativeWindow(window, wndconfig))+ return GLFW_FALSE;++ if (ctxconfig->client != GLFW_NO_API)+ {+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)+ {+ if (!_glfwInitWGL())+ return GLFW_FALSE;+ if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }+ else+ {+ if (!_glfwInitEGL())+ return GLFW_FALSE;+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }+ }++ if (window->monitor)+ {+ _glfwPlatformShowWindow(window);+ _glfwPlatformFocusWindow(window);+ if (!acquireMonitor(window))+ return GLFW_FALSE;++ centerCursor(window);+ }++ return GLFW_TRUE;+}++void _glfwPlatformDestroyWindow(_GLFWwindow* window)+{+ if (window->monitor)+ releaseMonitor(window);++ if (window->context.destroy)+ window->context.destroy(window);++ if (_glfw.win32.disabledCursorWindow == window)+ _glfw.win32.disabledCursorWindow = NULL;++ if (window->win32.handle)+ {+ RemovePropW(window->win32.handle, L"GLFW");+ DestroyWindow(window->win32.handle);+ window->win32.handle = NULL;+ }++ if (window->win32.bigIcon)+ DestroyIcon(window->win32.bigIcon);++ if (window->win32.smallIcon)+ DestroyIcon(window->win32.smallIcon);+}++void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)+{+ WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);+ if (!wideTitle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to convert window title to UTF-16");+ return;+ }++ SetWindowTextW(window->win32.handle, wideTitle);+ free(wideTitle);+}++void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+ int count, const GLFWimage* images)+{+ HICON bigIcon = NULL, smallIcon = NULL;++ if (count)+ {+ const GLFWimage* bigImage = chooseImage(count, images,+ GetSystemMetrics(SM_CXICON),+ GetSystemMetrics(SM_CYICON));+ const GLFWimage* smallImage = chooseImage(count, images,+ GetSystemMetrics(SM_CXSMICON),+ GetSystemMetrics(SM_CYSMICON));++ bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);+ smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);+ }+ else+ {+ bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);+ smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);+ }++ SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);+ SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);++ if (window->win32.bigIcon)+ DestroyIcon(window->win32.bigIcon);++ if (window->win32.smallIcon)+ DestroyIcon(window->win32.smallIcon);++ if (count)+ {+ window->win32.bigIcon = bigIcon;+ window->win32.smallIcon = smallIcon;+ }+}++void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)+{+ POINT pos = { 0, 0 };+ ClientToScreen(window->win32.handle, &pos);++ if (xpos)+ *xpos = pos.x;+ if (ypos)+ *ypos = pos.y;+}++void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)+{+ RECT rect = { xpos, ypos, xpos, ypos };+ AdjustWindowRectEx(&rect, getWindowStyle(window),+ FALSE, getWindowExStyle(window));+ SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);+}++void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)+{+ RECT area;+ GetClientRect(window->win32.handle, &area);++ if (width)+ *width = area.right;+ if (height)+ *height = area.bottom;+}++void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)+{+ if (window->monitor)+ {+ if (window->monitor->window == window)+ acquireMonitor(window);+ }+ else+ {+ RECT rect = { 0, 0, width, height };+ AdjustWindowRectEx(&rect, getWindowStyle(window),+ FALSE, getWindowExStyle(window));+ SetWindowPos(window->win32.handle, HWND_TOP,+ 0, 0, rect.right - rect.left, rect.bottom - rect.top,+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);+ }+}++void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ RECT area;++ if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&+ (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))+ {+ return;+ }++ GetWindowRect(window->win32.handle, &area);+ MoveWindow(window->win32.handle,+ area.left, area.top,+ area.right - area.left,+ area.bottom - area.top, TRUE);+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)+{+ RECT area;++ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)+ return;++ GetWindowRect(window->win32.handle, &area);+ applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area);+ MoveWindow(window->win32.handle,+ area.left, area.top,+ area.right - area.left,+ area.bottom - area.top, TRUE);+}++void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)+{+ _glfwPlatformGetWindowSize(window, width, height);+}++void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,+ int* left, int* top,+ int* right, int* bottom)+{+ RECT rect;+ int width, height;++ _glfwPlatformGetWindowSize(window, &width, &height);+ SetRect(&rect, 0, 0, width, height);+ AdjustWindowRectEx(&rect, getWindowStyle(window),+ FALSE, getWindowExStyle(window));++ if (left)+ *left = -rect.left;+ if (top)+ *top = -rect.top;+ if (right)+ *right = rect.right - width;+ if (bottom)+ *bottom = rect.bottom - height;+}++void _glfwPlatformIconifyWindow(_GLFWwindow* window)+{+ ShowWindow(window->win32.handle, SW_MINIMIZE);+}++void _glfwPlatformRestoreWindow(_GLFWwindow* window)+{+ ShowWindow(window->win32.handle, SW_RESTORE);+}++void _glfwPlatformMaximizeWindow(_GLFWwindow* window)+{+ ShowWindow(window->win32.handle, SW_MAXIMIZE);+}++void _glfwPlatformShowWindow(_GLFWwindow* window)+{+ ShowWindow(window->win32.handle, SW_SHOW);+}++void _glfwPlatformHideWindow(_GLFWwindow* window)+{+ ShowWindow(window->win32.handle, SW_HIDE);+}++void _glfwPlatformFocusWindow(_GLFWwindow* window)+{+ BringWindowToTop(window->win32.handle);+ SetForegroundWindow(window->win32.handle);+ SetFocus(window->win32.handle);+}++void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+ _GLFWmonitor* monitor,+ int xpos, int ypos,+ int width, int height,+ int refreshRate)+{+ if (window->monitor == monitor)+ {+ if (monitor)+ {+ if (monitor->window == window)+ acquireMonitor(window);+ }+ else+ {+ RECT rect = { xpos, ypos, xpos + width, ypos + height };+ AdjustWindowRectEx(&rect, getWindowStyle(window),+ FALSE, getWindowExStyle(window));+ SetWindowPos(window->win32.handle, HWND_TOP,+ rect.left, rect.top,+ rect.right - rect.left, rect.bottom - rect.top,+ SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);+ }++ return;+ }++ if (window->monitor)+ releaseMonitor(window);++ _glfwInputWindowMonitorChange(window, monitor);++ if (monitor)+ {+ GLFWvidmode mode;+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);+ UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;++ if (window->decorated)+ {+ style &= ~WS_OVERLAPPEDWINDOW;+ style |= getWindowStyle(window);+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);++ flags |= SWP_FRAMECHANGED;+ }++ _glfwPlatformGetVideoMode(monitor, &mode);+ _glfwPlatformGetMonitorPos(monitor, &xpos, &ypos);++ SetWindowPos(window->win32.handle, HWND_TOPMOST,+ xpos, ypos, mode.width, mode.height,+ flags);++ acquireMonitor(window);+ }+ else+ {+ HWND after;+ RECT rect = { xpos, ypos, xpos + width, ypos + height };+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);+ UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;++ if (window->decorated)+ {+ style &= ~WS_POPUP;+ style |= getWindowStyle(window);+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);++ flags |= SWP_FRAMECHANGED;+ }++ if (window->floating)+ after = HWND_TOPMOST;+ else+ after = HWND_NOTOPMOST;++ AdjustWindowRectEx(&rect, getWindowStyle(window),+ FALSE, getWindowExStyle(window));+ SetWindowPos(window->win32.handle, after,+ rect.left, rect.top,+ rect.right - rect.left, rect.bottom - rect.top,+ flags);+ }+}++int _glfwPlatformWindowFocused(_GLFWwindow* window)+{+ return window->win32.handle == GetActiveWindow();+}++int _glfwPlatformWindowIconified(_GLFWwindow* window)+{+ return IsIconic(window->win32.handle);+}++int _glfwPlatformWindowVisible(_GLFWwindow* window)+{+ return IsWindowVisible(window->win32.handle);+}++int _glfwPlatformWindowMaximized(_GLFWwindow* window)+{+ return IsZoomed(window->win32.handle);+}++void _glfwPlatformPollEvents(void)+{+ MSG msg;+ HWND handle;+ _GLFWwindow* window;++ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))+ {+ if (msg.message == WM_QUIT)+ {+ // Treat WM_QUIT as a close on all windows+ // While GLFW does not itself post WM_QUIT, other processes may post+ // it to this one, for example Task Manager++ window = _glfw.windowListHead;+ while (window)+ {+ _glfwInputWindowCloseRequest(window);+ window = window->next;+ }+ }+ else+ {+ TranslateMessage(&msg);+ DispatchMessageW(&msg);+ }+ }++ handle = GetActiveWindow();+ if (handle)+ {+ // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)+ // This is the only async event handling in GLFW, but it solves some+ // nasty problems+ window = GetPropW(handle, L"GLFW");+ if (window)+ {+ const int mods = getAsyncKeyMods();++ // Get current state of left and right shift keys+ const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;+ const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;++ // See if this differs from our belief of what has happened+ // (we only have to check for lost key up events)+ if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);++ if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);+ }+ }++ window = _glfw.win32.disabledCursorWindow;+ if (window)+ {+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);++ // NOTE: Re-center the cursor only if it has moved since the last call,+ // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE+ if (window->win32.lastCursorPosX != width / 2 ||+ window->win32.lastCursorPosY != height / 2)+ {+ _glfwPlatformSetCursorPos(window, width / 2, height / 2);+ }+ }+}++void _glfwPlatformWaitEvents(void)+{+ WaitMessage();++ _glfwPlatformPollEvents();+}++void _glfwPlatformWaitEventsTimeout(double timeout)+{+ MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);++ _glfwPlatformPollEvents();+}++void _glfwPlatformPostEmptyEvent(void)+{+ _GLFWwindow* window = _glfw.windowListHead;+ PostMessage(window->win32.handle, WM_NULL, 0, 0);+}++void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)+{+ POINT pos;++ if (GetCursorPos(&pos))+ {+ ScreenToClient(window->win32.handle, &pos);++ if (xpos)+ *xpos = pos.x;+ if (ypos)+ *ypos = pos.y;+ }+}++void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)+{+ POINT pos = { (int) xpos, (int) ypos };++ // Store the new position so it can be recognized later+ window->win32.lastCursorPosX = pos.x;+ window->win32.lastCursorPosY = pos.y;++ ClientToScreen(window->win32.handle, &pos);+ SetCursorPos(pos.x, pos.y);+}++void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)+{+ if (mode == GLFW_CURSOR_DISABLED)+ {+ _glfw.win32.disabledCursorWindow = window;+ _glfwPlatformGetCursorPos(window,+ &_glfw.win32.restoreCursorPosX,+ &_glfw.win32.restoreCursorPosY);+ centerCursor(window);+ updateClipRect(window);+ }+ else if (_glfw.win32.disabledCursorWindow == window)+ {+ _glfw.win32.disabledCursorWindow = NULL;+ updateClipRect(NULL);+ _glfwPlatformSetCursorPos(window,+ _glfw.win32.restoreCursorPosX,+ _glfw.win32.restoreCursorPosY);+ }++ if (cursorInClientArea(window))+ updateCursorImage(window);+}++const char* _glfwPlatformGetKeyName(int key, int scancode)+{+ WCHAR name[16];++ if (key != GLFW_KEY_UNKNOWN)+ scancode = _glfw.win32.nativeKeys[key];++ if (!_glfwIsPrintable(_glfw.win32.publicKeys[scancode]))+ return NULL;++ if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR)))+ return NULL;++ if (!WideCharToMultiByte(CP_UTF8, 0, name, -1,+ _glfw.win32.keyName,+ sizeof(_glfw.win32.keyName),+ NULL, NULL))+ {+ return NULL;+ }++ return _glfw.win32.keyName;+}++int _glfwPlatformCreateCursor(_GLFWcursor* cursor,+ const GLFWimage* image,+ int xhot, int yhot)+{+ cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);+ if (!cursor->win32.handle)+ return GLFW_FALSE;++ return GLFW_TRUE;+}++int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)+{+ cursor->win32.handle =+ CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));+ if (!cursor->win32.handle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to create standard cursor");+ return GLFW_FALSE;+ }++ return GLFW_TRUE;+}++void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)+{+ if (cursor->win32.handle)+ DestroyIcon((HICON) cursor->win32.handle);+}++void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)+{+ if (cursorInClientArea(window))+ updateCursorImage(window);+}++void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)+{+ int characterCount;+ HANDLE object;+ WCHAR* buffer;++ characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);+ if (!characterCount)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to convert clipboard string to UTF-16");+ return;+ }++ object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));+ if (!object)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to allocate global handle for clipboard");+ return;+ }++ buffer = GlobalLock(object);+ if (!buffer)+ {+ GlobalFree(object);++ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");+ return;+ }++ MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);+ GlobalUnlock(object);++ if (!OpenClipboard(_glfw.win32.helperWindowHandle))+ {+ GlobalFree(object);++ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");+ return;+ }++ EmptyClipboard();+ SetClipboardData(CF_UNICODETEXT, object);+ CloseClipboard();+}++const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)+{+ HANDLE object;+ WCHAR* buffer;++ if (!OpenClipboard(_glfw.win32.helperWindowHandle))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");+ return NULL;+ }++ object = GetClipboardData(CF_UNICODETEXT);+ if (!object)+ {+ CloseClipboard();++ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "Win32: Failed to convert clipboard to string");+ return NULL;+ }++ buffer = GlobalLock(object);+ if (!buffer)+ {+ CloseClipboard();++ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");+ return NULL;+ }++ free(_glfw.win32.clipboardString);+ _glfw.win32.clipboardString =+ _glfwCreateUTF8FromWideStringWin32(buffer);++ GlobalUnlock(object);+ CloseClipboard();++ if (!_glfw.win32.clipboardString)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to convert wide string to UTF-8");+ return NULL;+ }++ return _glfw.win32.clipboardString;+}++char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)+{+ char** extensions;++ *count = 0;++ if (!_glfw.vk.KHR_win32_surface)+ return NULL;++ extensions = calloc(2, sizeof(char*));+ extensions[0] = strdup("VK_KHR_surface");+ extensions[1] = strdup("VK_KHR_win32_surface");++ *count = 2;+ return extensions;+}++int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =+ (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");+ if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");+ return GLFW_FALSE;+ }++ return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);+}++VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,+ _GLFWwindow* window,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ VkResult err;+ VkWin32SurfaceCreateInfoKHR sci;+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;++ vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)+ vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");+ if (!vkCreateWin32SurfaceKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ memset(&sci, 0, sizeof(sci));+ sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;+ sci.hinstance = GetModuleHandle(NULL);+ sci.hwnd = window->win32.handle;++ err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Win32: Failed to create Vulkan surface: %s",+ _glfwGetVulkanResultString(err));+ }++ return err; }
glfw/src/window.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 - www.glfw.org+// GLFW 3.2 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> // // This software is provided 'as-is', without any express or implied@@ -28,20 +28,20 @@ #include "internal.h" +#include <assert.h> #include <string.h> #include <stdlib.h>+#include <float.h> ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean focused)+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (focused) {- _glfw.focusedWindow = window;- if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); }@@ -49,8 +49,6 @@ { int i; - _glfw.focusedWindow = NULL;- if (window->callbacks.focus) window->callbacks.focus((GLFWwindow*) window, focused); @@ -82,7 +80,7 @@ window->callbacks.size((GLFWwindow*) window, width, height); } -void _glfwInputWindowIconify(_GLFWwindow* window, int iconified)+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) { if (window->callbacks.iconify) window->callbacks.iconify((GLFWwindow*) window, iconified);@@ -102,13 +100,18 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window) {- window->closed = GL_TRUE;+ window->closed = GLFW_TRUE; if (window->callbacks.close) window->callbacks.close((GLFWwindow*) window); } +void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)+{+ window->monitor = monitor;+} + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// //////////////////////////////////////////////////////////////////////////@@ -124,55 +127,38 @@ _GLFWwindow* window; _GLFWwindow* previous; + assert(title != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); if (width <= 0 || height <= 0) {- _glfwInputError(GLFW_INVALID_VALUE, "Invalid window size");+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid window size %ix%i",+ width, height);+ return NULL; } - // Set up desired framebuffer config- fbconfig.redBits = _glfw.hints.redBits;- fbconfig.greenBits = _glfw.hints.greenBits;- fbconfig.blueBits = _glfw.hints.blueBits;- fbconfig.alphaBits = _glfw.hints.alphaBits;- fbconfig.depthBits = _glfw.hints.depthBits;- fbconfig.stencilBits = _glfw.hints.stencilBits;- fbconfig.accumRedBits = _glfw.hints.accumRedBits;- fbconfig.accumGreenBits = _glfw.hints.accumGreenBits;- fbconfig.accumBlueBits = _glfw.hints.accumBlueBits;- fbconfig.accumAlphaBits = _glfw.hints.accumAlphaBits;- fbconfig.auxBuffers = _glfw.hints.auxBuffers;- fbconfig.stereo = _glfw.hints.stereo ? GL_TRUE : GL_FALSE;- fbconfig.samples = _glfw.hints.samples;- fbconfig.sRGB = _glfw.hints.sRGB;- fbconfig.doublebuffer = _glfw.hints.doublebuffer ? GL_TRUE : GL_FALSE;+ fbconfig = _glfw.hints.framebuffer;+ ctxconfig = _glfw.hints.context;+ wndconfig = _glfw.hints.window; - // Set up desired window config- wndconfig.width = width;- wndconfig.height = height;- wndconfig.title = title;- wndconfig.resizable = _glfw.hints.resizable ? GL_TRUE : GL_FALSE;- wndconfig.visible = _glfw.hints.visible ? GL_TRUE : GL_FALSE;- wndconfig.decorated = _glfw.hints.decorated ? GL_TRUE : GL_FALSE;- wndconfig.focused = _glfw.hints.focused ? GL_TRUE : GL_FALSE;- wndconfig.autoIconify = _glfw.hints.autoIconify ? GL_TRUE : GL_FALSE;- wndconfig.floating = _glfw.hints.floating ? GL_TRUE : GL_FALSE;- wndconfig.monitor = (_GLFWmonitor*) monitor;+ wndconfig.width = width;+ wndconfig.height = height;+ wndconfig.title = title;+ ctxconfig.share = (_GLFWwindow*) share; - // Set up desired context config- ctxconfig.api = _glfw.hints.api;- ctxconfig.major = _glfw.hints.major;- ctxconfig.minor = _glfw.hints.minor;- ctxconfig.forward = _glfw.hints.forward ? GL_TRUE : GL_FALSE;- ctxconfig.debug = _glfw.hints.debug ? GL_TRUE : GL_FALSE;- ctxconfig.profile = _glfw.hints.profile;- ctxconfig.robustness = _glfw.hints.robustness;- ctxconfig.release = _glfw.hints.release;- ctxconfig.share = (_GLFWwindow*) share;+ if (ctxconfig.share)+ {+ if (ctxconfig.client == GLFW_NO_API ||+ ctxconfig.share->context.client == GLFW_NO_API)+ {+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);+ return NULL;+ }+ } - // Check the OpenGL bits of the window config if (!_glfwIsValidContextConfig(&ctxconfig)) return NULL; @@ -180,85 +166,63 @@ window->next = _glfw.windowListHead; _glfw.windowListHead = window; - if (wndconfig.monitor)- {- wndconfig.resizable = GL_TRUE;- wndconfig.visible = GL_TRUE;- wndconfig.focused = GL_TRUE;-- // Set up desired video mode- window->videoMode.width = width;- window->videoMode.height = height;- window->videoMode.redBits = _glfw.hints.redBits;- window->videoMode.greenBits = _glfw.hints.greenBits;- window->videoMode.blueBits = _glfw.hints.blueBits;- window->videoMode.refreshRate = _glfw.hints.refreshRate;- }+ window->videoMode.width = width;+ window->videoMode.height = height;+ window->videoMode.redBits = fbconfig.redBits;+ window->videoMode.greenBits = fbconfig.greenBits;+ window->videoMode.blueBits = fbconfig.blueBits;+ window->videoMode.refreshRate = _glfw.hints.refreshRate; - // Transfer window hints that are persistent settings and not- // just initial states- window->monitor = wndconfig.monitor;+ window->monitor = (_GLFWmonitor*) monitor; window->resizable = wndconfig.resizable; window->decorated = wndconfig.decorated; window->autoIconify = wndconfig.autoIconify; window->floating = wndconfig.floating; window->cursorMode = GLFW_CURSOR_NORMAL; + window->minwidth = GLFW_DONT_CARE;+ window->minheight = GLFW_DONT_CARE;+ window->maxwidth = GLFW_DONT_CARE;+ window->maxheight = GLFW_DONT_CARE;+ window->numer = GLFW_DONT_CARE;+ window->denom = GLFW_DONT_CARE;+ // Save the currently current context so it can be restored later previous = _glfwPlatformGetCurrentContext();+ if (ctxconfig.client != GLFW_NO_API)+ glfwMakeContextCurrent(NULL); // Open the actual window and create its context if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig)) {+ glfwMakeContextCurrent((GLFWwindow*) previous); glfwDestroyWindow((GLFWwindow*) window);- _glfwPlatformMakeContextCurrent(previous); return NULL; } - _glfwPlatformMakeContextCurrent(window);-- // Retrieve the actual (as opposed to requested) context attributes- if (!_glfwRefreshContextAttribs(&ctxconfig))- {- glfwDestroyWindow((GLFWwindow*) window);- _glfwPlatformMakeContextCurrent(previous);- return NULL;- }-- // Verify the context against the requested parameters- if (!_glfwIsValidContext(&ctxconfig))- {- glfwDestroyWindow((GLFWwindow*) window);- _glfwPlatformMakeContextCurrent(previous);- return NULL;- }-- // Clearing the front buffer to black to avoid garbage pixels left over- // from previous uses of our bit of VRAM- glClear(GL_COLOR_BUFFER_BIT);- _glfwPlatformSwapBuffers(window);-- // Restore the previously current context (or NULL)- _glfwPlatformMakeContextCurrent(previous);-- if (wndconfig.monitor)+ if (ctxconfig.client != GLFW_NO_API) {- int width, height;- _glfwPlatformGetWindowSize(window, &width, &height);+ window->context.makeCurrent(window); - window->cursorPosX = width / 2;- window->cursorPosY = height / 2;+ // Retrieve the actual (as opposed to requested) context attributes+ if (!_glfwRefreshContextAttribs(&ctxconfig))+ {+ glfwMakeContextCurrent((GLFWwindow*) previous);+ glfwDestroyWindow((GLFWwindow*) window);+ return NULL;+ } - _glfwPlatformSetCursorPos(window, window->cursorPosX, window->cursorPosY);+ // Restore the previously current context (or NULL)+ glfwMakeContextCurrent((GLFWwindow*) previous); }- else++ if (!window->monitor) { if (wndconfig.visible) {+ _glfwPlatformShowWindow(window); if (wndconfig.focused)- _glfwPlatformShowWindow(window);- else- _glfwPlatformUnhideWindow(window);+ _glfwPlatformFocusWindow(window); } } @@ -272,129 +236,139 @@ memset(&_glfw.hints, 0, sizeof(_glfw.hints)); // The default is OpenGL with minimum version 1.0- _glfw.hints.api = GLFW_OPENGL_API;- _glfw.hints.major = 1;- _glfw.hints.minor = 0;+ _glfw.hints.context.client = GLFW_OPENGL_API;+ _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;+ _glfw.hints.context.major = 1;+ _glfw.hints.context.minor = 0; // The default is a focused, visible, resizable window with decorations- _glfw.hints.resizable = GL_TRUE;- _glfw.hints.visible = GL_TRUE;- _glfw.hints.decorated = GL_TRUE;- _glfw.hints.focused = GL_TRUE;- _glfw.hints.autoIconify = GL_TRUE;-- // The default is to select the highest available refresh rate- _glfw.hints.refreshRate = GLFW_DONT_CARE;+ _glfw.hints.window.resizable = GLFW_TRUE;+ _glfw.hints.window.visible = GLFW_TRUE;+ _glfw.hints.window.decorated = GLFW_TRUE;+ _glfw.hints.window.focused = GLFW_TRUE;+ _glfw.hints.window.autoIconify = GLFW_TRUE; // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil, // double buffered- _glfw.hints.redBits = 8;- _glfw.hints.greenBits = 8;- _glfw.hints.blueBits = 8;- _glfw.hints.alphaBits = 8;- _glfw.hints.depthBits = 24;- _glfw.hints.stencilBits = 8;- _glfw.hints.doublebuffer = GL_TRUE;+ _glfw.hints.framebuffer.redBits = 8;+ _glfw.hints.framebuffer.greenBits = 8;+ _glfw.hints.framebuffer.blueBits = 8;+ _glfw.hints.framebuffer.alphaBits = 8;+ _glfw.hints.framebuffer.depthBits = 24;+ _glfw.hints.framebuffer.stencilBits = 8;+ _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;++ // The default is to select the highest available refresh rate+ _glfw.hints.refreshRate = GLFW_DONT_CARE; } -GLFWAPI void glfwWindowHint(int target, int hint)+GLFWAPI void glfwWindowHint(int hint, int value) { _GLFW_REQUIRE_INIT(); - switch (target)+ switch (hint) { case GLFW_RED_BITS:- _glfw.hints.redBits = hint;+ _glfw.hints.framebuffer.redBits = value; break; case GLFW_GREEN_BITS:- _glfw.hints.greenBits = hint;+ _glfw.hints.framebuffer.greenBits = value; break; case GLFW_BLUE_BITS:- _glfw.hints.blueBits = hint;+ _glfw.hints.framebuffer.blueBits = value; break; case GLFW_ALPHA_BITS:- _glfw.hints.alphaBits = hint;+ _glfw.hints.framebuffer.alphaBits = value; break; case GLFW_DEPTH_BITS:- _glfw.hints.depthBits = hint;+ _glfw.hints.framebuffer.depthBits = value; break; case GLFW_STENCIL_BITS:- _glfw.hints.stencilBits = hint;+ _glfw.hints.framebuffer.stencilBits = value; break; case GLFW_ACCUM_RED_BITS:- _glfw.hints.accumRedBits = hint;+ _glfw.hints.framebuffer.accumRedBits = value; break; case GLFW_ACCUM_GREEN_BITS:- _glfw.hints.accumGreenBits = hint;+ _glfw.hints.framebuffer.accumGreenBits = value; break; case GLFW_ACCUM_BLUE_BITS:- _glfw.hints.accumBlueBits = hint;+ _glfw.hints.framebuffer.accumBlueBits = value; break; case GLFW_ACCUM_ALPHA_BITS:- _glfw.hints.accumAlphaBits = hint;+ _glfw.hints.framebuffer.accumAlphaBits = value; break; case GLFW_AUX_BUFFERS:- _glfw.hints.auxBuffers = hint;+ _glfw.hints.framebuffer.auxBuffers = value; break; case GLFW_STEREO:- _glfw.hints.stereo = hint;- break;- case GLFW_REFRESH_RATE:- _glfw.hints.refreshRate = hint;+ _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_DOUBLEBUFFER:- _glfw.hints.doublebuffer = hint;+ _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE; break;+ case GLFW_SAMPLES:+ _glfw.hints.framebuffer.samples = value;+ break;+ case GLFW_SRGB_CAPABLE:+ _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;+ break; case GLFW_RESIZABLE:- _glfw.hints.resizable = hint;+ _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_DECORATED:- _glfw.hints.decorated = hint;+ _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_FOCUSED:- _glfw.hints.focused = hint;+ _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_AUTO_ICONIFY:- _glfw.hints.autoIconify = hint;+ _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_FLOATING:- _glfw.hints.floating = hint;- break;- case GLFW_VISIBLE:- _glfw.hints.visible = hint;+ _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE; break;- case GLFW_SAMPLES:- _glfw.hints.samples = hint;+ case GLFW_MAXIMIZED:+ _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE; break;- case GLFW_SRGB_CAPABLE:- _glfw.hints.sRGB = hint;+ case GLFW_VISIBLE:+ _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_CLIENT_API:- _glfw.hints.api = hint;+ _glfw.hints.context.client = value; break;+ case GLFW_CONTEXT_CREATION_API:+ _glfw.hints.context.source = value;+ break; case GLFW_CONTEXT_VERSION_MAJOR:- _glfw.hints.major = hint;+ _glfw.hints.context.major = value; break; case GLFW_CONTEXT_VERSION_MINOR:- _glfw.hints.minor = hint;+ _glfw.hints.context.minor = value; break; case GLFW_CONTEXT_ROBUSTNESS:- _glfw.hints.robustness = hint;+ _glfw.hints.context.robustness = value; break; case GLFW_OPENGL_FORWARD_COMPAT:- _glfw.hints.forward = hint;+ _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE; break; case GLFW_OPENGL_DEBUG_CONTEXT:- _glfw.hints.debug = hint;+ _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE; break;+ case GLFW_CONTEXT_NO_ERROR:+ _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;+ break; case GLFW_OPENGL_PROFILE:- _glfw.hints.profile = hint;+ _glfw.hints.context.profile = value; break; case GLFW_CONTEXT_RELEASE_BEHAVIOR:- _glfw.hints.release = hint;+ _glfw.hints.context.release = value; break;+ case GLFW_REFRESH_RATE:+ _glfw.hints.refreshRate = value;+ break; default:- _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint); break; } }@@ -415,11 +389,7 @@ // The window's context must not be current on another thread when the // window is destroyed if (window == _glfwPlatformGetCurrentContext())- _glfwPlatformMakeContextCurrent(NULL);-- // Clear the focused window pointer if this is the focused window- if (_glfw.focusedWindow == window)- _glfw.focusedWindow = NULL;+ glfwMakeContextCurrent(NULL); _glfwPlatformDestroyWindow(window); @@ -439,6 +409,8 @@ GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(0); return window->closed; }@@ -446,6 +418,8 @@ GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT(); window->closed = value; }@@ -453,13 +427,30 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* handle, const char* title) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);++ assert(title != NULL);+ _GLFW_REQUIRE_INIT(); _glfwPlatformSetWindowTitle(window, title); } +GLFWAPI void glfwSetWindowIcon(GLFWwindow* handle,+ int count, const GLFWimage* images)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ assert(count >= 0);+ assert(count == 0 || images != NULL);++ _GLFW_REQUIRE_INIT();+ _glfwPlatformSetWindowIcon(window, count, images);+}+ GLFWAPI void glfwGetWindowPos(GLFWwindow* handle, int* xpos, int* ypos) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); if (xpos) *xpos = 0;@@ -473,15 +464,12 @@ GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); if (window->monitor)- {- _glfwInputError(GLFW_INVALID_VALUE,- "Full screen windows cannot be positioned"); return;- } _glfwPlatformSetWindowPos(window, xpos, ypos); }@@ -489,6 +477,7 @@ GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); if (width) *width = 0;@@ -502,21 +491,92 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); - if (window->monitor)+ window->videoMode.width = width;+ window->videoMode.height = height;++ _glfwPlatformSetWindowSize(window, width, height);+}++GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* handle,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);++ _GLFW_REQUIRE_INIT();++ if (minwidth != GLFW_DONT_CARE && minheight != GLFW_DONT_CARE) {- window->videoMode.width = width;- window->videoMode.height = height;+ if (minwidth < 0 || minheight < 0)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid window minimum size %ix%i",+ minwidth, minheight);+ return;+ } } - _glfwPlatformSetWindowSize(window, width, height);+ if (maxwidth != GLFW_DONT_CARE && maxheight != GLFW_DONT_CARE)+ {+ if (maxwidth < 0 || maxheight < 0 ||+ maxwidth < minwidth || maxheight < minheight)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid window maximum size %ix%i",+ maxwidth, maxheight);+ return;+ }+ }++ window->minwidth = minwidth;+ window->minheight = minheight;+ window->maxwidth = maxwidth;+ window->maxheight = maxheight;++ if (window->monitor || !window->resizable)+ return;++ _glfwPlatformSetWindowSizeLimits(window,+ minwidth, minheight,+ maxwidth, maxheight); } +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* handle, int numer, int denom)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);++ _GLFW_REQUIRE_INIT();++ if (numer != GLFW_DONT_CARE && denom != GLFW_DONT_CARE)+ {+ if (numer <= 0 || denom <= 0)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid window aspect ratio %i:%i",+ numer, denom);+ return;+ }+ }++ window->numer = numer;+ window->denom = denom;++ if (window->monitor || !window->resizable)+ return;++ _glfwPlatformSetWindowAspectRatio(window, numer, denom);+}+ GLFWAPI void glfwGetFramebufferSize(GLFWwindow* handle, int* width, int* height) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); if (width) *width = 0;@@ -532,6 +592,7 @@ int* right, int* bottom) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); if (left) *left = 0;@@ -549,6 +610,8 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT(); _glfwPlatformIconifyWindow(window); }@@ -556,13 +619,25 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT(); _glfwPlatformRestoreWindow(window); } +GLFWAPI void glfwMaximizeWindow(GLFWwindow* handle)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);++ _GLFW_REQUIRE_INIT();+ _glfwPlatformMaximizeWindow(window);+}+ GLFWAPI void glfwShowWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -570,11 +645,13 @@ return; _glfwPlatformShowWindow(window);+ _glfwPlatformFocusWindow(window); } GLFWAPI void glfwHideWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT(); @@ -584,9 +661,20 @@ _glfwPlatformHideWindow(window); } +GLFWAPI void glfwFocusWindow(GLFWwindow* handle)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);++ _GLFW_REQUIRE_INIT();++ _glfwPlatformFocusWindow(window);+}+ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL); _GLFW_REQUIRE_INIT_OR_RETURN(0); @@ -598,6 +686,8 @@ return _glfwPlatformWindowIconified(window); case GLFW_VISIBLE: return _glfwPlatformWindowVisible(window);+ case GLFW_MAXIMIZED:+ return _glfwPlatformWindowMaximized(window); case GLFW_RESIZABLE: return window->resizable; case GLFW_DECORATED:@@ -605,7 +695,9 @@ case GLFW_FLOATING: return window->floating; case GLFW_CLIENT_API:- return window->context.api;+ return window->context.client;+ case GLFW_CONTEXT_CREATION_API:+ return window->context.source; case GLFW_CONTEXT_VERSION_MAJOR: return window->context.major; case GLFW_CONTEXT_VERSION_MINOR:@@ -622,22 +714,65 @@ return window->context.profile; case GLFW_CONTEXT_RELEASE_BEHAVIOR: return window->context.release;+ case GLFW_CONTEXT_NO_ERROR:+ return window->context.noerror; } - _glfwInputError(GLFW_INVALID_ENUM, NULL);+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute %i", attrib); return 0; } GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return (GLFWmonitor*) window->monitor; } +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,+ GLFWmonitor* mh,+ int xpos, int ypos,+ int width, int height,+ int refreshRate)+{+ _GLFWwindow* window = (_GLFWwindow*) wh;+ _GLFWmonitor* monitor = (_GLFWmonitor*) mh;+ assert(window != NULL);++ _GLFW_REQUIRE_INIT();++ if (width <= 0 || height <= 0)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid window size %ix%i",+ width, height);+ return;+ }++ if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)+ {+ _glfwInputError(GLFW_INVALID_VALUE,+ "Invalid refresh rate %i",+ refreshRate);+ return;+ }++ window->videoMode.width = width;+ window->videoMode.height = height;+ window->videoMode.refreshRate = refreshRate;++ _glfwPlatformSetWindowMonitor(window, monitor,+ xpos, ypos, width, height,+ refreshRate);+}+ GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT(); window->userPointer = pointer; }@@ -645,6 +780,8 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return window->userPointer; }@@ -653,6 +790,8 @@ GLFWwindowposfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun); return cbfun;@@ -662,6 +801,8 @@ GLFWwindowsizefun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun); return cbfun;@@ -671,6 +812,8 @@ GLFWwindowclosefun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun); return cbfun;@@ -680,6 +823,8 @@ GLFWwindowrefreshfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun); return cbfun;@@ -689,6 +834,8 @@ GLFWwindowfocusfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun); return cbfun;@@ -698,6 +845,8 @@ GLFWwindowiconifyfun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun); return cbfun;@@ -707,6 +856,8 @@ GLFWframebuffersizefun cbfun) { _GLFWwindow* window = (_GLFWwindow*) handle;+ assert(window != NULL);+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun); return cbfun;@@ -726,6 +877,19 @@ return; _glfwPlatformWaitEvents();+}++GLFWAPI void glfwWaitEventsTimeout(double timeout)+{+ _GLFW_REQUIRE_INIT();++ if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)+ {+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);+ return;+ }++ _glfwPlatformWaitEventsTimeout(timeout); } GLFWAPI void glfwPostEmptyEvent(void)
− glfw/src/winmm_joystick.c
@@ -1,177 +0,0 @@-//========================================================================-// GLFW 3.1 WinMM - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#include "internal.h"--#include <stdlib.h>---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Convert axis value to the [-1,1] range-//-static float normalizeAxis(DWORD pos, DWORD min, DWORD max)-{- float fpos = (float) pos;- float fmin = (float) min;- float fmax = (float) max;-- return (2.f * (fpos - fmin) / (fmax - fmin)) - 1.f;-}---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Initialize joystick interface-//-void _glfwInitJoysticks(void)-{-}--// Close all opened joystick handles-//-void _glfwTerminateJoysticks(void)-{- int i;-- for (i = 0; i < GLFW_JOYSTICK_LAST; i++)- free(_glfw.winmm_js[i].name);-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformJoystickPresent(int joy)-{- JOYINFO ji;-- if (_glfw_joyGetPos(joy, &ji) != JOYERR_NOERROR)- return GL_FALSE;-- return GL_TRUE;-}--const float* _glfwPlatformGetJoystickAxes(int joy, int* count)-{- JOYCAPS jc;- JOYINFOEX ji;- float* axes = _glfw.winmm_js[joy].axes;-- if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)- return NULL;-- ji.dwSize = sizeof(JOYINFOEX);- ji.dwFlags = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ |- JOY_RETURNR | JOY_RETURNU | JOY_RETURNV;- if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)- return NULL;-- axes[(*count)++] = normalizeAxis(ji.dwXpos, jc.wXmin, jc.wXmax);- axes[(*count)++] = normalizeAxis(ji.dwYpos, jc.wYmin, jc.wYmax);-- if (jc.wCaps & JOYCAPS_HASZ)- axes[(*count)++] = normalizeAxis(ji.dwZpos, jc.wZmin, jc.wZmax);-- if (jc.wCaps & JOYCAPS_HASR)- axes[(*count)++] = normalizeAxis(ji.dwRpos, jc.wRmin, jc.wRmax);-- if (jc.wCaps & JOYCAPS_HASU)- axes[(*count)++] = normalizeAxis(ji.dwUpos, jc.wUmin, jc.wUmax);-- if (jc.wCaps & JOYCAPS_HASV)- axes[(*count)++] = normalizeAxis(ji.dwVpos, jc.wVmin, jc.wVmax);-- return axes;-}--const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)-{- JOYCAPS jc;- JOYINFOEX ji;- unsigned char* buttons = _glfw.winmm_js[joy].buttons;-- if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)- return NULL;-- ji.dwSize = sizeof(JOYINFOEX);- ji.dwFlags = JOY_RETURNBUTTONS | JOY_RETURNPOV;- if (_glfw_joyGetPosEx(joy, &ji) != JOYERR_NOERROR)- return NULL;-- while (*count < (int) jc.wNumButtons)- {- buttons[*count] = (unsigned char)- (ji.dwButtons & (1UL << *count) ? GLFW_PRESS : GLFW_RELEASE);- (*count)++;- }-- // Virtual buttons - Inject data from hats- // Each hat is exposed as 4 buttons which exposes 8 directions with- // concurrent button presses- // NOTE: this API exposes only one hat-- if ((jc.wCaps & JOYCAPS_HASPOV) && (jc.wCaps & JOYCAPS_POV4DIR))- {- int i, value = ji.dwPOV / 100 / 45;-- // Bit fields of button presses for each direction, including nil- const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };-- if (value < 0 || value > 8)- value = 8;-- for (i = 0; i < 4; i++)- {- if (directions[value] & (1 << i))- buttons[(*count)++] = GLFW_PRESS;- else- buttons[(*count)++] = GLFW_RELEASE;- }- }-- return buttons;-}--const char* _glfwPlatformGetJoystickName(int joy)-{- JOYCAPS jc;-- if (_glfw_joyGetDevCaps(joy, &jc, sizeof(JOYCAPS)) != JOYERR_NOERROR)- return NULL;-- free(_glfw.winmm_js[joy].name);- _glfw.winmm_js[joy].name = _glfwCreateUTF8FromWideString(jc.szPname);-- return _glfw.winmm_js[joy].name;-}-
− glfw/src/winmm_joystick.h
@@ -1,47 +0,0 @@-//========================================================================-// GLFW 3.1 WinMM - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2006-2014 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#ifndef _winmm_joystick_h_-#define _winmm_joystick_h_--#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \- _GLFWjoystickWinMM winmm_js[GLFW_JOYSTICK_LAST + 1]---// WinMM-specific per-joystick data-//-typedef struct _GLFWjoystickWinMM-{- float axes[6];- unsigned char buttons[36]; // 32 buttons plus one hat- char* name;-} _GLFWjoystickWinMM;---void _glfwInitJoysticks(void);-void _glfwTerminateJoysticks(void);--#endif // _winmm_joystick_h_
glfw/src/wl_init.c view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Wayland - www.glfw.org+// GLFW 3.2 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -35,8 +35,12 @@ #include <wayland-client.h> #include <wayland-cursor.h> -#include "xkb_unicode.h" +static inline int min(int n1, int n2)+{+ return n1 < n2 ? n1 : n2;+}+ static void pointerHandleEnter(void* data, struct wl_pointer* pointer, uint32_t serial,@@ -50,7 +54,7 @@ _glfw.wl.pointerFocus = window; _glfwPlatformSetCursor(window, window->wl.currentCursor);- _glfwInputCursorEnter(window, GL_TRUE);+ _glfwInputCursorEnter(window, GLFW_TRUE); } static void pointerHandleLeave(void* data,@@ -65,7 +69,7 @@ _glfw.wl.pointerSerial = serial; _glfw.wl.pointerFocus = NULL;- _glfwInputCursorEnter(window, GL_FALSE);+ _glfwInputCursorEnter(window, GLFW_FALSE); } static void pointerHandleMotion(void* data,@@ -80,16 +84,16 @@ return; if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- /* TODO */- _glfwInputError(GLFW_PLATFORM_ERROR,- "Wayland: GLFW_CURSOR_DISABLED not supported"); return;+ else+ {+ window->wl.cursorPosX = wl_fixed_to_double(sx);+ window->wl.cursorPosY = wl_fixed_to_double(sy); } - _glfwInputCursorMotion(window,- wl_fixed_to_double(sx),- wl_fixed_to_double(sy));+ _glfwInputCursorPos(window,+ wl_fixed_to_double(sx),+ wl_fixed_to_double(sy)); } static void pointerHandleButton(void* data,@@ -229,7 +233,7 @@ _GLFWwindow* window = wl_surface_get_user_data(surface); _glfw.wl.keyboardFocus = window;- _glfwInputWindowFocus(window, GL_TRUE);+ _glfwInputWindowFocus(window, GLFW_TRUE); } static void keyboardHandleLeave(void* data,@@ -243,131 +247,15 @@ return; _glfw.wl.keyboardFocus = NULL;- _glfwInputWindowFocus(window, GL_FALSE);+ _glfwInputWindowFocus(window, GLFW_FALSE); } static int toGLFWKeyCode(uint32_t key) {- switch (key)- {- case KEY_GRAVE: return GLFW_KEY_GRAVE_ACCENT;- case KEY_1: return GLFW_KEY_1;- case KEY_2: return GLFW_KEY_2;- case KEY_3: return GLFW_KEY_3;- case KEY_4: return GLFW_KEY_4;- case KEY_5: return GLFW_KEY_5;- case KEY_6: return GLFW_KEY_6;- case KEY_7: return GLFW_KEY_7;- case KEY_8: return GLFW_KEY_8;- case KEY_9: return GLFW_KEY_9;- case KEY_0: return GLFW_KEY_0;- case KEY_MINUS: return GLFW_KEY_MINUS;- case KEY_EQUAL: return GLFW_KEY_EQUAL;- case KEY_Q: return GLFW_KEY_Q;- case KEY_W: return GLFW_KEY_W;- case KEY_E: return GLFW_KEY_E;- case KEY_R: return GLFW_KEY_R;- case KEY_T: return GLFW_KEY_T;- case KEY_Y: return GLFW_KEY_Y;- case KEY_U: return GLFW_KEY_U;- case KEY_I: return GLFW_KEY_I;- case KEY_O: return GLFW_KEY_O;- case KEY_P: return GLFW_KEY_P;- case KEY_LEFTBRACE: return GLFW_KEY_LEFT_BRACKET;- case KEY_RIGHTBRACE: return GLFW_KEY_RIGHT_BRACKET;- case KEY_A: return GLFW_KEY_A;- case KEY_S: return GLFW_KEY_S;- case KEY_D: return GLFW_KEY_D;- case KEY_F: return GLFW_KEY_F;- case KEY_G: return GLFW_KEY_G;- case KEY_H: return GLFW_KEY_H;- case KEY_J: return GLFW_KEY_J;- case KEY_K: return GLFW_KEY_K;- case KEY_L: return GLFW_KEY_L;- case KEY_SEMICOLON: return GLFW_KEY_SEMICOLON;- case KEY_APOSTROPHE: return GLFW_KEY_APOSTROPHE;- case KEY_Z: return GLFW_KEY_Z;- case KEY_X: return GLFW_KEY_X;- case KEY_C: return GLFW_KEY_C;- case KEY_V: return GLFW_KEY_V;- case KEY_B: return GLFW_KEY_B;- case KEY_N: return GLFW_KEY_N;- case KEY_M: return GLFW_KEY_M;- case KEY_COMMA: return GLFW_KEY_COMMA;- case KEY_DOT: return GLFW_KEY_PERIOD;- case KEY_SLASH: return GLFW_KEY_SLASH;- case KEY_BACKSLASH: return GLFW_KEY_BACKSLASH;- case KEY_ESC: return GLFW_KEY_ESCAPE;- case KEY_TAB: return GLFW_KEY_TAB;- case KEY_LEFTSHIFT: return GLFW_KEY_LEFT_SHIFT;- case KEY_RIGHTSHIFT: return GLFW_KEY_RIGHT_SHIFT;- case KEY_LEFTCTRL: return GLFW_KEY_LEFT_CONTROL;- case KEY_RIGHTCTRL: return GLFW_KEY_RIGHT_CONTROL;- case KEY_LEFTALT: return GLFW_KEY_LEFT_ALT;- case KEY_RIGHTALT: return GLFW_KEY_RIGHT_ALT;- case KEY_LEFTMETA: return GLFW_KEY_LEFT_SUPER;- case KEY_RIGHTMETA: return GLFW_KEY_RIGHT_SUPER;- case KEY_MENU: return GLFW_KEY_MENU;- case KEY_NUMLOCK: return GLFW_KEY_NUM_LOCK;- case KEY_CAPSLOCK: return GLFW_KEY_CAPS_LOCK;- case KEY_PRINT: return GLFW_KEY_PRINT_SCREEN;- case KEY_SCROLLLOCK: return GLFW_KEY_SCROLL_LOCK;- case KEY_PAUSE: return GLFW_KEY_PAUSE;- case KEY_DELETE: return GLFW_KEY_DELETE;- case KEY_BACKSPACE: return GLFW_KEY_BACKSPACE;- case KEY_ENTER: return GLFW_KEY_ENTER;- case KEY_HOME: return GLFW_KEY_HOME;- case KEY_END: return GLFW_KEY_END;- case KEY_PAGEUP: return GLFW_KEY_PAGE_UP;- case KEY_PAGEDOWN: return GLFW_KEY_PAGE_DOWN;- case KEY_INSERT: return GLFW_KEY_INSERT;- case KEY_LEFT: return GLFW_KEY_LEFT;- case KEY_RIGHT: return GLFW_KEY_RIGHT;- case KEY_DOWN: return GLFW_KEY_DOWN;- case KEY_UP: return GLFW_KEY_UP;- case KEY_F1: return GLFW_KEY_F1;- case KEY_F2: return GLFW_KEY_F2;- case KEY_F3: return GLFW_KEY_F3;- case KEY_F4: return GLFW_KEY_F4;- case KEY_F5: return GLFW_KEY_F5;- case KEY_F6: return GLFW_KEY_F6;- case KEY_F7: return GLFW_KEY_F7;- case KEY_F8: return GLFW_KEY_F8;- case KEY_F9: return GLFW_KEY_F9;- case KEY_F10: return GLFW_KEY_F10;- case KEY_F11: return GLFW_KEY_F11;- case KEY_F12: return GLFW_KEY_F12;- case KEY_F13: return GLFW_KEY_F13;- case KEY_F14: return GLFW_KEY_F14;- case KEY_F15: return GLFW_KEY_F15;- case KEY_F16: return GLFW_KEY_F16;- case KEY_F17: return GLFW_KEY_F17;- case KEY_F18: return GLFW_KEY_F18;- case KEY_F19: return GLFW_KEY_F19;- case KEY_F20: return GLFW_KEY_F20;- case KEY_F21: return GLFW_KEY_F21;- case KEY_F22: return GLFW_KEY_F22;- case KEY_F23: return GLFW_KEY_F23;- case KEY_F24: return GLFW_KEY_F24;- case KEY_KPSLASH: return GLFW_KEY_KP_DIVIDE;- case KEY_KPDOT: return GLFW_KEY_KP_MULTIPLY;- case KEY_KPMINUS: return GLFW_KEY_KP_SUBTRACT;- case KEY_KPPLUS: return GLFW_KEY_KP_ADD;- case KEY_KP0: return GLFW_KEY_KP_0;- case KEY_KP1: return GLFW_KEY_KP_1;- case KEY_KP2: return GLFW_KEY_KP_2;- case KEY_KP3: return GLFW_KEY_KP_3;- case KEY_KP4: return GLFW_KEY_KP_4;- case KEY_KP5: return GLFW_KEY_KP_5;- case KEY_KP6: return GLFW_KEY_KP_6;- case KEY_KP7: return GLFW_KEY_KP_7;- case KEY_KP8: return GLFW_KEY_KP_8;- case KEY_KP9: return GLFW_KEY_KP_9;- case KEY_KPCOMMA: return GLFW_KEY_KP_DECIMAL;- case KEY_KPEQUAL: return GLFW_KEY_KP_EQUAL;- case KEY_KPENTER: return GLFW_KEY_KP_ENTER;- default: return GLFW_KEY_UNKNOWN;- }+ if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))+ return _glfw.wl.publicKeys[key];++ return GLFW_KEY_UNKNOWN; } static void keyboardHandleKey(void* data,@@ -492,8 +380,10 @@ { if (strcmp(interface, "wl_compositor") == 0) {+ _glfw.wl.wl_compositor_version = min(3, version); _glfw.wl.compositor =- wl_registry_bind(registry, name, &wl_compositor_interface, 1);+ wl_registry_bind(registry, name, &wl_compositor_interface,+ _glfw.wl.wl_compositor_version); } else if (strcmp(interface, "wl_shm") == 0) {@@ -507,7 +397,7 @@ } else if (strcmp(interface, "wl_output") == 0) {- _glfwAddOutput(name, version);+ _glfwAddOutputWayland(name, version); } else if (strcmp(interface, "wl_seat") == 0) {@@ -518,6 +408,20 @@ wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); } }+ else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)+ {+ _glfw.wl.relativePointerManager =+ wl_registry_bind(registry, name,+ &zwp_relative_pointer_manager_v1_interface,+ 1);+ }+ else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)+ {+ _glfw.wl.pointerConstraints =+ wl_registry_bind(registry, name,+ &zwp_pointer_constraints_v1_interface,+ 1);+ } } static void registryHandleGlobalRemove(void *data,@@ -532,7 +436,131 @@ registryHandleGlobalRemove }; +// Create key code translation tables+//+static void createKeyTables(void)+{+ memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys)); + _glfw.wl.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;+ _glfw.wl.publicKeys[KEY_1] = GLFW_KEY_1;+ _glfw.wl.publicKeys[KEY_2] = GLFW_KEY_2;+ _glfw.wl.publicKeys[KEY_3] = GLFW_KEY_3;+ _glfw.wl.publicKeys[KEY_4] = GLFW_KEY_4;+ _glfw.wl.publicKeys[KEY_5] = GLFW_KEY_5;+ _glfw.wl.publicKeys[KEY_6] = GLFW_KEY_6;+ _glfw.wl.publicKeys[KEY_7] = GLFW_KEY_7;+ _glfw.wl.publicKeys[KEY_8] = GLFW_KEY_8;+ _glfw.wl.publicKeys[KEY_9] = GLFW_KEY_9;+ _glfw.wl.publicKeys[KEY_0] = GLFW_KEY_0;+ _glfw.wl.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;+ _glfw.wl.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;+ _glfw.wl.publicKeys[KEY_Q] = GLFW_KEY_Q;+ _glfw.wl.publicKeys[KEY_W] = GLFW_KEY_W;+ _glfw.wl.publicKeys[KEY_E] = GLFW_KEY_E;+ _glfw.wl.publicKeys[KEY_R] = GLFW_KEY_R;+ _glfw.wl.publicKeys[KEY_T] = GLFW_KEY_T;+ _glfw.wl.publicKeys[KEY_Y] = GLFW_KEY_Y;+ _glfw.wl.publicKeys[KEY_U] = GLFW_KEY_U;+ _glfw.wl.publicKeys[KEY_I] = GLFW_KEY_I;+ _glfw.wl.publicKeys[KEY_O] = GLFW_KEY_O;+ _glfw.wl.publicKeys[KEY_P] = GLFW_KEY_P;+ _glfw.wl.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;+ _glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;+ _glfw.wl.publicKeys[KEY_A] = GLFW_KEY_A;+ _glfw.wl.publicKeys[KEY_S] = GLFW_KEY_S;+ _glfw.wl.publicKeys[KEY_D] = GLFW_KEY_D;+ _glfw.wl.publicKeys[KEY_F] = GLFW_KEY_F;+ _glfw.wl.publicKeys[KEY_G] = GLFW_KEY_G;+ _glfw.wl.publicKeys[KEY_H] = GLFW_KEY_H;+ _glfw.wl.publicKeys[KEY_J] = GLFW_KEY_J;+ _glfw.wl.publicKeys[KEY_K] = GLFW_KEY_K;+ _glfw.wl.publicKeys[KEY_L] = GLFW_KEY_L;+ _glfw.wl.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;+ _glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;+ _glfw.wl.publicKeys[KEY_Z] = GLFW_KEY_Z;+ _glfw.wl.publicKeys[KEY_X] = GLFW_KEY_X;+ _glfw.wl.publicKeys[KEY_C] = GLFW_KEY_C;+ _glfw.wl.publicKeys[KEY_V] = GLFW_KEY_V;+ _glfw.wl.publicKeys[KEY_B] = GLFW_KEY_B;+ _glfw.wl.publicKeys[KEY_N] = GLFW_KEY_N;+ _glfw.wl.publicKeys[KEY_M] = GLFW_KEY_M;+ _glfw.wl.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;+ _glfw.wl.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;+ _glfw.wl.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;+ _glfw.wl.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;+ _glfw.wl.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;+ _glfw.wl.publicKeys[KEY_TAB] = GLFW_KEY_TAB;+ _glfw.wl.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;+ _glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;+ _glfw.wl.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;+ _glfw.wl.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;+ _glfw.wl.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;+ _glfw.wl.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;+ _glfw.wl.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;+ _glfw.wl.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;+ _glfw.wl.publicKeys[KEY_MENU] = GLFW_KEY_MENU;+ _glfw.wl.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;+ _glfw.wl.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;+ _glfw.wl.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;+ _glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;+ _glfw.wl.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;+ _glfw.wl.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;+ _glfw.wl.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;+ _glfw.wl.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;+ _glfw.wl.publicKeys[KEY_HOME] = GLFW_KEY_HOME;+ _glfw.wl.publicKeys[KEY_END] = GLFW_KEY_END;+ _glfw.wl.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;+ _glfw.wl.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;+ _glfw.wl.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;+ _glfw.wl.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;+ _glfw.wl.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;+ _glfw.wl.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;+ _glfw.wl.publicKeys[KEY_UP] = GLFW_KEY_UP;+ _glfw.wl.publicKeys[KEY_F1] = GLFW_KEY_F1;+ _glfw.wl.publicKeys[KEY_F2] = GLFW_KEY_F2;+ _glfw.wl.publicKeys[KEY_F3] = GLFW_KEY_F3;+ _glfw.wl.publicKeys[KEY_F4] = GLFW_KEY_F4;+ _glfw.wl.publicKeys[KEY_F5] = GLFW_KEY_F5;+ _glfw.wl.publicKeys[KEY_F6] = GLFW_KEY_F6;+ _glfw.wl.publicKeys[KEY_F7] = GLFW_KEY_F7;+ _glfw.wl.publicKeys[KEY_F8] = GLFW_KEY_F8;+ _glfw.wl.publicKeys[KEY_F9] = GLFW_KEY_F9;+ _glfw.wl.publicKeys[KEY_F10] = GLFW_KEY_F10;+ _glfw.wl.publicKeys[KEY_F11] = GLFW_KEY_F11;+ _glfw.wl.publicKeys[KEY_F12] = GLFW_KEY_F12;+ _glfw.wl.publicKeys[KEY_F13] = GLFW_KEY_F13;+ _glfw.wl.publicKeys[KEY_F14] = GLFW_KEY_F14;+ _glfw.wl.publicKeys[KEY_F15] = GLFW_KEY_F15;+ _glfw.wl.publicKeys[KEY_F16] = GLFW_KEY_F16;+ _glfw.wl.publicKeys[KEY_F17] = GLFW_KEY_F17;+ _glfw.wl.publicKeys[KEY_F18] = GLFW_KEY_F18;+ _glfw.wl.publicKeys[KEY_F19] = GLFW_KEY_F19;+ _glfw.wl.publicKeys[KEY_F20] = GLFW_KEY_F20;+ _glfw.wl.publicKeys[KEY_F21] = GLFW_KEY_F21;+ _glfw.wl.publicKeys[KEY_F22] = GLFW_KEY_F22;+ _glfw.wl.publicKeys[KEY_F23] = GLFW_KEY_F23;+ _glfw.wl.publicKeys[KEY_F24] = GLFW_KEY_F24;+ _glfw.wl.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;+ _glfw.wl.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;+ _glfw.wl.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;+ _glfw.wl.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;+ _glfw.wl.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;+ _glfw.wl.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;+ _glfw.wl.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;+ _glfw.wl.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;+ _glfw.wl.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;+ _glfw.wl.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;+ _glfw.wl.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;+ _glfw.wl.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;+ _glfw.wl.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;+ _glfw.wl.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;+ _glfw.wl.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;+ _glfw.wl.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;+ _glfw.wl.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;+}++ ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////@@ -544,7 +572,7 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to connect to display");- return GL_FALSE;+ return GLFW_FALSE; } _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);@@ -553,12 +581,14 @@ _glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*)); _glfw.wl.monitorsSize = 4; + createKeyTables();+ _glfw.wl.xkb.context = xkb_context_new(0); if (!_glfw.wl.xkb.context) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to initialize xkb context");- return GL_FALSE;+ return GLFW_FALSE; } // Sync so we got all registry objects@@ -567,12 +597,14 @@ // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); - if (!_glfwInitContextAPI())- return GL_FALSE;+ if (!_glfwInitThreadLocalStoragePOSIX())+ return GLFW_FALSE; - _glfwInitTimer();- _glfwInitJoysticks();+ if (!_glfwInitJoysticksLinux())+ return GLFW_FALSE; + _glfwInitTimerPOSIX();+ if (_glfw.wl.pointer && _glfw.wl.shm) { _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);@@ -580,27 +612,20 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Unable to load default cursor theme\n");- return GL_FALSE;- }- _glfw.wl.defaultCursor =- wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme, "left_ptr");- if (!_glfw.wl.defaultCursor)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "Wayland: Unable to load default left pointer\n");- return GL_FALSE;+ return GLFW_FALSE; } _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); } - return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformTerminate(void) {- _glfwTerminateContextAPI();- _glfwTerminateJoysticks();+ _glfwTerminateEGL();+ _glfwTerminateJoysticksLinux();+ _glfwTerminateThreadLocalStoragePOSIX(); if (_glfw.wl.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme);@@ -616,15 +641,18 @@ const char* _glfwPlatformGetVersionString(void) {- const char* version = _GLFW_VERSION_NUMBER " Wayland EGL "+ return _GLFW_VERSION_NUMBER " Wayland EGL" #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) " clock_gettime"+#else+ " gettimeofday" #endif+#if defined(__linux__)+ " /dev/js"+#endif #if defined(_GLFW_BUILD_DLL) " shared" #endif ;-- return version; }
glfw/src/wl_monitor.c view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Wayland - www.glfw.org+// GLFW 3.2 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -69,7 +69,7 @@ mode.base.width = width; mode.base.height = height;- mode.base.refreshRate = refresh;+ mode.base.refreshRate = refresh / 1000; mode.flags = flags; if (monitor->wl.modesCount + 1 >= monitor->wl.modesSize)@@ -90,13 +90,16 @@ { struct _GLFWmonitor *monitor = data; - monitor->wl.done = GL_TRUE;+ monitor->wl.done = GLFW_TRUE; } static void scale(void* data, struct wl_output* output, int32_t factor) {+ struct _GLFWmonitor *monitor = data;++ monitor->wl.scale = factor; } static const struct wl_output_listener output_listener = {@@ -111,13 +114,13 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwAddOutput(uint32_t name, uint32_t version)+void _glfwAddOutputWayland(uint32_t name, uint32_t version) { _GLFWmonitor *monitor; struct wl_output *output; char name_str[80]; - memset(name_str, 0, 80 * sizeof(char));+ memset(name_str, 0, sizeof(name_str)); snprintf(name_str, 79, "wl_output@%u", name); if (version < 2)@@ -142,6 +145,8 @@ monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland)); monitor->wl.modesSize = 4; + monitor->wl.scale = 1;+ monitor->wl.output = output; wl_output_add_listener(output, &output_listener, monitor); @@ -195,7 +200,7 @@ return NULL; } -GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) { return first->wl.output == second->wl.output; }@@ -239,12 +244,26 @@ void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) { // TODO- fprintf(stderr, "_glfwPlatformGetGammaRamp not implemented yet\n");+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Gamma ramp getting not supported yet"); } void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) { // TODO- fprintf(stderr, "_glfwPlatformSetGammaRamp not implemented yet\n");+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Gamma ramp setting not supported yet");+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW native API //////+//////////////////////////////////////////////////////////////////////////++GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)+{+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return monitor->wl.output; }
glfw/src/wl_platform.h view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Wayland - www.glfw.org+// GLFW 3.2 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -24,51 +24,86 @@ // //======================================================================== -#ifndef _wayland_platform_h_-#define _wayland_platform_h_-+#ifndef _glfw3_wayland_platform_h_+#define _glfw3_wayland_platform_h_ #include <wayland-client.h> #include <xkbcommon/xkbcommon.h>+#include <dlfcn.h> -#if defined(_GLFW_EGL)- #include "egl_context.h"-#else- #error "The Wayland backend depends on EGL platform support"-#endif+typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; +typedef struct VkWaylandSurfaceCreateInfoKHR+{+ VkStructureType sType;+ const void* pNext;+ VkWaylandSurfaceCreateFlagsKHR flags;+ struct wl_display* display;+ struct wl_surface* surface;+} VkWaylandSurfaceCreateInfoKHR;++typedef VkResult (APIENTRY *PFN_vkCreateWaylandSurfaceKHR)(VkInstance,const VkWaylandSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)(VkPhysicalDevice,uint32_t,struct wl_display*);+ #include "posix_tls.h" #include "posix_time.h" #include "linux_joystick.h"+#include "xkb_unicode.h"+#include "egl_context.h" -#define _GLFW_EGL_NATIVE_WINDOW window->wl.native-#define _GLFW_EGL_NATIVE_DISPLAY _glfw.wl.display+#include "wayland-relative-pointer-unstable-v1-client-protocol.h"+#include "wayland-pointer-constraints-unstable-v1-client-protocol.h" +#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)+#define _glfw_dlclose(handle) dlclose(handle)+#define _glfw_dlsym(handle, name) dlsym(handle, name)++#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->wl.native)+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)+ #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl +#define _GLFW_PLATFORM_CONTEXT_STATE+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE + // Wayland-specific video mode data // typedef struct _GLFWvidmodeWayland _GLFWvidmodeWayland; - // Wayland-specific per-window data // typedef struct _GLFWwindowWayland { int width, height;- GLboolean visible;+ GLFWbool visible;+ GLFWbool maximized; struct wl_surface* surface; struct wl_egl_window* native; struct wl_shell_surface* shell_surface; struct wl_callback* callback;+ _GLFWcursor* currentCursor;-} _GLFWwindowWayland;+ double cursorPosX, cursorPosY; + char* title; + // We need to track the monitors the window spans on to calculate the+ // optimal scaling factor.+ int scale;+ _GLFWmonitor** monitors;+ int monitorsCount;+ int monitorsSize;++ struct {+ struct zwp_relative_pointer_v1* relativePointer;+ struct zwp_locked_pointer_v1* lockedPointer;+ } pointerLock;+} _GLFWwindowWayland;+ // Wayland-specific global data // typedef struct _GLFWlibraryWayland@@ -81,9 +116,12 @@ struct wl_seat* seat; struct wl_pointer* pointer; struct wl_keyboard* keyboard;+ struct zwp_relative_pointer_manager_v1* relativePointerManager;+ struct zwp_pointer_constraints_v1* pointerConstraints; + int wl_compositor_version;+ struct wl_cursor_theme* cursorTheme;- struct wl_cursor* defaultCursor; struct wl_surface* cursorSurface; uint32_t pointerSerial; @@ -91,6 +129,8 @@ int monitorsCount; int monitorsSize; + short int publicKeys[256];+ struct { struct xkb_context* context; struct xkb_keymap* keymap;@@ -107,7 +147,6 @@ } _GLFWlibraryWayland; - // Wayland-specific per-monitor data // typedef struct _GLFWmonitorWayland@@ -117,24 +156,24 @@ _GLFWvidmodeWayland* modes; int modesCount; int modesSize;- GLboolean done;+ GLFWbool done; int x; int y;-+ int scale; } _GLFWmonitorWayland; - // Wayland-specific per-cursor data // typedef struct _GLFWcursorWayland {+ struct wl_cursor_image* image; struct wl_buffer* buffer; int width, height; int xhot, yhot; } _GLFWcursorWayland; -void _glfwAddOutput(uint32_t name, uint32_t version);+void _glfwAddOutputWayland(uint32_t name, uint32_t version); -#endif // _wayland_platform_h_+#endif // _glfw3_wayland_platform_h_
glfw/src/wl_window.c view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Wayland - www.glfw.org+// GLFW 3.2 Wayland - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -55,7 +55,32 @@ int32_t height) { _GLFWwindow* window = data;- _glfwInputFramebufferSize(window, width, height);+ float aspectRatio;+ float targetRatio;++ if (!window->monitor)+ {+ if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)+ {+ aspectRatio = (float)width / (float)height;+ targetRatio = (float)window->numer / (float)window->denom;+ if (aspectRatio < targetRatio)+ height = width / targetRatio;+ else if (aspectRatio > targetRatio)+ width = height * targetRatio;+ }++ if (window->minwidth != GLFW_DONT_CARE && width < window->minwidth)+ width = window->minwidth;+ else if (window->maxwidth != GLFW_DONT_CARE && width > window->maxwidth)+ width = window->maxwidth;++ if (window->minheight != GLFW_DONT_CARE && height < window->minheight)+ height = window->minheight;+ else if (window->maxheight != GLFW_DONT_CARE && height > window->maxheight)+ height = window->maxheight;+ }+ _glfwInputWindowSize(window, width, height); _glfwPlatformSetWindowSize(window, width, height); _glfwInputWindowDamage(window);@@ -72,34 +97,159 @@ handlePopupDone }; -static GLboolean createSurface(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig)+static void checkScaleChange(_GLFWwindow* window) {+ int scaledWidth, scaledHeight;+ int scale = 1;+ int i;+ int monitorScale;++ // Check if we will be able to set the buffer scale or not.+ if (_glfw.wl.wl_compositor_version < 3)+ return;++ // Get the scale factor from the highest scale monitor.+ for (i = 0; i < window->wl.monitorsCount; ++i)+ {+ monitorScale = window->wl.monitors[i]->wl.scale;+ if (scale < monitorScale)+ scale = monitorScale;+ }++ // Only change the framebuffer size if the scale changed.+ if (scale != window->wl.scale)+ {+ window->wl.scale = scale;+ scaledWidth = window->wl.width * scale;+ scaledHeight = window->wl.height * scale;+ wl_surface_set_buffer_scale(window->wl.surface, scale);+ wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);+ _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);+ }+}++static void handleEnter(void *data,+ struct wl_surface *surface,+ struct wl_output *output)+{+ _GLFWwindow* window = data;+ _GLFWmonitor* monitor = wl_output_get_user_data(output);++ if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)+ {+ ++window->wl.monitorsSize;+ window->wl.monitors =+ realloc(window->wl.monitors,+ window->wl.monitorsSize * sizeof(_GLFWmonitor*));+ }++ window->wl.monitors[window->wl.monitorsCount++] = monitor;++ checkScaleChange(window);+}++static void handleLeave(void *data,+ struct wl_surface *surface,+ struct wl_output *output)+{+ _GLFWwindow* window = data;+ _GLFWmonitor* monitor = wl_output_get_user_data(output);+ GLFWbool found;+ int i;++ for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)+ {+ if (monitor == window->wl.monitors[i])+ found = GLFW_TRUE;+ if (found)+ window->wl.monitors[i] = window->wl.monitors[i + 1];+ }+ window->wl.monitors[--window->wl.monitorsCount] = NULL;++ checkScaleChange(window);+}++static const struct wl_surface_listener surfaceListener = {+ handleEnter,+ handleLeave+};++// Makes the surface considered as XRGB instead of ARGB.+static void setOpaqueRegion(_GLFWwindow* window)+{+ struct wl_region* region;++ region = wl_compositor_create_region(_glfw.wl.compositor);+ if (!region)+ return;++ wl_region_add(region, 0, 0, window->wl.width, window->wl.height);+ wl_surface_set_opaque_region(window->wl.surface, region);+ wl_surface_commit(window->wl.surface);+ wl_region_destroy(region);+}++static GLFWbool createSurface(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig)+{ window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); if (!window->wl.surface)- return GL_FALSE;+ return GLFW_FALSE; + wl_surface_add_listener(window->wl.surface,+ &surfaceListener,+ window);+ wl_surface_set_user_data(window->wl.surface, window); window->wl.native = wl_egl_window_create(window->wl.surface, wndconfig->width, wndconfig->height); if (!window->wl.native)- return GL_FALSE;+ return GLFW_FALSE; + window->wl.width = wndconfig->width;+ window->wl.height = wndconfig->height;+ window->wl.scale = 1;++ // TODO: make this optional once issue #197 is fixed.+ setOpaqueRegion(window);++ return GLFW_TRUE;+}++static GLFWbool createShellSurface(_GLFWwindow* window)+{ window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell, window->wl.surface); if (!window->wl.shell_surface)- return GL_FALSE;+ return GLFW_FALSE; wl_shell_surface_add_listener(window->wl.shell_surface, &shellSurfaceListener, window); - window->wl.width = wndconfig->width;- window->wl.height = wndconfig->height;+ if (window->wl.title)+ wl_shell_surface_set_title(window->wl.shell_surface, window->wl.title); - return GL_TRUE;+ if (window->monitor)+ {+ wl_shell_surface_set_fullscreen(+ window->wl.shell_surface,+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,+ 0,+ window->monitor->wl.output);+ }+ else if (window->wl.maximized)+ {+ wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);+ }+ else+ {+ wl_shell_surface_set_toplevel(window->wl.shell_surface);+ }++ return GLFW_TRUE; } static int@@ -114,6 +264,43 @@ return fd; } +static void+handleEvents(int timeout)+{+ struct wl_display* display = _glfw.wl.display;+ struct pollfd fds[] = {+ { wl_display_get_fd(display), POLLIN },+ };++ while (wl_display_prepare_read(display) != 0)+ wl_display_dispatch_pending(display);++ // If an error different from EAGAIN happens, we have likely been+ // disconnected from the Wayland session, try to handle that the best we+ // can.+ if (wl_display_flush(display) < 0 && errno != EAGAIN)+ {+ _GLFWwindow* window = _glfw.windowListHead;+ while (window)+ {+ _glfwInputWindowCloseRequest(window);+ window = window->next;+ }+ wl_display_cancel_read(display);+ return;+ }++ if (poll(fds, 1, timeout) > 0)+ {+ wl_display_read_events(display);+ wl_display_dispatch_pending(display);+ }+ else+ {+ wl_display_cancel_read(display);+ }+}+ /* * Create a new, unique, anonymous file of the given size, and * return the file descriptor for it. The file descriptor is set@@ -150,7 +337,7 @@ return -1; } - name = malloc(strlen(path) + sizeof(template));+ name = calloc(strlen(path) + sizeof(template), 1); strcpy(name, path); strcat(name, template); @@ -170,6 +357,28 @@ return fd; } +// Translates a GLFW standard cursor to a theme cursor name+//+static char *translateCursorShape(int shape)+{+ switch (shape)+ {+ case GLFW_ARROW_CURSOR:+ return "left_ptr";+ case GLFW_IBEAM_CURSOR:+ return "xterm";+ case GLFW_CROSSHAIR_CURSOR:+ return "crosshair";+ case GLFW_HAND_CURSOR:+ return "grabbing";+ case GLFW_HRESIZE_CURSOR:+ return "sb_h_double_arrow";+ case GLFW_VRESIZE_CURSOR:+ return "sb_v_double_arrow";+ }+ return NULL;+}+ ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// //////////////////////////////////////////////////////////////////////////@@ -179,28 +388,40 @@ const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) {- if (!_glfwCreateContext(window, ctxconfig, fbconfig))- return GL_FALSE;- if (!createSurface(window, wndconfig))- return GL_FALSE;+ return GLFW_FALSE; - if (wndconfig->monitor)+ if (ctxconfig->client != GLFW_NO_API) {- wl_shell_surface_set_fullscreen(- window->wl.shell_surface,- WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,- 0,- wndconfig->monitor->wl.output);+ if (!_glfwInitEGL())+ return GLFW_FALSE;+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE; }++ if (wndconfig->title)+ window->wl.title = strdup(wndconfig->title);++ if (wndconfig->visible)+ {+ if (!createShellSurface(window))+ return GLFW_FALSE;++ window->wl.visible = GLFW_TRUE;+ } else {- wl_shell_surface_set_toplevel(window->wl.shell_surface);+ window->wl.shell_surface = NULL;+ window->wl.visible = GLFW_FALSE; } window->wl.currentCursor = NULL; - return GL_TRUE;+ window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));+ window->wl.monitorsCount = 0;+ window->wl.monitorsSize = 1;++ return GLFW_TRUE; } void _glfwPlatformDestroyWindow(_GLFWwindow* window)@@ -208,15 +429,16 @@ if (window == _glfw.wl.pointerFocus) { _glfw.wl.pointerFocus = NULL;- _glfwInputCursorEnter(window, GL_FALSE);+ _glfwInputCursorEnter(window, GLFW_FALSE); } if (window == _glfw.wl.keyboardFocus) { _glfw.wl.keyboardFocus = NULL;- _glfwInputWindowFocus(window, GL_FALSE);+ _glfwInputWindowFocus(window, GLFW_FALSE); } - _glfwDestroyContext(window);+ if (window->context.destroy)+ window->context.destroy(window); if (window->wl.native) wl_egl_window_destroy(window->wl.native);@@ -226,13 +448,27 @@ if (window->wl.surface) wl_surface_destroy(window->wl.surface);++ free(window->wl.title);+ free(window->wl.monitors); } void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) {- wl_shell_surface_set_title(window->wl.shell_surface, title);+ if (window->wl.title)+ free(window->wl.title);+ window->wl.title = strdup(title);+ if (window->wl.shell_surface)+ wl_shell_surface_set_title(window->wl.shell_surface, title); } +void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+ int count, const GLFWimage* images)+{+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Setting window icon not supported");+}+ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) { // A Wayland client is not aware of its position, so just warn and leave it@@ -260,111 +496,157 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height) {- wl_egl_window_resize(window->wl.native, width, height, 0, 0);+ int scaledWidth = width * window->wl.scale;+ int scaledHeight = height * window->wl.scale; window->wl.width = width; window->wl.height = height;+ wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);+ setOpaqueRegion(window);+ _glfwInputFramebufferSize(window, scaledWidth, scaledHeight); } +void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ // TODO: find out how to trigger a resize.+ // The actual limits are checked in the wl_shell_surface::configure handler.+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)+{+ // TODO: find out how to trigger a resize.+ // The actual limits are checked in the wl_shell_surface::configure handler.+}+ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) { _glfwPlatformGetWindowSize(window, width, height);+ *width *= window->wl.scale;+ *height *= window->wl.scale; } void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom) {- // TODO- fprintf(stderr, "_glfwPlatformGetWindowFrameSize not implemented yet\n");+ // TODO: will need a proper implementation once decorations are+ // implemented, but for now just leave everything as 0. } void _glfwPlatformIconifyWindow(_GLFWwindow* window) {- // TODO- fprintf(stderr, "_glfwPlatformIconifyWindow not implemented yet\n");+ // TODO: move to xdg_shell instead of wl_shell.+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Iconify window not supported"); } void _glfwPlatformRestoreWindow(_GLFWwindow* window) {- // TODO- fprintf(stderr, "_glfwPlatformRestoreWindow not implemented yet\n");+ // TODO: also do the same for iconified.+ if (window->monitor || window->wl.maximized)+ {+ if (window->wl.shell_surface)+ wl_shell_surface_set_toplevel(window->wl.shell_surface);++ window->wl.maximized = GLFW_FALSE;+ } } -void _glfwPlatformShowWindow(_GLFWwindow* window)+void _glfwPlatformMaximizeWindow(_GLFWwindow* window) {- wl_shell_surface_set_toplevel(window->wl.shell_surface);+ if (!window->monitor && !window->wl.maximized)+ {+ if (window->wl.shell_surface)+ {+ // Let the compositor select the best output.+ wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);+ }+ window->wl.maximized = GLFW_TRUE;+ } } -void _glfwPlatformUnhideWindow(_GLFWwindow* window)+void _glfwPlatformShowWindow(_GLFWwindow* window) {- // TODO- fprintf(stderr, "_glfwPlatformUnhideWindow not implemented yet\n");+ if (!window->monitor)+ {+ if (!window->wl.shell_surface)+ createShellSurface(window);+ window->wl.visible = GLFW_TRUE;+ } } void _glfwPlatformHideWindow(_GLFWwindow* window) {- wl_surface_attach(window->wl.surface, NULL, 0, 0);- wl_surface_commit(window->wl.surface);+ if (!window->monitor)+ {+ if (window->wl.shell_surface)+ wl_shell_surface_destroy(window->wl.shell_surface);+ window->wl.visible = GLFW_FALSE;+ } } +void _glfwPlatformFocusWindow(_GLFWwindow* window)+{+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Focusing a window requires user interaction");+}++void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+ _GLFWmonitor* monitor,+ int xpos, int ypos,+ int width, int height,+ int refreshRate)+{+ if (monitor)+ {+ wl_shell_surface_set_fullscreen(+ window->wl.shell_surface,+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,+ refreshRate * 1000, // Convert Hz to mHz.+ monitor->wl.output);+ }+ else+ {+ wl_shell_surface_set_toplevel(window->wl.shell_surface);+ }+ _glfwInputWindowMonitorChange(window, monitor);+}+ int _glfwPlatformWindowFocused(_GLFWwindow* window) {- // TODO- return GL_FALSE;+ return _glfw.wl.keyboardFocus == window; } int _glfwPlatformWindowIconified(_GLFWwindow* window) {- // TODO- return GL_FALSE;+ // TODO: move to xdg_shell, wl_shell doesn't have any iconified concept.+ return GLFW_FALSE; } int _glfwPlatformWindowVisible(_GLFWwindow* window) {- // TODO- return GL_FALSE;+ return window->wl.visible; } -void _glfwPlatformPollEvents(void)+int _glfwPlatformWindowMaximized(_GLFWwindow* window) {- struct wl_display* display = _glfw.wl.display;- struct pollfd fds[] = {- { wl_display_get_fd(display), POLLIN },- };+ return window->wl.maximized;+} - while (wl_display_prepare_read(display) != 0)- wl_display_dispatch_pending(display);- wl_display_flush(display);- if (poll(fds, 1, 0) > 0)- {- wl_display_read_events(display);- wl_display_dispatch_pending(display);- }- else- {- wl_display_cancel_read(display);- }+void _glfwPlatformPollEvents(void)+{+ handleEvents(0); } void _glfwPlatformWaitEvents(void) {- struct wl_display* display = _glfw.wl.display;- struct pollfd fds[] = {- { wl_display_get_fd(display), POLLIN },- };+ handleEvents(-1);+} - while (wl_display_prepare_read(display) != 0)- wl_display_dispatch_pending(display);- wl_display_flush(display);- if (poll(fds, 1, -1) > 0)- {- wl_display_read_events(display);- wl_display_dispatch_pending(display);- }- else- {- wl_display_cancel_read(display);- }+void _glfwPlatformWaitEventsTimeout(double timeout)+{+ handleEvents((int) (timeout * 1e3)); } void _glfwPlatformPostEmptyEvent(void)@@ -374,22 +656,36 @@ void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) {- // TODO- fprintf(stderr, "_glfwPlatformGetCursorPos not implemented yet\n");+ if (xpos)+ *xpos = window->wl.cursorPosX;+ if (ypos)+ *ypos = window->wl.cursorPosY; } +static GLFWbool isPointerLocked(_GLFWwindow* window);+ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) {- // A Wayland client can not set the cursor position- _glfwInputError(GLFW_PLATFORM_ERROR,- "Wayland: Cursor position setting not supported");+ if (isPointerLocked(window))+ {+ zwp_locked_pointer_v1_set_cursor_position_hint(+ window->wl.pointerLock.lockedPointer,+ wl_fixed_from_double(x), wl_fixed_from_double(y));+ wl_surface_commit(window->wl.surface);+ } } -void _glfwPlatformApplyCursorMode(_GLFWwindow* window)+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { _glfwPlatformSetCursor(window, window->wl.currentCursor); } +const char* _glfwPlatformGetKeyName(int key, int scancode)+{+ // TODO+ return NULL;+}+ int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot)@@ -404,18 +700,18 @@ if (fd < 0) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Wayland: Creating a buffer file for %d B failed: %m\n",+ "Wayland: Creating a buffer file for %d B failed: %m", length);- return GL_FALSE;+ return GLFW_FALSE; } data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { _glfwInputError(GLFW_PLATFORM_ERROR,- "Wayland: Cursor mmap failed: %m\n");+ "Wayland: Cursor mmap failed: %m"); close(fd);- return GL_FALSE;+ return GLFW_FALSE; } pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);@@ -425,10 +721,12 @@ unsigned char* target = data; for (i = 0; i < image->width * image->height; i++, source += 4) {- *target++ = source[2];- *target++ = source[1];- *target++ = source[0];- *target++ = source[3];+ unsigned int alpha = source[3];++ *target++ = (unsigned char) ((source[2] * alpha) / 255);+ *target++ = (unsigned char) ((source[1] * alpha) / 255);+ *target++ = (unsigned char) ((source[0] * alpha) / 255);+ *target++ = (unsigned char) alpha; } cursor->wl.buffer =@@ -443,24 +741,138 @@ cursor->wl.height = image->height; cursor->wl.xhot = xhot; cursor->wl.yhot = yhot;- return GL_TRUE;+ return GLFW_TRUE; } int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) {- // TODO- fprintf(stderr, "_glfwPlatformCreateStandardCursor not implemented yet\n");- return GL_FALSE;+ struct wl_cursor* standardCursor;++ standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,+ translateCursorShape(shape));+ if (!standardCursor)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Standard cursor \"%s\" not found",+ translateCursorShape(shape));+ return GLFW_FALSE;+ }++ cursor->wl.image = standardCursor->images[0];+ return GLFW_TRUE; } void _glfwPlatformDestroyCursor(_GLFWcursor* cursor) {- wl_buffer_destroy(cursor->wl.buffer);+ // If it's a standard cursor we don't need to do anything here+ if (cursor->wl.image)+ return;++ if (cursor->wl.buffer)+ wl_buffer_destroy(cursor->wl.buffer); } +static void handleRelativeMotion(void* data,+ struct zwp_relative_pointer_v1* pointer,+ uint32_t timeHi,+ uint32_t timeLo,+ wl_fixed_t dx,+ wl_fixed_t dy,+ wl_fixed_t dxUnaccel,+ wl_fixed_t dyUnaccel)+{+ _GLFWwindow* window = data;++ if (window->cursorMode != GLFW_CURSOR_DISABLED)+ return;++ _glfwInputCursorPos(window,+ window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel),+ window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel));+}++static const struct zwp_relative_pointer_v1_listener relativePointerListener = {+ handleRelativeMotion+};++static void handleLocked(void* data,+ struct zwp_locked_pointer_v1* lockedPointer)+{+}++static void unlockPointer(_GLFWwindow* window)+{+ struct zwp_relative_pointer_v1* relativePointer =+ window->wl.pointerLock.relativePointer;+ struct zwp_locked_pointer_v1* lockedPointer =+ window->wl.pointerLock.lockedPointer;++ zwp_relative_pointer_v1_destroy(relativePointer);+ zwp_locked_pointer_v1_destroy(lockedPointer);++ window->wl.pointerLock.relativePointer = NULL;+ window->wl.pointerLock.lockedPointer = NULL;+}++static void lockPointer(_GLFWwindow* window);++static void handleUnlocked(void* data,+ struct zwp_locked_pointer_v1* lockedPointer)+{+}++static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {+ handleLocked,+ handleUnlocked+};++static void lockPointer(_GLFWwindow* window)+{+ struct zwp_relative_pointer_v1* relativePointer;+ struct zwp_locked_pointer_v1* lockedPointer;++ if (!_glfw.wl.relativePointerManager)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: no relative pointer manager");+ return;+ }++ relativePointer =+ zwp_relative_pointer_manager_v1_get_relative_pointer(+ _glfw.wl.relativePointerManager,+ _glfw.wl.pointer);+ zwp_relative_pointer_v1_add_listener(relativePointer,+ &relativePointerListener,+ window);++ lockedPointer =+ zwp_pointer_constraints_v1_lock_pointer(+ _glfw.wl.pointerConstraints,+ window->wl.surface,+ _glfw.wl.pointer,+ NULL,+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);+ zwp_locked_pointer_v1_add_listener(lockedPointer,+ &lockedPointerListener,+ window);++ window->wl.pointerLock.relativePointer = relativePointer;+ window->wl.pointerLock.lockedPointer = lockedPointer;++ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,+ NULL, 0, 0);+}++static GLFWbool isPointerLocked(_GLFWwindow* window)+{+ return window->wl.pointerLock.lockedPointer != NULL;+}+ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) { struct wl_buffer* buffer;+ struct wl_cursor* defaultCursor; struct wl_cursor_image* image; struct wl_surface* surface = _glfw.wl.cursorSurface; @@ -474,11 +886,29 @@ if (window != _glfw.wl.pointerFocus) return; + // Unlock possible pointer lock if no longer disabled.+ if (window->cursorMode != GLFW_CURSOR_DISABLED && isPointerLocked(window))+ unlockPointer(window);+ if (window->cursorMode == GLFW_CURSOR_NORMAL) {- if (cursor == NULL)+ if (cursor)+ image = cursor->wl.image;+ else {- image = _glfw.wl.defaultCursor->images[0];+ defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,+ "left_ptr");+ if (!defaultCursor)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Standard cursor not found");+ return;+ }+ image = defaultCursor->images[0];+ }++ if (image)+ { buffer = wl_cursor_image_get_buffer(image); if (!buffer) return;@@ -503,22 +933,118 @@ wl_surface_commit(surface); } }- else /* Cursor is hidden set cursor surface to NULL */+ else if (window->cursorMode == GLFW_CURSOR_DISABLED) {- wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial, NULL, 0, 0);+ if (!isPointerLocked(window))+ lockPointer(window); }+ else if (window->cursorMode == GLFW_CURSOR_HIDDEN)+ {+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,+ NULL, 0, 0);+ } } void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) { // TODO- fprintf(stderr, "_glfwPlatformSetClipboardString not implemented yet\n");+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Clipboard setting not implemented yet"); } const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) { // TODO- fprintf(stderr, "_glfwPlatformGetClipboardString not implemented yet\n");+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Clipboard getting not implemented yet"); return NULL;+}++char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)+{+ char** extensions;++ *count = 0;++ if (!_glfw.vk.KHR_wayland_surface)+ return NULL;++ extensions = calloc(2, sizeof(char*));+ extensions[0] = strdup("VK_KHR_surface");+ extensions[1] = strdup("VK_KHR_wayland_surface");++ *count = 2;+ return extensions;+}++int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =+ (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");+ if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");+ return VK_NULL_HANDLE;+ }++ return vkGetPhysicalDeviceWaylandPresentationSupportKHR(device,+ queuefamily,+ _glfw.wl.display);+}++VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,+ _GLFWwindow* window,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ VkResult err;+ VkWaylandSurfaceCreateInfoKHR sci;+ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;++ vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)+ vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR");+ if (!vkCreateWaylandSurfaceKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ memset(&sci, 0, sizeof(sci));+ sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;+ sci.display = _glfw.wl.display;+ sci.surface = window->wl.surface;++ err = vkCreateWaylandSurfaceKHR(instance, &sci, allocator, surface);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "Wayland: Failed to create Vulkan surface: %s",+ _glfwGetVulkanResultString(err));+ }++ return err;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW native API //////+//////////////////////////////////////////////////////////////////////////++GLFWAPI struct wl_display* glfwGetWaylandDisplay(void)+{+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return _glfw.wl.display;+}++GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)+{+ _GLFWwindow* window = (_GLFWwindow*) handle;+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);+ return window->wl.surface; }
glfw/src/x11_init.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 X11 - www.glfw.org+// GLFW 3.2 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -38,7 +38,7 @@ // Translate an X11 key code to a GLFW key code. //-static int translateKey(int scancode)+static int translateKeyCode(int scancode) { int keySym; @@ -72,9 +72,8 @@ default: break; } - // Now try primary keysym for function keys (non-printable keys). These- // should not be layout dependent (i.e. US layout and international- // layouts should give the same result).+ // Now try primary keysym for function keys (non-printable keys)+ // These should not depend on the current keyboard layout keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0); } else@@ -234,6 +233,7 @@ int scancode, key; memset(_glfw.x11.publicKeys, -1, sizeof(_glfw.x11.publicKeys));+ memset(_glfw.x11.nativeKeys, -1, sizeof(_glfw.x11.nativeKeys)); if (_glfw.x11.xkb.available) {@@ -241,15 +241,14 @@ // keyboard layout char name[XkbKeyNameLength + 1];- XkbDescPtr descr = XkbGetKeyboard(_glfw.x11.display,- XkbAllComponentsMask,- XkbUseCoreKbd);+ XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd);+ XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc); // Find the X11 key code -> GLFW key code mapping- for (scancode = descr->min_key_code; scancode <= descr->max_key_code; scancode++)+ for (scancode = desc->min_key_code; scancode <= desc->max_key_code; scancode++) {- memcpy(name, descr->names->keys[scancode].name, XkbKeyNameLength);- name[XkbKeyNameLength] = 0;+ memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);+ name[XkbKeyNameLength] = '\0'; // Map the key name to a GLFW key code. Note: We only map printable // keys here, and we use the US keyboard layout. The rest of the@@ -309,34 +308,39 @@ _glfw.x11.publicKeys[scancode] = key; } - XkbFreeKeyboard(descr, 0, True);+ XkbFreeNames(desc, XkbKeyNamesMask, True);+ XkbFreeKeyboard(desc, 0, True); } - // Translate the un-translated key codes using traditional X11 KeySym- // lookups for (scancode = 0; scancode < 256; scancode++) {+ // Translate the un-translated key codes using traditional X11 KeySym+ // lookups if (_glfw.x11.publicKeys[scancode] < 0)- _glfw.x11.publicKeys[scancode] = translateKey(scancode);+ _glfw.x11.publicKeys[scancode] = translateKeyCode(scancode);++ // Store the reverse translation for faster key name lookup+ if (_glfw.x11.publicKeys[scancode] > 0)+ _glfw.x11.nativeKeys[_glfw.x11.publicKeys[scancode]] = scancode; } } // Check whether the IM has a usable style //-static GLboolean hasUsableInputMethodStyle(void)+static GLFWbool hasUsableInputMethodStyle(void) { unsigned int i;- GLboolean found = GL_FALSE;+ GLFWbool found = GLFW_FALSE; XIMStyles* styles = NULL; if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)- return GL_FALSE;+ return GLFW_FALSE; for (i = 0; i < styles->count_styles; i++) { if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing)) {- found = GL_TRUE;+ found = GLFW_TRUE; break; } }@@ -351,16 +355,13 @@ unsigned long atomCount, const char* atomName) {- Atom atom = XInternAtom(_glfw.x11.display, atomName, True);- if (atom != None)- {- unsigned long i;+ unsigned long i;+ const Atom atom = XInternAtom(_glfw.x11.display, atomName, False); - for (i = 0; i < atomCount; i++)- {- if (supportedAtoms[i] == atom)- return atom;- }+ for (i = 0; i < atomCount; i++)+ {+ if (supportedAtoms[i] == atom)+ return atom; } return None;@@ -373,33 +374,31 @@ Window* windowFromRoot = NULL; Window* windowFromChild = NULL; - // First we need a couple of atoms, which should already be there- Atom supportingWmCheck =- XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", True);- Atom wmSupported =- XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", True);- if (supportingWmCheck == None || wmSupported == None)- return;+ // First we need a couple of atoms+ const Atom supportingWmCheck =+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);+ const Atom wmSupported =+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False); // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window- if (_glfwGetWindowProperty(_glfw.x11.root,- supportingWmCheck,- XA_WINDOW,- (unsigned char**) &windowFromRoot) != 1)+ if (_glfwGetWindowPropertyX11(_glfw.x11.root,+ supportingWmCheck,+ XA_WINDOW,+ (unsigned char**) &windowFromRoot) != 1) { if (windowFromRoot) XFree(windowFromRoot); return; } - _glfwGrabXErrorHandler();+ _glfwGrabErrorHandlerX11(); // It should be the ID of a child window (of the root) // Then we look for the same property on the child window- if (_glfwGetWindowProperty(*windowFromRoot,- supportingWmCheck,- XA_WINDOW,- (unsigned char**) &windowFromChild) != 1)+ if (_glfwGetWindowPropertyX11(*windowFromRoot,+ supportingWmCheck,+ XA_WINDOW,+ (unsigned char**) &windowFromChild) != 1) { XFree(windowFromRoot); if (windowFromChild)@@ -407,7 +406,7 @@ return; } - _glfwReleaseXErrorHandler();+ _glfwReleaseErrorHandlerX11(); // It should be the ID of that same child window if (*windowFromRoot != *windowFromChild)@@ -427,10 +426,10 @@ // Now we need to check the _NET_SUPPORTED property of the root window // It should be a list of supported WM protocol and state atoms- atomCount = _glfwGetWindowProperty(_glfw.x11.root,- wmSupported,- XA_ATOM,- (unsigned char**) &supportedAtoms);+ atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,+ wmSupported,+ XA_ATOM,+ (unsigned char**) &supportedAtoms); // See which of the atoms we support that are supported by the WM _glfw.x11.NET_WM_STATE =@@ -439,46 +438,30 @@ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_ABOVE"); _glfw.x11.NET_WM_STATE_FULLSCREEN = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_FULLSCREEN");+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT =+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT");+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ =+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ"); _glfw.x11.NET_WM_FULLSCREEN_MONITORS = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");- _glfw.x11.NET_WM_NAME =- getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_NAME");- _glfw.x11.NET_WM_ICON_NAME =- getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_ICON_NAME");- _glfw.x11.NET_WM_PID =- getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PID");- _glfw.x11.NET_WM_PING =- getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_PING");+ _glfw.x11.NET_WM_WINDOW_TYPE =+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE");+ _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL =+ getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_WINDOW_TYPE_NORMAL"); _glfw.x11.NET_ACTIVE_WINDOW = getSupportedAtom(supportedAtoms, atomCount, "_NET_ACTIVE_WINDOW"); _glfw.x11.NET_FRAME_EXTENTS = getSupportedAtom(supportedAtoms, atomCount, "_NET_FRAME_EXTENTS"); _glfw.x11.NET_REQUEST_FRAME_EXTENTS = getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");- _glfw.x11.NET_WM_BYPASS_COMPOSITOR =- getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_BYPASS_COMPOSITOR"); XFree(supportedAtoms);-- _glfw.x11.hasEWMH = GL_TRUE; } // Initialize X11 display and look for supported X11 extensions //-static GLboolean initExtensions(void)+static GLFWbool initExtensions(void) {- // Find or create window manager atoms- _glfw.x11.WM_PROTOCOLS = XInternAtom(_glfw.x11.display,- "WM_PROTOCOLS",- False);- _glfw.x11.WM_STATE = XInternAtom(_glfw.x11.display, "WM_STATE", False);- _glfw.x11.WM_DELETE_WINDOW = XInternAtom(_glfw.x11.display,- "WM_DELETE_WINDOW",- False);- _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display,- "_MOTIF_WM_HINTS",- False);- #if defined(_GLFW_HAS_XF86VM) // Check for XF86VidMode extension _glfw.x11.vidmode.available =@@ -488,32 +471,29 @@ #endif /*_GLFW_HAS_XF86VM*/ // Check for RandR extension- _glfw.x11.randr.available =- XRRQueryExtension(_glfw.x11.display,+ if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase,- &_glfw.x11.randr.errorBase);-- if (_glfw.x11.randr.available)+ &_glfw.x11.randr.errorBase)) {- XRRScreenResources* sr;-- if (!XRRQueryVersion(_glfw.x11.display,- &_glfw.x11.randr.versionMajor,- &_glfw.x11.randr.versionMinor))+ if (XRRQueryVersion(_glfw.x11.display,+ &_glfw.x11.randr.major,+ &_glfw.x11.randr.minor)) {- _glfwInputError(GLFW_PLATFORM_ERROR,- "X11: Failed to query RandR version");- return GL_FALSE;+ // The GLFW RandR path requires at least version 1.3+ if (_glfw.x11.randr.major > 1 || _glfw.x11.randr.minor >= 3)+ _glfw.x11.randr.available = GLFW_TRUE; }-- // The GLFW RandR path requires at least version 1.3- if (_glfw.x11.randr.versionMajor == 1 &&- _glfw.x11.randr.versionMinor < 3)+ else {- _glfw.x11.randr.available = GL_FALSE;+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to query RandR version"); }+ } - sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);+ if (_glfw.x11.randr.available)+ {+ XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display,+ _glfw.x11.root); if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0])) {@@ -523,49 +503,33 @@ // available _glfwInputError(GLFW_PLATFORM_ERROR, "X11: RandR gamma ramp support seems broken");- _glfw.x11.randr.gammaBroken = GL_TRUE;+ _glfw.x11.randr.gammaBroken = GLFW_TRUE; } XRRFreeScreenResources(sr);++ XRRSelectInput(_glfw.x11.display, _glfw.x11.root,+ RROutputChangeNotifyMask); } if (XineramaQueryExtension(_glfw.x11.display,- &_glfw.x11.xinerama.versionMajor,- &_glfw.x11.xinerama.versionMinor))+ &_glfw.x11.xinerama.major,+ &_glfw.x11.xinerama.minor)) { if (XineramaIsActive(_glfw.x11.display))- _glfw.x11.xinerama.available = GL_TRUE;+ _glfw.x11.xinerama.available = GLFW_TRUE; } -#if defined(_GLFW_HAS_XINPUT)- if (XQueryExtension(_glfw.x11.display,- "XInputExtension",- &_glfw.x11.xi.majorOpcode,- &_glfw.x11.xi.eventBase,- &_glfw.x11.xi.errorBase))- {- _glfw.x11.xi.versionMajor = 2;- _glfw.x11.xi.versionMinor = 0;-- if (XIQueryVersion(_glfw.x11.display,- &_glfw.x11.xi.versionMajor,- &_glfw.x11.xi.versionMinor) != BadRequest)- {- _glfw.x11.xi.available = GL_TRUE;- }- }-#endif /*_GLFW_HAS_XINPUT*/- // Check if Xkb is supported on this display- _glfw.x11.xkb.versionMajor = 1;- _glfw.x11.xkb.versionMinor = 0;+ _glfw.x11.xkb.major = 1;+ _glfw.x11.xkb.minor = 0; _glfw.x11.xkb.available = XkbQueryExtension(_glfw.x11.display, &_glfw.x11.xkb.majorOpcode, &_glfw.x11.xkb.eventBase, &_glfw.x11.xkb.errorBase,- &_glfw.x11.xkb.versionMajor,- &_glfw.x11.xkb.versionMinor);+ &_glfw.x11.xkb.major,+ &_glfw.x11.xkb.minor); if (_glfw.x11.xkb.available) {@@ -574,10 +538,17 @@ if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported)) { if (supported)- _glfw.x11.xkb.detectable = GL_TRUE;+ _glfw.x11.xkb.detectable = GLFW_TRUE; } } + _glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so", RTLD_LAZY | RTLD_GLOBAL);+ if (_glfw.x11.x11xcb.handle)+ {+ _glfw.x11.x11xcb.XGetXCBConnection = (XGETXCBCONNECTION_T)+ dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");+ }+ // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping.@@ -586,7 +557,7 @@ // Detect whether an EWMH-conformant window manager is running detectEWMH(); - // Find or create string format atoms+ // String format atoms _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);@@ -594,45 +565,69 @@ XInternAtom(_glfw.x11.display, "COMPOUND_STRING", False); _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False); - // Find or create selection property atom+ // Custom selection property atom _glfw.x11.GLFW_SELECTION = XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False); - // Find or create standard clipboard atoms+ // ICCCM standard clipboard atoms _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False); _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False); _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False); - // Find or create clipboard manager atoms+ // Clipboard manager atoms _glfw.x11.CLIPBOARD_MANAGER = XInternAtom(_glfw.x11.display, "CLIPBOARD_MANAGER", False); _glfw.x11.SAVE_TARGETS = XInternAtom(_glfw.x11.display, "SAVE_TARGETS", False); - // Find Xdnd (drag and drop) atoms, if available- _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", True);- _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", True);- _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", True);- _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", True);- _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", True);- _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", True);- _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", True);- _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", True);- _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", True);+ // Xdnd (drag and drop) atoms+ _glfw.x11.XdndAware = XInternAtom(_glfw.x11.display, "XdndAware", False);+ _glfw.x11.XdndEnter = XInternAtom(_glfw.x11.display, "XdndEnter", False);+ _glfw.x11.XdndPosition = XInternAtom(_glfw.x11.display, "XdndPosition", False);+ _glfw.x11.XdndStatus = XInternAtom(_glfw.x11.display, "XdndStatus", False);+ _glfw.x11.XdndActionCopy = XInternAtom(_glfw.x11.display, "XdndActionCopy", False);+ _glfw.x11.XdndDrop = XInternAtom(_glfw.x11.display, "XdndDrop", False);+ _glfw.x11.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);+ _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);+ _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False); - return GL_TRUE;+ // ICCCM, EWMH and Motif window property atoms+ // These can be set safely even without WM support+ // The EWMH atoms that require WM support are handled in detectEWMH+ _glfw.x11.WM_PROTOCOLS =+ XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False);+ _glfw.x11.WM_STATE =+ XInternAtom(_glfw.x11.display, "WM_STATE", False);+ _glfw.x11.WM_DELETE_WINDOW =+ XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);+ _glfw.x11.NET_WM_ICON =+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);+ _glfw.x11.NET_WM_PING =+ XInternAtom(_glfw.x11.display, "_NET_WM_PING", False);+ _glfw.x11.NET_WM_PID =+ XInternAtom(_glfw.x11.display, "_NET_WM_PID", False);+ _glfw.x11.NET_WM_NAME =+ XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False);+ _glfw.x11.NET_WM_ICON_NAME =+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR =+ XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);+ _glfw.x11.MOTIF_WM_HINTS =+ XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);++ return GLFW_TRUE; } // Create a blank cursor for hidden and disabled cursor modes //-static Cursor createNULLCursor(void)+static Cursor createHiddenCursor(void) { unsigned char pixels[16 * 16 * 4]; GLFWimage image = { 16, 16, pixels }; memset(pixels, 0, sizeof(pixels)); - return _glfwCreateCursor(&image, 0, 0);+ return _glfwCreateCursorX11(&image, 0, 0); } // X error handler@@ -650,7 +645,7 @@ // Sets the X error handler callback //-void _glfwGrabXErrorHandler(void)+void _glfwGrabErrorHandlerX11(void) { _glfw.x11.errorCode = Success; XSetErrorHandler(errorHandler);@@ -658,7 +653,7 @@ // Clears the X error handler callback //-void _glfwReleaseXErrorHandler(void)+void _glfwReleaseErrorHandlerX11(void) { // Synchronize to make sure all commands are processed XSync(_glfw.x11.display, False);@@ -667,7 +662,7 @@ // Reports the specified error, appending information about the last X error //-void _glfwInputXError(int error, const char* message)+void _glfwInputErrorX11(int error, const char* message) { char buffer[8192]; XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,@@ -678,7 +673,7 @@ // Creates a native cursor object from the specified image and hotspot //-Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot) { int i; Cursor cursor;@@ -695,10 +690,12 @@ for (i = 0; i < image->width * image->height; i++, target++, source += 4) {- *target = (source[3] << 24) |- (source[0] << 16) |- (source[1] << 8) |- source[2];+ unsigned int alpha = source[3];++ *target = (alpha << 24) |+ ((unsigned char) ((source[0] * alpha) / 255) << 16) |+ ((unsigned char) ((source[1] * alpha) / 255) << 8) |+ ((unsigned char) ((source[2] * alpha) / 255) << 0); } cursor = XcursorImageLoadCursor(_glfw.x11.display, native);@@ -714,16 +711,31 @@ int _glfwPlatformInit(void) {+#if !defined(X_HAVE_UTF8_STRING)+ // HACK: If the current locale is C, apply the environment's locale+ // This is done because the C locale breaks wide character input if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0) setlocale(LC_CTYPE, "");+#endif XInitThreads(); _glfw.x11.display = XOpenDisplay(NULL); if (!_glfw.x11.display) {- _glfwInputError(GLFW_API_UNAVAILABLE, "X11: Failed to open X display");- return GL_FALSE;+ const char* display = getenv("DISPLAY");+ if (display)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to open display %s", display);+ }+ else+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: The DISPLAY environment variable is missing");+ }++ return GLFW_FALSE; } _glfw.x11.screen = DefaultScreen(_glfw.x11.display);@@ -731,15 +743,15 @@ _glfw.x11.context = XUniqueContext(); if (!initExtensions())- return GL_FALSE;+ return GLFW_FALSE; - _glfw.x11.cursor = createNULLCursor();+ _glfw.x11.cursor = createHiddenCursor(); if (XSupportsLocale()) { XSetLocaleModifiers(""); - _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, 0, 0);+ _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL); if (_glfw.x11.im) { if (!hasUsableInputMethodStyle())@@ -750,19 +762,25 @@ } } - if (!_glfwInitContextAPI())- return GL_FALSE;+ if (!_glfwInitThreadLocalStoragePOSIX())+ return GLFW_FALSE; - if (!_glfwInitJoysticks())- return GL_FALSE;+ if (!_glfwInitJoysticksLinux())+ return GLFW_FALSE; - _glfwInitTimer();+ _glfwInitTimerPOSIX(); - return GL_TRUE;+ return GLFW_TRUE; } void _glfwPlatformTerminate(void) {+ if (_glfw.x11.x11xcb.handle)+ {+ dlclose(_glfw.x11.x11xcb.handle);+ _glfw.x11.x11xcb.handle = NULL;+ }+ if (_glfw.x11.cursor) { XFreeCursor(_glfw.x11.display, _glfw.x11.cursor);@@ -777,44 +795,39 @@ _glfw.x11.im = NULL; } - _glfwTerminateJoysticks();- _glfwTerminateContextAPI();+ _glfwTerminateEGL(); if (_glfw.x11.display) { XCloseDisplay(_glfw.x11.display); _glfw.x11.display = NULL; }++ // NOTE: This needs to be done after XCloseDisplay, as libGL registers+ // cleanup callbacks that get called by it+ _glfwTerminateGLX();++ _glfwTerminateJoysticksLinux();+ _glfwTerminateThreadLocalStoragePOSIX(); } const char* _glfwPlatformGetVersionString(void) {- const char* version = _GLFW_VERSION_NUMBER " X11"-#if defined(_GLFW_GLX)- " GLX"-#elif defined(_GLFW_EGL)- " EGL"-#endif-#if defined(_GLFW_HAS_GLXGETPROCADDRESS)- " glXGetProcAddress"-#elif defined(_GLFW_HAS_GLXGETPROCADDRESSARB)- " glXGetProcAddressARB"-#elif defined(_GLFW_HAS_GLXGETPROCADDRESSEXT)- " glXGetProcAddressEXT"-#elif defined(_GLFW_DLOPEN_LIBGL)- " dlsym(libGL)"-#endif+ return _GLFW_VERSION_NUMBER " X11 GLX EGL" #if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK) " clock_gettime"+#else+ " gettimeofday" #endif #if defined(__linux__) " /dev/js" #endif+#if defined(_GLFW_HAS_XF86VM)+ " Xf86vm"+#endif #if defined(_GLFW_BUILD_DLL) " shared" #endif ;-- return version; }
glfw/src/x11_monitor.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 X11 - www.glfw.org+// GLFW 3.2 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -34,7 +34,7 @@ // Check whether the display mode should be included in enumeration //-static GLboolean modeIsGood(const XRRModeInfo* mi)+static GLFWbool modeIsGood(const XRRModeInfo* mi) { return (mi->modeFlags & RR_Interlace) == 0; }@@ -97,7 +97,7 @@ // Set the current video mode for the specified monitor //-GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired)+GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) {@@ -112,7 +112,7 @@ best = _glfwChooseVideoMode(monitor, desired); _glfwPlatformGetVideoMode(monitor, ¤t); if (_glfwCompareVideoModes(¤t, best) == 0)- return GL_TRUE;+ return GLFW_TRUE; sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root); ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);@@ -155,16 +155,16 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: Monitor mode list changed");- return GL_FALSE;+ return GLFW_FALSE; } } - return GL_TRUE;+ return GLFW_TRUE; } // Restore the saved (original) video mode for the specified monitor //-void _glfwRestoreVideoMode(_GLFWmonitor* monitor)+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor) { if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) {@@ -200,7 +200,7 @@ _GLFWmonitor** _glfwPlatformGetMonitors(int* count) {- int i, j, k, size = 0, found = 0;+ int i, j, k, found = 0; _GLFWmonitor** monitors = NULL; *count = 0;@@ -214,6 +214,8 @@ RROutput primary = XRRGetOutputPrimary(_glfw.x11.display, _glfw.x11.root); + monitors = calloc(sr->noutput, sizeof(_GLFWmonitor*));+ if (_glfw.x11.xinerama.available) screens = XineramaQueryScreens(_glfw.x11.display, &screenCount); @@ -225,6 +227,7 @@ for (j = 0; j < ci->noutput; j++) { int widthMM, heightMM;+ _GLFWmonitor* monitor; XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, ci->outputs[j]); if (oi->connection != RR_Connected)@@ -233,12 +236,6 @@ continue; } - if (found == size)- {- size += 4;- monitors = realloc(monitors, sizeof(_GLFWmonitor*) * size);- }- if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270) { widthMM = oi->mm_height;@@ -250,9 +247,9 @@ heightMM = oi->mm_height; } - monitors[found] = _glfwAllocMonitor(oi->name, widthMM, heightMM);- monitors[found]->x11.output = ci->outputs[j];- monitors[found]->x11.crtc = oi->crtc;+ monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);+ monitor->x11.output = ci->outputs[j];+ monitor->x11.crtc = oi->crtc; for (k = 0; k < screenCount; k++) {@@ -261,17 +258,18 @@ screens[k].width == ci->width && screens[k].height == ci->height) {- monitors[found]->x11.index = k;+ monitor->x11.index = k; break; } } XRRFreeOutputInfo(oi); - if (ci->outputs[j] == primary)- _GLFW_SWAP_POINTERS(monitors[0], monitors[found]);- found++;+ monitors[found - 1] = monitor;++ if (ci->outputs[j] == primary)+ _GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]); } XRRFreeCrtcInfo(ci);@@ -286,7 +284,10 @@ { _glfwInputError(GLFW_PLATFORM_ERROR, "X11: RandR monitor support seems broken");- _glfw.x11.randr.monitorBroken = GL_TRUE;++ _glfw.x11.randr.monitorBroken = GLFW_TRUE;+ free(monitors);+ monitors = NULL; } } @@ -305,7 +306,7 @@ return monitors; } -GLboolean _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second) { return first->x11.crtc == second->x11.crtc; }@@ -330,13 +331,11 @@ } } -GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) { GLFWvidmode* result; - *found = 0;-- // Build array of available resolutions+ *count = 0; if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) {@@ -359,20 +358,18 @@ const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); - for (j = 0; j < *found; j++)+ for (j = 0; j < *count; j++) { if (_glfwCompareVideoModes(result + j, &mode) == 0) break; } - if (j < *found)- {- // This is a duplicate, so skip it+ // Skip duplicate modes+ if (j < *count) continue;- } - result[*found] = mode;- (*found)++;+ (*count)++;+ result[*count - 1] = mode; } XRRFreeOutputInfo(oi);@@ -381,7 +378,7 @@ } else {- *found = 1;+ *count = 1; result = calloc(1, sizeof(GLFWvidmode)); _glfwPlatformGetVideoMode(monitor, result); }
glfw/src/x11_platform.h view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 X11 - www.glfw.org+// GLFW 3.2 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -25,12 +25,13 @@ // //======================================================================== -#ifndef _x11_platform_h_-#define _x11_platform_h_+#ifndef _glfw3_x11_platform_h_+#define _glfw3_x11_platform_h_ #include <unistd.h> #include <signal.h> #include <stdint.h>+#include <dlfcn.h> #include <X11/Xlib.h> #include <X11/keysym.h>@@ -46,34 +47,56 @@ // The Xinerama extension provides legacy monitor indices #include <X11/extensions/Xinerama.h> -#if defined(_GLFW_HAS_XINPUT)- // The XInput2 extension provides improved input events- #include <X11/extensions/XInput2.h>-#endif- #if defined(_GLFW_HAS_XF86VM) // The Xf86VidMode extension provides fallback gamma control #include <X11/extensions/xf86vmode.h> #endif -#include "posix_tls.h"+typedef XID xcb_window_t;+typedef XID xcb_visualid_t;+typedef struct xcb_connection_t xcb_connection_t;+typedef xcb_connection_t* (* XGETXCBCONNECTION_T)(Display*); -#if defined(_GLFW_GLX)- #define _GLFW_X11_CONTEXT_VISUAL window->glx.visual- #include "glx_context.h"-#elif defined(_GLFW_EGL)- #define _GLFW_X11_CONTEXT_VISUAL window->egl.visual- #define _GLFW_EGL_NATIVE_WINDOW window->x11.handle- #define _GLFW_EGL_NATIVE_DISPLAY _glfw.x11.display- #include "egl_context.h"-#else- #error "No supported context creation API selected"-#endif+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;+typedef VkFlags VkXcbSurfaceCreateFlagsKHR; +typedef struct VkXlibSurfaceCreateInfoKHR+{+ VkStructureType sType;+ const void* pNext;+ VkXlibSurfaceCreateFlagsKHR flags;+ Display* dpy;+ Window window;+} VkXlibSurfaceCreateInfoKHR;++typedef struct VkXcbSurfaceCreateInfoKHR+{+ VkStructureType sType;+ const void* pNext;+ VkXcbSurfaceCreateFlagsKHR flags;+ xcb_connection_t* connection;+ xcb_window_t window;+} VkXcbSurfaceCreateInfoKHR;++typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);+typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);++#include "posix_tls.h" #include "posix_time.h" #include "linux_joystick.h" #include "xkb_unicode.h"+#include "glx_context.h"+#include "egl_context.h" +#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)+#define _glfw_dlclose(handle) dlclose(handle)+#define _glfw_dlsym(handle, name) dlsym(handle, name)++#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)+ #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11 #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11@@ -88,19 +111,22 @@ Window handle; XIC ic; - GLboolean overrideRedirect;+ GLFWbool overrideRedirect; // Cached position and size used to filter out duplicate events int width, height; int xpos, ypos; // The last received cursor position, regardless of source- double cursorPosX, cursorPosY;+ int lastCursorPosX, lastCursorPosY; // The last position the cursor was warped to by GLFW- int warpPosX, warpPosY;+ int warpCursorPosX, warpCursorPosY; -} _GLFWwindowX11;+ // The information from the last KeyPress event+ unsigned int lastKeyCode;+ Time lastKeyTime; +} _GLFWwindowX11; // X11-specific global data //@@ -116,14 +142,20 @@ XContext context; // XIM input method XIM im;- // True if window manager supports EWMH- GLboolean hasEWMH; // Most recent error code received by X error handler int errorCode; // Clipboard string (while the selection is owned) char* clipboardString;+ // Key name string+ char keyName[64]; // X11 keycode to GLFW key LUT short int publicKeys[256];+ // GLFW key to X11 keycode LUT+ short int nativeKeys[GLFW_KEY_LAST + 1];+ // Where to place the cursor when re-enabled+ double restoreCursorPosX, restoreCursorPosY;+ // The window whose disabled cursor mode is active+ _GLFWwindow* disabledCursorWindow; // Window manager atoms Atom WM_PROTOCOLS;@@ -131,11 +163,16 @@ Atom WM_DELETE_WINDOW; Atom NET_WM_NAME; Atom NET_WM_ICON_NAME;+ Atom NET_WM_ICON; Atom NET_WM_PID; Atom NET_WM_PING;+ Atom NET_WM_WINDOW_TYPE;+ Atom NET_WM_WINDOW_TYPE_NORMAL; Atom NET_WM_STATE; Atom NET_WM_STATE_ABOVE; Atom NET_WM_STATE_FULLSCREEN;+ Atom NET_WM_STATE_MAXIMIZED_VERT;+ Atom NET_WM_STATE_MAXIMIZED_HORZ; Atom NET_WM_BYPASS_COMPOSITOR; Atom NET_WM_FULLSCREEN_MONITORS; Atom NET_ACTIVE_WINDOW;@@ -167,23 +204,23 @@ Atom GLFW_SELECTION; struct {- GLboolean available;+ GLFWbool available; int eventBase; int errorBase;- int versionMajor;- int versionMinor;- GLboolean gammaBroken;- GLboolean monitorBroken;+ int major;+ int minor;+ GLFWbool gammaBroken;+ GLFWbool monitorBroken; } randr; struct {- GLboolean available;- GLboolean detectable;+ GLFWbool available;+ GLFWbool detectable; int majorOpcode; int eventBase; int errorBase;- int versionMajor;- int versionMinor;+ int major;+ int minor; } xkb; struct {@@ -199,25 +236,19 @@ } xdnd; struct {- GLboolean available;- int versionMajor;- int versionMinor;+ GLFWbool available;+ int major;+ int minor; } xinerama; -#if defined(_GLFW_HAS_XINPUT) struct {- GLboolean available;- int majorOpcode;- int eventBase;- int errorBase;- int versionMajor;- int versionMinor;- } xi;-#endif /*_GLFW_HAS_XINPUT*/+ void* handle;+ XGETXCBCONNECTION_T XGetXCBConnection;+ } x11xcb; #if defined(_GLFW_HAS_XF86VM) struct {- GLboolean available;+ GLFWbool available; int eventBase; int errorBase; } vidmode;@@ -225,7 +256,6 @@ } _GLFWlibraryX11; - // X11-specific per-monitor data // typedef struct _GLFWmonitorX11@@ -240,7 +270,6 @@ } _GLFWmonitorX11; - // X11-specific per-cursor data // typedef struct _GLFWcursorX11@@ -250,18 +279,18 @@ } _GLFWcursorX11; -GLboolean _glfwSetVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired);-void _glfwRestoreVideoMode(_GLFWmonitor* monitor);+GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor); -Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot);+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot); -unsigned long _glfwGetWindowProperty(Window window,- Atom property,- Atom type,- unsigned char** value);+unsigned long _glfwGetWindowPropertyX11(Window window,+ Atom property,+ Atom type,+ unsigned char** value); -void _glfwGrabXErrorHandler(void);-void _glfwReleaseXErrorHandler(void);-void _glfwInputXError(int error, const char* message);+void _glfwGrabErrorHandlerX11(void);+void _glfwReleaseErrorHandlerX11(void);+void _glfwInputErrorX11(int error, const char* message); -#endif // _x11_platform_h_+#endif // _glfw3_x11_platform_h_
glfw/src/x11_window.c view
@@ -1,1924 +1,2458 @@ //========================================================================-// GLFW 3.1 X11 - www.glfw.org-//-------------------------------------------------------------------------// Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>-//-// This software is provided 'as-is', without any express or implied-// warranty. In no event will the authors be held liable for any damages-// arising from the use of this software.-//-// Permission is granted to anyone to use this software for any purpose,-// including commercial applications, and to alter it and redistribute it-// freely, subject to the following restrictions:-//-// 1. The origin of this software must not be misrepresented; you must not-// claim that you wrote the original software. If you use this software-// in a product, an acknowledgment in the product documentation would-// be appreciated but is not required.-//-// 2. Altered source versions must be plainly marked as such, and must not-// be misrepresented as being the original software.-//-// 3. This notice may not be removed or altered from any source-// distribution.-//-//========================================================================--#include "internal.h"--#include <X11/cursorfont.h>-#include <X11/Xmd.h>--#include <sys/select.h>--#include <string.h>-#include <stdio.h>-#include <stdlib.h>-#include <limits.h>--// Action for EWMH client messages-#define _NET_WM_STATE_REMOVE 0-#define _NET_WM_STATE_ADD 1-#define _NET_WM_STATE_TOGGLE 2--// Additional mouse button names for XButtonEvent-#define Button6 6-#define Button7 7--typedef struct-{- unsigned long flags;- unsigned long functions;- unsigned long decorations;- long input_mode;- unsigned long status;-} MotifWmHints;--#define MWM_HINTS_DECORATIONS (1L << 1)---// Returns whether the window is iconified-//-static int getWindowState(_GLFWwindow* window)-{- int result = WithdrawnState;- struct {- CARD32 state;- Window icon;- } *state = NULL;-- if (_glfwGetWindowProperty(window->x11.handle,- _glfw.x11.WM_STATE,- _glfw.x11.WM_STATE,- (unsigned char**) &state) >= 2)- {- result = state->state;- }-- XFree(state);- return result;-}--// Returns whether the event is a selection event-//-static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)-{- _GLFWwindow* window = (_GLFWwindow*) pointer;- return event->type == PropertyNotify &&- event->xproperty.state == PropertyNewValue &&- event->xproperty.window == window->x11.handle &&- event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;-}--// Translates a GLFW standard cursor to a font cursor shape-//-static int translateCursorShape(int shape)-{- switch (shape)- {- case GLFW_ARROW_CURSOR:- return XC_arrow;- case GLFW_IBEAM_CURSOR:- return XC_xterm;- case GLFW_CROSSHAIR_CURSOR:- return XC_crosshair;- case GLFW_HAND_CURSOR:- return XC_hand1;- case GLFW_HRESIZE_CURSOR:- return XC_sb_h_double_arrow;- case GLFW_VRESIZE_CURSOR:- return XC_sb_v_double_arrow;- }-- return 0;-}--// Translates an X event modifier state mask-//-static int translateState(int state)-{- int mods = 0;-- if (state & ShiftMask)- mods |= GLFW_MOD_SHIFT;- if (state & ControlMask)- mods |= GLFW_MOD_CONTROL;- if (state & Mod1Mask)- mods |= GLFW_MOD_ALT;- if (state & Mod4Mask)- mods |= GLFW_MOD_SUPER;-- return mods;-}--// Translates an X Window key to internal coding-//-static int translateKey(int scancode)-{- // Use the pre-filled LUT (see createKeyTables() in x11_init.c)- if (scancode < 0 || scancode > 255)- return GLFW_KEY_UNKNOWN;-- return _glfw.x11.publicKeys[scancode];-}--// Return the GLFW window corresponding to the specified X11 window-//-static _GLFWwindow* findWindowByHandle(Window handle)-{- _GLFWwindow* window;-- if (XFindContext(_glfw.x11.display,- handle,- _glfw.x11.context,- (XPointer*) &window) != 0)- {- return NULL;- }-- return window;-}--// Adds or removes an EWMH state to a window-//-static void changeWindowState(_GLFWwindow* window, Atom state, int action)-{- XEvent event;- memset(&event, 0, sizeof(event));-- event.type = ClientMessage;- event.xclient.window = window->x11.handle;- event.xclient.format = 32; // Data is 32-bit longs- event.xclient.message_type = _glfw.x11.NET_WM_STATE;- event.xclient.data.l[0] = action;- event.xclient.data.l[1] = state;- event.xclient.data.l[2] = 0; // No secondary property- event.xclient.data.l[3] = 1; // Sender is a normal application-- XSendEvent(_glfw.x11.display,- _glfw.x11.root,- False,- SubstructureNotifyMask | SubstructureRedirectMask,- &event);-}--// Splits and translates a text/uri-list into separate file paths-// NOTE: This function destroys the provided string-//-static char** parseUriList(char* text, int* count)-{- const char* prefix = "file://";- char** paths = NULL;- char* line;-- *count = 0;-- while ((line = strtok(text, "\r\n")))- {- text = NULL;-- if (line[0] == '#')- continue;-- if (strncmp(line, prefix, strlen(prefix)) == 0)- line += strlen(prefix);-- (*count)++;-- char* path = calloc(strlen(line) + 1, 1);- paths = realloc(paths, *count * sizeof(char*));- paths[*count - 1] = path;-- while (*line)- {- if (line[0] == '%' && line[1] && line[2])- {- const char digits[3] = { line[1], line[2], '\0' };- *path = strtol(digits, NULL, 16);- line += 2;- }- else- *path = *line;-- path++;- line++;- }- }-- return paths;-}--// Create the X11 window (and its colormap)-//-static GLboolean createWindow(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig)-{- unsigned long wamask;- XSetWindowAttributes wa;- XVisualInfo* visual = _GLFW_X11_CONTEXT_VISUAL;-- // Every window needs a colormap- // Create one based on the visual used by the current context- // TODO: Decouple this from context creation-- window->x11.colormap = XCreateColormap(_glfw.x11.display,- _glfw.x11.root,- visual->visual,- AllocNone);-- // Create the actual window- {- wamask = CWBorderPixel | CWColormap | CWEventMask;-- wa.colormap = window->x11.colormap;- wa.border_pixel = 0;- wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |- PointerMotionMask | ButtonPressMask | ButtonReleaseMask |- ExposureMask | FocusChangeMask | VisibilityChangeMask |- EnterWindowMask | LeaveWindowMask | PropertyChangeMask;-- _glfwGrabXErrorHandler();-- window->x11.handle = XCreateWindow(_glfw.x11.display,- _glfw.x11.root,- 0, 0,- wndconfig->width, wndconfig->height,- 0, // Border width- visual->depth, // Color depth- InputOutput,- visual->visual,- wamask,- &wa);-- _glfwReleaseXErrorHandler();-- if (!window->x11.handle)- {- _glfwInputXError(GLFW_PLATFORM_ERROR,- "X11: Failed to create window");- return GL_FALSE;- }-- if (!wndconfig->decorated)- {- MotifWmHints hints;- hints.flags = MWM_HINTS_DECORATIONS;- hints.decorations = 0;-- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.MOTIF_WM_HINTS,- _glfw.x11.MOTIF_WM_HINTS, 32,- PropModeReplace,- (unsigned char*) &hints,- sizeof(MotifWmHints) / sizeof(long));- }-- XSaveContext(_glfw.x11.display,- window->x11.handle,- _glfw.x11.context,- (XPointer) window);- }-- if (window->monitor && !_glfw.x11.hasEWMH)- {- // This is the butcher's way of removing window decorations- // Setting the override-redirect attribute on a window makes the window- // manager ignore the window completely (ICCCM, section 4)- // The good thing is that this makes undecorated full screen windows- // easy to do; the bad thing is that we have to do everything manually- // and some things (like iconify/restore) won't work at all, as those- // are tasks usually performed by the window manager-- XSetWindowAttributes attributes;- attributes.override_redirect = True;- XChangeWindowAttributes(_glfw.x11.display,- window->x11.handle,- CWOverrideRedirect,- &attributes);-- window->x11.overrideRedirect = GL_TRUE;- }-- // Declare the WM protocols supported by GLFW- {- int count = 0;- Atom protocols[2];-- // The WM_DELETE_WINDOW ICCCM protocol- // Basic window close notification protocol- if (_glfw.x11.WM_DELETE_WINDOW)- protocols[count++] = _glfw.x11.WM_DELETE_WINDOW;-- // The _NET_WM_PING EWMH protocol- // Tells the WM to ping the GLFW window and flag the application as- // unresponsive if the WM doesn't get a reply within a few seconds- if (_glfw.x11.NET_WM_PING)- protocols[count++] = _glfw.x11.NET_WM_PING;-- if (count > 0)- {- XSetWMProtocols(_glfw.x11.display, window->x11.handle,- protocols, count);- }- }-- if (_glfw.x11.NET_WM_PID)- {- const pid_t pid = getpid();-- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.NET_WM_PID, XA_CARDINAL, 32,- PropModeReplace,- (unsigned char*) &pid, 1);- }-- // Set ICCCM WM_HINTS property- {- XWMHints* hints = XAllocWMHints();- if (!hints)- {- _glfwInputError(GLFW_OUT_OF_MEMORY,- "X11: Failed to allocate WM hints");- return GL_FALSE;- }-- hints->flags = StateHint;- hints->initial_state = NormalState;-- XSetWMHints(_glfw.x11.display, window->x11.handle, hints);- XFree(hints);- }-- // Set ICCCM WM_NORMAL_HINTS property (even if no parts are set)- {- XSizeHints* hints = XAllocSizeHints();- hints->flags = 0;-- if (wndconfig->monitor)- {- hints->flags |= PPosition;- _glfwPlatformGetMonitorPos(wndconfig->monitor, &hints->x, &hints->y);- }- else- {- // HACK: Explicitly setting PPosition to any value causes some WMs,- // notably Compiz and Metacity, to honor the position of- // unmapped windows set by XMoveWindow- hints->flags |= PPosition;- hints->x = hints->y = 0;- }-- if (!wndconfig->resizable)- {- hints->flags |= (PMinSize | PMaxSize);- hints->min_width = hints->max_width = wndconfig->width;- hints->min_height = hints->max_height = wndconfig->height;- }-- XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);- XFree(hints);- }-- // Set ICCCM WM_CLASS property- // HACK: Until a mechanism for specifying the application name is added, the- // initial window title is used as the window class name- if (strlen(wndconfig->title))- {- XClassHint* hint = XAllocClassHint();- hint->res_name = (char*) wndconfig->title;- hint->res_class = (char*) wndconfig->title;-- XSetClassHint(_glfw.x11.display, window->x11.handle, hint);- XFree(hint);- }--#if defined(_GLFW_HAS_XINPUT)- if (_glfw.x11.xi.available)- {- // Select for XInput2 events-- XIEventMask eventmask;- unsigned char mask[] = { 0 };-- eventmask.deviceid = 2;- eventmask.mask_len = sizeof(mask);- eventmask.mask = mask;- XISetMask(mask, XI_Motion);-- XISelectEvents(_glfw.x11.display, window->x11.handle, &eventmask, 1);- }-#endif /*_GLFW_HAS_XINPUT*/-- if (_glfw.x11.XdndAware)- {- // Announce support for Xdnd (drag and drop)- const Atom version = 5;- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.XdndAware, XA_ATOM, 32,- PropModeReplace, (unsigned char*) &version, 1);- }-- if (_glfw.x11.NET_REQUEST_FRAME_EXTENTS)- {- // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to- // function before the window is mapped-- XEvent event;- memset(&event, 0, sizeof(event));-- event.type = ClientMessage;- event.xclient.window = window->x11.handle;- event.xclient.format = 32; // Data is 32-bit longs- event.xclient.message_type = _glfw.x11.NET_REQUEST_FRAME_EXTENTS;-- XSendEvent(_glfw.x11.display,- _glfw.x11.root,- False,- SubstructureNotifyMask | SubstructureRedirectMask,- &event);- XIfEvent(_glfw.x11.display, &event, isFrameExtentsEvent, (XPointer) window);- }-- if (wndconfig->floating && !wndconfig->monitor)- {- if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_ABOVE)- {- changeWindowState(window,- _glfw.x11.NET_WM_STATE_ABOVE,- _NET_WM_STATE_ADD);- }- }-- _glfwPlatformSetWindowTitle(window, wndconfig->title);-- XRRSelectInput(_glfw.x11.display, window->x11.handle,- RRScreenChangeNotifyMask);-- if (_glfw.x11.im)- {- window->x11.ic = XCreateIC(_glfw.x11.im,- XNInputStyle,- XIMPreeditNothing | XIMStatusNothing,- XNClientWindow,- window->x11.handle,- XNFocusWindow,- window->x11.handle,- NULL);- }-- _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);- _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);-- return GL_TRUE;-}--// Hide the mouse cursor-//-static void hideCursor(_GLFWwindow* window)-{- XUngrabPointer(_glfw.x11.display, CurrentTime);- XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor);-}--// Disable the mouse cursor-//-static void disableCursor(_GLFWwindow* window)-{- XGrabPointer(_glfw.x11.display, window->x11.handle, True,- ButtonPressMask | ButtonReleaseMask | PointerMotionMask,- GrabModeAsync, GrabModeAsync,- window->x11.handle, _glfw.x11.cursor, CurrentTime);-}--// Restores the mouse cursor-//-static void restoreCursor(_GLFWwindow* window)-{- XUngrabPointer(_glfw.x11.display, CurrentTime);-- if (window->cursor)- {- XDefineCursor(_glfw.x11.display, window->x11.handle,- window->cursor->x11.handle);- }- else- XUndefineCursor(_glfw.x11.display, window->x11.handle);-}--// Returns whether the event is a selection event-//-static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)-{- return event->type == SelectionRequest ||- event->type == SelectionNotify ||- event->type == SelectionClear;-}--// Set the specified property to the selection converted to the requested target-//-static Atom writeTargetToProperty(const XSelectionRequestEvent* request)-{- int i;- const Atom formats[] = { _glfw.x11.UTF8_STRING,- _glfw.x11.COMPOUND_STRING,- XA_STRING };- const int formatCount = sizeof(formats) / sizeof(formats[0]);-- if (request->property == None)- {- // The requester is a legacy client (ICCCM section 2.2)- // We don't support legacy clients, so fail here- return None;- }-- if (request->target == _glfw.x11.TARGETS)- {- // The list of supported targets was requested-- const Atom targets[] = { _glfw.x11.TARGETS,- _glfw.x11.MULTIPLE,- _glfw.x11.UTF8_STRING,- _glfw.x11.COMPOUND_STRING,- XA_STRING };-- XChangeProperty(_glfw.x11.display,- request->requestor,- request->property,- XA_ATOM,- 32,- PropModeReplace,- (unsigned char*) targets,- sizeof(targets) / sizeof(targets[0]));-- return request->property;- }-- if (request->target == _glfw.x11.MULTIPLE)- {- // Multiple conversions were requested-- Atom* targets;- unsigned long i, count;-- count = _glfwGetWindowProperty(request->requestor,- request->property,- _glfw.x11.ATOM_PAIR,- (unsigned char**) &targets);-- for (i = 0; i < count; i += 2)- {- int j;-- for (j = 0; j < formatCount; j++)- {- if (targets[i] == formats[j])- break;- }-- if (j < formatCount)- {- XChangeProperty(_glfw.x11.display,- request->requestor,- targets[i + 1],- targets[i],- 8,- PropModeReplace,- (unsigned char*) _glfw.x11.clipboardString,- strlen(_glfw.x11.clipboardString));- }- else- targets[i + 1] = None;- }-- XChangeProperty(_glfw.x11.display,- request->requestor,- request->property,- _glfw.x11.ATOM_PAIR,- 32,- PropModeReplace,- (unsigned char*) targets,- count);-- XFree(targets);-- return request->property;- }-- if (request->target == _glfw.x11.SAVE_TARGETS)- {- // The request is a check whether we support SAVE_TARGETS- // It should be handled as a no-op side effect target-- XChangeProperty(_glfw.x11.display,- request->requestor,- request->property,- _glfw.x11.NULL_,- 32,- PropModeReplace,- NULL,- 0);-- return request->property;- }-- // Conversion to a data target was requested-- for (i = 0; i < formatCount; i++)- {- if (request->target == formats[i])- {- // The requested target is one we support-- XChangeProperty(_glfw.x11.display,- request->requestor,- request->property,- request->target,- 8,- PropModeReplace,- (unsigned char*) _glfw.x11.clipboardString,- strlen(_glfw.x11.clipboardString));-- return request->property;- }- }-- // The requested target is not supported-- return None;-}--static void handleSelectionClear(XEvent* event)-{- free(_glfw.x11.clipboardString);- _glfw.x11.clipboardString = NULL;-}--static void handleSelectionRequest(XEvent* event)-{- const XSelectionRequestEvent* request = &event->xselectionrequest;-- XEvent response;- memset(&response, 0, sizeof(response));-- response.xselection.property = writeTargetToProperty(request);- response.xselection.type = SelectionNotify;- response.xselection.display = request->display;- response.xselection.requestor = request->requestor;- response.xselection.selection = request->selection;- response.xselection.target = request->target;- response.xselection.time = request->time;-- XSendEvent(_glfw.x11.display, request->requestor, False, 0, &response);-}--static void pushSelectionToManager(_GLFWwindow* window)-{- XConvertSelection(_glfw.x11.display,- _glfw.x11.CLIPBOARD_MANAGER,- _glfw.x11.SAVE_TARGETS,- None,- window->x11.handle,- CurrentTime);-- for (;;)- {- XEvent event;-- if (!XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))- continue;-- switch (event.type)- {- case SelectionRequest:- handleSelectionRequest(&event);- break;-- case SelectionClear:- handleSelectionClear(&event);- break;-- case SelectionNotify:- {- if (event.xselection.target == _glfw.x11.SAVE_TARGETS)- {- // This means one of two things; either the selection was- // not owned, which means there is no clipboard manager, or- // the transfer to the clipboard manager has completed- // In either case, it means we are done here- return;- }-- break;- }- }- }-}--// Enter full screen mode-//-static void enterFullscreenMode(_GLFWwindow* window)-{- if (_glfw.x11.saver.count == 0)- {- // Remember old screen saver settings- XGetScreenSaver(_glfw.x11.display,- &_glfw.x11.saver.timeout,- &_glfw.x11.saver.interval,- &_glfw.x11.saver.blanking,- &_glfw.x11.saver.exposure);-- // Disable screen saver- XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking,- DefaultExposures);- }-- _glfw.x11.saver.count++;-- _glfwSetVideoMode(window->monitor, &window->videoMode);-- if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)- {- const unsigned long value = 1;-- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,- PropModeReplace, (unsigned char*) &value, 1);- }-- if (_glfw.x11.xinerama.available && _glfw.x11.NET_WM_FULLSCREEN_MONITORS)- {- XEvent event;- memset(&event, 0, sizeof(event));-- event.type = ClientMessage;- event.xclient.window = window->x11.handle;- event.xclient.format = 32; // Data is 32-bit longs- event.xclient.message_type = _glfw.x11.NET_WM_FULLSCREEN_MONITORS;- event.xclient.data.l[0] = window->monitor->x11.index;- event.xclient.data.l[1] = window->monitor->x11.index;- event.xclient.data.l[2] = window->monitor->x11.index;- event.xclient.data.l[3] = window->monitor->x11.index;-- XSendEvent(_glfw.x11.display,- _glfw.x11.root,- False,- SubstructureNotifyMask | SubstructureRedirectMask,- &event);- }-- if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)- {- int x, y;- _glfwPlatformGetMonitorPos(window->monitor, &x, &y);- _glfwPlatformSetWindowPos(window, x, y);-- if (_glfw.x11.NET_ACTIVE_WINDOW)- {- // Ask the window manager to raise and focus the GLFW window- // Only focused windows with the _NET_WM_STATE_FULLSCREEN state end- // up on top of all other windows ("Stacking order" in EWMH spec)-- XEvent event;- memset(&event, 0, sizeof(event));-- event.type = ClientMessage;- event.xclient.window = window->x11.handle;- event.xclient.format = 32; // Data is 32-bit longs- event.xclient.message_type = _glfw.x11.NET_ACTIVE_WINDOW;- event.xclient.data.l[0] = 1; // Sender is a normal application- event.xclient.data.l[1] = 0; // We don't really know the timestamp-- XSendEvent(_glfw.x11.display,- _glfw.x11.root,- False,- SubstructureNotifyMask | SubstructureRedirectMask,- &event);- }-- // Ask the window manager to make the GLFW window a full screen window- // Full screen windows are undecorated and, when focused, are kept- // on top of all other windows-- changeWindowState(window,- _glfw.x11.NET_WM_STATE_FULLSCREEN,- _NET_WM_STATE_ADD);- }- else if (window->x11.overrideRedirect)- {- // In override-redirect mode we have divorced ourselves from the- // window manager, so we need to do everything manually- int xpos, ypos;- GLFWvidmode mode;-- _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);- _glfwPlatformGetVideoMode(window->monitor, &mode);-- XRaiseWindow(_glfw.x11.display, window->x11.handle);- XSetInputFocus(_glfw.x11.display, window->x11.handle,- RevertToParent, CurrentTime);- XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);- XResizeWindow(_glfw.x11.display, window->x11.handle,- mode.width, mode.height);- }-}--// Leave full screen mode-//-static void leaveFullscreenMode(_GLFWwindow* window)-{- _glfwRestoreVideoMode(window->monitor);-- _glfw.x11.saver.count--;-- if (_glfw.x11.saver.count == 0)- {- // Restore old screen saver settings- XSetScreenSaver(_glfw.x11.display,- _glfw.x11.saver.timeout,- _glfw.x11.saver.interval,- _glfw.x11.saver.blanking,- _glfw.x11.saver.exposure);- }-- if (_glfw.x11.NET_WM_BYPASS_COMPOSITOR)- {- const unsigned long value = 0;-- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,- PropModeReplace, (unsigned char*) &value, 1);- }-- if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)- {- // Ask the window manager to make the GLFW window a normal window- // Normal windows usually have frames and other decorations-- changeWindowState(window,- _glfw.x11.NET_WM_STATE_FULLSCREEN,- _NET_WM_STATE_REMOVE);- }-}--// Process the specified X event-//-static void processEvent(XEvent *event)-{- _GLFWwindow* window = NULL;-- if (event->type != GenericEvent)- {- window = findWindowByHandle(event->xany.window);- if (window == NULL)- {- // This is an event for a window that has already been destroyed- return;- }- }-- switch (event->type)- {- case KeyPress:- {- const int key = translateKey(event->xkey.keycode);- const int mods = translateState(event->xkey.state);- const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));-- if (event->xkey.keycode)- _glfwInputKey(window, key, event->xkey.keycode, GLFW_PRESS, mods);-- if (window->x11.ic)- {- // Translate keys to characters with XIM input context-- int i;- Status status;- wchar_t buffer[16];-- if (XFilterEvent(event, None))- {- // Discard intermediary (dead key) events for character input- break;- }-- const int count = XwcLookupString(window->x11.ic,- &event->xkey,- buffer, sizeof(buffer),- NULL, &status);-- for (i = 0; i < count; i++)- _glfwInputChar(window, buffer[i], mods, plain);- }- else- {- // Translate keys to characters with fallback lookup table-- KeySym keysym;- XLookupString(&event->xkey, NULL, 0, &keysym, NULL);-- const long character = _glfwKeySym2Unicode(keysym);- if (character != -1)- _glfwInputChar(window, character, mods, plain);- }-- break;- }-- case KeyRelease:- {- const int key = translateKey(event->xkey.keycode);- const int mods = translateState(event->xkey.state);-- if (!_glfw.x11.xkb.detectable)- {- // HACK: Key repeat events will arrive as KeyRelease/KeyPress- // pairs with similar or identical time stamps- // The key repeat logic in _glfwInputKey expects only key- // presses to repeat, so detect and discard release events- if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))- {- XEvent nextEvent;- XPeekEvent(_glfw.x11.display, &nextEvent);-- if (nextEvent.type == KeyPress &&- nextEvent.xkey.window == event->xkey.window &&- nextEvent.xkey.keycode == event->xkey.keycode)- {- // HACK: Repeat events sometimes leak through due to- // some sort of time drift, so add an epsilon- // Toshiyuki Takahashi can press a button 16 times- // per second so it's fairly safe to assume that- // no human is pressing the key 50 times per- // second (value is ms)- if ((nextEvent.xkey.time - event->xkey.time) < 20)- {- // This is very likely a server-generated key repeat- // event, so ignore it- break;- }- }- }- }-- _glfwInputKey(window, key, event->xkey.keycode, GLFW_RELEASE, mods);- break;- }-- case ButtonPress:- {- const int mods = translateState(event->xbutton.state);-- if (event->xbutton.button == Button1)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);- else if (event->xbutton.button == Button2)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);- else if (event->xbutton.button == Button3)- _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);-- // Modern X provides scroll events as mouse button presses- else if (event->xbutton.button == Button4)- _glfwInputScroll(window, 0.0, 1.0);- else if (event->xbutton.button == Button5)- _glfwInputScroll(window, 0.0, -1.0);- else if (event->xbutton.button == Button6)- _glfwInputScroll(window, 1.0, 0.0);- else if (event->xbutton.button == Button7)- _glfwInputScroll(window, -1.0, 0.0);-- else- {- // Additional buttons after 7 are treated as regular buttons- // We subtract 4 to fill the gap left by scroll input above- _glfwInputMouseClick(window,- event->xbutton.button - 4,- GLFW_PRESS,- mods);- }-- break;- }-- case ButtonRelease:- {- const int mods = translateState(event->xbutton.state);-- if (event->xbutton.button == Button1)- {- _glfwInputMouseClick(window,- GLFW_MOUSE_BUTTON_LEFT,- GLFW_RELEASE,- mods);- }- else if (event->xbutton.button == Button2)- {- _glfwInputMouseClick(window,- GLFW_MOUSE_BUTTON_MIDDLE,- GLFW_RELEASE,- mods);- }- else if (event->xbutton.button == Button3)- {- _glfwInputMouseClick(window,- GLFW_MOUSE_BUTTON_RIGHT,- GLFW_RELEASE,- mods);- }- else if (event->xbutton.button > Button7)- {- // Additional buttons after 7 are treated as regular buttons- // We subtract 4 to fill the gap left by scroll input above- _glfwInputMouseClick(window,- event->xbutton.button - 4,- GLFW_RELEASE,- mods);- }- break;- }-- case EnterNotify:- {- _glfwInputCursorEnter(window, GL_TRUE);- break;- }-- case LeaveNotify:- {- _glfwInputCursorEnter(window, GL_FALSE);- break;- }-- case MotionNotify:- {- const int x = event->xmotion.x;- const int y = event->xmotion.y;-- if (x != window->x11.warpPosX || y != window->x11.warpPosY)- {- // The cursor was moved by something other than GLFW-- if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- if (_glfw.focusedWindow != window)- break;-- _glfwInputCursorMotion(window,- x - window->x11.cursorPosX,- y - window->x11.cursorPosY);- }- else- _glfwInputCursorMotion(window, x, y);- }-- window->x11.cursorPosX = x;- window->x11.cursorPosY = y;- break;- }-- case ConfigureNotify:- {- if (event->xconfigure.width != window->x11.width ||- event->xconfigure.height != window->x11.height)- {- _glfwInputFramebufferSize(window,- event->xconfigure.width,- event->xconfigure.height);-- _glfwInputWindowSize(window,- event->xconfigure.width,- event->xconfigure.height);-- window->x11.width = event->xconfigure.width;- window->x11.height = event->xconfigure.height;- }-- if (event->xconfigure.x != window->x11.xpos ||- event->xconfigure.y != window->x11.ypos)- {- _glfwInputWindowPos(window,- event->xconfigure.x,- event->xconfigure.y);-- window->x11.xpos = event->xconfigure.x;- window->x11.ypos = event->xconfigure.y;- }-- break;- }-- case ClientMessage:- {- // Custom client message, probably from the window manager-- if (event->xclient.message_type == None)- break;-- if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)- {- if (_glfw.x11.WM_DELETE_WINDOW &&- (Atom) event->xclient.data.l[0] == _glfw.x11.WM_DELETE_WINDOW)- {- // The window manager was asked to close the window, for example by- // the user pressing a 'close' window decoration button-- _glfwInputWindowCloseRequest(window);- }- else if (_glfw.x11.NET_WM_PING &&- (Atom) event->xclient.data.l[0] == _glfw.x11.NET_WM_PING)- {- // The window manager is pinging the application to ensure it's- // still responding to events-- event->xclient.window = _glfw.x11.root;- XSendEvent(_glfw.x11.display,- event->xclient.window,- False,- SubstructureNotifyMask | SubstructureRedirectMask,- event);- }- }- else if (event->xclient.message_type == _glfw.x11.XdndEnter)- {- // A drag operation has entered the window- // TODO: Check if UTF-8 string is supported by the source- }- else if (event->xclient.message_type == _glfw.x11.XdndDrop)- {- // The drag operation has finished dropping on- // the window, ask to convert it to a UTF-8 string- _glfw.x11.xdnd.source = event->xclient.data.l[0];- XConvertSelection(_glfw.x11.display,- _glfw.x11.XdndSelection,- _glfw.x11.UTF8_STRING,- _glfw.x11.XdndSelection,- window->x11.handle, CurrentTime);- }- else if (event->xclient.message_type == _glfw.x11.XdndPosition)- {- // The drag operation has moved over the window- const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF;- const int absY = (event->xclient.data.l[2]) & 0xFFFF;- int x, y;-- _glfwPlatformGetWindowPos(window, &x, &y);- _glfwInputCursorMotion(window, absX - x, absY - y);-- // Reply that we are ready to copy the dragged data- XEvent reply;- memset(&reply, 0, sizeof(reply));-- reply.type = ClientMessage;- reply.xclient.window = event->xclient.data.l[0];- reply.xclient.message_type = _glfw.x11.XdndStatus;- reply.xclient.format = 32;- reply.xclient.data.l[0] = window->x11.handle;- reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle- reply.xclient.data.l[2] = 0; // Specify an empty rectangle- reply.xclient.data.l[3] = 0;- reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;-- XSendEvent(_glfw.x11.display, event->xclient.data.l[0],- False, NoEventMask, &reply);- XFlush(_glfw.x11.display);- }-- break;- }-- case SelectionNotify:- {- if (event->xselection.property)- {- // The converted data from the drag operation has arrived- char* data;- const int result =- _glfwGetWindowProperty(event->xselection.requestor,- event->xselection.property,- event->xselection.target,- (unsigned char**) &data);-- if (result)- {- int i, count;- char** paths = parseUriList(data, &count);-- _glfwInputDrop(window, count, (const char**) paths);-- for (i = 0; i < count; i++)- free(paths[i]);- free(paths);- }-- XFree(data);-- XEvent reply;- memset(&reply, 0, sizeof(reply));-- reply.type = ClientMessage;- reply.xclient.window = _glfw.x11.xdnd.source;- reply.xclient.message_type = _glfw.x11.XdndFinished;- reply.xclient.format = 32;- reply.xclient.data.l[0] = window->x11.handle;- reply.xclient.data.l[1] = result;- reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;-- // Reply that all is well- XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,- False, NoEventMask, &reply);- XFlush(_glfw.x11.display);- }-- break;- }-- case FocusIn:- {- if (event->xfocus.mode == NotifyNormal)- {- _glfwInputWindowFocus(window, GL_TRUE);-- if (window->cursorMode == GLFW_CURSOR_DISABLED)- disableCursor(window);- }-- break;- }-- case FocusOut:- {- if (event->xfocus.mode == NotifyNormal)- {- _glfwInputWindowFocus(window, GL_FALSE);-- if (window->cursorMode == GLFW_CURSOR_DISABLED)- restoreCursor(window);- }-- break;- }-- case Expose:- {- _glfwInputWindowDamage(window);- break;- }-- case PropertyNotify:- {- if (event->xproperty.atom == _glfw.x11.WM_STATE &&- event->xproperty.state == PropertyNewValue)- {- const int state = getWindowState(window);- if (state == IconicState)- _glfwInputWindowIconify(window, GL_TRUE);- else if (state == NormalState)- _glfwInputWindowIconify(window, GL_FALSE);- }-- break;- }-- case SelectionClear:- {- handleSelectionClear(event);- break;- }-- case SelectionRequest:- {- handleSelectionRequest(event);- break;- }-- case DestroyNotify:- return;--#if defined(_GLFW_HAS_XINPUT)- case GenericEvent:- {- if (event->xcookie.extension == _glfw.x11.xi.majorOpcode &&- XGetEventData(_glfw.x11.display, &event->xcookie))- {- if (event->xcookie.evtype == XI_Motion)- {- XIDeviceEvent* data = (XIDeviceEvent*) event->xcookie.data;-- window = findWindowByHandle(data->event);- if (window)- {- if (data->event_x != window->x11.warpPosX ||- data->event_y != window->x11.warpPosY)- {- // The cursor was moved by something other than GLFW-- double x, y;-- if (window->cursorMode == GLFW_CURSOR_DISABLED)- {- if (_glfw.focusedWindow != window)- break;-- x = data->event_x - window->x11.cursorPosX;- y = data->event_y - window->x11.cursorPosY;- }- else- {- x = data->event_x;- y = data->event_y;- }-- _glfwInputCursorMotion(window, x, y);- }-- window->x11.cursorPosX = data->event_x;- window->x11.cursorPosY = data->event_y;- }- }- }-- XFreeEventData(_glfw.x11.display, &event->xcookie);- break;- }-#endif /*_GLFW_HAS_XINPUT*/-- default:- {- switch (event->type - _glfw.x11.randr.eventBase)- {- case RRScreenChangeNotify:- {- XRRUpdateConfiguration(event);- break;- }- }-- break;- }- }-}---//////////////////////////////////////////////////////////////////////////-////// GLFW internal API //////-//////////////////////////////////////////////////////////////////////////--// Retrieve a single window property of the specified type-// Inspired by fghGetWindowProperty from freeglut-//-unsigned long _glfwGetWindowProperty(Window window,- Atom property,- Atom type,- unsigned char** value)-{- Atom actualType;- int actualFormat;- unsigned long itemCount, bytesAfter;-- XGetWindowProperty(_glfw.x11.display,- window,- property,- 0,- LONG_MAX,- False,- type,- &actualType,- &actualFormat,- &itemCount,- &bytesAfter,- value);-- if (type != AnyPropertyType && actualType != type)- return 0;-- return itemCount;-}---//////////////////////////////////////////////////////////////////////////-////// GLFW platform API //////-//////////////////////////////////////////////////////////////////////////--int _glfwPlatformCreateWindow(_GLFWwindow* window,- const _GLFWwndconfig* wndconfig,- const _GLFWctxconfig* ctxconfig,- const _GLFWfbconfig* fbconfig)-{- if (!_glfwCreateContext(window, ctxconfig, fbconfig))- return GL_FALSE;-- if (!createWindow(window, wndconfig))- return GL_FALSE;-- if (wndconfig->monitor)- {- _glfwPlatformShowWindow(window);- enterFullscreenMode(window);- }-- return GL_TRUE;-}--void _glfwPlatformDestroyWindow(_GLFWwindow* window)-{- if (window->monitor)- leaveFullscreenMode(window);-- if (window->x11.ic)- {- XDestroyIC(window->x11.ic);- window->x11.ic = NULL;- }-- _glfwDestroyContext(window);-- if (window->x11.handle)- {- if (window->x11.handle ==- XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD))- {- pushSelectionToManager(window);- }-- XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);- XUnmapWindow(_glfw.x11.display, window->x11.handle);- XDestroyWindow(_glfw.x11.display, window->x11.handle);- window->x11.handle = (Window) 0;- }-- if (window->x11.colormap)- {- XFreeColormap(_glfw.x11.display, window->x11.colormap);- window->x11.colormap = (Colormap) 0;- }-- XFlush(_glfw.x11.display);-}--void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)-{-#if defined(X_HAVE_UTF8_STRING)- Xutf8SetWMProperties(_glfw.x11.display,- window->x11.handle,- title, title,- NULL, 0,- NULL, NULL, NULL);-#else- // This may be a slightly better fallback than using XStoreName and- // XSetIconName, which always store their arguments using STRING- XmbSetWMProperties(_glfw.x11.display,- window->x11.handle,- title, title,- NULL, 0,- NULL, NULL, NULL);-#endif-- if (_glfw.x11.NET_WM_NAME)- {- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8,- PropModeReplace,- (unsigned char*) title, strlen(title));- }-- if (_glfw.x11.NET_WM_ICON_NAME)- {- XChangeProperty(_glfw.x11.display, window->x11.handle,- _glfw.x11.NET_WM_ICON_NAME, _glfw.x11.UTF8_STRING, 8,- PropModeReplace,- (unsigned char*) title, strlen(title));- }-- XFlush(_glfw.x11.display);-}--void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)-{- Window child;- int x, y;-- XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,- 0, 0, &x, &y, &child);-- if (child)- {- int left, top;- XTranslateCoordinates(_glfw.x11.display, window->x11.handle, child,- 0, 0, &left, &top, &child);-- x -= left;- y -= top;- }-- if (xpos)- *xpos = x;- if (ypos)- *ypos = y;-}--void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)-{- XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);- XFlush(_glfw.x11.display);-}--void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)-{- XWindowAttributes attribs;- XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);-- if (width)- *width = attribs.width;- if (height)- *height = attribs.height;-}--void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)-{- if (window->monitor)- {- _glfwSetVideoMode(window->monitor, &window->videoMode);-- if (window->x11.overrideRedirect)- {- GLFWvidmode mode;- _glfwPlatformGetVideoMode(window->monitor, &mode);- XResizeWindow(_glfw.x11.display, window->x11.handle,- mode.width, mode.height);- }- }- else- {- if (!window->resizable)- {- // Update window size restrictions to match new window size-- XSizeHints* hints = XAllocSizeHints();-- hints->flags |= (PMinSize | PMaxSize);- hints->min_width = hints->max_width = width;- hints->min_height = hints->max_height = height;-- XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);- XFree(hints);- }-- XResizeWindow(_glfw.x11.display, window->x11.handle, width, height);- }-- XFlush(_glfw.x11.display);-}--void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)-{- _glfwPlatformGetWindowSize(window, width, height);-}--void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,- int* left, int* top,- int* right, int* bottom)-{- long* extents = NULL;-- if (_glfw.x11.NET_FRAME_EXTENTS == None)- return;-- if (_glfwGetWindowProperty(window->x11.handle,- _glfw.x11.NET_FRAME_EXTENTS,- XA_CARDINAL,- (unsigned char**) &extents) == 4)- {- if (left)- *left = extents[0];- if (top)- *top = extents[2];- if (right)- *right = extents[1];- if (bottom)- *bottom = extents[3];- }-- if (extents)- XFree(extents);-}--void _glfwPlatformIconifyWindow(_GLFWwindow* window)-{- if (window->x11.overrideRedirect)- {- // Override-redirect windows cannot be iconified or restored, as those- // tasks are performed by the window manager- _glfwInputError(GLFW_API_UNAVAILABLE,- "X11: Iconification of full screen windows requires "- "a WM that supports EWMH");- return;- }-- XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);- XFlush(_glfw.x11.display);-}--void _glfwPlatformRestoreWindow(_GLFWwindow* window)-{- if (window->x11.overrideRedirect)- {- // Override-redirect windows cannot be iconified or restored, as those- // tasks are performed by the window manager- _glfwInputError(GLFW_API_UNAVAILABLE,- "X11: Iconification of full screen windows requires "- "a WM that supports EWMH");- return;- }-- XMapWindow(_glfw.x11.display, window->x11.handle);- XFlush(_glfw.x11.display);-}--void _glfwPlatformShowWindow(_GLFWwindow* window)-{- XMapRaised(_glfw.x11.display, window->x11.handle);- XFlush(_glfw.x11.display);-}--void _glfwPlatformUnhideWindow(_GLFWwindow* window)-{- XMapWindow(_glfw.x11.display, window->x11.handle);- XFlush(_glfw.x11.display);-}--void _glfwPlatformHideWindow(_GLFWwindow* window)-{- XUnmapWindow(_glfw.x11.display, window->x11.handle);- XFlush(_glfw.x11.display);-}--int _glfwPlatformWindowFocused(_GLFWwindow* window)-{- Window focused;- int state;-- XGetInputFocus(_glfw.x11.display, &focused, &state);- return window->x11.handle == focused;-}--int _glfwPlatformWindowIconified(_GLFWwindow* window)-{- return getWindowState(window) == IconicState;-}--int _glfwPlatformWindowVisible(_GLFWwindow* window)-{- XWindowAttributes wa;- XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);- return wa.map_state == IsViewable;-}--void _glfwPlatformPollEvents(void)-{- int count = XPending(_glfw.x11.display);- while (count--)- {- XEvent event;- XNextEvent(_glfw.x11.display, &event);- processEvent(&event);- }-- _GLFWwindow* window = _glfw.focusedWindow;- if (window && window->cursorMode == GLFW_CURSOR_DISABLED)- {- int width, height;- _glfwPlatformGetWindowSize(window, &width, &height);- _glfwPlatformSetCursorPos(window, width / 2, height / 2);- }-}--void _glfwPlatformWaitEvents(void)-{- if (!XPending(_glfw.x11.display))- {- fd_set fds;- const int fd = ConnectionNumber(_glfw.x11.display);-- FD_ZERO(&fds);- FD_SET(fd, &fds);-- // select(1) is used instead of an X function like XNextEvent, as the- // wait inside those are guarded by the mutex protecting the display- // struct, locking out other threads from using X (including GLX)- if (select(fd + 1, &fds, NULL, NULL, NULL) < 0)- return;- }-- _glfwPlatformPollEvents();-}--void _glfwPlatformPostEmptyEvent(void)-{- XEvent event;- _GLFWwindow* window = _glfw.windowListHead;-- memset(&event, 0, sizeof(event));- event.type = ClientMessage;- event.xclient.window = window->x11.handle;- event.xclient.format = 32; // Data is 32-bit longs- event.xclient.message_type = _glfw.x11.NULL_;-- XSendEvent(_glfw.x11.display, window->x11.handle, False, 0, &event);- XFlush(_glfw.x11.display);-}--void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)-{- Window root, child;- int rootX, rootY, childX, childY;- unsigned int mask;-- XQueryPointer(_glfw.x11.display, window->x11.handle,- &root, &child,- &rootX, &rootY, &childX, &childY,- &mask);-- if (xpos)- *xpos = childX;- if (ypos)- *ypos = childY;-}--void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)-{- // Store the new position so it can be recognized later- window->x11.warpPosX = (int) x;- window->x11.warpPosY = (int) y;-- XWarpPointer(_glfw.x11.display, None, window->x11.handle,- 0,0,0,0, (int) x, (int) y);-}--void _glfwPlatformApplyCursorMode(_GLFWwindow* window)-{- switch (window->cursorMode)- {- case GLFW_CURSOR_NORMAL:- restoreCursor(window);- break;- case GLFW_CURSOR_HIDDEN:- hideCursor(window);- break;- case GLFW_CURSOR_DISABLED:- disableCursor(window);- break;- }-}--int _glfwPlatformCreateCursor(_GLFWcursor* cursor,- const GLFWimage* image,- int xhot, int yhot)-{- cursor->x11.handle = _glfwCreateCursor(image, xhot, yhot);- if (!cursor->x11.handle)- return GL_FALSE;-- return GL_TRUE;-}--int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)-{- const unsigned int native = translateCursorShape(shape);- if (!native)- {- _glfwInputError(GLFW_INVALID_ENUM, "X11: Invalid standard cursor");- return GL_FALSE;- }-- cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);- if (!cursor->x11.handle)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "X11: Failed to create standard cursor");- return GL_FALSE;- }-- return GL_TRUE;-}--void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)-{- if (cursor->x11.handle)- XFreeCursor(_glfw.x11.display, cursor->x11.handle);-}--void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)-{- if (window->cursorMode == GLFW_CURSOR_NORMAL)- {- if (cursor)- XDefineCursor(_glfw.x11.display, window->x11.handle, cursor->x11.handle);- else- XUndefineCursor(_glfw.x11.display, window->x11.handle);-- XFlush(_glfw.x11.display);- }-}--void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)-{- free(_glfw.x11.clipboardString);- _glfw.x11.clipboardString = strdup(string);-- XSetSelectionOwner(_glfw.x11.display,- _glfw.x11.CLIPBOARD,- window->x11.handle, CurrentTime);-- if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=- window->x11.handle)- {- _glfwInputError(GLFW_PLATFORM_ERROR,- "X11: Failed to become owner of the clipboard selection");- }-}--const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)-{- size_t i;- const Atom formats[] = { _glfw.x11.UTF8_STRING,- _glfw.x11.COMPOUND_STRING,- XA_STRING };- const size_t formatCount = sizeof(formats) / sizeof(formats[0]);-- if (findWindowByHandle(XGetSelectionOwner(_glfw.x11.display,- _glfw.x11.CLIPBOARD)))- {- // Instead of doing a large number of X round-trips just to put this- // string into a window property and then read it back, just return it- return _glfw.x11.clipboardString;- }-- free(_glfw.x11.clipboardString);- _glfw.x11.clipboardString = NULL;-- for (i = 0; i < formatCount; i++)- {- char* data;- XEvent event;-- XConvertSelection(_glfw.x11.display,- _glfw.x11.CLIPBOARD,- formats[i],- _glfw.x11.GLFW_SELECTION,- window->x11.handle, CurrentTime);-- // XCheckTypedEvent is used instead of XIfEvent in order not to lock- // other threads out from the display during the entire wait period- while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))- ;-- if (event.xselection.property == None)- continue;-- if (_glfwGetWindowProperty(event.xselection.requestor,- event.xselection.property,- event.xselection.target,- (unsigned char**) &data))- {- _glfw.x11.clipboardString = strdup(data);- }-- XFree(data);-- XDeleteProperty(_glfw.x11.display,- event.xselection.requestor,- event.xselection.property);-- if (_glfw.x11.clipboardString)- break;- }-- if (_glfw.x11.clipboardString == NULL)- {- _glfwInputError(GLFW_FORMAT_UNAVAILABLE,- "X11: Failed to convert selection to string");- }-- return _glfw.x11.clipboardString;+// GLFW 3.2 X11 - www.glfw.org+//------------------------------------------------------------------------+// Copyright (c) 2002-2006 Marcus Geelnard+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>+//+// This software is provided 'as-is', without any express or implied+// warranty. In no event will the authors be held liable for any damages+// arising from the use of this software.+//+// Permission is granted to anyone to use this software for any purpose,+// including commercial applications, and to alter it and redistribute it+// freely, subject to the following restrictions:+//+// 1. The origin of this software must not be misrepresented; you must not+// claim that you wrote the original software. If you use this software+// in a product, an acknowledgment in the product documentation would+// be appreciated but is not required.+//+// 2. Altered source versions must be plainly marked as such, and must not+// be misrepresented as being the original software.+//+// 3. This notice may not be removed or altered from any source+// distribution.+//+//========================================================================++#include "internal.h"++#include <X11/cursorfont.h>+#include <X11/Xmd.h>++#include <sys/select.h>++#include <string.h>+#include <stdio.h>+#include <stdlib.h>+#include <limits.h>+#include <errno.h>+#include <assert.h>++// Action for EWMH client messages+#define _NET_WM_STATE_REMOVE 0+#define _NET_WM_STATE_ADD 1+#define _NET_WM_STATE_TOGGLE 2++// Additional mouse button names for XButtonEvent+#define Button6 6+#define Button7 7+++// Wait for data to arrive using select+// This avoids blocking other threads via the per-display Xlib lock that also+// covers GLX functions+//+static GLFWbool waitForEvent(double* timeout)+{+ fd_set fds;+ const int fd = ConnectionNumber(_glfw.x11.display);+ int count = fd + 1;++ FD_ZERO(&fds);+ FD_SET(fd, &fds);+#if defined(__linux__)+ FD_SET(_glfw.linux_js.inotify, &fds);++ if (fd < _glfw.linux_js.inotify)+ count = _glfw.linux_js.inotify + 1;+#endif+ for (;;)+ {+ if (timeout)+ {+ const long seconds = (long) *timeout;+ const long microseconds = (long) ((*timeout - seconds) * 1e6);+ struct timeval tv = { seconds, microseconds };+ const uint64_t base = _glfwPlatformGetTimerValue();++ const int result = select(count, &fds, NULL, NULL, &tv);+ const int error = errno;++ *timeout -= (_glfwPlatformGetTimerValue() - base) /+ (double) _glfwPlatformGetTimerFrequency();++ if (result > 0)+ return GLFW_TRUE;+ if ((result == -1 && error == EINTR) || *timeout <= 0.0)+ return GLFW_FALSE;+ }+ else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)+ return GLFW_TRUE;+ }+}++// Waits until a VisibilityNotify event arrives for the specified window or the+// timeout period elapses (ICCCM section 4.2.2)+//+static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)+{+ XEvent dummy;+ double timeout = 0.1;++ while (!XCheckTypedWindowEvent(_glfw.x11.display,+ window->x11.handle,+ VisibilityNotify,+ &dummy))+ {+ if (!waitForEvent(&timeout))+ return GLFW_FALSE;+ }++ return GLFW_TRUE;+}++// Returns whether the window is iconified+//+static int getWindowState(_GLFWwindow* window)+{+ int result = WithdrawnState;+ struct {+ CARD32 state;+ Window icon;+ } *state = NULL;++ if (_glfwGetWindowPropertyX11(window->x11.handle,+ _glfw.x11.WM_STATE,+ _glfw.x11.WM_STATE,+ (unsigned char**) &state) >= 2)+ {+ result = state->state;+ }++ XFree(state);+ return result;+}++// Returns whether the event is a selection event+//+static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)+{+ return event->type == SelectionRequest ||+ event->type == SelectionNotify ||+ event->type == SelectionClear;+}++// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window+//+static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)+{+ _GLFWwindow* window = (_GLFWwindow*) pointer;+ return event->type == PropertyNotify &&+ event->xproperty.state == PropertyNewValue &&+ event->xproperty.window == window->x11.handle &&+ event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;+}++// Translates a GLFW standard cursor to a font cursor shape+//+static int translateCursorShape(int shape)+{+ switch (shape)+ {+ case GLFW_ARROW_CURSOR:+ return XC_left_ptr;+ case GLFW_IBEAM_CURSOR:+ return XC_xterm;+ case GLFW_CROSSHAIR_CURSOR:+ return XC_crosshair;+ case GLFW_HAND_CURSOR:+ return XC_hand1;+ case GLFW_HRESIZE_CURSOR:+ return XC_sb_h_double_arrow;+ case GLFW_VRESIZE_CURSOR:+ return XC_sb_v_double_arrow;+ }++ return 0;+}++// Translates an X event modifier state mask+//+static int translateState(int state)+{+ int mods = 0;++ if (state & ShiftMask)+ mods |= GLFW_MOD_SHIFT;+ if (state & ControlMask)+ mods |= GLFW_MOD_CONTROL;+ if (state & Mod1Mask)+ mods |= GLFW_MOD_ALT;+ if (state & Mod4Mask)+ mods |= GLFW_MOD_SUPER;++ return mods;+}++// Translates an X11 key code to a GLFW key token+//+static int translateKey(int scancode)+{+ // Use the pre-filled LUT (see createKeyTables() in x11_init.c)+ if (scancode < 0 || scancode > 255)+ return GLFW_KEY_UNKNOWN;++ return _glfw.x11.publicKeys[scancode];+}++// Return the GLFW window corresponding to the specified X11 window+//+static _GLFWwindow* findWindowByHandle(Window handle)+{+ _GLFWwindow* window;++ if (XFindContext(_glfw.x11.display,+ handle,+ _glfw.x11.context,+ (XPointer*) &window) != 0)+ {+ return NULL;+ }++ return window;+}++// Sends an EWMH or ICCCM event to the window manager+//+static void sendEventToWM(_GLFWwindow* window, Atom type,+ long a, long b, long c, long d, long e)+{+ XEvent event;+ memset(&event, 0, sizeof(event));++ event.type = ClientMessage;+ event.xclient.window = window->x11.handle;+ event.xclient.format = 32; // Data is 32-bit longs+ event.xclient.message_type = type;+ event.xclient.data.l[0] = a;+ event.xclient.data.l[1] = b;+ event.xclient.data.l[2] = c;+ event.xclient.data.l[3] = d;+ event.xclient.data.l[4] = e;++ XSendEvent(_glfw.x11.display, _glfw.x11.root,+ False,+ SubstructureNotifyMask | SubstructureRedirectMask,+ &event);+}++// Updates the normal hints according to the window settings+//+static void updateNormalHints(_GLFWwindow* window, int width, int height)+{+ XSizeHints* hints = XAllocSizeHints();++ if (!window->monitor)+ {+ if (window->resizable)+ {+ if (window->minwidth != GLFW_DONT_CARE &&+ window->minheight != GLFW_DONT_CARE)+ {+ hints->flags |= PMinSize;+ hints->min_width = window->minwidth;+ hints->min_height = window->minheight;+ }++ if (window->maxwidth != GLFW_DONT_CARE &&+ window->maxheight != GLFW_DONT_CARE)+ {+ hints->flags |= PMaxSize;+ hints->max_width = window->maxwidth;+ hints->max_height = window->maxheight;+ }++ if (window->numer != GLFW_DONT_CARE &&+ window->denom != GLFW_DONT_CARE)+ {+ hints->flags |= PAspect;+ hints->min_aspect.x = hints->max_aspect.x = window->numer;+ hints->min_aspect.y = hints->max_aspect.y = window->denom;+ }+ }+ else+ {+ hints->flags |= (PMinSize | PMaxSize);+ hints->min_width = hints->max_width = width;+ hints->min_height = hints->max_height = height;+ }+ }++ hints->flags |= PWinGravity;+ hints->win_gravity = StaticGravity;++ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);+ XFree(hints);+}++// Updates the full screen status of the window+//+static void updateWindowMode(_GLFWwindow* window)+{+ if (window->monitor)+ {+ if (_glfw.x11.xinerama.available &&+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)+ {+ sendEventToWM(window,+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS,+ window->monitor->x11.index,+ window->monitor->x11.index,+ window->monitor->x11.index,+ window->monitor->x11.index,+ 0);+ }++ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)+ {+ sendEventToWM(window,+ _glfw.x11.NET_WM_STATE,+ _NET_WM_STATE_ADD,+ _glfw.x11.NET_WM_STATE_FULLSCREEN,+ 0, 1, 0);+ }+ else+ {+ // This is the butcher's way of removing window decorations+ // Setting the override-redirect attribute on a window makes the+ // window manager ignore the window completely (ICCCM, section 4)+ // The good thing is that this makes undecorated full screen windows+ // easy to do; the bad thing is that we have to do everything+ // manually and some things (like iconify/restore) won't work at+ // all, as those are tasks usually performed by the window manager++ XSetWindowAttributes attributes;+ attributes.override_redirect = True;+ XChangeWindowAttributes(_glfw.x11.display,+ window->x11.handle,+ CWOverrideRedirect,+ &attributes);++ window->x11.overrideRedirect = GLFW_TRUE;+ }++ // Enable compositor bypass+ {+ const unsigned long value = 1;++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,+ PropModeReplace, (unsigned char*) &value, 1);+ }+ }+ else+ {+ if (_glfw.x11.xinerama.available &&+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)+ {+ XDeleteProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS);+ }++ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)+ {+ sendEventToWM(window,+ _glfw.x11.NET_WM_STATE,+ _NET_WM_STATE_REMOVE,+ _glfw.x11.NET_WM_STATE_FULLSCREEN,+ 0, 1, 0);+ }+ else+ {+ XSetWindowAttributes attributes;+ attributes.override_redirect = False;+ XChangeWindowAttributes(_glfw.x11.display,+ window->x11.handle,+ CWOverrideRedirect,+ &attributes);++ window->x11.overrideRedirect = GLFW_FALSE;+ }++ // Disable compositor bypass+ {+ XDeleteProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR);+ }+ }+}++// Splits and translates a text/uri-list into separate file paths+// NOTE: This function destroys the provided string+//+static char** parseUriList(char* text, int* count)+{+ const char* prefix = "file://";+ char** paths = NULL;+ char* line;++ *count = 0;++ while ((line = strtok(text, "\r\n")))+ {+ text = NULL;++ if (line[0] == '#')+ continue;++ if (strncmp(line, prefix, strlen(prefix)) == 0)+ line += strlen(prefix);++ (*count)++;++ char* path = calloc(strlen(line) + 1, 1);+ paths = realloc(paths, *count * sizeof(char*));+ paths[*count - 1] = path;++ while (*line)+ {+ if (line[0] == '%' && line[1] && line[2])+ {+ const char digits[3] = { line[1], line[2], '\0' };+ *path = strtol(digits, NULL, 16);+ line += 2;+ }+ else+ *path = *line;++ path++;+ line++;+ }+ }++ return paths;+}++// Centers the cursor over the window client area+//+static void centerCursor(_GLFWwindow* window)+{+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);+}++// Updates the cursor image according to its cursor mode+//+static void updateCursorImage(_GLFWwindow* window)+{+ if (window->cursorMode == GLFW_CURSOR_NORMAL)+ {+ if (window->cursor)+ {+ XDefineCursor(_glfw.x11.display, window->x11.handle,+ window->cursor->x11.handle);+ }+ else+ XUndefineCursor(_glfw.x11.display, window->x11.handle);+ }+ else+ XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor);+}++// Create the X11 window (and its colormap)+//+static GLFWbool createNativeWindow(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig,+ Visual* visual, int depth)+{+ // Create a colormap based on the visual used by the current context+ window->x11.colormap = XCreateColormap(_glfw.x11.display,+ _glfw.x11.root,+ visual,+ AllocNone);++ // Create the actual window+ {+ XSetWindowAttributes wa;+ const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;++ wa.colormap = window->x11.colormap;+ wa.border_pixel = 0;+ wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask |+ ExposureMask | FocusChangeMask | VisibilityChangeMask |+ EnterWindowMask | LeaveWindowMask | PropertyChangeMask;++ _glfwGrabErrorHandlerX11();++ window->x11.handle = XCreateWindow(_glfw.x11.display,+ _glfw.x11.root,+ 0, 0,+ wndconfig->width, wndconfig->height,+ 0, // Border width+ depth, // Color depth+ InputOutput,+ visual,+ wamask,+ &wa);++ _glfwReleaseErrorHandlerX11();++ if (!window->x11.handle)+ {+ _glfwInputErrorX11(GLFW_PLATFORM_ERROR,+ "X11: Failed to create window");+ return GLFW_FALSE;+ }++ XSaveContext(_glfw.x11.display,+ window->x11.handle,+ _glfw.x11.context,+ (XPointer) window);+ }++ if (!wndconfig->decorated)+ {+ struct+ {+ unsigned long flags;+ unsigned long functions;+ unsigned long decorations;+ long input_mode;+ unsigned long status;+ } hints;++ hints.flags = 2; // Set decorations+ hints.decorations = 0; // No decorations++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.MOTIF_WM_HINTS,+ _glfw.x11.MOTIF_WM_HINTS, 32,+ PropModeReplace,+ (unsigned char*) &hints,+ sizeof(hints) / sizeof(long));+ }++ if (_glfw.x11.NET_WM_STATE && !window->monitor)+ {+ Atom states[3];+ int count = 0;++ if (wndconfig->floating)+ {+ if (_glfw.x11.NET_WM_STATE_ABOVE)+ states[count++] = _glfw.x11.NET_WM_STATE_ABOVE;+ }++ if (wndconfig->maximized)+ {+ if (_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)+ {+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;+ }+ }++ if (count)+ {+ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_STATE, XA_ATOM, 32,+ PropModeReplace, (unsigned char*) &states, count);+ }+ }++ // Declare the WM protocols supported by GLFW+ {+ Atom protocols[] =+ {+ _glfw.x11.WM_DELETE_WINDOW,+ _glfw.x11.NET_WM_PING+ };++ XSetWMProtocols(_glfw.x11.display, window->x11.handle,+ protocols, sizeof(protocols) / sizeof(Atom));+ }++ // Declare our PID+ {+ const pid_t pid = getpid();++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_PID, XA_CARDINAL, 32,+ PropModeReplace,+ (unsigned char*) &pid, 1);+ }++ if (_glfw.x11.NET_WM_WINDOW_TYPE && _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL)+ {+ Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL;+ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,+ PropModeReplace, (unsigned char*) &type, 1);+ }++ // Set ICCCM WM_HINTS property+ {+ XWMHints* hints = XAllocWMHints();+ if (!hints)+ {+ _glfwInputError(GLFW_OUT_OF_MEMORY,+ "X11: Failed to allocate WM hints");+ return GLFW_FALSE;+ }++ hints->flags = StateHint;+ hints->initial_state = NormalState;++ XSetWMHints(_glfw.x11.display, window->x11.handle, hints);+ XFree(hints);+ }++ updateNormalHints(window, wndconfig->width, wndconfig->height);++ // Set ICCCM WM_CLASS property+ // HACK: Until a mechanism for specifying the application name is added, the+ // initial window title is used as the window class name+ if (strlen(wndconfig->title))+ {+ XClassHint* hint = XAllocClassHint();+ hint->res_name = (char*) wndconfig->title;+ hint->res_class = (char*) wndconfig->title;++ XSetClassHint(_glfw.x11.display, window->x11.handle, hint);+ XFree(hint);+ }++ if (_glfw.x11.XdndAware)+ {+ // Announce support for Xdnd (drag and drop)+ const Atom version = 5;+ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.XdndAware, XA_ATOM, 32,+ PropModeReplace, (unsigned char*) &version, 1);+ }++ _glfwPlatformSetWindowTitle(window, wndconfig->title);++ if (_glfw.x11.im)+ {+ window->x11.ic = XCreateIC(_glfw.x11.im,+ XNInputStyle,+ XIMPreeditNothing | XIMStatusNothing,+ XNClientWindow,+ window->x11.handle,+ XNFocusWindow,+ window->x11.handle,+ NULL);+ }++ _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);+ _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);++ return GLFW_TRUE;+}++// Set the specified property to the selection converted to the requested target+//+static Atom writeTargetToProperty(const XSelectionRequestEvent* request)+{+ int i;+ const Atom formats[] = { _glfw.x11.UTF8_STRING,+ _glfw.x11.COMPOUND_STRING,+ XA_STRING };+ const int formatCount = sizeof(formats) / sizeof(formats[0]);++ if (request->property == None)+ {+ // The requester is a legacy client (ICCCM section 2.2)+ // We don't support legacy clients, so fail here+ return None;+ }++ if (request->target == _glfw.x11.TARGETS)+ {+ // The list of supported targets was requested++ const Atom targets[] = { _glfw.x11.TARGETS,+ _glfw.x11.MULTIPLE,+ _glfw.x11.UTF8_STRING,+ _glfw.x11.COMPOUND_STRING,+ XA_STRING };++ XChangeProperty(_glfw.x11.display,+ request->requestor,+ request->property,+ XA_ATOM,+ 32,+ PropModeReplace,+ (unsigned char*) targets,+ sizeof(targets) / sizeof(targets[0]));++ return request->property;+ }++ if (request->target == _glfw.x11.MULTIPLE)+ {+ // Multiple conversions were requested++ Atom* targets;+ unsigned long i, count;++ count = _glfwGetWindowPropertyX11(request->requestor,+ request->property,+ _glfw.x11.ATOM_PAIR,+ (unsigned char**) &targets);++ for (i = 0; i < count; i += 2)+ {+ int j;++ for (j = 0; j < formatCount; j++)+ {+ if (targets[i] == formats[j])+ break;+ }++ if (j < formatCount)+ {+ XChangeProperty(_glfw.x11.display,+ request->requestor,+ targets[i + 1],+ targets[i],+ 8,+ PropModeReplace,+ (unsigned char*) _glfw.x11.clipboardString,+ strlen(_glfw.x11.clipboardString));+ }+ else+ targets[i + 1] = None;+ }++ XChangeProperty(_glfw.x11.display,+ request->requestor,+ request->property,+ _glfw.x11.ATOM_PAIR,+ 32,+ PropModeReplace,+ (unsigned char*) targets,+ count);++ XFree(targets);++ return request->property;+ }++ if (request->target == _glfw.x11.SAVE_TARGETS)+ {+ // The request is a check whether we support SAVE_TARGETS+ // It should be handled as a no-op side effect target++ XChangeProperty(_glfw.x11.display,+ request->requestor,+ request->property,+ _glfw.x11.NULL_,+ 32,+ PropModeReplace,+ NULL,+ 0);++ return request->property;+ }++ // Conversion to a data target was requested++ for (i = 0; i < formatCount; i++)+ {+ if (request->target == formats[i])+ {+ // The requested target is one we support++ XChangeProperty(_glfw.x11.display,+ request->requestor,+ request->property,+ request->target,+ 8,+ PropModeReplace,+ (unsigned char*) _glfw.x11.clipboardString,+ strlen(_glfw.x11.clipboardString));++ return request->property;+ }+ }++ // The requested target is not supported++ return None;+}++static void handleSelectionClear(XEvent* event)+{+ free(_glfw.x11.clipboardString);+ _glfw.x11.clipboardString = NULL;+}++static void handleSelectionRequest(XEvent* event)+{+ const XSelectionRequestEvent* request = &event->xselectionrequest;++ XEvent reply;+ memset(&reply, 0, sizeof(reply));++ reply.xselection.property = writeTargetToProperty(request);+ reply.xselection.type = SelectionNotify;+ reply.xselection.display = request->display;+ reply.xselection.requestor = request->requestor;+ reply.xselection.selection = request->selection;+ reply.xselection.target = request->target;+ reply.xselection.time = request->time;++ XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);+}++static void pushSelectionToManager(_GLFWwindow* window)+{+ XConvertSelection(_glfw.x11.display,+ _glfw.x11.CLIPBOARD_MANAGER,+ _glfw.x11.SAVE_TARGETS,+ None,+ window->x11.handle,+ CurrentTime);++ for (;;)+ {+ XEvent event;++ while (XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))+ {+ switch (event.type)+ {+ case SelectionRequest:+ handleSelectionRequest(&event);+ break;++ case SelectionClear:+ handleSelectionClear(&event);+ break;++ case SelectionNotify:+ {+ if (event.xselection.target == _glfw.x11.SAVE_TARGETS)+ {+ // This means one of two things; either the selection was+ // not owned, which means there is no clipboard manager, or+ // the transfer to the clipboard manager has completed+ // In either case, it means we are done here+ return;+ }++ break;+ }+ }+ }++ waitForEvent(NULL);+ }+}++// Make the specified window and its video mode active on its monitor+//+static GLFWbool acquireMonitor(_GLFWwindow* window)+{+ GLFWbool status;++ if (_glfw.x11.saver.count == 0)+ {+ // Remember old screen saver settings+ XGetScreenSaver(_glfw.x11.display,+ &_glfw.x11.saver.timeout,+ &_glfw.x11.saver.interval,+ &_glfw.x11.saver.blanking,+ &_glfw.x11.saver.exposure);++ // Disable screen saver+ XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking,+ DefaultExposures);+ }++ if (!window->monitor->window)+ _glfw.x11.saver.count++;++ status = _glfwSetVideoModeX11(window->monitor, &window->videoMode);++ if (window->x11.overrideRedirect)+ {+ int xpos, ypos;+ GLFWvidmode mode;++ // Manually position the window over its monitor+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);+ _glfwPlatformGetVideoMode(window->monitor, &mode);++ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,+ xpos, ypos, mode.width, mode.height);+ }++ _glfwInputMonitorWindowChange(window->monitor, window);+ return status;+}++// Remove the window and restore the original video mode+//+static void releaseMonitor(_GLFWwindow* window)+{+ if (window->monitor->window != window)+ return;++ _glfwInputMonitorWindowChange(window->monitor, NULL);+ _glfwRestoreVideoModeX11(window->monitor);++ _glfw.x11.saver.count--;++ if (_glfw.x11.saver.count == 0)+ {+ // Restore old screen saver settings+ XSetScreenSaver(_glfw.x11.display,+ _glfw.x11.saver.timeout,+ _glfw.x11.saver.interval,+ _glfw.x11.saver.blanking,+ _glfw.x11.saver.exposure);+ }+}++// Decode a Unicode code point from a UTF-8 stream+// Based on cutef8 by Jeff Bezanson (Public Domain)+//+#if defined(X_HAVE_UTF8_STRING)+static unsigned int decodeUTF8(const char** s)+{+ unsigned int ch = 0, count = 0;+ static const unsigned int offsets[] =+ {+ 0x00000000u, 0x00003080u, 0x000e2080u,+ 0x03c82080u, 0xfa082080u, 0x82082080u+ };++ do+ {+ ch = (ch << 6) + (unsigned char) **s;+ (*s)++;+ count++;+ } while ((**s & 0xc0) == 0x80);++ assert(count <= 6);+ return ch - offsets[count - 1];+}+#endif /*X_HAVE_UTF8_STRING*/++// Process the specified X event+//+static void processEvent(XEvent *event)+{+ _GLFWwindow* window = NULL;+ int keycode = 0;+ Bool filtered = False;++ // HACK: Save scancode as some IMs clear the field in XFilterEvent+ if (event->type == KeyPress || event->type == KeyRelease)+ keycode = event->xkey.keycode;++ if (_glfw.x11.im)+ filtered = XFilterEvent(event, None);++ if (_glfw.x11.randr.available)+ {+ if (event->type == _glfw.x11.randr.eventBase + RRNotify)+ {+ XRRUpdateConfiguration(event);+ _glfwInputMonitorChange();+ return;+ }+ }++ if (event->type != GenericEvent)+ {+ window = findWindowByHandle(event->xany.window);+ if (window == NULL)+ {+ // This is an event for a window that has already been destroyed+ return;+ }+ }++ switch (event->type)+ {+ case KeyPress:+ {+ const int key = translateKey(keycode);+ const int mods = translateState(event->xkey.state);+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));++ if (window->x11.ic)+ {+ // HACK: Ignore duplicate key press events generated by ibus+ // Corresponding release events are filtered out by the+ // GLFW key repeat logic+ if (window->x11.lastKeyCode != keycode ||+ window->x11.lastKeyTime != event->xkey.time)+ {+ if (keycode)+ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);+ }++ window->x11.lastKeyCode = keycode;+ window->x11.lastKeyTime = event->xkey.time;++ if (!filtered)+ {+ int count;+ Status status;+#if defined(X_HAVE_UTF8_STRING)+ char buffer[100];+ char* chars = buffer;++ count = Xutf8LookupString(window->x11.ic,+ &event->xkey,+ buffer, sizeof(buffer) - 1,+ NULL, &status);++ if (status == XBufferOverflow)+ {+ chars = calloc(count + 1, 1);+ count = Xutf8LookupString(window->x11.ic,+ &event->xkey,+ chars, count,+ NULL, &status);+ }++ if (status == XLookupChars || status == XLookupBoth)+ {+ const char* c = chars;+ chars[count] = '\0';+ while (c - chars < count)+ _glfwInputChar(window, decodeUTF8(&c), mods, plain);+ }+#else /*X_HAVE_UTF8_STRING*/+ wchar_t buffer[16];+ wchar_t* chars = buffer;++ count = XwcLookupString(window->x11.ic,+ &event->xkey,+ buffer, sizeof(buffer) / sizeof(wchar_t),+ NULL, &status);++ if (status == XBufferOverflow)+ {+ chars = calloc(count, sizeof(wchar_t));+ count = XwcLookupString(window->x11.ic,+ &event->xkey,+ chars, count,+ NULL, &status);+ }++ if (status == XLookupChars || status == XLookupBoth)+ {+ int i;+ for (i = 0; i < count; i++)+ _glfwInputChar(window, chars[i], mods, plain);+ }+#endif /*X_HAVE_UTF8_STRING*/++ if (chars != buffer)+ free(chars);+ }+ }+ else+ {+ KeySym keysym;+ XLookupString(&event->xkey, NULL, 0, &keysym, NULL);++ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);++ const long character = _glfwKeySym2Unicode(keysym);+ if (character != -1)+ _glfwInputChar(window, character, mods, plain);+ }++ return;+ }++ case KeyRelease:+ {+ const int key = translateKey(keycode);+ const int mods = translateState(event->xkey.state);++ if (!_glfw.x11.xkb.detectable)+ {+ // HACK: Key repeat events will arrive as KeyRelease/KeyPress+ // pairs with similar or identical time stamps+ // The key repeat logic in _glfwInputKey expects only key+ // presses to repeat, so detect and discard release events+ if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))+ {+ XEvent next;+ XPeekEvent(_glfw.x11.display, &next);++ if (next.type == KeyPress &&+ next.xkey.window == event->xkey.window &&+ next.xkey.keycode == keycode)+ {+ // HACK: The time of repeat events sometimes doesn't+ // match that of the press event, so add an+ // epsilon+ // Toshiyuki Takahashi can press a button+ // 16 times per second so it's fairly safe to+ // assume that no human is pressing the key 50+ // times per second (value is ms)+ if ((next.xkey.time - event->xkey.time) < 20)+ {+ // This is very likely a server-generated key repeat+ // event, so ignore it+ return;+ }+ }+ }+ }++ _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);+ return;+ }++ case ButtonPress:+ {+ const int mods = translateState(event->xbutton.state);++ if (event->xbutton.button == Button1)+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);+ else if (event->xbutton.button == Button2)+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);+ else if (event->xbutton.button == Button3)+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);++ // Modern X provides scroll events as mouse button presses+ else if (event->xbutton.button == Button4)+ _glfwInputScroll(window, 0.0, 1.0);+ else if (event->xbutton.button == Button5)+ _glfwInputScroll(window, 0.0, -1.0);+ else if (event->xbutton.button == Button6)+ _glfwInputScroll(window, 1.0, 0.0);+ else if (event->xbutton.button == Button7)+ _glfwInputScroll(window, -1.0, 0.0);++ else+ {+ // Additional buttons after 7 are treated as regular buttons+ // We subtract 4 to fill the gap left by scroll input above+ _glfwInputMouseClick(window,+ event->xbutton.button - Button1 - 4,+ GLFW_PRESS,+ mods);+ }++ return;+ }++ case ButtonRelease:+ {+ const int mods = translateState(event->xbutton.state);++ if (event->xbutton.button == Button1)+ {+ _glfwInputMouseClick(window,+ GLFW_MOUSE_BUTTON_LEFT,+ GLFW_RELEASE,+ mods);+ }+ else if (event->xbutton.button == Button2)+ {+ _glfwInputMouseClick(window,+ GLFW_MOUSE_BUTTON_MIDDLE,+ GLFW_RELEASE,+ mods);+ }+ else if (event->xbutton.button == Button3)+ {+ _glfwInputMouseClick(window,+ GLFW_MOUSE_BUTTON_RIGHT,+ GLFW_RELEASE,+ mods);+ }+ else if (event->xbutton.button > Button7)+ {+ // Additional buttons after 7 are treated as regular buttons+ // We subtract 4 to fill the gap left by scroll input above+ _glfwInputMouseClick(window,+ event->xbutton.button - Button1 - 4,+ GLFW_RELEASE,+ mods);+ }++ return;+ }++ case EnterNotify:+ {+ // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise+ // ignore the defined cursor for hidden cursor mode+ if (window->cursorMode == GLFW_CURSOR_HIDDEN)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_HIDDEN);++ _glfwInputCursorEnter(window, GLFW_TRUE);+ return;+ }++ case LeaveNotify:+ {+ _glfwInputCursorEnter(window, GLFW_FALSE);+ return;+ }++ case MotionNotify:+ {+ const int x = event->xmotion.x;+ const int y = event->xmotion.y;++ if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY)+ {+ // The cursor was moved by something other than GLFW++ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ {+ if (_glfw.x11.disabledCursorWindow != window)+ return;++ const int dx = x - window->x11.lastCursorPosX;+ const int dy = y - window->x11.lastCursorPosY;++ _glfwInputCursorPos(window,+ window->virtualCursorPosX + dx,+ window->virtualCursorPosY + dy);+ }+ else+ _glfwInputCursorPos(window, x, y);+ }++ window->x11.lastCursorPosX = x;+ window->x11.lastCursorPosY = y;+ return;+ }++ case ConfigureNotify:+ {+ if (event->xconfigure.width != window->x11.width ||+ event->xconfigure.height != window->x11.height)+ {+ _glfwInputFramebufferSize(window,+ event->xconfigure.width,+ event->xconfigure.height);++ _glfwInputWindowSize(window,+ event->xconfigure.width,+ event->xconfigure.height);++ window->x11.width = event->xconfigure.width;+ window->x11.height = event->xconfigure.height;+ }++ if (event->xconfigure.x != window->x11.xpos ||+ event->xconfigure.y != window->x11.ypos)+ {+ if (window->x11.overrideRedirect || event->xany.send_event)+ {+ _glfwInputWindowPos(window,+ event->xconfigure.x,+ event->xconfigure.y);++ window->x11.xpos = event->xconfigure.x;+ window->x11.ypos = event->xconfigure.y;+ }+ }++ return;+ }++ case ClientMessage:+ {+ // Custom client message, probably from the window manager++ if (filtered)+ return;++ if (event->xclient.message_type == None)+ return;++ if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)+ {+ const Atom protocol = event->xclient.data.l[0];+ if (protocol == None)+ return;++ if (protocol == _glfw.x11.WM_DELETE_WINDOW)+ {+ // The window manager was asked to close the window, for example by+ // the user pressing a 'close' window decoration button+ _glfwInputWindowCloseRequest(window);+ }+ else if (protocol == _glfw.x11.NET_WM_PING)+ {+ // The window manager is pinging the application to ensure it's+ // still responding to events++ XEvent reply = *event;+ reply.xclient.window = _glfw.x11.root;++ XSendEvent(_glfw.x11.display, _glfw.x11.root,+ False,+ SubstructureNotifyMask | SubstructureRedirectMask,+ &reply);+ }+ }+ else if (event->xclient.message_type == _glfw.x11.XdndEnter)+ {+ // A drag operation has entered the window+ // TODO: Check if UTF-8 string is supported by the source+ }+ else if (event->xclient.message_type == _glfw.x11.XdndDrop)+ {+ // The drag operation has finished dropping on+ // the window, ask to convert it to a UTF-8 string+ _glfw.x11.xdnd.source = event->xclient.data.l[0];+ XConvertSelection(_glfw.x11.display,+ _glfw.x11.XdndSelection,+ _glfw.x11.UTF8_STRING,+ _glfw.x11.XdndSelection,+ window->x11.handle, CurrentTime);+ }+ else if (event->xclient.message_type == _glfw.x11.XdndPosition)+ {+ // The drag operation has moved over the window+ const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF;+ const int absY = (event->xclient.data.l[2]) & 0xFFFF;+ int x, y;++ _glfwPlatformGetWindowPos(window, &x, &y);+ _glfwInputCursorPos(window, absX - x, absY - y);++ // Reply that we are ready to copy the dragged data+ XEvent reply;+ memset(&reply, 0, sizeof(reply));++ reply.type = ClientMessage;+ reply.xclient.window = event->xclient.data.l[0];+ reply.xclient.message_type = _glfw.x11.XdndStatus;+ reply.xclient.format = 32;+ reply.xclient.data.l[0] = window->x11.handle;+ reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle+ reply.xclient.data.l[2] = 0; // Specify an empty rectangle+ reply.xclient.data.l[3] = 0;+ reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;++ XSendEvent(_glfw.x11.display, event->xclient.data.l[0],+ False, NoEventMask, &reply);+ XFlush(_glfw.x11.display);+ }++ return;+ }++ case SelectionNotify:+ {+ if (event->xselection.property)+ {+ // The converted data from the drag operation has arrived+ char* data;+ const int result =+ _glfwGetWindowPropertyX11(event->xselection.requestor,+ event->xselection.property,+ event->xselection.target,+ (unsigned char**) &data);++ if (result)+ {+ int i, count;+ char** paths = parseUriList(data, &count);++ _glfwInputDrop(window, count, (const char**) paths);++ for (i = 0; i < count; i++)+ free(paths[i]);+ free(paths);+ }++ XFree(data);++ XEvent reply;+ memset(&reply, 0, sizeof(reply));++ reply.type = ClientMessage;+ reply.xclient.window = _glfw.x11.xdnd.source;+ reply.xclient.message_type = _glfw.x11.XdndFinished;+ reply.xclient.format = 32;+ reply.xclient.data.l[0] = window->x11.handle;+ reply.xclient.data.l[1] = result;+ reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;++ // Reply that all is well+ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,+ False, NoEventMask, &reply);+ XFlush(_glfw.x11.display);+ }++ return;+ }++ case FocusIn:+ {+ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);++ if (event->xfocus.mode == NotifyGrab ||+ event->xfocus.mode == NotifyUngrab)+ {+ // Ignore focus events from popup indicator windows, window menu+ // key chords and window dragging+ return;+ }++ if (window->x11.ic)+ XSetICFocus(window->x11.ic);++ _glfwInputWindowFocus(window, GLFW_TRUE);+ return;+ }++ case FocusOut:+ {+ if (window->cursorMode == GLFW_CURSOR_DISABLED)+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);++ if (event->xfocus.mode == NotifyGrab ||+ event->xfocus.mode == NotifyUngrab)+ {+ // Ignore focus events from popup indicator windows, window menu+ // key chords and window dragging+ return;+ }++ if (window->x11.ic)+ XUnsetICFocus(window->x11.ic);++ if (window->monitor && window->autoIconify)+ _glfwPlatformIconifyWindow(window);++ _glfwInputWindowFocus(window, GLFW_FALSE);+ return;+ }++ case Expose:+ {+ _glfwInputWindowDamage(window);+ return;+ }++ case PropertyNotify:+ {+ if (event->xproperty.atom == _glfw.x11.WM_STATE &&+ event->xproperty.state == PropertyNewValue)+ {+ const int state = getWindowState(window);+ if (state == IconicState)+ {+ if (window->monitor)+ releaseMonitor(window);++ _glfwInputWindowIconify(window, GLFW_TRUE);+ }+ else if (state == NormalState)+ {+ if (window->monitor)+ acquireMonitor(window);++ _glfwInputWindowIconify(window, GLFW_FALSE);+ }+ }++ return;+ }++ case SelectionClear:+ {+ handleSelectionClear(event);+ return;+ }++ case SelectionRequest:+ {+ handleSelectionRequest(event);+ return;+ }++ case DestroyNotify:+ return;+ }+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW internal API //////+//////////////////////////////////////////////////////////////////////////++// Retrieve a single window property of the specified type+// Inspired by fghGetWindowProperty from freeglut+//+unsigned long _glfwGetWindowPropertyX11(Window window,+ Atom property,+ Atom type,+ unsigned char** value)+{+ Atom actualType;+ int actualFormat;+ unsigned long itemCount, bytesAfter;++ XGetWindowProperty(_glfw.x11.display,+ window,+ property,+ 0,+ LONG_MAX,+ False,+ type,+ &actualType,+ &actualFormat,+ &itemCount,+ &bytesAfter,+ value);++ if (type != AnyPropertyType && actualType != type)+ return 0;++ return itemCount;+}+++//////////////////////////////////////////////////////////////////////////+////// GLFW platform API //////+//////////////////////////////////////////////////////////////////////////++int _glfwPlatformCreateWindow(_GLFWwindow* window,+ const _GLFWwndconfig* wndconfig,+ const _GLFWctxconfig* ctxconfig,+ const _GLFWfbconfig* fbconfig)+{+ Visual* visual;+ int depth;++ if (ctxconfig->client == GLFW_NO_API)+ {+ visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);+ depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);+ }+ else+ {+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)+ {+ if (!_glfwInitGLX())+ return GLFW_FALSE;+ if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth))+ return GLFW_FALSE;+ }+ else+ {+ if (!_glfwInitEGL())+ return GLFW_FALSE;+ if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth))+ return GLFW_FALSE;+ }+ }++ if (!createNativeWindow(window, wndconfig, visual, depth))+ return GLFW_FALSE;++ if (ctxconfig->client != GLFW_NO_API)+ {+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)+ {+ if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }+ else+ {+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))+ return GLFW_FALSE;+ }+ }++ if (window->monitor)+ {+ _glfwPlatformShowWindow(window);+ updateWindowMode(window);+ if (!acquireMonitor(window))+ return GLFW_FALSE;++ centerCursor(window);+ }++ XFlush(_glfw.x11.display);+ return GLFW_TRUE;+}++void _glfwPlatformDestroyWindow(_GLFWwindow* window)+{+ if (_glfw.x11.disabledCursorWindow == window)+ _glfw.x11.disabledCursorWindow = NULL;++ if (window->monitor)+ releaseMonitor(window);++ if (window->x11.ic)+ {+ XDestroyIC(window->x11.ic);+ window->x11.ic = NULL;+ }++ if (window->context.destroy)+ window->context.destroy(window);++ if (window->x11.handle)+ {+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==+ window->x11.handle)+ {+ pushSelectionToManager(window);+ }++ XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);+ XUnmapWindow(_glfw.x11.display, window->x11.handle);+ XDestroyWindow(_glfw.x11.display, window->x11.handle);+ window->x11.handle = (Window) 0;+ }++ if (window->x11.colormap)+ {+ XFreeColormap(_glfw.x11.display, window->x11.colormap);+ window->x11.colormap = (Colormap) 0;+ }++ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)+{+#if defined(X_HAVE_UTF8_STRING)+ Xutf8SetWMProperties(_glfw.x11.display,+ window->x11.handle,+ title, title,+ NULL, 0,+ NULL, NULL, NULL);+#else+ // This may be a slightly better fallback than using XStoreName and+ // XSetIconName, which always store their arguments using STRING+ XmbSetWMProperties(_glfw.x11.display,+ window->x11.handle,+ title, title,+ NULL, 0,+ NULL, NULL, NULL);+#endif++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8,+ PropModeReplace,+ (unsigned char*) title, strlen(title));++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_ICON_NAME, _glfw.x11.UTF8_STRING, 8,+ PropModeReplace,+ (unsigned char*) title, strlen(title));++ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetWindowIcon(_GLFWwindow* window,+ int count, const GLFWimage* images)+{+ if (count)+ {+ int i, j, longCount = 0;++ for (i = 0; i < count; i++)+ longCount += 2 + images[i].width * images[i].height;++ long* icon = calloc(longCount, sizeof(long));+ long* target = icon;++ for (i = 0; i < count; i++)+ {+ *target++ = images[i].width;+ *target++ = images[i].height;++ for (j = 0; j < images[i].width * images[i].height; j++)+ {+ *target++ = (images[i].pixels[j * 4 + 0] << 16) |+ (images[i].pixels[j * 4 + 1] << 8) |+ (images[i].pixels[j * 4 + 2] << 0) |+ (images[i].pixels[j * 4 + 3] << 24);+ }+ }++ XChangeProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_ICON,+ XA_CARDINAL, 32,+ PropModeReplace,+ (unsigned char*) icon,+ longCount);++ free(icon);+ }+ else+ {+ XDeleteProperty(_glfw.x11.display, window->x11.handle,+ _glfw.x11.NET_WM_ICON);+ }++ XFlush(_glfw.x11.display);+}++void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)+{+ Window dummy;+ int x, y;++ XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,+ 0, 0, &x, &y, &dummy);++ if (xpos)+ *xpos = x;+ if (ypos)+ *ypos = y;+}++void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)+{+ // HACK: Explicitly setting PPosition to any value causes some WMs, notably+ // Compiz and Metacity, to honor the position of unmapped windows+ if (!_glfwPlatformWindowVisible(window))+ {+ long supplied;+ XSizeHints* hints = XAllocSizeHints();++ if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied))+ {+ hints->flags |= PPosition;+ hints->x = hints->y = 0;++ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);+ }++ XFree(hints);+ }++ XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)+{+ XWindowAttributes attribs;+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);++ if (width)+ *width = attribs.width;+ if (height)+ *height = attribs.height;+}++void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)+{+ if (window->monitor)+ {+ if (window->monitor->window == window)+ acquireMonitor(window);+ }+ else+ {+ if (!window->resizable)+ updateNormalHints(window, width, height);++ XResizeWindow(_glfw.x11.display, window->x11.handle, width, height);+ }++ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,+ int minwidth, int minheight,+ int maxwidth, int maxheight)+{+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);+ updateNormalHints(window, width, height);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)+{+ int width, height;+ _glfwPlatformGetWindowSize(window, &width, &height);+ updateNormalHints(window, width, height);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)+{+ _glfwPlatformGetWindowSize(window, width, height);+}++void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,+ int* left, int* top,+ int* right, int* bottom)+{+ long* extents = NULL;++ if (window->monitor || !window->decorated)+ return;++ if (_glfw.x11.NET_FRAME_EXTENTS == None)+ return;++ if (!_glfwPlatformWindowVisible(window) &&+ _glfw.x11.NET_REQUEST_FRAME_EXTENTS)+ {+ XEvent event;+ double timeout = 0.5;++ // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to+ // function before the window is mapped+ sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,+ 0, 0, 0, 0, 0);++ // HACK: Use a timeout because earlier versions of some window managers+ // (at least Unity, Fluxbox and Xfwm) failed to send the reply+ // They have been fixed but broken versions are still in the wild+ // If you are affected by this and your window manager is NOT+ // listed above, PLEASE report it to their and our issue trackers+ while (!XCheckIfEvent(_glfw.x11.display,+ &event,+ isFrameExtentsEvent,+ (XPointer) window))+ {+ if (!waitForEvent(&timeout))+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");+ return;+ }+ }+ }++ if (_glfwGetWindowPropertyX11(window->x11.handle,+ _glfw.x11.NET_FRAME_EXTENTS,+ XA_CARDINAL,+ (unsigned char**) &extents) == 4)+ {+ if (left)+ *left = extents[0];+ if (top)+ *top = extents[2];+ if (right)+ *right = extents[1];+ if (bottom)+ *bottom = extents[3];+ }++ if (extents)+ XFree(extents);+}++void _glfwPlatformIconifyWindow(_GLFWwindow* window)+{+ if (window->x11.overrideRedirect)+ {+ // Override-redirect windows cannot be iconified or restored, as those+ // tasks are performed by the window manager+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");+ return;+ }++ XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformRestoreWindow(_GLFWwindow* window)+{+ if (window->x11.overrideRedirect)+ {+ // Override-redirect windows cannot be iconified or restored, as those+ // tasks are performed by the window manager+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");+ return;+ }++ if (_glfwPlatformWindowIconified(window))+ {+ XMapWindow(_glfw.x11.display, window->x11.handle);+ waitForVisibilityNotify(window);+ }+ else if (_glfwPlatformWindowVisible(window))+ {+ if (_glfw.x11.NET_WM_STATE &&+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)+ {+ sendEventToWM(window,+ _glfw.x11.NET_WM_STATE,+ _NET_WM_STATE_REMOVE,+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,+ 1, 0);+ }+ }++ XFlush(_glfw.x11.display);+}++void _glfwPlatformMaximizeWindow(_GLFWwindow* window)+{+ if (_glfw.x11.NET_WM_STATE &&+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)+ {+ sendEventToWM(window,+ _glfw.x11.NET_WM_STATE,+ _NET_WM_STATE_ADD,+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,+ 1, 0);+ XFlush(_glfw.x11.display);+ }+}++void _glfwPlatformShowWindow(_GLFWwindow* window)+{+ if (_glfwPlatformWindowVisible(window))+ return;++ XMapWindow(_glfw.x11.display, window->x11.handle);+ waitForVisibilityNotify(window);+}++void _glfwPlatformHideWindow(_GLFWwindow* window)+{+ XUnmapWindow(_glfw.x11.display, window->x11.handle);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformFocusWindow(_GLFWwindow* window)+{+ if (_glfw.x11.NET_ACTIVE_WINDOW)+ sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);+ else+ {+ XRaiseWindow(_glfw.x11.display, window->x11.handle);+ XSetInputFocus(_glfw.x11.display, window->x11.handle,+ RevertToParent, CurrentTime);+ }++ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,+ _GLFWmonitor* monitor,+ int xpos, int ypos,+ int width, int height,+ int refreshRate)+{+ if (window->monitor == monitor)+ {+ if (monitor)+ {+ if (monitor->window == window)+ acquireMonitor(window);+ }+ else+ {+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,+ xpos, ypos, width, height);+ }++ return;+ }++ if (window->monitor)+ releaseMonitor(window);++ _glfwInputWindowMonitorChange(window, monitor);+ updateNormalHints(window, width, height);+ updateWindowMode(window);++ if (window->monitor)+ {+ XMapRaised(_glfw.x11.display, window->x11.handle);+ if (waitForVisibilityNotify(window))+ acquireMonitor(window);+ }+ else+ {+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,+ xpos, ypos, width, height);+ }++ XFlush(_glfw.x11.display);+}++int _glfwPlatformWindowFocused(_GLFWwindow* window)+{+ Window focused;+ int state;++ XGetInputFocus(_glfw.x11.display, &focused, &state);+ return window->x11.handle == focused;+}++int _glfwPlatformWindowIconified(_GLFWwindow* window)+{+ return getWindowState(window) == IconicState;+}++int _glfwPlatformWindowVisible(_GLFWwindow* window)+{+ XWindowAttributes wa;+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);+ return wa.map_state == IsViewable;+}++int _glfwPlatformWindowMaximized(_GLFWwindow* window)+{+ Atom* states;+ unsigned long i;+ GLFWbool maximized = GLFW_FALSE;+ const unsigned long count =+ _glfwGetWindowPropertyX11(window->x11.handle,+ _glfw.x11.NET_WM_STATE,+ XA_ATOM,+ (unsigned char**) &states);++ for (i = 0; i < count; i++)+ {+ if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||+ states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)+ {+ maximized = GLFW_TRUE;+ break;+ }+ }++ XFree(states);+ return maximized;+}++void _glfwPlatformPollEvents(void)+{+ _glfwPollJoystickEvents();++ int count = XPending(_glfw.x11.display);+ while (count--)+ {+ XEvent event;+ XNextEvent(_glfw.x11.display, &event);+ processEvent(&event);+ }++ if (_glfw.x11.disabledCursorWindow)+ centerCursor(_glfw.x11.disabledCursorWindow);++ XFlush(_glfw.x11.display);+}++void _glfwPlatformWaitEvents(void)+{+ while (!XPending(_glfw.x11.display))+ waitForEvent(NULL);++ _glfwPlatformPollEvents();+}++void _glfwPlatformWaitEventsTimeout(double timeout)+{+ while (!XPending(_glfw.x11.display))+ {+ if (!waitForEvent(&timeout))+ break;+ }++ _glfwPlatformPollEvents();+}++void _glfwPlatformPostEmptyEvent(void)+{+ XEvent event;+ _GLFWwindow* window = _glfw.windowListHead;++ memset(&event, 0, sizeof(event));+ event.type = ClientMessage;+ event.xclient.window = window->x11.handle;+ event.xclient.format = 32; // Data is 32-bit longs+ event.xclient.message_type = _glfw.x11.NULL_;++ XSendEvent(_glfw.x11.display, window->x11.handle, False, 0, &event);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)+{+ Window root, child;+ int rootX, rootY, childX, childY;+ unsigned int mask;++ XQueryPointer(_glfw.x11.display, window->x11.handle,+ &root, &child,+ &rootX, &rootY, &childX, &childY,+ &mask);++ if (xpos)+ *xpos = childX;+ if (ypos)+ *ypos = childY;+}++void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)+{+ // Store the new position so it can be recognized later+ window->x11.warpCursorPosX = (int) x;+ window->x11.warpCursorPosY = (int) y;++ XWarpPointer(_glfw.x11.display, None, window->x11.handle,+ 0,0,0,0, (int) x, (int) y);+ XFlush(_glfw.x11.display);+}++void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)+{+ if (mode == GLFW_CURSOR_DISABLED)+ {+ _glfw.x11.disabledCursorWindow = window;+ _glfwPlatformGetCursorPos(window,+ &_glfw.x11.restoreCursorPosX,+ &_glfw.x11.restoreCursorPosY);+ centerCursor(window);+ XGrabPointer(_glfw.x11.display, window->x11.handle, True,+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask,+ GrabModeAsync, GrabModeAsync,+ window->x11.handle, _glfw.x11.cursor, CurrentTime);+ }+ else if (_glfw.x11.disabledCursorWindow == window)+ {+ _glfw.x11.disabledCursorWindow = NULL;+ XUngrabPointer(_glfw.x11.display, CurrentTime);+ _glfwPlatformSetCursorPos(window,+ _glfw.x11.restoreCursorPosX,+ _glfw.x11.restoreCursorPosY);+ }++ updateCursorImage(window);+ XFlush(_glfw.x11.display);+}++const char* _glfwPlatformGetKeyName(int key, int scancode)+{+ KeySym keysym;+ int extra;++ if (!_glfw.x11.xkb.available)+ return NULL;++ if (key != GLFW_KEY_UNKNOWN)+ scancode = _glfw.x11.nativeKeys[key];++ if (!_glfwIsPrintable(_glfw.x11.publicKeys[scancode]))+ return NULL;++ keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0);+ if (keysym == NoSymbol)+ return NULL;++ XkbTranslateKeySym(_glfw.x11.display, &keysym, 0,+ _glfw.x11.keyName, sizeof(_glfw.x11.keyName),+ &extra);++ if (!strlen(_glfw.x11.keyName))+ return NULL;++ return _glfw.x11.keyName;+}++int _glfwPlatformCreateCursor(_GLFWcursor* cursor,+ const GLFWimage* image,+ int xhot, int yhot)+{+ cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);+ if (!cursor->x11.handle)+ return GLFW_FALSE;++ return GLFW_TRUE;+}++int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)+{+ cursor->x11.handle = XCreateFontCursor(_glfw.x11.display,+ translateCursorShape(shape));+ if (!cursor->x11.handle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to create standard cursor");+ return GLFW_FALSE;+ }++ return GLFW_TRUE;+}++void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)+{+ if (cursor->x11.handle)+ XFreeCursor(_glfw.x11.display, cursor->x11.handle);+}++void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)+{+ if (window->cursorMode == GLFW_CURSOR_NORMAL)+ {+ updateCursorImage(window);+ XFlush(_glfw.x11.display);+ }+}++void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)+{+ free(_glfw.x11.clipboardString);+ _glfw.x11.clipboardString = strdup(string);++ XSetSelectionOwner(_glfw.x11.display,+ _glfw.x11.CLIPBOARD,+ window->x11.handle, CurrentTime);++ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=+ window->x11.handle)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to become owner of clipboard selection");+ }+}++const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)+{+ size_t i;+ const Atom formats[] = { _glfw.x11.UTF8_STRING,+ _glfw.x11.COMPOUND_STRING,+ XA_STRING };+ const size_t formatCount = sizeof(formats) / sizeof(formats[0]);++ if (findWindowByHandle(XGetSelectionOwner(_glfw.x11.display,+ _glfw.x11.CLIPBOARD)))+ {+ // Instead of doing a large number of X round-trips just to put this+ // string into a window property and then read it back, just return it+ return _glfw.x11.clipboardString;+ }++ free(_glfw.x11.clipboardString);+ _glfw.x11.clipboardString = NULL;++ for (i = 0; i < formatCount; i++)+ {+ char* data;+ XEvent event;++ XConvertSelection(_glfw.x11.display,+ _glfw.x11.CLIPBOARD,+ formats[i],+ _glfw.x11.GLFW_SELECTION,+ window->x11.handle, CurrentTime);++ while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))+ waitForEvent(NULL);++ if (event.xselection.property == None)+ continue;++ if (_glfwGetWindowPropertyX11(event.xselection.requestor,+ event.xselection.property,+ event.xselection.target,+ (unsigned char**) &data))+ {+ _glfw.x11.clipboardString = strdup(data);+ }++ XFree(data);++ XDeleteProperty(_glfw.x11.display,+ event.xselection.requestor,+ event.xselection.property);++ if (_glfw.x11.clipboardString)+ break;+ }++ if (_glfw.x11.clipboardString == NULL)+ {+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,+ "X11: Failed to convert clipboard to string");+ }++ return _glfw.x11.clipboardString;+}++char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)+{+ char** extensions;++ *count = 0;++ if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)+ {+ if (!_glfw.vk.KHR_xlib_surface)+ return NULL;+ }++ extensions = calloc(2, sizeof(char*));+ extensions[0] = strdup("VK_KHR_surface");++ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)+ extensions[1] = strdup("VK_KHR_xcb_surface");+ else+ extensions[1] = strdup("VK_KHR_xlib_surface");++ *count = 2;+ return extensions;+}++int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,+ VkPhysicalDevice device,+ uint32_t queuefamily)+{+ VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,+ _glfw.x11.screen));++ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)+ {+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR =+ (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");+ if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");+ return GLFW_FALSE;+ }++ xcb_connection_t* connection =+ _glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);+ if (!connection)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to retrieve XCB connection");+ return GLFW_FALSE;+ }++ return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,+ queuefamily,+ connection,+ visualID);+ }+ else+ {+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR =+ (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");+ if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");+ return GLFW_FALSE;+ }++ return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,+ queuefamily,+ _glfw.x11.display,+ visualID);+ }+}++VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,+ _GLFWwindow* window,+ const VkAllocationCallbacks* allocator,+ VkSurfaceKHR* surface)+{+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)+ {+ VkResult err;+ VkXcbSurfaceCreateInfoKHR sci;+ PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;++ xcb_connection_t* connection =+ _glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);+ if (!connection)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to retrieve XCB connection");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)+ vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR");+ if (!vkCreateXcbSurfaceKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ memset(&sci, 0, sizeof(sci));+ sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;+ sci.connection = connection;+ sci.window = window->x11.handle;++ err = vkCreateXcbSurfaceKHR(instance, &sci, allocator, surface);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to create Vulkan XCB surface: %s",+ _glfwGetVulkanResultString(err));+ }++ return err;+ }+ else+ {+ VkResult err;+ VkXlibSurfaceCreateInfoKHR sci;+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;++ vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)+ vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR");+ if (!vkCreateXlibSurfaceKHR)+ {+ _glfwInputError(GLFW_API_UNAVAILABLE,+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");+ return VK_ERROR_EXTENSION_NOT_PRESENT;+ }++ memset(&sci, 0, sizeof(sci));+ sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;+ sci.dpy = _glfw.x11.display;+ sci.window = window->x11.handle;++ err = vkCreateXlibSurfaceKHR(instance, &sci, allocator, surface);+ if (err)+ {+ _glfwInputError(GLFW_PLATFORM_ERROR,+ "X11: Failed to create Vulkan X11 surface: %s",+ _glfwGetVulkanResultString(err));+ }++ return err;+ } }
glfw/src/xkb_unicode.c view
@@ -1,8 +1,8 @@ //========================================================================-// GLFW 3.1 X11 - www.glfw.org+// GLFW 3.2 X11 - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard-// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org> // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages@@ -827,24 +827,24 @@ { 0x13be, 0x0178 }, { 0x20ac, 0x20ac }, // Numeric keypad with numlock on- { XK_KP_Space, ' ' },- { XK_KP_Equal, '=' },- { XK_KP_Multiply, '*' },- { XK_KP_Add, '+' },- { XK_KP_Separator, ',' },- { XK_KP_Subtract, '-' },- { XK_KP_Decimal, '.' },- { XK_KP_Divide, '/' },- { XK_KP_0, 0x0030 },- { XK_KP_1, 0x0031 },- { XK_KP_2, 0x0032 },- { XK_KP_3, 0x0033 },- { XK_KP_4, 0x0034 },- { XK_KP_5, 0x0035 },- { XK_KP_6, 0x0036 },- { XK_KP_7, 0x0037 },- { XK_KP_8, 0x0038 },- { XK_KP_9, 0x0039 }+ { 0xff80 /*XKB_KEY_KP_Space*/, ' ' },+ { 0xffbd /*XKB_KEY_KP_Equal*/, '=' },+ { 0xffaa /*XKB_KEY_KP_Multiply*/, '*' },+ { 0xffab /*XKB_KEY_KP_Add*/, '+' },+ { 0xffac /*XKB_KEY_KP_Separator*/, ',' },+ { 0xffad /*XKB_KEY_KP_Subtract*/, '-' },+ { 0xffae /*XKB_KEY_KP_Decimal*/, '.' },+ { 0xffaf /*XKB_KEY_KP_Divide*/, '/' },+ { 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 },+ { 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 },+ { 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 },+ { 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 },+ { 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 },+ { 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 },+ { 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 },+ { 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 },+ { 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 },+ { 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 } };
glfw/src/xkb_unicode.h view
@@ -1,5 +1,5 @@ //========================================================================-// GLFW 3.1 Linux - www.glfw.org+// GLFW 3.2 Linux - www.glfw.org //------------------------------------------------------------------------ // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com> //@@ -24,10 +24,10 @@ // //======================================================================== -#ifndef _xkb_unicode_h_-#define _xkb_unicode_h_+#ifndef _glfw3_xkb_unicode_h_+#define _glfw3_xkb_unicode_h_ long _glfwKeySym2Unicode(unsigned int keysym); -#endif // _xkb_unicode_h_+#endif // _glfw3_xkb_unicode_h_