diff --git a/Test.hs b/Test.hs
--- a/Test.hs
+++ b/Test.hs
@@ -61,7 +61,7 @@
 versionMajor, versionMinor, versionRevision :: Int
 versionMajor    = 3
 versionMinor    = 3
-versionRevision = 1
+versionRevision = 2
 
 giveItTime :: IO ()
 giveItTime = threadDelay 500000
diff --git a/bindings-GLFW.cabal b/bindings-GLFW.cabal
--- a/bindings-GLFW.cabal
+++ b/bindings-GLFW.cabal
@@ -1,5 +1,5 @@
 name:         bindings-GLFW
-version:      3.3.1.0
+version:      3.3.2.0
 category:     Graphics
 
 author:       Brian Lewis <brian@lorf.org>
diff --git a/glfw/deps/glad/gl.h b/glfw/deps/glad/gl.h
--- a/glfw/deps/glad/gl.h
+++ b/glfw/deps/glad/gl.h
@@ -1,3840 +1,3840 @@
-/**
- * Loader generated by glad 2.0.0-beta on Sun Apr 14 17:03:32 2019
- *
- * Generator: C/C++
- * Specification: gl
- * Extensions: 3
- *
- * APIs:
- *  - gl:compatibility=3.3
- *
- * Options:
- *  - MX_GLOBAL = False
- *  - LOADER = False
- *  - ALIAS = False
- *  - HEADER_ONLY = False
- *  - DEBUG = False
- *  - MX = False
- *
- * Commandline:
- *    --api='gl:compatibility=3.3' --extensions='GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug' c
- *
- * Online:
- *    http://glad.sh/#api=gl%3Acompatibility%3D3.3&extensions=GL_ARB_multisample%2CGL_ARB_robustness%2CGL_KHR_debug&generator=c&options=
- *
- */
-
-#ifndef GLAD_GL_H_
-#define GLAD_GL_H_
-
-#ifdef __gl_h_
-    #error OpenGL header already included (API: gl), remove previous include!
-#endif
-#define __gl_h_ 1
-
-
-#define GLAD_GL
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef GLAD_PLATFORM_H_
-#define GLAD_PLATFORM_H_
-
-#ifndef GLAD_PLATFORM_WIN32
-  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
-    #define GLAD_PLATFORM_WIN32 1
-  #else
-    #define GLAD_PLATFORM_WIN32 0
-  #endif
-#endif
-
-#ifndef GLAD_PLATFORM_APPLE
-  #ifdef __APPLE__
-    #define GLAD_PLATFORM_APPLE 1
-  #else
-    #define GLAD_PLATFORM_APPLE 0
-  #endif
-#endif
-
-#ifndef GLAD_PLATFORM_EMSCRIPTEN
-  #ifdef __EMSCRIPTEN__
-    #define GLAD_PLATFORM_EMSCRIPTEN 1
-  #else
-    #define GLAD_PLATFORM_EMSCRIPTEN 0
-  #endif
-#endif
-
-#ifndef GLAD_PLATFORM_UWP
-  #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
-    #ifdef __has_include
-      #if __has_include(<winapifamily.h>)
-        #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
-      #endif
-    #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
-      #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
-    #endif
-  #endif
-
-  #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
-    #include <winapifamily.h>
-    #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
-      #define GLAD_PLATFORM_UWP 1
-    #endif
-  #endif
-
-  #ifndef GLAD_PLATFORM_UWP
-    #define GLAD_PLATFORM_UWP 0
-  #endif
-#endif
-
-#ifdef __GNUC__
-  #define GLAD_GNUC_EXTENSION __extension__
-#else
-  #define GLAD_GNUC_EXTENSION
-#endif
-
-#ifndef GLAD_API_CALL
-  #if defined(GLAD_API_CALL_EXPORT)
-    #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
-      #if defined(GLAD_API_CALL_EXPORT_BUILD)
-        #if defined(__GNUC__)
-          #define GLAD_API_CALL __attribute__ ((dllexport)) extern
-        #else
-          #define GLAD_API_CALL __declspec(dllexport) extern
-        #endif
-      #else
-        #if defined(__GNUC__)
-          #define GLAD_API_CALL __attribute__ ((dllimport)) extern
-        #else
-          #define GLAD_API_CALL __declspec(dllimport) extern
-        #endif
-      #endif
-    #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
-      #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
-    #else
-      #define GLAD_API_CALL extern
-    #endif
-  #else
-    #define GLAD_API_CALL extern
-  #endif
-#endif
-
-#ifdef APIENTRY
-  #define GLAD_API_PTR APIENTRY
-#elif GLAD_PLATFORM_WIN32
-  #define GLAD_API_PTR __stdcall
-#else
-  #define GLAD_API_PTR
-#endif
-
-#ifndef GLAPI
-#define GLAPI GLAD_API_CALL
-#endif
-
-#ifndef GLAPIENTRY
-#define GLAPIENTRY GLAD_API_PTR
-#endif
-
-
-#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
-#define GLAD_VERSION_MAJOR(version) (version / 10000)
-#define GLAD_VERSION_MINOR(version) (version % 10000)
-
-typedef void (*GLADapiproc)(void);
-
-typedef GLADapiproc (*GLADloadfunc)(const char *name);
-typedef GLADapiproc (*GLADuserptrloadfunc)(const char *name, void *userptr);
-
-typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
-typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
-
-#endif /* GLAD_PLATFORM_H_ */
-
-#define GL_2D 0x0600
-#define GL_2_BYTES 0x1407
-#define GL_3D 0x0601
-#define GL_3D_COLOR 0x0602
-#define GL_3D_COLOR_TEXTURE 0x0603
-#define GL_3_BYTES 0x1408
-#define GL_4D_COLOR_TEXTURE 0x0604
-#define GL_4_BYTES 0x1409
-#define GL_ACCUM 0x0100
-#define GL_ACCUM_ALPHA_BITS 0x0D5B
-#define GL_ACCUM_BLUE_BITS 0x0D5A
-#define GL_ACCUM_BUFFER_BIT 0x00000200
-#define GL_ACCUM_CLEAR_VALUE 0x0B80
-#define GL_ACCUM_GREEN_BITS 0x0D59
-#define GL_ACCUM_RED_BITS 0x0D58
-#define GL_ACTIVE_ATTRIBUTES 0x8B89
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
-#define GL_ACTIVE_TEXTURE 0x84E0
-#define GL_ACTIVE_UNIFORMS 0x8B86
-#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
-#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
-#define GL_ADD 0x0104
-#define GL_ADD_SIGNED 0x8574
-#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
-#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
-#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_ALPHA 0x1906
-#define GL_ALPHA12 0x803D
-#define GL_ALPHA16 0x803E
-#define GL_ALPHA4 0x803B
-#define GL_ALPHA8 0x803C
-#define GL_ALPHA_BIAS 0x0D1D
-#define GL_ALPHA_BITS 0x0D55
-#define GL_ALPHA_INTEGER 0x8D97
-#define GL_ALPHA_SCALE 0x0D1C
-#define GL_ALPHA_TEST 0x0BC0
-#define GL_ALPHA_TEST_FUNC 0x0BC1
-#define GL_ALPHA_TEST_REF 0x0BC2
-#define GL_ALREADY_SIGNALED 0x911A
-#define GL_ALWAYS 0x0207
-#define GL_AMBIENT 0x1200
-#define GL_AMBIENT_AND_DIFFUSE 0x1602
-#define GL_AND 0x1501
-#define GL_AND_INVERTED 0x1504
-#define GL_AND_REVERSE 0x1502
-#define GL_ANY_SAMPLES_PASSED 0x8C2F
-#define GL_ARRAY_BUFFER 0x8892
-#define GL_ARRAY_BUFFER_BINDING 0x8894
-#define GL_ATTACHED_SHADERS 0x8B85
-#define GL_ATTRIB_STACK_DEPTH 0x0BB0
-#define GL_AUTO_NORMAL 0x0D80
-#define GL_AUX0 0x0409
-#define GL_AUX1 0x040A
-#define GL_AUX2 0x040B
-#define GL_AUX3 0x040C
-#define GL_AUX_BUFFERS 0x0C00
-#define GL_BACK 0x0405
-#define GL_BACK_LEFT 0x0402
-#define GL_BACK_RIGHT 0x0403
-#define GL_BGR 0x80E0
-#define GL_BGRA 0x80E1
-#define GL_BGRA_INTEGER 0x8D9B
-#define GL_BGR_INTEGER 0x8D9A
-#define GL_BITMAP 0x1A00
-#define GL_BITMAP_TOKEN 0x0704
-#define GL_BLEND 0x0BE2
-#define GL_BLEND_COLOR 0x8005
-#define GL_BLEND_DST 0x0BE0
-#define GL_BLEND_DST_ALPHA 0x80CA
-#define GL_BLEND_DST_RGB 0x80C8
-#define GL_BLEND_EQUATION 0x8009
-#define GL_BLEND_EQUATION_ALPHA 0x883D
-#define GL_BLEND_EQUATION_RGB 0x8009
-#define GL_BLEND_SRC 0x0BE1
-#define GL_BLEND_SRC_ALPHA 0x80CB
-#define GL_BLEND_SRC_RGB 0x80C9
-#define GL_BLUE 0x1905
-#define GL_BLUE_BIAS 0x0D1B
-#define GL_BLUE_BITS 0x0D54
-#define GL_BLUE_INTEGER 0x8D96
-#define GL_BLUE_SCALE 0x0D1A
-#define GL_BOOL 0x8B56
-#define GL_BOOL_VEC2 0x8B57
-#define GL_BOOL_VEC3 0x8B58
-#define GL_BOOL_VEC4 0x8B59
-#define GL_BUFFER 0x82E0
-#define GL_BUFFER_ACCESS 0x88BB
-#define GL_BUFFER_ACCESS_FLAGS 0x911F
-#define GL_BUFFER_MAPPED 0x88BC
-#define GL_BUFFER_MAP_LENGTH 0x9120
-#define GL_BUFFER_MAP_OFFSET 0x9121
-#define GL_BUFFER_MAP_POINTER 0x88BD
-#define GL_BUFFER_SIZE 0x8764
-#define GL_BUFFER_USAGE 0x8765
-#define GL_BYTE 0x1400
-#define GL_C3F_V3F 0x2A24
-#define GL_C4F_N3F_V3F 0x2A26
-#define GL_C4UB_V2F 0x2A22
-#define GL_C4UB_V3F 0x2A23
-#define GL_CCW 0x0901
-#define GL_CLAMP 0x2900
-#define GL_CLAMP_FRAGMENT_COLOR 0x891B
-#define GL_CLAMP_READ_COLOR 0x891C
-#define GL_CLAMP_TO_BORDER 0x812D
-#define GL_CLAMP_TO_EDGE 0x812F
-#define GL_CLAMP_VERTEX_COLOR 0x891A
-#define GL_CLEAR 0x1500
-#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
-#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
-#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
-#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
-#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
-#define GL_CLIP_DISTANCE0 0x3000
-#define GL_CLIP_DISTANCE1 0x3001
-#define GL_CLIP_DISTANCE2 0x3002
-#define GL_CLIP_DISTANCE3 0x3003
-#define GL_CLIP_DISTANCE4 0x3004
-#define GL_CLIP_DISTANCE5 0x3005
-#define GL_CLIP_DISTANCE6 0x3006
-#define GL_CLIP_DISTANCE7 0x3007
-#define GL_CLIP_PLANE0 0x3000
-#define GL_CLIP_PLANE1 0x3001
-#define GL_CLIP_PLANE2 0x3002
-#define GL_CLIP_PLANE3 0x3003
-#define GL_CLIP_PLANE4 0x3004
-#define GL_CLIP_PLANE5 0x3005
-#define GL_COEFF 0x0A00
-#define GL_COLOR 0x1800
-#define GL_COLOR_ARRAY 0x8076
-#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
-#define GL_COLOR_ARRAY_POINTER 0x8090
-#define GL_COLOR_ARRAY_SIZE 0x8081
-#define GL_COLOR_ARRAY_STRIDE 0x8083
-#define GL_COLOR_ARRAY_TYPE 0x8082
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#define GL_COLOR_ATTACHMENT1 0x8CE1
-#define GL_COLOR_ATTACHMENT10 0x8CEA
-#define GL_COLOR_ATTACHMENT11 0x8CEB
-#define GL_COLOR_ATTACHMENT12 0x8CEC
-#define GL_COLOR_ATTACHMENT13 0x8CED
-#define GL_COLOR_ATTACHMENT14 0x8CEE
-#define GL_COLOR_ATTACHMENT15 0x8CEF
-#define GL_COLOR_ATTACHMENT16 0x8CF0
-#define GL_COLOR_ATTACHMENT17 0x8CF1
-#define GL_COLOR_ATTACHMENT18 0x8CF2
-#define GL_COLOR_ATTACHMENT19 0x8CF3
-#define GL_COLOR_ATTACHMENT2 0x8CE2
-#define GL_COLOR_ATTACHMENT20 0x8CF4
-#define GL_COLOR_ATTACHMENT21 0x8CF5
-#define GL_COLOR_ATTACHMENT22 0x8CF6
-#define GL_COLOR_ATTACHMENT23 0x8CF7
-#define GL_COLOR_ATTACHMENT24 0x8CF8
-#define GL_COLOR_ATTACHMENT25 0x8CF9
-#define GL_COLOR_ATTACHMENT26 0x8CFA
-#define GL_COLOR_ATTACHMENT27 0x8CFB
-#define GL_COLOR_ATTACHMENT28 0x8CFC
-#define GL_COLOR_ATTACHMENT29 0x8CFD
-#define GL_COLOR_ATTACHMENT3 0x8CE3
-#define GL_COLOR_ATTACHMENT30 0x8CFE
-#define GL_COLOR_ATTACHMENT31 0x8CFF
-#define GL_COLOR_ATTACHMENT4 0x8CE4
-#define GL_COLOR_ATTACHMENT5 0x8CE5
-#define GL_COLOR_ATTACHMENT6 0x8CE6
-#define GL_COLOR_ATTACHMENT7 0x8CE7
-#define GL_COLOR_ATTACHMENT8 0x8CE8
-#define GL_COLOR_ATTACHMENT9 0x8CE9
-#define GL_COLOR_BUFFER_BIT 0x00004000
-#define GL_COLOR_CLEAR_VALUE 0x0C22
-#define GL_COLOR_INDEX 0x1900
-#define GL_COLOR_INDEXES 0x1603
-#define GL_COLOR_LOGIC_OP 0x0BF2
-#define GL_COLOR_MATERIAL 0x0B57
-#define GL_COLOR_MATERIAL_FACE 0x0B55
-#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
-#define GL_COLOR_SUM 0x8458
-#define GL_COLOR_WRITEMASK 0x0C23
-#define GL_COMBINE 0x8570
-#define GL_COMBINE_ALPHA 0x8572
-#define GL_COMBINE_RGB 0x8571
-#define GL_COMPARE_REF_TO_TEXTURE 0x884E
-#define GL_COMPARE_R_TO_TEXTURE 0x884E
-#define GL_COMPILE 0x1300
-#define GL_COMPILE_AND_EXECUTE 0x1301
-#define GL_COMPILE_STATUS 0x8B81
-#define GL_COMPRESSED_ALPHA 0x84E9
-#define GL_COMPRESSED_INTENSITY 0x84EC
-#define GL_COMPRESSED_LUMINANCE 0x84EA
-#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
-#define GL_COMPRESSED_RED 0x8225
-#define GL_COMPRESSED_RED_RGTC1 0x8DBB
-#define GL_COMPRESSED_RG 0x8226
-#define GL_COMPRESSED_RGB 0x84ED
-#define GL_COMPRESSED_RGBA 0x84EE
-#define GL_COMPRESSED_RG_RGTC2 0x8DBD
-#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
-#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
-#define GL_COMPRESSED_SLUMINANCE 0x8C4A
-#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
-#define GL_COMPRESSED_SRGB 0x8C48
-#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
-#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
-#define GL_CONDITION_SATISFIED 0x911C
-#define GL_CONSTANT 0x8576
-#define GL_CONSTANT_ALPHA 0x8003
-#define GL_CONSTANT_ATTENUATION 0x1207
-#define GL_CONSTANT_COLOR 0x8001
-#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
-#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
-#define GL_CONTEXT_FLAGS 0x821E
-#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
-#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
-#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
-#define GL_CONTEXT_PROFILE_MASK 0x9126
-#define GL_COORD_REPLACE 0x8862
-#define GL_COPY 0x1503
-#define GL_COPY_INVERTED 0x150C
-#define GL_COPY_PIXEL_TOKEN 0x0706
-#define GL_COPY_READ_BUFFER 0x8F36
-#define GL_COPY_WRITE_BUFFER 0x8F37
-#define GL_CULL_FACE 0x0B44
-#define GL_CULL_FACE_MODE 0x0B45
-#define GL_CURRENT_BIT 0x00000001
-#define GL_CURRENT_COLOR 0x0B00
-#define GL_CURRENT_FOG_COORD 0x8453
-#define GL_CURRENT_FOG_COORDINATE 0x8453
-#define GL_CURRENT_INDEX 0x0B01
-#define GL_CURRENT_NORMAL 0x0B02
-#define GL_CURRENT_PROGRAM 0x8B8D
-#define GL_CURRENT_QUERY 0x8865
-#define GL_CURRENT_RASTER_COLOR 0x0B04
-#define GL_CURRENT_RASTER_DISTANCE 0x0B09
-#define GL_CURRENT_RASTER_INDEX 0x0B05
-#define GL_CURRENT_RASTER_POSITION 0x0B07
-#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
-#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
-#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
-#define GL_CURRENT_SECONDARY_COLOR 0x8459
-#define GL_CURRENT_TEXTURE_COORDS 0x0B03
-#define GL_CURRENT_VERTEX_ATTRIB 0x8626
-#define GL_CW 0x0900
-#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
-#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
-#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
-#define GL_DEBUG_LOGGED_MESSAGES 0x9145
-#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
-#define GL_DEBUG_OUTPUT 0x92E0
-#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
-#define GL_DEBUG_SEVERITY_HIGH 0x9146
-#define GL_DEBUG_SEVERITY_LOW 0x9148
-#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
-#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
-#define GL_DEBUG_SOURCE_API 0x8246
-#define GL_DEBUG_SOURCE_APPLICATION 0x824A
-#define GL_DEBUG_SOURCE_OTHER 0x824B
-#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
-#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
-#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
-#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
-#define GL_DEBUG_TYPE_ERROR 0x824C
-#define GL_DEBUG_TYPE_MARKER 0x8268
-#define GL_DEBUG_TYPE_OTHER 0x8251
-#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
-#define GL_DEBUG_TYPE_POP_GROUP 0x826A
-#define GL_DEBUG_TYPE_PORTABILITY 0x824F
-#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
-#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
-#define GL_DECAL 0x2101
-#define GL_DECR 0x1E03
-#define GL_DECR_WRAP 0x8508
-#define GL_DELETE_STATUS 0x8B80
-#define GL_DEPTH 0x1801
-#define GL_DEPTH24_STENCIL8 0x88F0
-#define GL_DEPTH32F_STENCIL8 0x8CAD
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#define GL_DEPTH_BIAS 0x0D1F
-#define GL_DEPTH_BITS 0x0D56
-#define GL_DEPTH_BUFFER_BIT 0x00000100
-#define GL_DEPTH_CLAMP 0x864F
-#define GL_DEPTH_CLEAR_VALUE 0x0B73
-#define GL_DEPTH_COMPONENT 0x1902
-#define GL_DEPTH_COMPONENT16 0x81A5
-#define GL_DEPTH_COMPONENT24 0x81A6
-#define GL_DEPTH_COMPONENT32 0x81A7
-#define GL_DEPTH_COMPONENT32F 0x8CAC
-#define GL_DEPTH_FUNC 0x0B74
-#define GL_DEPTH_RANGE 0x0B70
-#define GL_DEPTH_SCALE 0x0D1E
-#define GL_DEPTH_STENCIL 0x84F9
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#define GL_DEPTH_TEST 0x0B71
-#define GL_DEPTH_TEXTURE_MODE 0x884B
-#define GL_DEPTH_WRITEMASK 0x0B72
-#define GL_DIFFUSE 0x1201
-#define GL_DISPLAY_LIST 0x82E7
-#define GL_DITHER 0x0BD0
-#define GL_DOMAIN 0x0A02
-#define GL_DONT_CARE 0x1100
-#define GL_DOT3_RGB 0x86AE
-#define GL_DOT3_RGBA 0x86AF
-#define GL_DOUBLE 0x140A
-#define GL_DOUBLEBUFFER 0x0C32
-#define GL_DRAW_BUFFER 0x0C01
-#define GL_DRAW_BUFFER0 0x8825
-#define GL_DRAW_BUFFER1 0x8826
-#define GL_DRAW_BUFFER10 0x882F
-#define GL_DRAW_BUFFER11 0x8830
-#define GL_DRAW_BUFFER12 0x8831
-#define GL_DRAW_BUFFER13 0x8832
-#define GL_DRAW_BUFFER14 0x8833
-#define GL_DRAW_BUFFER15 0x8834
-#define GL_DRAW_BUFFER2 0x8827
-#define GL_DRAW_BUFFER3 0x8828
-#define GL_DRAW_BUFFER4 0x8829
-#define GL_DRAW_BUFFER5 0x882A
-#define GL_DRAW_BUFFER6 0x882B
-#define GL_DRAW_BUFFER7 0x882C
-#define GL_DRAW_BUFFER8 0x882D
-#define GL_DRAW_BUFFER9 0x882E
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_DRAW_PIXEL_TOKEN 0x0705
-#define GL_DST_ALPHA 0x0304
-#define GL_DST_COLOR 0x0306
-#define GL_DYNAMIC_COPY 0x88EA
-#define GL_DYNAMIC_DRAW 0x88E8
-#define GL_DYNAMIC_READ 0x88E9
-#define GL_EDGE_FLAG 0x0B43
-#define GL_EDGE_FLAG_ARRAY 0x8079
-#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
-#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
-#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
-#define GL_ELEMENT_ARRAY_BUFFER 0x8893
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
-#define GL_EMISSION 0x1600
-#define GL_ENABLE_BIT 0x00002000
-#define GL_EQUAL 0x0202
-#define GL_EQUIV 0x1509
-#define GL_EVAL_BIT 0x00010000
-#define GL_EXP 0x0800
-#define GL_EXP2 0x0801
-#define GL_EXTENSIONS 0x1F03
-#define GL_EYE_LINEAR 0x2400
-#define GL_EYE_PLANE 0x2502
-#define GL_FALSE 0
-#define GL_FASTEST 0x1101
-#define GL_FEEDBACK 0x1C01
-#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
-#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
-#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
-#define GL_FILL 0x1B02
-#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
-#define GL_FIXED_ONLY 0x891D
-#define GL_FLAT 0x1D00
-#define GL_FLOAT 0x1406
-#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
-#define GL_FLOAT_MAT2 0x8B5A
-#define GL_FLOAT_MAT2x3 0x8B65
-#define GL_FLOAT_MAT2x4 0x8B66
-#define GL_FLOAT_MAT3 0x8B5B
-#define GL_FLOAT_MAT3x2 0x8B67
-#define GL_FLOAT_MAT3x4 0x8B68
-#define GL_FLOAT_MAT4 0x8B5C
-#define GL_FLOAT_MAT4x2 0x8B69
-#define GL_FLOAT_MAT4x3 0x8B6A
-#define GL_FLOAT_VEC2 0x8B50
-#define GL_FLOAT_VEC3 0x8B51
-#define GL_FLOAT_VEC4 0x8B52
-#define GL_FOG 0x0B60
-#define GL_FOG_BIT 0x00000080
-#define GL_FOG_COLOR 0x0B66
-#define GL_FOG_COORD 0x8451
-#define GL_FOG_COORDINATE 0x8451
-#define GL_FOG_COORDINATE_ARRAY 0x8457
-#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
-#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
-#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
-#define GL_FOG_COORDINATE_SOURCE 0x8450
-#define GL_FOG_COORD_ARRAY 0x8457
-#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
-#define GL_FOG_COORD_ARRAY_POINTER 0x8456
-#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
-#define GL_FOG_COORD_ARRAY_TYPE 0x8454
-#define GL_FOG_COORD_SRC 0x8450
-#define GL_FOG_DENSITY 0x0B62
-#define GL_FOG_END 0x0B64
-#define GL_FOG_HINT 0x0C54
-#define GL_FOG_INDEX 0x0B61
-#define GL_FOG_MODE 0x0B65
-#define GL_FOG_START 0x0B63
-#define GL_FRAGMENT_DEPTH 0x8452
-#define GL_FRAGMENT_SHADER 0x8B30
-#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
-#define GL_FRAMEBUFFER 0x8D40
-#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
-#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
-#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
-#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
-#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
-#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
-#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
-#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
-#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
-#define GL_FRAMEBUFFER_BINDING 0x8CA6
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#define GL_FRAMEBUFFER_DEFAULT 0x8218
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
-#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
-#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
-#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
-#define GL_FRAMEBUFFER_SRGB 0x8DB9
-#define GL_FRAMEBUFFER_UNDEFINED 0x8219
-#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
-#define GL_FRONT 0x0404
-#define GL_FRONT_AND_BACK 0x0408
-#define GL_FRONT_FACE 0x0B46
-#define GL_FRONT_LEFT 0x0400
-#define GL_FRONT_RIGHT 0x0401
-#define GL_FUNC_ADD 0x8006
-#define GL_FUNC_REVERSE_SUBTRACT 0x800B
-#define GL_FUNC_SUBTRACT 0x800A
-#define GL_GENERATE_MIPMAP 0x8191
-#define GL_GENERATE_MIPMAP_HINT 0x8192
-#define GL_GEOMETRY_INPUT_TYPE 0x8917
-#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
-#define GL_GEOMETRY_SHADER 0x8DD9
-#define GL_GEOMETRY_VERTICES_OUT 0x8916
-#define GL_GEQUAL 0x0206
-#define GL_GREATER 0x0204
-#define GL_GREEN 0x1904
-#define GL_GREEN_BIAS 0x0D19
-#define GL_GREEN_BITS 0x0D53
-#define GL_GREEN_INTEGER 0x8D95
-#define GL_GREEN_SCALE 0x0D18
-#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
-#define GL_HALF_FLOAT 0x140B
-#define GL_HINT_BIT 0x00008000
-#define GL_INCR 0x1E02
-#define GL_INCR_WRAP 0x8507
-#define GL_INDEX 0x8222
-#define GL_INDEX_ARRAY 0x8077
-#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
-#define GL_INDEX_ARRAY_POINTER 0x8091
-#define GL_INDEX_ARRAY_STRIDE 0x8086
-#define GL_INDEX_ARRAY_TYPE 0x8085
-#define GL_INDEX_BITS 0x0D51
-#define GL_INDEX_CLEAR_VALUE 0x0C20
-#define GL_INDEX_LOGIC_OP 0x0BF1
-#define GL_INDEX_MODE 0x0C30
-#define GL_INDEX_OFFSET 0x0D13
-#define GL_INDEX_SHIFT 0x0D12
-#define GL_INDEX_WRITEMASK 0x0C21
-#define GL_INFO_LOG_LENGTH 0x8B84
-#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
-#define GL_INT 0x1404
-#define GL_INTENSITY 0x8049
-#define GL_INTENSITY12 0x804C
-#define GL_INTENSITY16 0x804D
-#define GL_INTENSITY4 0x804A
-#define GL_INTENSITY8 0x804B
-#define GL_INTERLEAVED_ATTRIBS 0x8C8C
-#define GL_INTERPOLATE 0x8575
-#define GL_INT_2_10_10_10_REV 0x8D9F
-#define GL_INT_SAMPLER_1D 0x8DC9
-#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
-#define GL_INT_SAMPLER_2D 0x8DCA
-#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
-#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
-#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
-#define GL_INT_SAMPLER_2D_RECT 0x8DCD
-#define GL_INT_SAMPLER_3D 0x8DCB
-#define GL_INT_SAMPLER_BUFFER 0x8DD0
-#define GL_INT_SAMPLER_CUBE 0x8DCC
-#define GL_INT_VEC2 0x8B53
-#define GL_INT_VEC3 0x8B54
-#define GL_INT_VEC4 0x8B55
-#define GL_INVALID_ENUM 0x0500
-#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
-#define GL_INVALID_INDEX 0xFFFFFFFF
-#define GL_INVALID_OPERATION 0x0502
-#define GL_INVALID_VALUE 0x0501
-#define GL_INVERT 0x150A
-#define GL_KEEP 0x1E00
-#define GL_LAST_VERTEX_CONVENTION 0x8E4E
-#define GL_LEFT 0x0406
-#define GL_LEQUAL 0x0203
-#define GL_LESS 0x0201
-#define GL_LIGHT0 0x4000
-#define GL_LIGHT1 0x4001
-#define GL_LIGHT2 0x4002
-#define GL_LIGHT3 0x4003
-#define GL_LIGHT4 0x4004
-#define GL_LIGHT5 0x4005
-#define GL_LIGHT6 0x4006
-#define GL_LIGHT7 0x4007
-#define GL_LIGHTING 0x0B50
-#define GL_LIGHTING_BIT 0x00000040
-#define GL_LIGHT_MODEL_AMBIENT 0x0B53
-#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
-#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
-#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
-#define GL_LINE 0x1B01
-#define GL_LINEAR 0x2601
-#define GL_LINEAR_ATTENUATION 0x1208
-#define GL_LINEAR_MIPMAP_LINEAR 0x2703
-#define GL_LINEAR_MIPMAP_NEAREST 0x2701
-#define GL_LINES 0x0001
-#define GL_LINES_ADJACENCY 0x000A
-#define GL_LINE_BIT 0x00000004
-#define GL_LINE_LOOP 0x0002
-#define GL_LINE_RESET_TOKEN 0x0707
-#define GL_LINE_SMOOTH 0x0B20
-#define GL_LINE_SMOOTH_HINT 0x0C52
-#define GL_LINE_STIPPLE 0x0B24
-#define GL_LINE_STIPPLE_PATTERN 0x0B25
-#define GL_LINE_STIPPLE_REPEAT 0x0B26
-#define GL_LINE_STRIP 0x0003
-#define GL_LINE_STRIP_ADJACENCY 0x000B
-#define GL_LINE_TOKEN 0x0702
-#define GL_LINE_WIDTH 0x0B21
-#define GL_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_LINE_WIDTH_RANGE 0x0B22
-#define GL_LINK_STATUS 0x8B82
-#define GL_LIST_BASE 0x0B32
-#define GL_LIST_BIT 0x00020000
-#define GL_LIST_INDEX 0x0B33
-#define GL_LIST_MODE 0x0B30
-#define GL_LOAD 0x0101
-#define GL_LOGIC_OP 0x0BF1
-#define GL_LOGIC_OP_MODE 0x0BF0
-#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
-#define GL_LOWER_LEFT 0x8CA1
-#define GL_LUMINANCE 0x1909
-#define GL_LUMINANCE12 0x8041
-#define GL_LUMINANCE12_ALPHA12 0x8047
-#define GL_LUMINANCE12_ALPHA4 0x8046
-#define GL_LUMINANCE16 0x8042
-#define GL_LUMINANCE16_ALPHA16 0x8048
-#define GL_LUMINANCE4 0x803F
-#define GL_LUMINANCE4_ALPHA4 0x8043
-#define GL_LUMINANCE6_ALPHA2 0x8044
-#define GL_LUMINANCE8 0x8040
-#define GL_LUMINANCE8_ALPHA8 0x8045
-#define GL_LUMINANCE_ALPHA 0x190A
-#define GL_MAJOR_VERSION 0x821B
-#define GL_MAP1_COLOR_4 0x0D90
-#define GL_MAP1_GRID_DOMAIN 0x0DD0
-#define GL_MAP1_GRID_SEGMENTS 0x0DD1
-#define GL_MAP1_INDEX 0x0D91
-#define GL_MAP1_NORMAL 0x0D92
-#define GL_MAP1_TEXTURE_COORD_1 0x0D93
-#define GL_MAP1_TEXTURE_COORD_2 0x0D94
-#define GL_MAP1_TEXTURE_COORD_3 0x0D95
-#define GL_MAP1_TEXTURE_COORD_4 0x0D96
-#define GL_MAP1_VERTEX_3 0x0D97
-#define GL_MAP1_VERTEX_4 0x0D98
-#define GL_MAP2_COLOR_4 0x0DB0
-#define GL_MAP2_GRID_DOMAIN 0x0DD2
-#define GL_MAP2_GRID_SEGMENTS 0x0DD3
-#define GL_MAP2_INDEX 0x0DB1
-#define GL_MAP2_NORMAL 0x0DB2
-#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
-#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
-#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
-#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
-#define GL_MAP2_VERTEX_3 0x0DB7
-#define GL_MAP2_VERTEX_4 0x0DB8
-#define GL_MAP_COLOR 0x0D10
-#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
-#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
-#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
-#define GL_MAP_READ_BIT 0x0001
-#define GL_MAP_STENCIL 0x0D11
-#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
-#define GL_MAP_WRITE_BIT 0x0002
-#define GL_MATRIX_MODE 0x0BA0
-#define GL_MAX 0x8008
-#define GL_MAX_3D_TEXTURE_SIZE 0x8073
-#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
-#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
-#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
-#define GL_MAX_CLIP_DISTANCES 0x0D32
-#define GL_MAX_CLIP_PLANES 0x0D32
-#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
-#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
-#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
-#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
-#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
-#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
-#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
-#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
-#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
-#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
-#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
-#define GL_MAX_DRAW_BUFFERS 0x8824
-#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
-#define GL_MAX_ELEMENTS_INDICES 0x80E9
-#define GL_MAX_ELEMENTS_VERTICES 0x80E8
-#define GL_MAX_EVAL_ORDER 0x0D30
-#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
-#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
-#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
-#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
-#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
-#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
-#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
-#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
-#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
-#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
-#define GL_MAX_INTEGER_SAMPLES 0x9110
-#define GL_MAX_LABEL_LENGTH 0x82E8
-#define GL_MAX_LIGHTS 0x0D31
-#define GL_MAX_LIST_NESTING 0x0B31
-#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
-#define GL_MAX_NAME_STACK_DEPTH 0x0D37
-#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
-#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
-#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
-#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
-#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
-#define GL_MAX_SAMPLES 0x8D57
-#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
-#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
-#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
-#define GL_MAX_TEXTURE_COORDS 0x8871
-#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
-#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
-#define GL_MAX_TEXTURE_SIZE 0x0D33
-#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
-#define GL_MAX_TEXTURE_UNITS 0x84E2
-#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
-#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
-#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
-#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
-#define GL_MAX_VARYING_COMPONENTS 0x8B4B
-#define GL_MAX_VARYING_FLOATS 0x8B4B
-#define GL_MAX_VERTEX_ATTRIBS 0x8869
-#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
-#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
-#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
-#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
-#define GL_MAX_VIEWPORT_DIMS 0x0D3A
-#define GL_MIN 0x8007
-#define GL_MINOR_VERSION 0x821C
-#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
-#define GL_MIRRORED_REPEAT 0x8370
-#define GL_MODELVIEW 0x1700
-#define GL_MODELVIEW_MATRIX 0x0BA6
-#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
-#define GL_MODULATE 0x2100
-#define GL_MULT 0x0103
-#define GL_MULTISAMPLE 0x809D
-#define GL_MULTISAMPLE_ARB 0x809D
-#define GL_MULTISAMPLE_BIT 0x20000000
-#define GL_MULTISAMPLE_BIT_ARB 0x20000000
-#define GL_N3F_V3F 0x2A25
-#define GL_NAME_STACK_DEPTH 0x0D70
-#define GL_NAND 0x150E
-#define GL_NEAREST 0x2600
-#define GL_NEAREST_MIPMAP_LINEAR 0x2702
-#define GL_NEAREST_MIPMAP_NEAREST 0x2700
-#define GL_NEVER 0x0200
-#define GL_NICEST 0x1102
-#define GL_NONE 0
-#define GL_NOOP 0x1505
-#define GL_NOR 0x1508
-#define GL_NORMALIZE 0x0BA1
-#define GL_NORMAL_ARRAY 0x8075
-#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
-#define GL_NORMAL_ARRAY_POINTER 0x808F
-#define GL_NORMAL_ARRAY_STRIDE 0x807F
-#define GL_NORMAL_ARRAY_TYPE 0x807E
-#define GL_NORMAL_MAP 0x8511
-#define GL_NOTEQUAL 0x0205
-#define GL_NO_ERROR 0
-#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
-#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
-#define GL_NUM_EXTENSIONS 0x821D
-#define GL_OBJECT_LINEAR 0x2401
-#define GL_OBJECT_PLANE 0x2501
-#define GL_OBJECT_TYPE 0x9112
-#define GL_ONE 1
-#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
-#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
-#define GL_ONE_MINUS_DST_ALPHA 0x0305
-#define GL_ONE_MINUS_DST_COLOR 0x0307
-#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
-#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
-#define GL_ONE_MINUS_SRC_ALPHA 0x0303
-#define GL_ONE_MINUS_SRC_COLOR 0x0301
-#define GL_OPERAND0_ALPHA 0x8598
-#define GL_OPERAND0_RGB 0x8590
-#define GL_OPERAND1_ALPHA 0x8599
-#define GL_OPERAND1_RGB 0x8591
-#define GL_OPERAND2_ALPHA 0x859A
-#define GL_OPERAND2_RGB 0x8592
-#define GL_OR 0x1507
-#define GL_ORDER 0x0A01
-#define GL_OR_INVERTED 0x150D
-#define GL_OR_REVERSE 0x150B
-#define GL_OUT_OF_MEMORY 0x0505
-#define GL_PACK_ALIGNMENT 0x0D05
-#define GL_PACK_IMAGE_HEIGHT 0x806C
-#define GL_PACK_LSB_FIRST 0x0D01
-#define GL_PACK_ROW_LENGTH 0x0D02
-#define GL_PACK_SKIP_IMAGES 0x806B
-#define GL_PACK_SKIP_PIXELS 0x0D04
-#define GL_PACK_SKIP_ROWS 0x0D03
-#define GL_PACK_SWAP_BYTES 0x0D00
-#define GL_PASS_THROUGH_TOKEN 0x0700
-#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
-#define GL_PIXEL_MAP_A_TO_A 0x0C79
-#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
-#define GL_PIXEL_MAP_B_TO_B 0x0C78
-#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
-#define GL_PIXEL_MAP_G_TO_G 0x0C77
-#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
-#define GL_PIXEL_MAP_I_TO_A 0x0C75
-#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
-#define GL_PIXEL_MAP_I_TO_B 0x0C74
-#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
-#define GL_PIXEL_MAP_I_TO_G 0x0C73
-#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
-#define GL_PIXEL_MAP_I_TO_I 0x0C70
-#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
-#define GL_PIXEL_MAP_I_TO_R 0x0C72
-#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
-#define GL_PIXEL_MAP_R_TO_R 0x0C76
-#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
-#define GL_PIXEL_MAP_S_TO_S 0x0C71
-#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
-#define GL_PIXEL_MODE_BIT 0x00000020
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
-#define GL_POINT 0x1B00
-#define GL_POINTS 0x0000
-#define GL_POINT_BIT 0x00000002
-#define GL_POINT_DISTANCE_ATTENUATION 0x8129
-#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
-#define GL_POINT_SIZE 0x0B11
-#define GL_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_POINT_SIZE_MAX 0x8127
-#define GL_POINT_SIZE_MIN 0x8126
-#define GL_POINT_SIZE_RANGE 0x0B12
-#define GL_POINT_SMOOTH 0x0B10
-#define GL_POINT_SMOOTH_HINT 0x0C51
-#define GL_POINT_SPRITE 0x8861
-#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
-#define GL_POINT_TOKEN 0x0701
-#define GL_POLYGON 0x0009
-#define GL_POLYGON_BIT 0x00000008
-#define GL_POLYGON_MODE 0x0B40
-#define GL_POLYGON_OFFSET_FACTOR 0x8038
-#define GL_POLYGON_OFFSET_FILL 0x8037
-#define GL_POLYGON_OFFSET_LINE 0x2A02
-#define GL_POLYGON_OFFSET_POINT 0x2A01
-#define GL_POLYGON_OFFSET_UNITS 0x2A00
-#define GL_POLYGON_SMOOTH 0x0B41
-#define GL_POLYGON_SMOOTH_HINT 0x0C53
-#define GL_POLYGON_STIPPLE 0x0B42
-#define GL_POLYGON_STIPPLE_BIT 0x00000010
-#define GL_POLYGON_TOKEN 0x0703
-#define GL_POSITION 0x1203
-#define GL_PREVIOUS 0x8578
-#define GL_PRIMARY_COLOR 0x8577
-#define GL_PRIMITIVES_GENERATED 0x8C87
-#define GL_PRIMITIVE_RESTART 0x8F9D
-#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
-#define GL_PROGRAM 0x82E2
-#define GL_PROGRAM_PIPELINE 0x82E4
-#define GL_PROGRAM_POINT_SIZE 0x8642
-#define GL_PROJECTION 0x1701
-#define GL_PROJECTION_MATRIX 0x0BA7
-#define GL_PROJECTION_STACK_DEPTH 0x0BA4
-#define GL_PROVOKING_VERTEX 0x8E4F
-#define GL_PROXY_TEXTURE_1D 0x8063
-#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
-#define GL_PROXY_TEXTURE_2D 0x8064
-#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
-#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
-#define GL_PROXY_TEXTURE_3D 0x8070
-#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
-#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
-#define GL_Q 0x2003
-#define GL_QUADRATIC_ATTENUATION 0x1209
-#define GL_QUADS 0x0007
-#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
-#define GL_QUAD_STRIP 0x0008
-#define GL_QUERY 0x82E3
-#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
-#define GL_QUERY_BY_REGION_WAIT 0x8E15
-#define GL_QUERY_COUNTER_BITS 0x8864
-#define GL_QUERY_NO_WAIT 0x8E14
-#define GL_QUERY_RESULT 0x8866
-#define GL_QUERY_RESULT_AVAILABLE 0x8867
-#define GL_QUERY_WAIT 0x8E13
-#define GL_R 0x2002
-#define GL_R11F_G11F_B10F 0x8C3A
-#define GL_R16 0x822A
-#define GL_R16F 0x822D
-#define GL_R16I 0x8233
-#define GL_R16UI 0x8234
-#define GL_R16_SNORM 0x8F98
-#define GL_R32F 0x822E
-#define GL_R32I 0x8235
-#define GL_R32UI 0x8236
-#define GL_R3_G3_B2 0x2A10
-#define GL_R8 0x8229
-#define GL_R8I 0x8231
-#define GL_R8UI 0x8232
-#define GL_R8_SNORM 0x8F94
-#define GL_RASTERIZER_DISCARD 0x8C89
-#define GL_READ_BUFFER 0x0C02
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
-#define GL_READ_ONLY 0x88B8
-#define GL_READ_WRITE 0x88BA
-#define GL_RED 0x1903
-#define GL_RED_BIAS 0x0D15
-#define GL_RED_BITS 0x0D52
-#define GL_RED_INTEGER 0x8D94
-#define GL_RED_SCALE 0x0D14
-#define GL_REFLECTION_MAP 0x8512
-#define GL_RENDER 0x1C00
-#define GL_RENDERBUFFER 0x8D41
-#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
-#define GL_RENDERBUFFER_BINDING 0x8CA7
-#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
-#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
-#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
-#define GL_RENDERBUFFER_HEIGHT 0x8D43
-#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
-#define GL_RENDERBUFFER_RED_SIZE 0x8D50
-#define GL_RENDERBUFFER_SAMPLES 0x8CAB
-#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
-#define GL_RENDERBUFFER_WIDTH 0x8D42
-#define GL_RENDERER 0x1F01
-#define GL_RENDER_MODE 0x0C40
-#define GL_REPEAT 0x2901
-#define GL_REPLACE 0x1E01
-#define GL_RESCALE_NORMAL 0x803A
-#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
-#define GL_RETURN 0x0102
-#define GL_RG 0x8227
-#define GL_RG16 0x822C
-#define GL_RG16F 0x822F
-#define GL_RG16I 0x8239
-#define GL_RG16UI 0x823A
-#define GL_RG16_SNORM 0x8F99
-#define GL_RG32F 0x8230
-#define GL_RG32I 0x823B
-#define GL_RG32UI 0x823C
-#define GL_RG8 0x822B
-#define GL_RG8I 0x8237
-#define GL_RG8UI 0x8238
-#define GL_RG8_SNORM 0x8F95
-#define GL_RGB 0x1907
-#define GL_RGB10 0x8052
-#define GL_RGB10_A2 0x8059
-#define GL_RGB10_A2UI 0x906F
-#define GL_RGB12 0x8053
-#define GL_RGB16 0x8054
-#define GL_RGB16F 0x881B
-#define GL_RGB16I 0x8D89
-#define GL_RGB16UI 0x8D77
-#define GL_RGB16_SNORM 0x8F9A
-#define GL_RGB32F 0x8815
-#define GL_RGB32I 0x8D83
-#define GL_RGB32UI 0x8D71
-#define GL_RGB4 0x804F
-#define GL_RGB5 0x8050
-#define GL_RGB5_A1 0x8057
-#define GL_RGB8 0x8051
-#define GL_RGB8I 0x8D8F
-#define GL_RGB8UI 0x8D7D
-#define GL_RGB8_SNORM 0x8F96
-#define GL_RGB9_E5 0x8C3D
-#define GL_RGBA 0x1908
-#define GL_RGBA12 0x805A
-#define GL_RGBA16 0x805B
-#define GL_RGBA16F 0x881A
-#define GL_RGBA16I 0x8D88
-#define GL_RGBA16UI 0x8D76
-#define GL_RGBA16_SNORM 0x8F9B
-#define GL_RGBA2 0x8055
-#define GL_RGBA32F 0x8814
-#define GL_RGBA32I 0x8D82
-#define GL_RGBA32UI 0x8D70
-#define GL_RGBA4 0x8056
-#define GL_RGBA8 0x8058
-#define GL_RGBA8I 0x8D8E
-#define GL_RGBA8UI 0x8D7C
-#define GL_RGBA8_SNORM 0x8F97
-#define GL_RGBA_INTEGER 0x8D99
-#define GL_RGBA_MODE 0x0C31
-#define GL_RGB_INTEGER 0x8D98
-#define GL_RGB_SCALE 0x8573
-#define GL_RG_INTEGER 0x8228
-#define GL_RIGHT 0x0407
-#define GL_S 0x2000
-#define GL_SAMPLER 0x82E6
-#define GL_SAMPLER_1D 0x8B5D
-#define GL_SAMPLER_1D_ARRAY 0x8DC0
-#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
-#define GL_SAMPLER_1D_SHADOW 0x8B61
-#define GL_SAMPLER_2D 0x8B5E
-#define GL_SAMPLER_2D_ARRAY 0x8DC1
-#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
-#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
-#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
-#define GL_SAMPLER_2D_RECT 0x8B63
-#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
-#define GL_SAMPLER_2D_SHADOW 0x8B62
-#define GL_SAMPLER_3D 0x8B5F
-#define GL_SAMPLER_BINDING 0x8919
-#define GL_SAMPLER_BUFFER 0x8DC2
-#define GL_SAMPLER_CUBE 0x8B60
-#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
-#define GL_SAMPLES 0x80A9
-#define GL_SAMPLES_ARB 0x80A9
-#define GL_SAMPLES_PASSED 0x8914
-#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
-#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
-#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
-#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
-#define GL_SAMPLE_BUFFERS 0x80A8
-#define GL_SAMPLE_BUFFERS_ARB 0x80A8
-#define GL_SAMPLE_COVERAGE 0x80A0
-#define GL_SAMPLE_COVERAGE_ARB 0x80A0
-#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
-#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
-#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
-#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
-#define GL_SAMPLE_MASK 0x8E51
-#define GL_SAMPLE_MASK_VALUE 0x8E52
-#define GL_SAMPLE_POSITION 0x8E50
-#define GL_SCISSOR_BIT 0x00080000
-#define GL_SCISSOR_BOX 0x0C10
-#define GL_SCISSOR_TEST 0x0C11
-#define GL_SECONDARY_COLOR_ARRAY 0x845E
-#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
-#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
-#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
-#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
-#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
-#define GL_SELECT 0x1C02
-#define GL_SELECTION_BUFFER_POINTER 0x0DF3
-#define GL_SELECTION_BUFFER_SIZE 0x0DF4
-#define GL_SEPARATE_ATTRIBS 0x8C8D
-#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
-#define GL_SET 0x150F
-#define GL_SHADER 0x82E1
-#define GL_SHADER_SOURCE_LENGTH 0x8B88
-#define GL_SHADER_TYPE 0x8B4F
-#define GL_SHADE_MODEL 0x0B54
-#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
-#define GL_SHININESS 0x1601
-#define GL_SHORT 0x1402
-#define GL_SIGNALED 0x9119
-#define GL_SIGNED_NORMALIZED 0x8F9C
-#define GL_SINGLE_COLOR 0x81F9
-#define GL_SLUMINANCE 0x8C46
-#define GL_SLUMINANCE8 0x8C47
-#define GL_SLUMINANCE8_ALPHA8 0x8C45
-#define GL_SLUMINANCE_ALPHA 0x8C44
-#define GL_SMOOTH 0x1D01
-#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
-#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
-#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
-#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
-#define GL_SOURCE0_ALPHA 0x8588
-#define GL_SOURCE0_RGB 0x8580
-#define GL_SOURCE1_ALPHA 0x8589
-#define GL_SOURCE1_RGB 0x8581
-#define GL_SOURCE2_ALPHA 0x858A
-#define GL_SOURCE2_RGB 0x8582
-#define GL_SPECULAR 0x1202
-#define GL_SPHERE_MAP 0x2402
-#define GL_SPOT_CUTOFF 0x1206
-#define GL_SPOT_DIRECTION 0x1204
-#define GL_SPOT_EXPONENT 0x1205
-#define GL_SRC0_ALPHA 0x8588
-#define GL_SRC0_RGB 0x8580
-#define GL_SRC1_ALPHA 0x8589
-#define GL_SRC1_COLOR 0x88F9
-#define GL_SRC1_RGB 0x8581
-#define GL_SRC2_ALPHA 0x858A
-#define GL_SRC2_RGB 0x8582
-#define GL_SRC_ALPHA 0x0302
-#define GL_SRC_ALPHA_SATURATE 0x0308
-#define GL_SRC_COLOR 0x0300
-#define GL_SRGB 0x8C40
-#define GL_SRGB8 0x8C41
-#define GL_SRGB8_ALPHA8 0x8C43
-#define GL_SRGB_ALPHA 0x8C42
-#define GL_STACK_OVERFLOW 0x0503
-#define GL_STACK_UNDERFLOW 0x0504
-#define GL_STATIC_COPY 0x88E6
-#define GL_STATIC_DRAW 0x88E4
-#define GL_STATIC_READ 0x88E5
-#define GL_STENCIL 0x1802
-#define GL_STENCIL_ATTACHMENT 0x8D20
-#define GL_STENCIL_BACK_FAIL 0x8801
-#define GL_STENCIL_BACK_FUNC 0x8800
-#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
-#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
-#define GL_STENCIL_BACK_REF 0x8CA3
-#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
-#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
-#define GL_STENCIL_BITS 0x0D57
-#define GL_STENCIL_BUFFER_BIT 0x00000400
-#define GL_STENCIL_CLEAR_VALUE 0x0B91
-#define GL_STENCIL_FAIL 0x0B94
-#define GL_STENCIL_FUNC 0x0B92
-#define GL_STENCIL_INDEX 0x1901
-#define GL_STENCIL_INDEX1 0x8D46
-#define GL_STENCIL_INDEX16 0x8D49
-#define GL_STENCIL_INDEX4 0x8D47
-#define GL_STENCIL_INDEX8 0x8D48
-#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
-#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
-#define GL_STENCIL_REF 0x0B97
-#define GL_STENCIL_TEST 0x0B90
-#define GL_STENCIL_VALUE_MASK 0x0B93
-#define GL_STENCIL_WRITEMASK 0x0B98
-#define GL_STEREO 0x0C33
-#define GL_STREAM_COPY 0x88E2
-#define GL_STREAM_DRAW 0x88E0
-#define GL_STREAM_READ 0x88E1
-#define GL_SUBPIXEL_BITS 0x0D50
-#define GL_SUBTRACT 0x84E7
-#define GL_SYNC_CONDITION 0x9113
-#define GL_SYNC_FENCE 0x9116
-#define GL_SYNC_FLAGS 0x9115
-#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
-#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
-#define GL_SYNC_STATUS 0x9114
-#define GL_T 0x2001
-#define GL_T2F_C3F_V3F 0x2A2A
-#define GL_T2F_C4F_N3F_V3F 0x2A2C
-#define GL_T2F_C4UB_V3F 0x2A29
-#define GL_T2F_N3F_V3F 0x2A2B
-#define GL_T2F_V3F 0x2A27
-#define GL_T4F_C4F_N3F_V4F 0x2A2D
-#define GL_T4F_V4F 0x2A28
-#define GL_TEXTURE 0x1702
-#define GL_TEXTURE0 0x84C0
-#define GL_TEXTURE1 0x84C1
-#define GL_TEXTURE10 0x84CA
-#define GL_TEXTURE11 0x84CB
-#define GL_TEXTURE12 0x84CC
-#define GL_TEXTURE13 0x84CD
-#define GL_TEXTURE14 0x84CE
-#define GL_TEXTURE15 0x84CF
-#define GL_TEXTURE16 0x84D0
-#define GL_TEXTURE17 0x84D1
-#define GL_TEXTURE18 0x84D2
-#define GL_TEXTURE19 0x84D3
-#define GL_TEXTURE2 0x84C2
-#define GL_TEXTURE20 0x84D4
-#define GL_TEXTURE21 0x84D5
-#define GL_TEXTURE22 0x84D6
-#define GL_TEXTURE23 0x84D7
-#define GL_TEXTURE24 0x84D8
-#define GL_TEXTURE25 0x84D9
-#define GL_TEXTURE26 0x84DA
-#define GL_TEXTURE27 0x84DB
-#define GL_TEXTURE28 0x84DC
-#define GL_TEXTURE29 0x84DD
-#define GL_TEXTURE3 0x84C3
-#define GL_TEXTURE30 0x84DE
-#define GL_TEXTURE31 0x84DF
-#define GL_TEXTURE4 0x84C4
-#define GL_TEXTURE5 0x84C5
-#define GL_TEXTURE6 0x84C6
-#define GL_TEXTURE7 0x84C7
-#define GL_TEXTURE8 0x84C8
-#define GL_TEXTURE9 0x84C9
-#define GL_TEXTURE_1D 0x0DE0
-#define GL_TEXTURE_1D_ARRAY 0x8C18
-#define GL_TEXTURE_2D 0x0DE1
-#define GL_TEXTURE_2D_ARRAY 0x8C1A
-#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
-#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
-#define GL_TEXTURE_3D 0x806F
-#define GL_TEXTURE_ALPHA_SIZE 0x805F
-#define GL_TEXTURE_ALPHA_TYPE 0x8C13
-#define GL_TEXTURE_BASE_LEVEL 0x813C
-#define GL_TEXTURE_BINDING_1D 0x8068
-#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
-#define GL_TEXTURE_BINDING_2D 0x8069
-#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
-#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
-#define GL_TEXTURE_BINDING_3D 0x806A
-#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
-#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
-#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
-#define GL_TEXTURE_BIT 0x00040000
-#define GL_TEXTURE_BLUE_SIZE 0x805E
-#define GL_TEXTURE_BLUE_TYPE 0x8C12
-#define GL_TEXTURE_BORDER 0x1005
-#define GL_TEXTURE_BORDER_COLOR 0x1004
-#define GL_TEXTURE_BUFFER 0x8C2A
-#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
-#define GL_TEXTURE_COMPARE_FUNC 0x884D
-#define GL_TEXTURE_COMPARE_MODE 0x884C
-#define GL_TEXTURE_COMPONENTS 0x1003
-#define GL_TEXTURE_COMPRESSED 0x86A1
-#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
-#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
-#define GL_TEXTURE_COORD_ARRAY 0x8078
-#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
-#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
-#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
-#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
-#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
-#define GL_TEXTURE_CUBE_MAP 0x8513
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
-#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
-#define GL_TEXTURE_DEPTH 0x8071
-#define GL_TEXTURE_DEPTH_SIZE 0x884A
-#define GL_TEXTURE_DEPTH_TYPE 0x8C16
-#define GL_TEXTURE_ENV 0x2300
-#define GL_TEXTURE_ENV_COLOR 0x2201
-#define GL_TEXTURE_ENV_MODE 0x2200
-#define GL_TEXTURE_FILTER_CONTROL 0x8500
-#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
-#define GL_TEXTURE_GEN_MODE 0x2500
-#define GL_TEXTURE_GEN_Q 0x0C63
-#define GL_TEXTURE_GEN_R 0x0C62
-#define GL_TEXTURE_GEN_S 0x0C60
-#define GL_TEXTURE_GEN_T 0x0C61
-#define GL_TEXTURE_GREEN_SIZE 0x805D
-#define GL_TEXTURE_GREEN_TYPE 0x8C11
-#define GL_TEXTURE_HEIGHT 0x1001
-#define GL_TEXTURE_INTENSITY_SIZE 0x8061
-#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
-#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
-#define GL_TEXTURE_LOD_BIAS 0x8501
-#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
-#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
-#define GL_TEXTURE_MAG_FILTER 0x2800
-#define GL_TEXTURE_MATRIX 0x0BA8
-#define GL_TEXTURE_MAX_LEVEL 0x813D
-#define GL_TEXTURE_MAX_LOD 0x813B
-#define GL_TEXTURE_MIN_FILTER 0x2801
-#define GL_TEXTURE_MIN_LOD 0x813A
-#define GL_TEXTURE_PRIORITY 0x8066
-#define GL_TEXTURE_RECTANGLE 0x84F5
-#define GL_TEXTURE_RED_SIZE 0x805C
-#define GL_TEXTURE_RED_TYPE 0x8C10
-#define GL_TEXTURE_RESIDENT 0x8067
-#define GL_TEXTURE_SAMPLES 0x9106
-#define GL_TEXTURE_SHARED_SIZE 0x8C3F
-#define GL_TEXTURE_STACK_DEPTH 0x0BA5
-#define GL_TEXTURE_STENCIL_SIZE 0x88F1
-#define GL_TEXTURE_SWIZZLE_A 0x8E45
-#define GL_TEXTURE_SWIZZLE_B 0x8E44
-#define GL_TEXTURE_SWIZZLE_G 0x8E43
-#define GL_TEXTURE_SWIZZLE_R 0x8E42
-#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
-#define GL_TEXTURE_WIDTH 0x1000
-#define GL_TEXTURE_WRAP_R 0x8072
-#define GL_TEXTURE_WRAP_S 0x2802
-#define GL_TEXTURE_WRAP_T 0x2803
-#define GL_TIMEOUT_EXPIRED 0x911B
-#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
-#define GL_TIMESTAMP 0x8E28
-#define GL_TIME_ELAPSED 0x88BF
-#define GL_TRANSFORM_BIT 0x00001000
-#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
-#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
-#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
-#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
-#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
-#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
-#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
-#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
-#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
-#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
-#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
-#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
-#define GL_TRIANGLES 0x0004
-#define GL_TRIANGLES_ADJACENCY 0x000C
-#define GL_TRIANGLE_FAN 0x0006
-#define GL_TRIANGLE_STRIP 0x0005
-#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
-#define GL_TRUE 1
-#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
-#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
-#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
-#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
-#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
-#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
-#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
-#define GL_UNIFORM_BUFFER 0x8A11
-#define GL_UNIFORM_BUFFER_BINDING 0x8A28
-#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
-#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
-#define GL_UNIFORM_BUFFER_START 0x8A29
-#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
-#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
-#define GL_UNIFORM_NAME_LENGTH 0x8A39
-#define GL_UNIFORM_OFFSET 0x8A3B
-#define GL_UNIFORM_SIZE 0x8A38
-#define GL_UNIFORM_TYPE 0x8A37
-#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
-#define GL_UNPACK_ALIGNMENT 0x0CF5
-#define GL_UNPACK_IMAGE_HEIGHT 0x806E
-#define GL_UNPACK_LSB_FIRST 0x0CF1
-#define GL_UNPACK_ROW_LENGTH 0x0CF2
-#define GL_UNPACK_SKIP_IMAGES 0x806D
-#define GL_UNPACK_SKIP_PIXELS 0x0CF4
-#define GL_UNPACK_SKIP_ROWS 0x0CF3
-#define GL_UNPACK_SWAP_BYTES 0x0CF0
-#define GL_UNSIGNALED 0x9118
-#define GL_UNSIGNED_BYTE 0x1401
-#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
-#define GL_UNSIGNED_BYTE_3_3_2 0x8032
-#define GL_UNSIGNED_INT 0x1405
-#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
-#define GL_UNSIGNED_INT_10_10_10_2 0x8036
-#define GL_UNSIGNED_INT_24_8 0x84FA
-#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
-#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
-#define GL_UNSIGNED_INT_8_8_8_8 0x8035
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
-#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
-#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
-#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
-#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
-#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
-#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
-#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
-#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
-#define GL_UNSIGNED_INT_VEC2 0x8DC6
-#define GL_UNSIGNED_INT_VEC3 0x8DC7
-#define GL_UNSIGNED_INT_VEC4 0x8DC8
-#define GL_UNSIGNED_NORMALIZED 0x8C17
-#define GL_UNSIGNED_SHORT 0x1403
-#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
-#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
-#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
-#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
-#define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
-#define GL_UPPER_LEFT 0x8CA2
-#define GL_V2F 0x2A20
-#define GL_V3F 0x2A21
-#define GL_VALIDATE_STATUS 0x8B83
-#define GL_VENDOR 0x1F00
-#define GL_VERSION 0x1F02
-#define GL_VERTEX_ARRAY 0x8074
-#define GL_VERTEX_ARRAY_BINDING 0x85B5
-#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
-#define GL_VERTEX_ARRAY_POINTER 0x808E
-#define GL_VERTEX_ARRAY_SIZE 0x807A
-#define GL_VERTEX_ARRAY_STRIDE 0x807C
-#define GL_VERTEX_ARRAY_TYPE 0x807B
-#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
-#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
-#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
-#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
-#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
-#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
-#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
-#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
-#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
-#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
-#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
-#define GL_VERTEX_SHADER 0x8B31
-#define GL_VIEWPORT 0x0BA2
-#define GL_VIEWPORT_BIT 0x00000800
-#define GL_WAIT_FAILED 0x911D
-#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
-#define GL_WRITE_ONLY 0x88B9
-#define GL_XOR 0x1506
-#define GL_ZERO 0
-#define GL_ZOOM_X 0x0D16
-#define GL_ZOOM_Y 0x0D17
-
-
-#include <glad/khrplatform.h>
-typedef unsigned int GLenum;
-typedef unsigned char GLboolean;
-typedef unsigned int GLbitfield;
-typedef void GLvoid;
-typedef khronos_int8_t GLbyte;
-typedef khronos_uint8_t GLubyte;
-typedef khronos_int16_t GLshort;
-typedef khronos_uint16_t GLushort;
-typedef int GLint;
-typedef unsigned int GLuint;
-typedef khronos_int32_t GLclampx;
-typedef int GLsizei;
-typedef khronos_float_t GLfloat;
-typedef khronos_float_t GLclampf;
-typedef double GLdouble;
-typedef double GLclampd;
-typedef void *GLeglClientBufferEXT;
-typedef void *GLeglImageOES;
-typedef char GLchar;
-typedef char GLcharARB;
-#ifdef __APPLE__
-typedef void *GLhandleARB;
-#else
-typedef unsigned int GLhandleARB;
-#endif
-typedef khronos_uint16_t GLhalf;
-typedef khronos_uint16_t GLhalfARB;
-typedef khronos_int32_t GLfixed;
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef khronos_intptr_t GLintptr;
-#else
-typedef khronos_intptr_t GLintptr;
-#endif
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef khronos_intptr_t GLintptrARB;
-#else
-typedef khronos_intptr_t GLintptrARB;
-#endif
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef khronos_ssize_t GLsizeiptr;
-#else
-typedef khronos_ssize_t GLsizeiptr;
-#endif
-#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
-typedef khronos_ssize_t GLsizeiptrARB;
-#else
-typedef khronos_ssize_t GLsizeiptrARB;
-#endif
-typedef khronos_int64_t GLint64;
-typedef khronos_int64_t GLint64EXT;
-typedef khronos_uint64_t GLuint64;
-typedef khronos_uint64_t GLuint64EXT;
-typedef struct __GLsync *GLsync;
-struct _cl_context;
-struct _cl_event;
-typedef void ( *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void ( *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void ( *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
-typedef void ( *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
-typedef unsigned short GLhalfNV;
-typedef GLintptr GLvdpauSurfaceNV;
-typedef void ( *GLVULKANPROCNV)(void);
-
-
-#define GL_VERSION_1_0 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_0;
-#define GL_VERSION_1_1 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_1;
-#define GL_VERSION_1_2 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_2;
-#define GL_VERSION_1_3 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_3;
-#define GL_VERSION_1_4 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_4;
-#define GL_VERSION_1_5 1
-GLAD_API_CALL int GLAD_GL_VERSION_1_5;
-#define GL_VERSION_2_0 1
-GLAD_API_CALL int GLAD_GL_VERSION_2_0;
-#define GL_VERSION_2_1 1
-GLAD_API_CALL int GLAD_GL_VERSION_2_1;
-#define GL_VERSION_3_0 1
-GLAD_API_CALL int GLAD_GL_VERSION_3_0;
-#define GL_VERSION_3_1 1
-GLAD_API_CALL int GLAD_GL_VERSION_3_1;
-#define GL_VERSION_3_2 1
-GLAD_API_CALL int GLAD_GL_VERSION_3_2;
-#define GL_VERSION_3_3 1
-GLAD_API_CALL int GLAD_GL_VERSION_3_3;
-#define GL_ARB_multisample 1
-GLAD_API_CALL int GLAD_GL_ARB_multisample;
-#define GL_ARB_robustness 1
-GLAD_API_CALL int GLAD_GL_ARB_robustness;
-#define GL_KHR_debug 1
-GLAD_API_CALL int GLAD_GL_KHR_debug;
-
-
-typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum   op, GLfloat   value);
-typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum   texture);
-typedef void (GLAD_API_PTR *PFNGLALPHAFUNCPROC)(GLenum   func, GLfloat   ref);
-typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTPROC)(GLsizei   n, const  GLuint  * textures, GLboolean  * residences);
-typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTPROC)(GLint   i);
-typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint   program, GLuint   shader);
-typedef void (GLAD_API_PTR *PFNGLBEGINPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint   id, GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum   target, GLuint   id);
-typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum   primitiveMode);
-typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint   program, GLuint   index, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum   target, GLuint   buffer);
-typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum   target, GLuint   index, GLuint   buffer);
-typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum   target, GLuint   index, GLuint   buffer, GLintptr   offset, GLsizeiptr   size);
-typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint   program, GLuint   color, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint   program, GLuint   colorNumber, GLuint   index, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum   target, GLuint   framebuffer);
-typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum   target, GLuint   renderbuffer);
-typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint   unit, GLuint   sampler);
-typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum   target, GLuint   texture);
-typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint   array);
-typedef void (GLAD_API_PTR *PFNGLBITMAPPROC)(GLsizei   width, GLsizei   height, GLfloat   xorig, GLfloat   yorig, GLfloat   xmove, GLfloat   ymove, const  GLubyte  * bitmap);
-typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
-typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum   modeRGB, GLenum   modeAlpha);
-typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum   sfactor, GLenum   dfactor);
-typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum   sfactorRGB, GLenum   dfactorRGB, GLenum   sfactorAlpha, GLenum   dfactorAlpha);
-typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint   srcX0, GLint   srcY0, GLint   srcX1, GLint   srcY1, GLint   dstX0, GLint   dstY0, GLint   dstX1, GLint   dstY1, GLbitfield   mask, GLenum   filter);
-typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum   target, GLsizeiptr   size, const void * data, GLenum   usage);
-typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   size, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCALLLISTPROC)(GLuint   list);
-typedef void (GLAD_API_PTR *PFNGLCALLLISTSPROC)(GLsizei   n, GLenum   type, const void * lists);
-typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum   target);
-typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum   target, GLenum   clamp);
-typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield   mask);
-typedef void (GLAD_API_PTR *PFNGLCLEARACCUMPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
-typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum   buffer, GLint   drawbuffer, GLfloat   depth, GLint   stencil);
-typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLint  * value);
-typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
-typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble   depth);
-typedef void (GLAD_API_PTR *PFNGLCLEARINDEXPROC)(GLfloat   c);
-typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint   s);
-typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREPROC)(GLenum   texture);
-typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync   sync, GLbitfield   flags, GLuint64   timeout);
-typedef void (GLAD_API_PTR *PFNGLCLIPPLANEPROC)(GLenum   plane, const  GLdouble  * equation);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3BVPROC)(const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3IPROC)(GLint   red, GLint   green, GLint   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3SPROC)(GLshort   red, GLshort   green, GLshort   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3UBVPROC)(const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3UIPROC)(GLuint   red, GLuint   green, GLuint   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3UIVPROC)(const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3USPROC)(GLushort   red, GLushort   green, GLushort   blue);
-typedef void (GLAD_API_PTR *PFNGLCOLOR3USVPROC)(const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue, GLbyte   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4BVPROC)(const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue, GLdouble   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4IPROC)(GLint   red, GLint   green, GLint   blue, GLint   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4SPROC)(GLshort   red, GLshort   green, GLshort   blue, GLshort   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue, GLubyte   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4UBVPROC)(const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4UIPROC)(GLuint   red, GLuint   green, GLuint   blue, GLuint   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4UIVPROC)(const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4USPROC)(GLushort   red, GLushort   green, GLushort   blue, GLushort   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLOR4USVPROC)(const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean   red, GLboolean   green, GLboolean   blue, GLboolean   alpha);
-typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint   index, GLboolean   r, GLboolean   g, GLboolean   b, GLboolean   a);
-typedef void (GLAD_API_PTR *PFNGLCOLORMATERIALPROC)(GLenum   face, GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLCOLORP3UIPROC)(GLenum   type, GLuint   color);
-typedef void (GLAD_API_PTR *PFNGLCOLORP3UIVPROC)(GLenum   type, const  GLuint  * color);
-typedef void (GLAD_API_PTR *PFNGLCOLORP4UIPROC)(GLenum   type, GLuint   color);
-typedef void (GLAD_API_PTR *PFNGLCOLORP4UIVPROC)(GLenum   type, const  GLuint  * color);
-typedef void (GLAD_API_PTR *PFNGLCOLORPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint   shader);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLint   border, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLsizei   height, GLint   border, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLint   border, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLsizei   width, GLenum   format, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLsizei   width, GLsizei   height, GLenum   format, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLsizei   width, GLsizei   height, GLsizei   depth, GLenum   format, GLsizei   imageSize, const void * data);
-typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum   readTarget, GLenum   writeTarget, GLintptr   readOffset, GLintptr   writeOffset, GLsizeiptr   size);
-typedef void (GLAD_API_PTR *PFNGLCOPYPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   type);
-typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLint   x, GLint   y, GLsizei   width, GLint   border);
-typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLint   border);
-typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   x, GLint   y, GLsizei   width);
-typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   x, GLint   y, GLsizei   width, GLsizei   height);
-typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLint   x, GLint   y, GLsizei   width, GLsizei   height);
-typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
-typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum   type);
-typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC   callback, const void * userParam);
-typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum   source, GLenum   type, GLenum   severity, GLsizei   count, const  GLuint  * ids, GLboolean   enabled);
-typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum   source, GLenum   type, GLuint   id, GLenum   severity, GLsizei   length, const  GLchar  * buf);
-typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei   n, const  GLuint  * buffers);
-typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei   n, const  GLuint  * framebuffers);
-typedef void (GLAD_API_PTR *PFNGLDELETELISTSPROC)(GLuint   list, GLsizei   range);
-typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint   program);
-typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei   n, const  GLuint  * ids);
-typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei   n, const  GLuint  * renderbuffers);
-typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei   count, const  GLuint  * samplers);
-typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint   shader);
-typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync   sync);
-typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei   n, const  GLuint  * textures);
-typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei   n, const  GLuint  * arrays);
-typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum   func);
-typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean   flag);
-typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble   n, GLdouble   f);
-typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint   program, GLuint   shader);
-typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum   cap);
-typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEPROC)(GLenum   array);
-typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum   target, GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum   mode, GLint   first, GLsizei   count);
-typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum   mode, GLint   first, GLsizei   count, GLsizei   instancecount);
-typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum   buf);
-typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei   n, const  GLenum  * bufs);
-typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices);
-typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLint   basevertex);
-typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLsizei   instancecount);
-typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLsizei   instancecount, GLint   basevertex);
-typedef void (GLAD_API_PTR *PFNGLDRAWPIXELSPROC)(GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum   mode, GLuint   start, GLuint   end, GLsizei   count, GLenum   type, const void * indices);
-typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum   mode, GLuint   start, GLuint   end, GLsizei   count, GLenum   type, const void * indices, GLint   basevertex);
-typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPROC)(GLboolean   flag);
-typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTERPROC)(GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLEDGEFLAGVPROC)(const  GLboolean  * flag);
-typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum   cap);
-typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEPROC)(GLenum   array);
-typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum   target, GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLENDPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLENDLISTPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum   target);
-typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DPROC)(GLdouble   u);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DVPROC)(const  GLdouble  * u);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FPROC)(GLfloat   u);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FVPROC)(const  GLfloat  * u);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DPROC)(GLdouble   u, GLdouble   v);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DVPROC)(const  GLdouble  * u);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FPROC)(GLfloat   u, GLfloat   v);
-typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FVPROC)(const  GLfloat  * u);
-typedef void (GLAD_API_PTR *PFNGLEVALMESH1PROC)(GLenum   mode, GLint   i1, GLint   i2);
-typedef void (GLAD_API_PTR *PFNGLEVALMESH2PROC)(GLenum   mode, GLint   i1, GLint   i2, GLint   j1, GLint   j2);
-typedef void (GLAD_API_PTR *PFNGLEVALPOINT1PROC)(GLint   i);
-typedef void (GLAD_API_PTR *PFNGLEVALPOINT2PROC)(GLint   i, GLint   j);
-typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERPROC)(GLsizei   size, GLenum   type, GLfloat  * buffer);
-typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum   condition, GLbitfield   flags);
-typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   length);
-typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLFOGCOORDDPROC)(GLdouble   coord);
-typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVPROC)(const  GLdouble  * coord);
-typedef void (GLAD_API_PTR *PFNGLFOGCOORDFPROC)(GLfloat   coord);
-typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVPROC)(const  GLfloat  * coord);
-typedef void (GLAD_API_PTR *PFNGLFOGFPROC)(GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLFOGFVPROC)(GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLFOGIPROC)(GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLFOGIVPROC)(GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum   target, GLenum   attachment, GLenum   renderbuffertarget, GLuint   renderbuffer);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum   target, GLenum   attachment, GLuint   texture, GLint   level);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level, GLint   zoffset);
-typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum   target, GLenum   attachment, GLuint   texture, GLint   level, GLint   layer);
-typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLFRUSTUMPROC)(GLdouble   left, GLdouble   right, GLdouble   bottom, GLdouble   top, GLdouble   zNear, GLdouble   zFar);
-typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei   n, GLuint  * buffers);
-typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei   n, GLuint  * framebuffers);
-typedef GLuint (GLAD_API_PTR *PFNGLGENLISTSPROC)(GLsizei   range);
-typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei   n, GLuint  * ids);
-typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei   n, GLuint  * renderbuffers);
-typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei   count, GLuint  * samplers);
-typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei   n, GLuint  * textures);
-typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei   n, GLuint  * arrays);
-typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum   target);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLint  * size, GLenum  * type, GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLint  * size, GLenum  * type, GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint   program, GLuint   uniformBlockIndex, GLsizei   bufSize, GLsizei  * length, GLchar  * uniformBlockName);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint   program, GLuint   uniformBlockIndex, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint   program, GLuint   uniformIndex, GLsizei   bufSize, GLsizei  * length, GLchar  * uniformName);
-typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint   program, GLsizei   uniformCount, const  GLuint  * uniformIndices, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint   program, GLsizei   maxCount, GLsizei  * count, GLuint  * shaders);
-typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint   program, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum   target, GLuint   index, GLboolean  * data);
-typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum   pname, GLboolean  * data);
-typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum   target, GLenum   pname, GLint64  * params);
-typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum   target, GLenum   pname, void ** params);
-typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   size, void * data);
-typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEPROC)(GLenum   plane, GLdouble  * equation);
-typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum   target, GLint   level, void * img);
-typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint   count, GLsizei   bufSize, GLenum  * sources, GLenum  * types, GLuint  * ids, GLenum  * severities, GLsizei  * lengths, GLchar  * messageLog);
-typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum   pname, GLdouble  * data);
-typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum   pname, GLfloat  * data);
-typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint   program, const  GLchar  * name);
-typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint   program, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum   target, GLenum   attachment, GLenum   pname, GLint  * params);
-typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSARBPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum   target, GLuint   index, GLint64  * data);
-typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum   pname, GLint64  * data);
-typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum   target, GLuint   index, GLint  * data);
-typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum   pname, GLint  * data);
-typedef void (GLAD_API_PTR *PFNGLGETLIGHTFVPROC)(GLenum   light, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETLIGHTIVPROC)(GLenum   light, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETMAPDVPROC)(GLenum   target, GLenum   query, GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLGETMAPFVPROC)(GLenum   target, GLenum   query, GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLGETMAPIVPROC)(GLenum   target, GLenum   query, GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLGETMATERIALFVPROC)(GLenum   face, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETMATERIALIVPROC)(GLenum   face, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum   pname, GLuint   index, GLfloat  * val);
-typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELPROC)(GLenum   identifier, GLuint   name, GLsizei   bufSize, GLsizei  * length, GLchar  * label);
-typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELPROC)(const void * ptr, GLsizei   bufSize, GLsizei  * length, GLchar  * label);
-typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPFVPROC)(GLenum   map, GLfloat  * values);
-typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUIVPROC)(GLenum   map, GLuint  * values);
-typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUSVPROC)(GLenum   map, GLushort  * values);
-typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum   pname, void ** params);
-typedef void (GLAD_API_PTR *PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte  * mask);
-typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint   program, GLsizei   bufSize, GLsizei  * length, GLchar  * infoLog);
-typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint   program, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint   id, GLenum   pname, GLint64  * params);
-typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint   id, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint   id, GLenum   pname, GLuint64  * params);
-typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint   id, GLenum   pname, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint   sampler, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint   sampler, GLenum   pname, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint   sampler, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint   sampler, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint   shader, GLsizei   bufSize, GLsizei  * length, GLchar  * infoLog);
-typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint   shader, GLsizei   bufSize, GLsizei  * length, GLchar  * source);
-typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint   shader, GLenum   pname, GLint  * params);
-typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum   name);
-typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum   name, GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync   sync, GLenum   pname, GLsizei   bufSize, GLsizei  * length, GLint  * values);
-typedef void (GLAD_API_PTR *PFNGLGETTEXENVFVPROC)(GLenum   target, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXENVIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXGENDVPROC)(GLenum   coord, GLenum   pname, GLdouble  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXGENFVPROC)(GLenum   coord, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXGENIVPROC)(GLenum   coord, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum   target, GLint   level, GLenum   format, GLenum   type, void * pixels);
-typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum   target, GLint   level, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum   target, GLint   level, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum   target, GLenum   pname, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum   target, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLsizei  * size, GLenum  * type, GLchar  * name);
-typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint   program, const  GLchar  * uniformBlockName);
-typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint   program, GLsizei   uniformCount, const  GLchar  *const* uniformNames, GLuint  * uniformIndices);
-typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint   program, const  GLchar  * name);
-typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint   program, GLint   location, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint   program, GLint   location, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint   program, GLint   location, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint   index, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint   index, GLenum   pname, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint   index, GLenum   pname, void ** pointer);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint   index, GLenum   pname, GLdouble  * params);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint   index, GLenum   pname, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint   index, GLenum   pname, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETNCOLORTABLEARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   bufSize, void * table);
-typedef void (GLAD_API_PTR *PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC)(GLenum   target, GLint   lod, GLsizei   bufSize, void * img);
-typedef void (GLAD_API_PTR *PFNGLGETNCONVOLUTIONFILTERARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   bufSize, void * image);
-typedef void (GLAD_API_PTR *PFNGLGETNHISTOGRAMARBPROC)(GLenum   target, GLboolean   reset, GLenum   format, GLenum   type, GLsizei   bufSize, void * values);
-typedef void (GLAD_API_PTR *PFNGLGETNMAPDVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLGETNMAPFVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLGETNMAPIVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLGETNMINMAXARBPROC)(GLenum   target, GLboolean   reset, GLenum   format, GLenum   type, GLsizei   bufSize, void * values);
-typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPFVARBPROC)(GLenum   map, GLsizei   bufSize, GLfloat  * values);
-typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUIVARBPROC)(GLenum   map, GLsizei   bufSize, GLuint  * values);
-typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUSVARBPROC)(GLenum   map, GLsizei   bufSize, GLushort  * values);
-typedef void (GLAD_API_PTR *PFNGLGETNPOLYGONSTIPPLEARBPROC)(GLsizei   bufSize, GLubyte  * pattern);
-typedef void (GLAD_API_PTR *PFNGLGETNSEPARABLEFILTERARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   rowBufSize, void * row, GLsizei   columnBufSize, void * column, void * span);
-typedef void (GLAD_API_PTR *PFNGLGETNTEXIMAGEARBPROC)(GLenum   target, GLint   level, GLenum   format, GLenum   type, GLsizei   bufSize, void * img);
-typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMDVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLdouble  * params);
-typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum   target, GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLINDEXMASKPROC)(GLuint   mask);
-typedef void (GLAD_API_PTR *PFNGLINDEXPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLINDEXDPROC)(GLdouble   c);
-typedef void (GLAD_API_PTR *PFNGLINDEXDVPROC)(const  GLdouble  * c);
-typedef void (GLAD_API_PTR *PFNGLINDEXFPROC)(GLfloat   c);
-typedef void (GLAD_API_PTR *PFNGLINDEXFVPROC)(const  GLfloat  * c);
-typedef void (GLAD_API_PTR *PFNGLINDEXIPROC)(GLint   c);
-typedef void (GLAD_API_PTR *PFNGLINDEXIVPROC)(const  GLint  * c);
-typedef void (GLAD_API_PTR *PFNGLINDEXSPROC)(GLshort   c);
-typedef void (GLAD_API_PTR *PFNGLINDEXSVPROC)(const  GLshort  * c);
-typedef void (GLAD_API_PTR *PFNGLINDEXUBPROC)(GLubyte   c);
-typedef void (GLAD_API_PTR *PFNGLINDEXUBVPROC)(const  GLubyte  * c);
-typedef void (GLAD_API_PTR *PFNGLINITNAMESPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLINTERLEAVEDARRAYSPROC)(GLenum   format, GLsizei   stride, const void * pointer);
-typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint   buffer);
-typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum   cap);
-typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum   target, GLuint   index);
-typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint   framebuffer);
-typedef GLboolean (GLAD_API_PTR *PFNGLISLISTPROC)(GLuint   list);
-typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint   program);
-typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint   id);
-typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint   renderbuffer);
-typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint   sampler);
-typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint   shader);
-typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync   sync);
-typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint   texture);
-typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint   array);
-typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFPROC)(GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFVPROC)(GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIPROC)(GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIVPROC)(GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLLIGHTFPROC)(GLenum   light, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLLIGHTFVPROC)(GLenum   light, GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLLIGHTIPROC)(GLenum   light, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLLIGHTIVPROC)(GLenum   light, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLLINESTIPPLEPROC)(GLint   factor, GLushort   pattern);
-typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat   width);
-typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint   program);
-typedef void (GLAD_API_PTR *PFNGLLISTBASEPROC)(GLuint   base);
-typedef void (GLAD_API_PTR *PFNGLLOADIDENTITYPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLLOADMATRIXDPROC)(const  GLdouble  * m);
-typedef void (GLAD_API_PTR *PFNGLLOADMATRIXFPROC)(const  GLfloat  * m);
-typedef void (GLAD_API_PTR *PFNGLLOADNAMEPROC)(GLuint   name);
-typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDPROC)(const  GLdouble  * m);
-typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFPROC)(const  GLfloat  * m);
-typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum   opcode);
-typedef void (GLAD_API_PTR *PFNGLMAP1DPROC)(GLenum   target, GLdouble   u1, GLdouble   u2, GLint   stride, GLint   order, const  GLdouble  * points);
-typedef void (GLAD_API_PTR *PFNGLMAP1FPROC)(GLenum   target, GLfloat   u1, GLfloat   u2, GLint   stride, GLint   order, const  GLfloat  * points);
-typedef void (GLAD_API_PTR *PFNGLMAP2DPROC)(GLenum   target, GLdouble   u1, GLdouble   u2, GLint   ustride, GLint   uorder, GLdouble   v1, GLdouble   v2, GLint   vstride, GLint   vorder, const  GLdouble  * points);
-typedef void (GLAD_API_PTR *PFNGLMAP2FPROC)(GLenum   target, GLfloat   u1, GLfloat   u2, GLint   ustride, GLint   uorder, GLfloat   v1, GLfloat   v2, GLint   vstride, GLint   vorder, const  GLfloat  * points);
-typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum   target, GLenum   access);
-typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   length, GLbitfield   access);
-typedef void (GLAD_API_PTR *PFNGLMAPGRID1DPROC)(GLint   un, GLdouble   u1, GLdouble   u2);
-typedef void (GLAD_API_PTR *PFNGLMAPGRID1FPROC)(GLint   un, GLfloat   u1, GLfloat   u2);
-typedef void (GLAD_API_PTR *PFNGLMAPGRID2DPROC)(GLint   un, GLdouble   u1, GLdouble   u2, GLint   vn, GLdouble   v1, GLdouble   v2);
-typedef void (GLAD_API_PTR *PFNGLMAPGRID2FPROC)(GLint   un, GLfloat   u1, GLfloat   u2, GLint   vn, GLfloat   v1, GLfloat   v2);
-typedef void (GLAD_API_PTR *PFNGLMATERIALFPROC)(GLenum   face, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLMATERIALFVPROC)(GLenum   face, GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLMATERIALIPROC)(GLenum   face, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLMATERIALIVPROC)(GLenum   face, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLMATRIXMODEPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLMULTMATRIXDPROC)(const  GLdouble  * m);
-typedef void (GLAD_API_PTR *PFNGLMULTMATRIXFPROC)(const  GLfloat  * m);
-typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDPROC)(const  GLdouble  * m);
-typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFPROC)(const  GLfloat  * m);
-typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum   mode, const  GLint  * first, const  GLsizei  * count, GLsizei   drawcount);
-typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum   mode, const  GLsizei  * count, GLenum   type, const void *const* indices, GLsizei   drawcount);
-typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum   mode, const  GLsizei  * count, GLenum   type, const void *const* indices, GLsizei   drawcount, const  GLint  * basevertex);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DPROC)(GLenum   target, GLdouble   s);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVPROC)(GLenum   target, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FPROC)(GLenum   target, GLfloat   s);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVPROC)(GLenum   target, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IPROC)(GLenum   target, GLint   s);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVPROC)(GLenum   target, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SPROC)(GLenum   target, GLshort   s);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVPROC)(GLenum   target, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DPROC)(GLenum   target, GLdouble   s, GLdouble   t);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVPROC)(GLenum   target, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FPROC)(GLenum   target, GLfloat   s, GLfloat   t);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVPROC)(GLenum   target, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IPROC)(GLenum   target, GLint   s, GLint   t);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVPROC)(GLenum   target, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SPROC)(GLenum   target, GLshort   s, GLshort   t);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVPROC)(GLenum   target, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DPROC)(GLenum   target, GLdouble   s, GLdouble   t, GLdouble   r);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVPROC)(GLenum   target, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FPROC)(GLenum   target, GLfloat   s, GLfloat   t, GLfloat   r);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVPROC)(GLenum   target, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IPROC)(GLenum   target, GLint   s, GLint   t, GLint   r);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVPROC)(GLenum   target, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SPROC)(GLenum   target, GLshort   s, GLshort   t, GLshort   r);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVPROC)(GLenum   target, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DPROC)(GLenum   target, GLdouble   s, GLdouble   t, GLdouble   r, GLdouble   q);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVPROC)(GLenum   target, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FPROC)(GLenum   target, GLfloat   s, GLfloat   t, GLfloat   r, GLfloat   q);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVPROC)(GLenum   target, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IPROC)(GLenum   target, GLint   s, GLint   t, GLint   r, GLint   q);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVPROC)(GLenum   target, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SPROC)(GLenum   target, GLshort   s, GLshort   t, GLshort   r, GLshort   q);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVPROC)(GLenum   target, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint   list, GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte   nx, GLbyte   ny, GLbyte   nz);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3DPROC)(GLdouble   nx, GLdouble   ny, GLdouble   nz);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3FPROC)(GLfloat   nx, GLfloat   ny, GLfloat   nz);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3IPROC)(GLint   nx, GLint   ny, GLint   nz);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3SPROC)(GLshort   nx, GLshort   ny, GLshort   nz);
-typedef void (GLAD_API_PTR *PFNGLNORMAL3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLNORMALP3UIPROC)(GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLNORMALP3UIVPROC)(GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLNORMALPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLOBJECTLABELPROC)(GLenum   identifier, GLuint   name, GLsizei   length, const  GLchar  * label);
-typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELPROC)(const void * ptr, GLsizei   length, const  GLchar  * label);
-typedef void (GLAD_API_PTR *PFNGLORTHOPROC)(GLdouble   left, GLdouble   right, GLdouble   bottom, GLdouble   top, GLdouble   zNear, GLdouble   zFar);
-typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHPROC)(GLfloat   token);
-typedef void (GLAD_API_PTR *PFNGLPIXELMAPFVPROC)(GLenum   map, GLsizei   mapsize, const  GLfloat  * values);
-typedef void (GLAD_API_PTR *PFNGLPIXELMAPUIVPROC)(GLenum   map, GLsizei   mapsize, const  GLuint  * values);
-typedef void (GLAD_API_PTR *PFNGLPIXELMAPUSVPROC)(GLenum   map, GLsizei   mapsize, const  GLushort  * values);
-typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERFPROC)(GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERIPROC)(GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLPIXELZOOMPROC)(GLfloat   xfactor, GLfloat   yfactor);
-typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat   size);
-typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum   face, GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat   factor, GLfloat   units);
-typedef void (GLAD_API_PTR *PFNGLPOLYGONSTIPPLEPROC)(const  GLubyte  * mask);
-typedef void (GLAD_API_PTR *PFNGLPOPATTRIBPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPOPCLIENTATTRIBPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPOPMATRIXPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPOPNAMEPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint   index);
-typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESPROC)(GLsizei   n, const  GLuint  * textures, const  GLfloat  * priorities);
-typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLPUSHATTRIBPROC)(GLbitfield   mask);
-typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield   mask);
-typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPPROC)(GLenum   source, GLuint   id, GLsizei   length, const  GLchar  * message);
-typedef void (GLAD_API_PTR *PFNGLPUSHMATRIXPROC)(void);
-typedef void (GLAD_API_PTR *PFNGLPUSHNAMEPROC)(GLuint   name);
-typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint   id, GLenum   target);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DPROC)(GLdouble   x, GLdouble   y);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FPROC)(GLfloat   x, GLfloat   y);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IPROC)(GLint   x, GLint   y);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SPROC)(GLshort   x, GLshort   y);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IPROC)(GLint   x, GLint   y, GLint   z);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SPROC)(GLshort   x, GLshort   y, GLshort   z);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DPROC)(GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FPROC)(GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IPROC)(GLint   x, GLint   y, GLint   z, GLint   w);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SPROC)(GLshort   x, GLshort   y, GLshort   z, GLshort   w);
-typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum   src);
-typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, void * pixels);
-typedef void (GLAD_API_PTR *PFNGLREADNPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, GLsizei   bufSize, void * data);
-typedef void (GLAD_API_PTR *PFNGLREADNPIXELSARBPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, GLsizei   bufSize, void * data);
-typedef void (GLAD_API_PTR *PFNGLRECTDPROC)(GLdouble   x1, GLdouble   y1, GLdouble   x2, GLdouble   y2);
-typedef void (GLAD_API_PTR *PFNGLRECTDVPROC)(const  GLdouble  * v1, const  GLdouble  * v2);
-typedef void (GLAD_API_PTR *PFNGLRECTFPROC)(GLfloat   x1, GLfloat   y1, GLfloat   x2, GLfloat   y2);
-typedef void (GLAD_API_PTR *PFNGLRECTFVPROC)(const  GLfloat  * v1, const  GLfloat  * v2);
-typedef void (GLAD_API_PTR *PFNGLRECTIPROC)(GLint   x1, GLint   y1, GLint   x2, GLint   y2);
-typedef void (GLAD_API_PTR *PFNGLRECTIVPROC)(const  GLint  * v1, const  GLint  * v2);
-typedef void (GLAD_API_PTR *PFNGLRECTSPROC)(GLshort   x1, GLshort   y1, GLshort   x2, GLshort   y2);
-typedef void (GLAD_API_PTR *PFNGLRECTSVPROC)(const  GLshort  * v1, const  GLshort  * v2);
-typedef GLint (GLAD_API_PTR *PFNGLRENDERMODEPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum   target, GLenum   internalformat, GLsizei   width, GLsizei   height);
-typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height);
-typedef void (GLAD_API_PTR *PFNGLROTATEDPROC)(GLdouble   angle, GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLROTATEFPROC)(GLfloat   angle, GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat   value, GLboolean   invert);
-typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEARBPROC)(GLfloat   value, GLboolean   invert);
-typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint   maskNumber, GLbitfield   mask);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint   sampler, GLenum   pname, const  GLint  * param);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint   sampler, GLenum   pname, const  GLuint  * param);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint   sampler, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint   sampler, GLenum   pname, const  GLfloat  * param);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint   sampler, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint   sampler, GLenum   pname, const  GLint  * param);
-typedef void (GLAD_API_PTR *PFNGLSCALEDPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLSCALEFPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BVPROC)(const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IPROC)(GLint   red, GLint   green, GLint   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SPROC)(GLshort   red, GLshort   green, GLshort   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBVPROC)(const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIPROC)(GLuint   red, GLuint   green, GLuint   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIVPROC)(const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USPROC)(GLushort   red, GLushort   green, GLushort   blue);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USVPROC)(const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIPROC)(GLenum   type, GLuint   color);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIVPROC)(GLenum   type, const  GLuint  * color);
-typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLSELECTBUFFERPROC)(GLsizei   size, GLuint  * buffer);
-typedef void (GLAD_API_PTR *PFNGLSHADEMODELPROC)(GLenum   mode);
-typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint   shader, GLsizei   count, const  GLchar  *const* string, const  GLint  * length);
-typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum   func, GLint   ref, GLuint   mask);
-typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum   face, GLenum   func, GLint   ref, GLuint   mask);
-typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint   mask);
-typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum   face, GLuint   mask);
-typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum   fail, GLenum   zfail, GLenum   zpass);
-typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum   face, GLenum   sfail, GLenum   dpfail, GLenum   dppass);
-typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum   target, GLenum   internalformat, GLuint   buffer);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DPROC)(GLdouble   s);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FPROC)(GLfloat   s);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IPROC)(GLint   s);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SPROC)(GLshort   s);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DPROC)(GLdouble   s, GLdouble   t);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FPROC)(GLfloat   s, GLfloat   t);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IPROC)(GLint   s, GLint   t);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SPROC)(GLshort   s, GLshort   t);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DPROC)(GLdouble   s, GLdouble   t, GLdouble   r);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FPROC)(GLfloat   s, GLfloat   t, GLfloat   r);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IPROC)(GLint   s, GLint   t, GLint   r);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SPROC)(GLshort   s, GLshort   t, GLshort   r);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DPROC)(GLdouble   s, GLdouble   t, GLdouble   r, GLdouble   q);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FPROC)(GLfloat   s, GLfloat   t, GLfloat   r, GLfloat   q);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IPROC)(GLint   s, GLint   t, GLint   r, GLint   q);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SPROC)(GLshort   s, GLshort   t, GLshort   r, GLshort   q);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIPROC)(GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIVPROC)(GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIPROC)(GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIVPROC)(GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIPROC)(GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIVPROC)(GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIPROC)(GLenum   type, GLuint   coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIVPROC)(GLenum   type, const  GLuint  * coords);
-typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLTEXENVFPROC)(GLenum   target, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLTEXENVFVPROC)(GLenum   target, GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXENVIPROC)(GLenum   target, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLTEXENVIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXGENDPROC)(GLenum   coord, GLenum   pname, GLdouble   param);
-typedef void (GLAD_API_PTR *PFNGLTEXGENDVPROC)(GLenum   coord, GLenum   pname, const  GLdouble  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXGENFPROC)(GLenum   coord, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLTEXGENFVPROC)(GLenum   coord, GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXGENIPROC)(GLenum   coord, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLTEXGENIVPROC)(GLenum   coord, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLint   border, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLsizei   height, GLint   border, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height, GLboolean   fixedsamplelocations);
-typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLint   border, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLboolean   fixedsamplelocations);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum   target, GLenum   pname, const  GLuint  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum   target, GLenum   pname, GLfloat   param);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum   target, GLenum   pname, const  GLfloat  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum   target, GLenum   pname, GLint   param);
-typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
-typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLsizei   width, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLsizei   width, GLsizei   height, GLsizei   depth, GLenum   format, GLenum   type, const void * pixels);
-typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint   program, GLsizei   count, const  GLchar  *const* varyings, GLenum   bufferMode);
-typedef void (GLAD_API_PTR *PFNGLTRANSLATEDPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLTRANSLATEFPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint   location, GLfloat   v0);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint   location, GLint   v0);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint   location, GLuint   v0);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint   location, GLfloat   v0, GLfloat   v1);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint   location, GLint   v0, GLint   v1);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint   location, GLuint   v0, GLuint   v1);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint   location, GLfloat   v0, GLfloat   v1, GLfloat   v2);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint   location, GLint   v0, GLint   v1, GLint   v2);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint   location, GLuint   v0, GLuint   v1, GLuint   v2);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint   location, GLfloat   v0, GLfloat   v1, GLfloat   v2, GLfloat   v3);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint   location, GLint   v0, GLint   v1, GLint   v2, GLint   v3);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint   location, GLuint   v0, GLuint   v1, GLuint   v2, GLuint   v3);
-typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint   program, GLuint   uniformBlockIndex, GLuint   uniformBlockBinding);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
-typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum   target);
-typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint   program);
-typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint   program);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2DPROC)(GLdouble   x, GLdouble   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2FPROC)(GLfloat   x, GLfloat   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2IPROC)(GLint   x, GLint   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2SPROC)(GLshort   x, GLshort   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEX2SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3IPROC)(GLint   x, GLint   y, GLint   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3SPROC)(GLshort   x, GLshort   y, GLshort   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEX3SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4DPROC)(GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4FPROC)(GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4IPROC)(GLint   x, GLint   y, GLint   z, GLint   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4SPROC)(GLshort   x, GLshort   y, GLshort   z, GLshort   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEX4SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint   index, GLdouble   x);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint   index, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint   index, GLfloat   x);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint   index, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint   index, GLshort   x);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint   index, GLdouble   x, GLdouble   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint   index, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint   index, GLfloat   x, GLfloat   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint   index, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint   index, GLshort   x, GLshort   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint   index, GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint   index, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint   index, GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint   index, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint   index, GLshort   x, GLshort   y, GLshort   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint   index, const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint   index, GLubyte   x, GLubyte   y, GLubyte   z, GLubyte   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint   index, const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint   index, const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint   index, const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint   index, GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint   index, const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint   index, GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint   index, const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint   index, GLshort   x, GLshort   y, GLshort   z, GLshort   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint   index, const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint   index, const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint   index, GLuint   divisor);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint   index, GLint   x);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint   index, GLuint   x);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint   index, GLint   x, GLint   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint   index, GLuint   x, GLuint   y);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint   index, GLint   x, GLint   y, GLint   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint   index, GLuint   x, GLuint   y, GLuint   z);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint   index, const  GLbyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint   index, GLint   x, GLint   y, GLint   z, GLint   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint   index, const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint   index, const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint   index, const  GLubyte  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint   index, GLuint   x, GLuint   y, GLuint   z, GLuint   w);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint   index, const  GLuint  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint   index, const  GLushort  * v);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint   index, GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint   index, GLint   size, GLenum   type, GLboolean   normalized, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIPROC)(GLenum   type, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIVPROC)(GLenum   type, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIPROC)(GLenum   type, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIVPROC)(GLenum   type, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIPROC)(GLenum   type, GLuint   value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIVPROC)(GLenum   type, const  GLuint  * value);
-typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
-typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height);
-typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync   sync, GLbitfield   flags, GLuint64   timeout);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DPROC)(GLdouble   x, GLdouble   y);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FPROC)(GLfloat   x, GLfloat   y);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IPROC)(GLint   x, GLint   y);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SPROC)(GLshort   x, GLshort   y);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SVPROC)(const  GLshort  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DVPROC)(const  GLdouble  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FVPROC)(const  GLfloat  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IPROC)(GLint   x, GLint   y, GLint   z);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IVPROC)(const  GLint  * v);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SPROC)(GLshort   x, GLshort   y, GLshort   z);
-typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SVPROC)(const  GLshort  * v);
-
-GLAD_API_CALL PFNGLACCUMPROC glad_glAccum;
-#define glAccum glad_glAccum
-GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
-#define glActiveTexture glad_glActiveTexture
-GLAD_API_CALL PFNGLALPHAFUNCPROC glad_glAlphaFunc;
-#define glAlphaFunc glad_glAlphaFunc
-GLAD_API_CALL PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
-#define glAreTexturesResident glad_glAreTexturesResident
-GLAD_API_CALL PFNGLARRAYELEMENTPROC glad_glArrayElement;
-#define glArrayElement glad_glArrayElement
-GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
-#define glAttachShader glad_glAttachShader
-GLAD_API_CALL PFNGLBEGINPROC glad_glBegin;
-#define glBegin glad_glBegin
-GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
-#define glBeginConditionalRender glad_glBeginConditionalRender
-GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
-#define glBeginQuery glad_glBeginQuery
-GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
-#define glBeginTransformFeedback glad_glBeginTransformFeedback
-GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
-#define glBindAttribLocation glad_glBindAttribLocation
-GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
-#define glBindBuffer glad_glBindBuffer
-GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
-#define glBindBufferBase glad_glBindBufferBase
-GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
-#define glBindBufferRange glad_glBindBufferRange
-GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
-#define glBindFragDataLocation glad_glBindFragDataLocation
-GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
-#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
-GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
-#define glBindFramebuffer glad_glBindFramebuffer
-GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
-#define glBindRenderbuffer glad_glBindRenderbuffer
-GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
-#define glBindSampler glad_glBindSampler
-GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
-#define glBindTexture glad_glBindTexture
-GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
-#define glBindVertexArray glad_glBindVertexArray
-GLAD_API_CALL PFNGLBITMAPPROC glad_glBitmap;
-#define glBitmap glad_glBitmap
-GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
-#define glBlendColor glad_glBlendColor
-GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
-#define glBlendEquation glad_glBlendEquation
-GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
-#define glBlendEquationSeparate glad_glBlendEquationSeparate
-GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
-#define glBlendFunc glad_glBlendFunc
-GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
-#define glBlendFuncSeparate glad_glBlendFuncSeparate
-GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
-#define glBlitFramebuffer glad_glBlitFramebuffer
-GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
-#define glBufferData glad_glBufferData
-GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
-#define glBufferSubData glad_glBufferSubData
-GLAD_API_CALL PFNGLCALLLISTPROC glad_glCallList;
-#define glCallList glad_glCallList
-GLAD_API_CALL PFNGLCALLLISTSPROC glad_glCallLists;
-#define glCallLists glad_glCallLists
-GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
-#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
-GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
-#define glClampColor glad_glClampColor
-GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
-#define glClear glad_glClear
-GLAD_API_CALL PFNGLCLEARACCUMPROC glad_glClearAccum;
-#define glClearAccum glad_glClearAccum
-GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
-#define glClearBufferfi glad_glClearBufferfi
-GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
-#define glClearBufferfv glad_glClearBufferfv
-GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
-#define glClearBufferiv glad_glClearBufferiv
-GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
-#define glClearBufferuiv glad_glClearBufferuiv
-GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
-#define glClearColor glad_glClearColor
-GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
-#define glClearDepth glad_glClearDepth
-GLAD_API_CALL PFNGLCLEARINDEXPROC glad_glClearIndex;
-#define glClearIndex glad_glClearIndex
-GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
-#define glClearStencil glad_glClearStencil
-GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
-#define glClientActiveTexture glad_glClientActiveTexture
-GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
-#define glClientWaitSync glad_glClientWaitSync
-GLAD_API_CALL PFNGLCLIPPLANEPROC glad_glClipPlane;
-#define glClipPlane glad_glClipPlane
-GLAD_API_CALL PFNGLCOLOR3BPROC glad_glColor3b;
-#define glColor3b glad_glColor3b
-GLAD_API_CALL PFNGLCOLOR3BVPROC glad_glColor3bv;
-#define glColor3bv glad_glColor3bv
-GLAD_API_CALL PFNGLCOLOR3DPROC glad_glColor3d;
-#define glColor3d glad_glColor3d
-GLAD_API_CALL PFNGLCOLOR3DVPROC glad_glColor3dv;
-#define glColor3dv glad_glColor3dv
-GLAD_API_CALL PFNGLCOLOR3FPROC glad_glColor3f;
-#define glColor3f glad_glColor3f
-GLAD_API_CALL PFNGLCOLOR3FVPROC glad_glColor3fv;
-#define glColor3fv glad_glColor3fv
-GLAD_API_CALL PFNGLCOLOR3IPROC glad_glColor3i;
-#define glColor3i glad_glColor3i
-GLAD_API_CALL PFNGLCOLOR3IVPROC glad_glColor3iv;
-#define glColor3iv glad_glColor3iv
-GLAD_API_CALL PFNGLCOLOR3SPROC glad_glColor3s;
-#define glColor3s glad_glColor3s
-GLAD_API_CALL PFNGLCOLOR3SVPROC glad_glColor3sv;
-#define glColor3sv glad_glColor3sv
-GLAD_API_CALL PFNGLCOLOR3UBPROC glad_glColor3ub;
-#define glColor3ub glad_glColor3ub
-GLAD_API_CALL PFNGLCOLOR3UBVPROC glad_glColor3ubv;
-#define glColor3ubv glad_glColor3ubv
-GLAD_API_CALL PFNGLCOLOR3UIPROC glad_glColor3ui;
-#define glColor3ui glad_glColor3ui
-GLAD_API_CALL PFNGLCOLOR3UIVPROC glad_glColor3uiv;
-#define glColor3uiv glad_glColor3uiv
-GLAD_API_CALL PFNGLCOLOR3USPROC glad_glColor3us;
-#define glColor3us glad_glColor3us
-GLAD_API_CALL PFNGLCOLOR3USVPROC glad_glColor3usv;
-#define glColor3usv glad_glColor3usv
-GLAD_API_CALL PFNGLCOLOR4BPROC glad_glColor4b;
-#define glColor4b glad_glColor4b
-GLAD_API_CALL PFNGLCOLOR4BVPROC glad_glColor4bv;
-#define glColor4bv glad_glColor4bv
-GLAD_API_CALL PFNGLCOLOR4DPROC glad_glColor4d;
-#define glColor4d glad_glColor4d
-GLAD_API_CALL PFNGLCOLOR4DVPROC glad_glColor4dv;
-#define glColor4dv glad_glColor4dv
-GLAD_API_CALL PFNGLCOLOR4FPROC glad_glColor4f;
-#define glColor4f glad_glColor4f
-GLAD_API_CALL PFNGLCOLOR4FVPROC glad_glColor4fv;
-#define glColor4fv glad_glColor4fv
-GLAD_API_CALL PFNGLCOLOR4IPROC glad_glColor4i;
-#define glColor4i glad_glColor4i
-GLAD_API_CALL PFNGLCOLOR4IVPROC glad_glColor4iv;
-#define glColor4iv glad_glColor4iv
-GLAD_API_CALL PFNGLCOLOR4SPROC glad_glColor4s;
-#define glColor4s glad_glColor4s
-GLAD_API_CALL PFNGLCOLOR4SVPROC glad_glColor4sv;
-#define glColor4sv glad_glColor4sv
-GLAD_API_CALL PFNGLCOLOR4UBPROC glad_glColor4ub;
-#define glColor4ub glad_glColor4ub
-GLAD_API_CALL PFNGLCOLOR4UBVPROC glad_glColor4ubv;
-#define glColor4ubv glad_glColor4ubv
-GLAD_API_CALL PFNGLCOLOR4UIPROC glad_glColor4ui;
-#define glColor4ui glad_glColor4ui
-GLAD_API_CALL PFNGLCOLOR4UIVPROC glad_glColor4uiv;
-#define glColor4uiv glad_glColor4uiv
-GLAD_API_CALL PFNGLCOLOR4USPROC glad_glColor4us;
-#define glColor4us glad_glColor4us
-GLAD_API_CALL PFNGLCOLOR4USVPROC glad_glColor4usv;
-#define glColor4usv glad_glColor4usv
-GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
-#define glColorMask glad_glColorMask
-GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
-#define glColorMaski glad_glColorMaski
-GLAD_API_CALL PFNGLCOLORMATERIALPROC glad_glColorMaterial;
-#define glColorMaterial glad_glColorMaterial
-GLAD_API_CALL PFNGLCOLORP3UIPROC glad_glColorP3ui;
-#define glColorP3ui glad_glColorP3ui
-GLAD_API_CALL PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
-#define glColorP3uiv glad_glColorP3uiv
-GLAD_API_CALL PFNGLCOLORP4UIPROC glad_glColorP4ui;
-#define glColorP4ui glad_glColorP4ui
-GLAD_API_CALL PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
-#define glColorP4uiv glad_glColorP4uiv
-GLAD_API_CALL PFNGLCOLORPOINTERPROC glad_glColorPointer;
-#define glColorPointer glad_glColorPointer
-GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
-#define glCompileShader glad_glCompileShader
-GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
-#define glCompressedTexImage1D glad_glCompressedTexImage1D
-GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
-#define glCompressedTexImage2D glad_glCompressedTexImage2D
-GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
-#define glCompressedTexImage3D glad_glCompressedTexImage3D
-GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
-#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
-GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
-#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
-GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
-#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
-GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
-#define glCopyBufferSubData glad_glCopyBufferSubData
-GLAD_API_CALL PFNGLCOPYPIXELSPROC glad_glCopyPixels;
-#define glCopyPixels glad_glCopyPixels
-GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
-#define glCopyTexImage1D glad_glCopyTexImage1D
-GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
-#define glCopyTexImage2D glad_glCopyTexImage2D
-GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
-#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
-GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
-#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
-GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
-#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
-GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
-#define glCreateProgram glad_glCreateProgram
-GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
-#define glCreateShader glad_glCreateShader
-GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
-#define glCullFace glad_glCullFace
-GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
-#define glDebugMessageCallback glad_glDebugMessageCallback
-GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
-#define glDebugMessageControl glad_glDebugMessageControl
-GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
-#define glDebugMessageInsert glad_glDebugMessageInsert
-GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
-#define glDeleteBuffers glad_glDeleteBuffers
-GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
-#define glDeleteFramebuffers glad_glDeleteFramebuffers
-GLAD_API_CALL PFNGLDELETELISTSPROC glad_glDeleteLists;
-#define glDeleteLists glad_glDeleteLists
-GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
-#define glDeleteProgram glad_glDeleteProgram
-GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
-#define glDeleteQueries glad_glDeleteQueries
-GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
-#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
-GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
-#define glDeleteSamplers glad_glDeleteSamplers
-GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
-#define glDeleteShader glad_glDeleteShader
-GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
-#define glDeleteSync glad_glDeleteSync
-GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
-#define glDeleteTextures glad_glDeleteTextures
-GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
-#define glDeleteVertexArrays glad_glDeleteVertexArrays
-GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
-#define glDepthFunc glad_glDepthFunc
-GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
-#define glDepthMask glad_glDepthMask
-GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
-#define glDepthRange glad_glDepthRange
-GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
-#define glDetachShader glad_glDetachShader
-GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
-#define glDisable glad_glDisable
-GLAD_API_CALL PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
-#define glDisableClientState glad_glDisableClientState
-GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
-#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
-GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
-#define glDisablei glad_glDisablei
-GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
-#define glDrawArrays glad_glDrawArrays
-GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
-#define glDrawArraysInstanced glad_glDrawArraysInstanced
-GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
-#define glDrawBuffer glad_glDrawBuffer
-GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
-#define glDrawBuffers glad_glDrawBuffers
-GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
-#define glDrawElements glad_glDrawElements
-GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
-#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
-GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
-#define glDrawElementsInstanced glad_glDrawElementsInstanced
-GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
-#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
-GLAD_API_CALL PFNGLDRAWPIXELSPROC glad_glDrawPixels;
-#define glDrawPixels glad_glDrawPixels
-GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
-#define glDrawRangeElements glad_glDrawRangeElements
-GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
-#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
-GLAD_API_CALL PFNGLEDGEFLAGPROC glad_glEdgeFlag;
-#define glEdgeFlag glad_glEdgeFlag
-GLAD_API_CALL PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
-#define glEdgeFlagPointer glad_glEdgeFlagPointer
-GLAD_API_CALL PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
-#define glEdgeFlagv glad_glEdgeFlagv
-GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
-#define glEnable glad_glEnable
-GLAD_API_CALL PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
-#define glEnableClientState glad_glEnableClientState
-GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
-#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
-GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
-#define glEnablei glad_glEnablei
-GLAD_API_CALL PFNGLENDPROC glad_glEnd;
-#define glEnd glad_glEnd
-GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
-#define glEndConditionalRender glad_glEndConditionalRender
-GLAD_API_CALL PFNGLENDLISTPROC glad_glEndList;
-#define glEndList glad_glEndList
-GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
-#define glEndQuery glad_glEndQuery
-GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
-#define glEndTransformFeedback glad_glEndTransformFeedback
-GLAD_API_CALL PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
-#define glEvalCoord1d glad_glEvalCoord1d
-GLAD_API_CALL PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
-#define glEvalCoord1dv glad_glEvalCoord1dv
-GLAD_API_CALL PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
-#define glEvalCoord1f glad_glEvalCoord1f
-GLAD_API_CALL PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
-#define glEvalCoord1fv glad_glEvalCoord1fv
-GLAD_API_CALL PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
-#define glEvalCoord2d glad_glEvalCoord2d
-GLAD_API_CALL PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
-#define glEvalCoord2dv glad_glEvalCoord2dv
-GLAD_API_CALL PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
-#define glEvalCoord2f glad_glEvalCoord2f
-GLAD_API_CALL PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
-#define glEvalCoord2fv glad_glEvalCoord2fv
-GLAD_API_CALL PFNGLEVALMESH1PROC glad_glEvalMesh1;
-#define glEvalMesh1 glad_glEvalMesh1
-GLAD_API_CALL PFNGLEVALMESH2PROC glad_glEvalMesh2;
-#define glEvalMesh2 glad_glEvalMesh2
-GLAD_API_CALL PFNGLEVALPOINT1PROC glad_glEvalPoint1;
-#define glEvalPoint1 glad_glEvalPoint1
-GLAD_API_CALL PFNGLEVALPOINT2PROC glad_glEvalPoint2;
-#define glEvalPoint2 glad_glEvalPoint2
-GLAD_API_CALL PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
-#define glFeedbackBuffer glad_glFeedbackBuffer
-GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
-#define glFenceSync glad_glFenceSync
-GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
-#define glFinish glad_glFinish
-GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
-#define glFlush glad_glFlush
-GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
-#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
-GLAD_API_CALL PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
-#define glFogCoordPointer glad_glFogCoordPointer
-GLAD_API_CALL PFNGLFOGCOORDDPROC glad_glFogCoordd;
-#define glFogCoordd glad_glFogCoordd
-GLAD_API_CALL PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
-#define glFogCoorddv glad_glFogCoorddv
-GLAD_API_CALL PFNGLFOGCOORDFPROC glad_glFogCoordf;
-#define glFogCoordf glad_glFogCoordf
-GLAD_API_CALL PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
-#define glFogCoordfv glad_glFogCoordfv
-GLAD_API_CALL PFNGLFOGFPROC glad_glFogf;
-#define glFogf glad_glFogf
-GLAD_API_CALL PFNGLFOGFVPROC glad_glFogfv;
-#define glFogfv glad_glFogfv
-GLAD_API_CALL PFNGLFOGIPROC glad_glFogi;
-#define glFogi glad_glFogi
-GLAD_API_CALL PFNGLFOGIVPROC glad_glFogiv;
-#define glFogiv glad_glFogiv
-GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
-#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
-GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
-#define glFramebufferTexture glad_glFramebufferTexture
-GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
-#define glFramebufferTexture1D glad_glFramebufferTexture1D
-GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
-#define glFramebufferTexture2D glad_glFramebufferTexture2D
-GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
-#define glFramebufferTexture3D glad_glFramebufferTexture3D
-GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
-#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
-GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
-#define glFrontFace glad_glFrontFace
-GLAD_API_CALL PFNGLFRUSTUMPROC glad_glFrustum;
-#define glFrustum glad_glFrustum
-GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
-#define glGenBuffers glad_glGenBuffers
-GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
-#define glGenFramebuffers glad_glGenFramebuffers
-GLAD_API_CALL PFNGLGENLISTSPROC glad_glGenLists;
-#define glGenLists glad_glGenLists
-GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
-#define glGenQueries glad_glGenQueries
-GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
-#define glGenRenderbuffers glad_glGenRenderbuffers
-GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
-#define glGenSamplers glad_glGenSamplers
-GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
-#define glGenTextures glad_glGenTextures
-GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
-#define glGenVertexArrays glad_glGenVertexArrays
-GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
-#define glGenerateMipmap glad_glGenerateMipmap
-GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
-#define glGetActiveAttrib glad_glGetActiveAttrib
-GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
-#define glGetActiveUniform glad_glGetActiveUniform
-GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
-#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
-GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
-#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
-GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
-#define glGetActiveUniformName glad_glGetActiveUniformName
-GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
-#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
-GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
-#define glGetAttachedShaders glad_glGetAttachedShaders
-GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
-#define glGetAttribLocation glad_glGetAttribLocation
-GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
-#define glGetBooleani_v glad_glGetBooleani_v
-GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
-#define glGetBooleanv glad_glGetBooleanv
-GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
-#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
-GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
-#define glGetBufferParameteriv glad_glGetBufferParameteriv
-GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
-#define glGetBufferPointerv glad_glGetBufferPointerv
-GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
-#define glGetBufferSubData glad_glGetBufferSubData
-GLAD_API_CALL PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
-#define glGetClipPlane glad_glGetClipPlane
-GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
-#define glGetCompressedTexImage glad_glGetCompressedTexImage
-GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
-#define glGetDebugMessageLog glad_glGetDebugMessageLog
-GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
-#define glGetDoublev glad_glGetDoublev
-GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
-#define glGetError glad_glGetError
-GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
-#define glGetFloatv glad_glGetFloatv
-GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
-#define glGetFragDataIndex glad_glGetFragDataIndex
-GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
-#define glGetFragDataLocation glad_glGetFragDataLocation
-GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
-#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
-GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB;
-#define glGetGraphicsResetStatusARB glad_glGetGraphicsResetStatusARB
-GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
-#define glGetInteger64i_v glad_glGetInteger64i_v
-GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
-#define glGetInteger64v glad_glGetInteger64v
-GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
-#define glGetIntegeri_v glad_glGetIntegeri_v
-GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
-#define glGetIntegerv glad_glGetIntegerv
-GLAD_API_CALL PFNGLGETLIGHTFVPROC glad_glGetLightfv;
-#define glGetLightfv glad_glGetLightfv
-GLAD_API_CALL PFNGLGETLIGHTIVPROC glad_glGetLightiv;
-#define glGetLightiv glad_glGetLightiv
-GLAD_API_CALL PFNGLGETMAPDVPROC glad_glGetMapdv;
-#define glGetMapdv glad_glGetMapdv
-GLAD_API_CALL PFNGLGETMAPFVPROC glad_glGetMapfv;
-#define glGetMapfv glad_glGetMapfv
-GLAD_API_CALL PFNGLGETMAPIVPROC glad_glGetMapiv;
-#define glGetMapiv glad_glGetMapiv
-GLAD_API_CALL PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
-#define glGetMaterialfv glad_glGetMaterialfv
-GLAD_API_CALL PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
-#define glGetMaterialiv glad_glGetMaterialiv
-GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
-#define glGetMultisamplefv glad_glGetMultisamplefv
-GLAD_API_CALL PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
-#define glGetObjectLabel glad_glGetObjectLabel
-GLAD_API_CALL PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
-#define glGetObjectPtrLabel glad_glGetObjectPtrLabel
-GLAD_API_CALL PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
-#define glGetPixelMapfv glad_glGetPixelMapfv
-GLAD_API_CALL PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
-#define glGetPixelMapuiv glad_glGetPixelMapuiv
-GLAD_API_CALL PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
-#define glGetPixelMapusv glad_glGetPixelMapusv
-GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv;
-#define glGetPointerv glad_glGetPointerv
-GLAD_API_CALL PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
-#define glGetPolygonStipple glad_glGetPolygonStipple
-GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
-#define glGetProgramInfoLog glad_glGetProgramInfoLog
-GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
-#define glGetProgramiv glad_glGetProgramiv
-GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
-#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
-GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
-#define glGetQueryObjectiv glad_glGetQueryObjectiv
-GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
-#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
-GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
-#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
-GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
-#define glGetQueryiv glad_glGetQueryiv
-GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
-#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
-GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
-#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
-GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
-#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
-GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
-#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
-GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
-#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
-GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
-#define glGetShaderInfoLog glad_glGetShaderInfoLog
-GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
-#define glGetShaderSource glad_glGetShaderSource
-GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
-#define glGetShaderiv glad_glGetShaderiv
-GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
-#define glGetString glad_glGetString
-GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
-#define glGetStringi glad_glGetStringi
-GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
-#define glGetSynciv glad_glGetSynciv
-GLAD_API_CALL PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
-#define glGetTexEnvfv glad_glGetTexEnvfv
-GLAD_API_CALL PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
-#define glGetTexEnviv glad_glGetTexEnviv
-GLAD_API_CALL PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
-#define glGetTexGendv glad_glGetTexGendv
-GLAD_API_CALL PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
-#define glGetTexGenfv glad_glGetTexGenfv
-GLAD_API_CALL PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
-#define glGetTexGeniv glad_glGetTexGeniv
-GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
-#define glGetTexImage glad_glGetTexImage
-GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
-#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
-GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
-#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
-GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
-#define glGetTexParameterIiv glad_glGetTexParameterIiv
-GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
-#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
-GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
-#define glGetTexParameterfv glad_glGetTexParameterfv
-GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
-#define glGetTexParameteriv glad_glGetTexParameteriv
-GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
-#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
-GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
-#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
-GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
-#define glGetUniformIndices glad_glGetUniformIndices
-GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
-#define glGetUniformLocation glad_glGetUniformLocation
-GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
-#define glGetUniformfv glad_glGetUniformfv
-GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
-#define glGetUniformiv glad_glGetUniformiv
-GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
-#define glGetUniformuiv glad_glGetUniformuiv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
-#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
-#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
-#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
-#define glGetVertexAttribdv glad_glGetVertexAttribdv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
-#define glGetVertexAttribfv glad_glGetVertexAttribfv
-GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
-#define glGetVertexAttribiv glad_glGetVertexAttribiv
-GLAD_API_CALL PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB;
-#define glGetnColorTableARB glad_glGetnColorTableARB
-GLAD_API_CALL PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB;
-#define glGetnCompressedTexImageARB glad_glGetnCompressedTexImageARB
-GLAD_API_CALL PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB;
-#define glGetnConvolutionFilterARB glad_glGetnConvolutionFilterARB
-GLAD_API_CALL PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB;
-#define glGetnHistogramARB glad_glGetnHistogramARB
-GLAD_API_CALL PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB;
-#define glGetnMapdvARB glad_glGetnMapdvARB
-GLAD_API_CALL PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB;
-#define glGetnMapfvARB glad_glGetnMapfvARB
-GLAD_API_CALL PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB;
-#define glGetnMapivARB glad_glGetnMapivARB
-GLAD_API_CALL PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB;
-#define glGetnMinmaxARB glad_glGetnMinmaxARB
-GLAD_API_CALL PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB;
-#define glGetnPixelMapfvARB glad_glGetnPixelMapfvARB
-GLAD_API_CALL PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB;
-#define glGetnPixelMapuivARB glad_glGetnPixelMapuivARB
-GLAD_API_CALL PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB;
-#define glGetnPixelMapusvARB glad_glGetnPixelMapusvARB
-GLAD_API_CALL PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB;
-#define glGetnPolygonStippleARB glad_glGetnPolygonStippleARB
-GLAD_API_CALL PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB;
-#define glGetnSeparableFilterARB glad_glGetnSeparableFilterARB
-GLAD_API_CALL PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB;
-#define glGetnTexImageARB glad_glGetnTexImageARB
-GLAD_API_CALL PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB;
-#define glGetnUniformdvARB glad_glGetnUniformdvARB
-GLAD_API_CALL PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB;
-#define glGetnUniformfvARB glad_glGetnUniformfvARB
-GLAD_API_CALL PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB;
-#define glGetnUniformivARB glad_glGetnUniformivARB
-GLAD_API_CALL PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB;
-#define glGetnUniformuivARB glad_glGetnUniformuivARB
-GLAD_API_CALL PFNGLHINTPROC glad_glHint;
-#define glHint glad_glHint
-GLAD_API_CALL PFNGLINDEXMASKPROC glad_glIndexMask;
-#define glIndexMask glad_glIndexMask
-GLAD_API_CALL PFNGLINDEXPOINTERPROC glad_glIndexPointer;
-#define glIndexPointer glad_glIndexPointer
-GLAD_API_CALL PFNGLINDEXDPROC glad_glIndexd;
-#define glIndexd glad_glIndexd
-GLAD_API_CALL PFNGLINDEXDVPROC glad_glIndexdv;
-#define glIndexdv glad_glIndexdv
-GLAD_API_CALL PFNGLINDEXFPROC glad_glIndexf;
-#define glIndexf glad_glIndexf
-GLAD_API_CALL PFNGLINDEXFVPROC glad_glIndexfv;
-#define glIndexfv glad_glIndexfv
-GLAD_API_CALL PFNGLINDEXIPROC glad_glIndexi;
-#define glIndexi glad_glIndexi
-GLAD_API_CALL PFNGLINDEXIVPROC glad_glIndexiv;
-#define glIndexiv glad_glIndexiv
-GLAD_API_CALL PFNGLINDEXSPROC glad_glIndexs;
-#define glIndexs glad_glIndexs
-GLAD_API_CALL PFNGLINDEXSVPROC glad_glIndexsv;
-#define glIndexsv glad_glIndexsv
-GLAD_API_CALL PFNGLINDEXUBPROC glad_glIndexub;
-#define glIndexub glad_glIndexub
-GLAD_API_CALL PFNGLINDEXUBVPROC glad_glIndexubv;
-#define glIndexubv glad_glIndexubv
-GLAD_API_CALL PFNGLINITNAMESPROC glad_glInitNames;
-#define glInitNames glad_glInitNames
-GLAD_API_CALL PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
-#define glInterleavedArrays glad_glInterleavedArrays
-GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
-#define glIsBuffer glad_glIsBuffer
-GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
-#define glIsEnabled glad_glIsEnabled
-GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
-#define glIsEnabledi glad_glIsEnabledi
-GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
-#define glIsFramebuffer glad_glIsFramebuffer
-GLAD_API_CALL PFNGLISLISTPROC glad_glIsList;
-#define glIsList glad_glIsList
-GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
-#define glIsProgram glad_glIsProgram
-GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
-#define glIsQuery glad_glIsQuery
-GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
-#define glIsRenderbuffer glad_glIsRenderbuffer
-GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
-#define glIsSampler glad_glIsSampler
-GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
-#define glIsShader glad_glIsShader
-GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
-#define glIsSync glad_glIsSync
-GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
-#define glIsTexture glad_glIsTexture
-GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
-#define glIsVertexArray glad_glIsVertexArray
-GLAD_API_CALL PFNGLLIGHTMODELFPROC glad_glLightModelf;
-#define glLightModelf glad_glLightModelf
-GLAD_API_CALL PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
-#define glLightModelfv glad_glLightModelfv
-GLAD_API_CALL PFNGLLIGHTMODELIPROC glad_glLightModeli;
-#define glLightModeli glad_glLightModeli
-GLAD_API_CALL PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
-#define glLightModeliv glad_glLightModeliv
-GLAD_API_CALL PFNGLLIGHTFPROC glad_glLightf;
-#define glLightf glad_glLightf
-GLAD_API_CALL PFNGLLIGHTFVPROC glad_glLightfv;
-#define glLightfv glad_glLightfv
-GLAD_API_CALL PFNGLLIGHTIPROC glad_glLighti;
-#define glLighti glad_glLighti
-GLAD_API_CALL PFNGLLIGHTIVPROC glad_glLightiv;
-#define glLightiv glad_glLightiv
-GLAD_API_CALL PFNGLLINESTIPPLEPROC glad_glLineStipple;
-#define glLineStipple glad_glLineStipple
-GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
-#define glLineWidth glad_glLineWidth
-GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
-#define glLinkProgram glad_glLinkProgram
-GLAD_API_CALL PFNGLLISTBASEPROC glad_glListBase;
-#define glListBase glad_glListBase
-GLAD_API_CALL PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
-#define glLoadIdentity glad_glLoadIdentity
-GLAD_API_CALL PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
-#define glLoadMatrixd glad_glLoadMatrixd
-GLAD_API_CALL PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
-#define glLoadMatrixf glad_glLoadMatrixf
-GLAD_API_CALL PFNGLLOADNAMEPROC glad_glLoadName;
-#define glLoadName glad_glLoadName
-GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
-#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
-GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
-#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
-GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
-#define glLogicOp glad_glLogicOp
-GLAD_API_CALL PFNGLMAP1DPROC glad_glMap1d;
-#define glMap1d glad_glMap1d
-GLAD_API_CALL PFNGLMAP1FPROC glad_glMap1f;
-#define glMap1f glad_glMap1f
-GLAD_API_CALL PFNGLMAP2DPROC glad_glMap2d;
-#define glMap2d glad_glMap2d
-GLAD_API_CALL PFNGLMAP2FPROC glad_glMap2f;
-#define glMap2f glad_glMap2f
-GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
-#define glMapBuffer glad_glMapBuffer
-GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
-#define glMapBufferRange glad_glMapBufferRange
-GLAD_API_CALL PFNGLMAPGRID1DPROC glad_glMapGrid1d;
-#define glMapGrid1d glad_glMapGrid1d
-GLAD_API_CALL PFNGLMAPGRID1FPROC glad_glMapGrid1f;
-#define glMapGrid1f glad_glMapGrid1f
-GLAD_API_CALL PFNGLMAPGRID2DPROC glad_glMapGrid2d;
-#define glMapGrid2d glad_glMapGrid2d
-GLAD_API_CALL PFNGLMAPGRID2FPROC glad_glMapGrid2f;
-#define glMapGrid2f glad_glMapGrid2f
-GLAD_API_CALL PFNGLMATERIALFPROC glad_glMaterialf;
-#define glMaterialf glad_glMaterialf
-GLAD_API_CALL PFNGLMATERIALFVPROC glad_glMaterialfv;
-#define glMaterialfv glad_glMaterialfv
-GLAD_API_CALL PFNGLMATERIALIPROC glad_glMateriali;
-#define glMateriali glad_glMateriali
-GLAD_API_CALL PFNGLMATERIALIVPROC glad_glMaterialiv;
-#define glMaterialiv glad_glMaterialiv
-GLAD_API_CALL PFNGLMATRIXMODEPROC glad_glMatrixMode;
-#define glMatrixMode glad_glMatrixMode
-GLAD_API_CALL PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
-#define glMultMatrixd glad_glMultMatrixd
-GLAD_API_CALL PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
-#define glMultMatrixf glad_glMultMatrixf
-GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
-#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
-GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
-#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
-GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
-#define glMultiDrawArrays glad_glMultiDrawArrays
-GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
-#define glMultiDrawElements glad_glMultiDrawElements
-GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
-#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
-GLAD_API_CALL PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
-#define glMultiTexCoord1d glad_glMultiTexCoord1d
-GLAD_API_CALL PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
-#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
-GLAD_API_CALL PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
-#define glMultiTexCoord1f glad_glMultiTexCoord1f
-GLAD_API_CALL PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
-#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
-GLAD_API_CALL PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
-#define glMultiTexCoord1i glad_glMultiTexCoord1i
-GLAD_API_CALL PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
-#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
-GLAD_API_CALL PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
-#define glMultiTexCoord1s glad_glMultiTexCoord1s
-GLAD_API_CALL PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
-#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
-GLAD_API_CALL PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
-#define glMultiTexCoord2d glad_glMultiTexCoord2d
-GLAD_API_CALL PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
-#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
-GLAD_API_CALL PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
-#define glMultiTexCoord2f glad_glMultiTexCoord2f
-GLAD_API_CALL PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
-#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
-GLAD_API_CALL PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
-#define glMultiTexCoord2i glad_glMultiTexCoord2i
-GLAD_API_CALL PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
-#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
-GLAD_API_CALL PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
-#define glMultiTexCoord2s glad_glMultiTexCoord2s
-GLAD_API_CALL PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
-#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
-GLAD_API_CALL PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
-#define glMultiTexCoord3d glad_glMultiTexCoord3d
-GLAD_API_CALL PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
-#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
-GLAD_API_CALL PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
-#define glMultiTexCoord3f glad_glMultiTexCoord3f
-GLAD_API_CALL PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
-#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
-GLAD_API_CALL PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
-#define glMultiTexCoord3i glad_glMultiTexCoord3i
-GLAD_API_CALL PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
-#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
-GLAD_API_CALL PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
-#define glMultiTexCoord3s glad_glMultiTexCoord3s
-GLAD_API_CALL PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
-#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
-GLAD_API_CALL PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
-#define glMultiTexCoord4d glad_glMultiTexCoord4d
-GLAD_API_CALL PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
-#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
-GLAD_API_CALL PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
-#define glMultiTexCoord4f glad_glMultiTexCoord4f
-GLAD_API_CALL PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
-#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
-GLAD_API_CALL PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
-#define glMultiTexCoord4i glad_glMultiTexCoord4i
-GLAD_API_CALL PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
-#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
-GLAD_API_CALL PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
-#define glMultiTexCoord4s glad_glMultiTexCoord4s
-GLAD_API_CALL PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
-#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
-GLAD_API_CALL PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
-#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
-GLAD_API_CALL PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
-#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
-GLAD_API_CALL PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
-#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
-GLAD_API_CALL PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
-#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
-GLAD_API_CALL PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
-#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
-GLAD_API_CALL PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
-#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
-GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
-#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
-GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
-#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
-GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList;
-#define glNewList glad_glNewList
-GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b;
-#define glNormal3b glad_glNormal3b
-GLAD_API_CALL PFNGLNORMAL3BVPROC glad_glNormal3bv;
-#define glNormal3bv glad_glNormal3bv
-GLAD_API_CALL PFNGLNORMAL3DPROC glad_glNormal3d;
-#define glNormal3d glad_glNormal3d
-GLAD_API_CALL PFNGLNORMAL3DVPROC glad_glNormal3dv;
-#define glNormal3dv glad_glNormal3dv
-GLAD_API_CALL PFNGLNORMAL3FPROC glad_glNormal3f;
-#define glNormal3f glad_glNormal3f
-GLAD_API_CALL PFNGLNORMAL3FVPROC glad_glNormal3fv;
-#define glNormal3fv glad_glNormal3fv
-GLAD_API_CALL PFNGLNORMAL3IPROC glad_glNormal3i;
-#define glNormal3i glad_glNormal3i
-GLAD_API_CALL PFNGLNORMAL3IVPROC glad_glNormal3iv;
-#define glNormal3iv glad_glNormal3iv
-GLAD_API_CALL PFNGLNORMAL3SPROC glad_glNormal3s;
-#define glNormal3s glad_glNormal3s
-GLAD_API_CALL PFNGLNORMAL3SVPROC glad_glNormal3sv;
-#define glNormal3sv glad_glNormal3sv
-GLAD_API_CALL PFNGLNORMALP3UIPROC glad_glNormalP3ui;
-#define glNormalP3ui glad_glNormalP3ui
-GLAD_API_CALL PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
-#define glNormalP3uiv glad_glNormalP3uiv
-GLAD_API_CALL PFNGLNORMALPOINTERPROC glad_glNormalPointer;
-#define glNormalPointer glad_glNormalPointer
-GLAD_API_CALL PFNGLOBJECTLABELPROC glad_glObjectLabel;
-#define glObjectLabel glad_glObjectLabel
-GLAD_API_CALL PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
-#define glObjectPtrLabel glad_glObjectPtrLabel
-GLAD_API_CALL PFNGLORTHOPROC glad_glOrtho;
-#define glOrtho glad_glOrtho
-GLAD_API_CALL PFNGLPASSTHROUGHPROC glad_glPassThrough;
-#define glPassThrough glad_glPassThrough
-GLAD_API_CALL PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
-#define glPixelMapfv glad_glPixelMapfv
-GLAD_API_CALL PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
-#define glPixelMapuiv glad_glPixelMapuiv
-GLAD_API_CALL PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
-#define glPixelMapusv glad_glPixelMapusv
-GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
-#define glPixelStoref glad_glPixelStoref
-GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
-#define glPixelStorei glad_glPixelStorei
-GLAD_API_CALL PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
-#define glPixelTransferf glad_glPixelTransferf
-GLAD_API_CALL PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
-#define glPixelTransferi glad_glPixelTransferi
-GLAD_API_CALL PFNGLPIXELZOOMPROC glad_glPixelZoom;
-#define glPixelZoom glad_glPixelZoom
-GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
-#define glPointParameterf glad_glPointParameterf
-GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
-#define glPointParameterfv glad_glPointParameterfv
-GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
-#define glPointParameteri glad_glPointParameteri
-GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
-#define glPointParameteriv glad_glPointParameteriv
-GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
-#define glPointSize glad_glPointSize
-GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
-#define glPolygonMode glad_glPolygonMode
-GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
-#define glPolygonOffset glad_glPolygonOffset
-GLAD_API_CALL PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
-#define glPolygonStipple glad_glPolygonStipple
-GLAD_API_CALL PFNGLPOPATTRIBPROC glad_glPopAttrib;
-#define glPopAttrib glad_glPopAttrib
-GLAD_API_CALL PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
-#define glPopClientAttrib glad_glPopClientAttrib
-GLAD_API_CALL PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
-#define glPopDebugGroup glad_glPopDebugGroup
-GLAD_API_CALL PFNGLPOPMATRIXPROC glad_glPopMatrix;
-#define glPopMatrix glad_glPopMatrix
-GLAD_API_CALL PFNGLPOPNAMEPROC glad_glPopName;
-#define glPopName glad_glPopName
-GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
-#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
-GLAD_API_CALL PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
-#define glPrioritizeTextures glad_glPrioritizeTextures
-GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
-#define glProvokingVertex glad_glProvokingVertex
-GLAD_API_CALL PFNGLPUSHATTRIBPROC glad_glPushAttrib;
-#define glPushAttrib glad_glPushAttrib
-GLAD_API_CALL PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
-#define glPushClientAttrib glad_glPushClientAttrib
-GLAD_API_CALL PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
-#define glPushDebugGroup glad_glPushDebugGroup
-GLAD_API_CALL PFNGLPUSHMATRIXPROC glad_glPushMatrix;
-#define glPushMatrix glad_glPushMatrix
-GLAD_API_CALL PFNGLPUSHNAMEPROC glad_glPushName;
-#define glPushName glad_glPushName
-GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
-#define glQueryCounter glad_glQueryCounter
-GLAD_API_CALL PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
-#define glRasterPos2d glad_glRasterPos2d
-GLAD_API_CALL PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
-#define glRasterPos2dv glad_glRasterPos2dv
-GLAD_API_CALL PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
-#define glRasterPos2f glad_glRasterPos2f
-GLAD_API_CALL PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
-#define glRasterPos2fv glad_glRasterPos2fv
-GLAD_API_CALL PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
-#define glRasterPos2i glad_glRasterPos2i
-GLAD_API_CALL PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
-#define glRasterPos2iv glad_glRasterPos2iv
-GLAD_API_CALL PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
-#define glRasterPos2s glad_glRasterPos2s
-GLAD_API_CALL PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
-#define glRasterPos2sv glad_glRasterPos2sv
-GLAD_API_CALL PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
-#define glRasterPos3d glad_glRasterPos3d
-GLAD_API_CALL PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
-#define glRasterPos3dv glad_glRasterPos3dv
-GLAD_API_CALL PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
-#define glRasterPos3f glad_glRasterPos3f
-GLAD_API_CALL PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
-#define glRasterPos3fv glad_glRasterPos3fv
-GLAD_API_CALL PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
-#define glRasterPos3i glad_glRasterPos3i
-GLAD_API_CALL PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
-#define glRasterPos3iv glad_glRasterPos3iv
-GLAD_API_CALL PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
-#define glRasterPos3s glad_glRasterPos3s
-GLAD_API_CALL PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
-#define glRasterPos3sv glad_glRasterPos3sv
-GLAD_API_CALL PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
-#define glRasterPos4d glad_glRasterPos4d
-GLAD_API_CALL PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
-#define glRasterPos4dv glad_glRasterPos4dv
-GLAD_API_CALL PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
-#define glRasterPos4f glad_glRasterPos4f
-GLAD_API_CALL PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
-#define glRasterPos4fv glad_glRasterPos4fv
-GLAD_API_CALL PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
-#define glRasterPos4i glad_glRasterPos4i
-GLAD_API_CALL PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
-#define glRasterPos4iv glad_glRasterPos4iv
-GLAD_API_CALL PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
-#define glRasterPos4s glad_glRasterPos4s
-GLAD_API_CALL PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
-#define glRasterPos4sv glad_glRasterPos4sv
-GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
-#define glReadBuffer glad_glReadBuffer
-GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
-#define glReadPixels glad_glReadPixels
-GLAD_API_CALL PFNGLREADNPIXELSPROC glad_glReadnPixels;
-#define glReadnPixels glad_glReadnPixels
-GLAD_API_CALL PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB;
-#define glReadnPixelsARB glad_glReadnPixelsARB
-GLAD_API_CALL PFNGLRECTDPROC glad_glRectd;
-#define glRectd glad_glRectd
-GLAD_API_CALL PFNGLRECTDVPROC glad_glRectdv;
-#define glRectdv glad_glRectdv
-GLAD_API_CALL PFNGLRECTFPROC glad_glRectf;
-#define glRectf glad_glRectf
-GLAD_API_CALL PFNGLRECTFVPROC glad_glRectfv;
-#define glRectfv glad_glRectfv
-GLAD_API_CALL PFNGLRECTIPROC glad_glRecti;
-#define glRecti glad_glRecti
-GLAD_API_CALL PFNGLRECTIVPROC glad_glRectiv;
-#define glRectiv glad_glRectiv
-GLAD_API_CALL PFNGLRECTSPROC glad_glRects;
-#define glRects glad_glRects
-GLAD_API_CALL PFNGLRECTSVPROC glad_glRectsv;
-#define glRectsv glad_glRectsv
-GLAD_API_CALL PFNGLRENDERMODEPROC glad_glRenderMode;
-#define glRenderMode glad_glRenderMode
-GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
-#define glRenderbufferStorage glad_glRenderbufferStorage
-GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
-#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
-GLAD_API_CALL PFNGLROTATEDPROC glad_glRotated;
-#define glRotated glad_glRotated
-GLAD_API_CALL PFNGLROTATEFPROC glad_glRotatef;
-#define glRotatef glad_glRotatef
-GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
-#define glSampleCoverage glad_glSampleCoverage
-GLAD_API_CALL PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
-#define glSampleCoverageARB glad_glSampleCoverageARB
-GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
-#define glSampleMaski glad_glSampleMaski
-GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
-#define glSamplerParameterIiv glad_glSamplerParameterIiv
-GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
-#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
-GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
-#define glSamplerParameterf glad_glSamplerParameterf
-GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
-#define glSamplerParameterfv glad_glSamplerParameterfv
-GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
-#define glSamplerParameteri glad_glSamplerParameteri
-GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
-#define glSamplerParameteriv glad_glSamplerParameteriv
-GLAD_API_CALL PFNGLSCALEDPROC glad_glScaled;
-#define glScaled glad_glScaled
-GLAD_API_CALL PFNGLSCALEFPROC glad_glScalef;
-#define glScalef glad_glScalef
-GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
-#define glScissor glad_glScissor
-GLAD_API_CALL PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
-#define glSecondaryColor3b glad_glSecondaryColor3b
-GLAD_API_CALL PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
-#define glSecondaryColor3bv glad_glSecondaryColor3bv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
-#define glSecondaryColor3d glad_glSecondaryColor3d
-GLAD_API_CALL PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
-#define glSecondaryColor3dv glad_glSecondaryColor3dv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
-#define glSecondaryColor3f glad_glSecondaryColor3f
-GLAD_API_CALL PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
-#define glSecondaryColor3fv glad_glSecondaryColor3fv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
-#define glSecondaryColor3i glad_glSecondaryColor3i
-GLAD_API_CALL PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
-#define glSecondaryColor3iv glad_glSecondaryColor3iv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
-#define glSecondaryColor3s glad_glSecondaryColor3s
-GLAD_API_CALL PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
-#define glSecondaryColor3sv glad_glSecondaryColor3sv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
-#define glSecondaryColor3ub glad_glSecondaryColor3ub
-GLAD_API_CALL PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
-#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
-#define glSecondaryColor3ui glad_glSecondaryColor3ui
-GLAD_API_CALL PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
-#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
-GLAD_API_CALL PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
-#define glSecondaryColor3us glad_glSecondaryColor3us
-GLAD_API_CALL PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
-#define glSecondaryColor3usv glad_glSecondaryColor3usv
-GLAD_API_CALL PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
-#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
-GLAD_API_CALL PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
-#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
-GLAD_API_CALL PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
-#define glSecondaryColorPointer glad_glSecondaryColorPointer
-GLAD_API_CALL PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
-#define glSelectBuffer glad_glSelectBuffer
-GLAD_API_CALL PFNGLSHADEMODELPROC glad_glShadeModel;
-#define glShadeModel glad_glShadeModel
-GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
-#define glShaderSource glad_glShaderSource
-GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
-#define glStencilFunc glad_glStencilFunc
-GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
-#define glStencilFuncSeparate glad_glStencilFuncSeparate
-GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
-#define glStencilMask glad_glStencilMask
-GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
-#define glStencilMaskSeparate glad_glStencilMaskSeparate
-GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
-#define glStencilOp glad_glStencilOp
-GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
-#define glStencilOpSeparate glad_glStencilOpSeparate
-GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
-#define glTexBuffer glad_glTexBuffer
-GLAD_API_CALL PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
-#define glTexCoord1d glad_glTexCoord1d
-GLAD_API_CALL PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
-#define glTexCoord1dv glad_glTexCoord1dv
-GLAD_API_CALL PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
-#define glTexCoord1f glad_glTexCoord1f
-GLAD_API_CALL PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
-#define glTexCoord1fv glad_glTexCoord1fv
-GLAD_API_CALL PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
-#define glTexCoord1i glad_glTexCoord1i
-GLAD_API_CALL PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
-#define glTexCoord1iv glad_glTexCoord1iv
-GLAD_API_CALL PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
-#define glTexCoord1s glad_glTexCoord1s
-GLAD_API_CALL PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
-#define glTexCoord1sv glad_glTexCoord1sv
-GLAD_API_CALL PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
-#define glTexCoord2d glad_glTexCoord2d
-GLAD_API_CALL PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
-#define glTexCoord2dv glad_glTexCoord2dv
-GLAD_API_CALL PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
-#define glTexCoord2f glad_glTexCoord2f
-GLAD_API_CALL PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
-#define glTexCoord2fv glad_glTexCoord2fv
-GLAD_API_CALL PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
-#define glTexCoord2i glad_glTexCoord2i
-GLAD_API_CALL PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
-#define glTexCoord2iv glad_glTexCoord2iv
-GLAD_API_CALL PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
-#define glTexCoord2s glad_glTexCoord2s
-GLAD_API_CALL PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
-#define glTexCoord2sv glad_glTexCoord2sv
-GLAD_API_CALL PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
-#define glTexCoord3d glad_glTexCoord3d
-GLAD_API_CALL PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
-#define glTexCoord3dv glad_glTexCoord3dv
-GLAD_API_CALL PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
-#define glTexCoord3f glad_glTexCoord3f
-GLAD_API_CALL PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
-#define glTexCoord3fv glad_glTexCoord3fv
-GLAD_API_CALL PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
-#define glTexCoord3i glad_glTexCoord3i
-GLAD_API_CALL PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
-#define glTexCoord3iv glad_glTexCoord3iv
-GLAD_API_CALL PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
-#define glTexCoord3s glad_glTexCoord3s
-GLAD_API_CALL PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
-#define glTexCoord3sv glad_glTexCoord3sv
-GLAD_API_CALL PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
-#define glTexCoord4d glad_glTexCoord4d
-GLAD_API_CALL PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
-#define glTexCoord4dv glad_glTexCoord4dv
-GLAD_API_CALL PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
-#define glTexCoord4f glad_glTexCoord4f
-GLAD_API_CALL PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
-#define glTexCoord4fv glad_glTexCoord4fv
-GLAD_API_CALL PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
-#define glTexCoord4i glad_glTexCoord4i
-GLAD_API_CALL PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
-#define glTexCoord4iv glad_glTexCoord4iv
-GLAD_API_CALL PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
-#define glTexCoord4s glad_glTexCoord4s
-GLAD_API_CALL PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
-#define glTexCoord4sv glad_glTexCoord4sv
-GLAD_API_CALL PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
-#define glTexCoordP1ui glad_glTexCoordP1ui
-GLAD_API_CALL PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
-#define glTexCoordP1uiv glad_glTexCoordP1uiv
-GLAD_API_CALL PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
-#define glTexCoordP2ui glad_glTexCoordP2ui
-GLAD_API_CALL PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
-#define glTexCoordP2uiv glad_glTexCoordP2uiv
-GLAD_API_CALL PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
-#define glTexCoordP3ui glad_glTexCoordP3ui
-GLAD_API_CALL PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
-#define glTexCoordP3uiv glad_glTexCoordP3uiv
-GLAD_API_CALL PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
-#define glTexCoordP4ui glad_glTexCoordP4ui
-GLAD_API_CALL PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
-#define glTexCoordP4uiv glad_glTexCoordP4uiv
-GLAD_API_CALL PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
-#define glTexCoordPointer glad_glTexCoordPointer
-GLAD_API_CALL PFNGLTEXENVFPROC glad_glTexEnvf;
-#define glTexEnvf glad_glTexEnvf
-GLAD_API_CALL PFNGLTEXENVFVPROC glad_glTexEnvfv;
-#define glTexEnvfv glad_glTexEnvfv
-GLAD_API_CALL PFNGLTEXENVIPROC glad_glTexEnvi;
-#define glTexEnvi glad_glTexEnvi
-GLAD_API_CALL PFNGLTEXENVIVPROC glad_glTexEnviv;
-#define glTexEnviv glad_glTexEnviv
-GLAD_API_CALL PFNGLTEXGENDPROC glad_glTexGend;
-#define glTexGend glad_glTexGend
-GLAD_API_CALL PFNGLTEXGENDVPROC glad_glTexGendv;
-#define glTexGendv glad_glTexGendv
-GLAD_API_CALL PFNGLTEXGENFPROC glad_glTexGenf;
-#define glTexGenf glad_glTexGenf
-GLAD_API_CALL PFNGLTEXGENFVPROC glad_glTexGenfv;
-#define glTexGenfv glad_glTexGenfv
-GLAD_API_CALL PFNGLTEXGENIPROC glad_glTexGeni;
-#define glTexGeni glad_glTexGeni
-GLAD_API_CALL PFNGLTEXGENIVPROC glad_glTexGeniv;
-#define glTexGeniv glad_glTexGeniv
-GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
-#define glTexImage1D glad_glTexImage1D
-GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
-#define glTexImage2D glad_glTexImage2D
-GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
-#define glTexImage2DMultisample glad_glTexImage2DMultisample
-GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
-#define glTexImage3D glad_glTexImage3D
-GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
-#define glTexImage3DMultisample glad_glTexImage3DMultisample
-GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
-#define glTexParameterIiv glad_glTexParameterIiv
-GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
-#define glTexParameterIuiv glad_glTexParameterIuiv
-GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
-#define glTexParameterf glad_glTexParameterf
-GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
-#define glTexParameterfv glad_glTexParameterfv
-GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
-#define glTexParameteri glad_glTexParameteri
-GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
-#define glTexParameteriv glad_glTexParameteriv
-GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
-#define glTexSubImage1D glad_glTexSubImage1D
-GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
-#define glTexSubImage2D glad_glTexSubImage2D
-GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
-#define glTexSubImage3D glad_glTexSubImage3D
-GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
-#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
-GLAD_API_CALL PFNGLTRANSLATEDPROC glad_glTranslated;
-#define glTranslated glad_glTranslated
-GLAD_API_CALL PFNGLTRANSLATEFPROC glad_glTranslatef;
-#define glTranslatef glad_glTranslatef
-GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
-#define glUniform1f glad_glUniform1f
-GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
-#define glUniform1fv glad_glUniform1fv
-GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
-#define glUniform1i glad_glUniform1i
-GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
-#define glUniform1iv glad_glUniform1iv
-GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
-#define glUniform1ui glad_glUniform1ui
-GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
-#define glUniform1uiv glad_glUniform1uiv
-GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
-#define glUniform2f glad_glUniform2f
-GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
-#define glUniform2fv glad_glUniform2fv
-GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
-#define glUniform2i glad_glUniform2i
-GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
-#define glUniform2iv glad_glUniform2iv
-GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
-#define glUniform2ui glad_glUniform2ui
-GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
-#define glUniform2uiv glad_glUniform2uiv
-GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
-#define glUniform3f glad_glUniform3f
-GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
-#define glUniform3fv glad_glUniform3fv
-GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
-#define glUniform3i glad_glUniform3i
-GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
-#define glUniform3iv glad_glUniform3iv
-GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
-#define glUniform3ui glad_glUniform3ui
-GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
-#define glUniform3uiv glad_glUniform3uiv
-GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
-#define glUniform4f glad_glUniform4f
-GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
-#define glUniform4fv glad_glUniform4fv
-GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
-#define glUniform4i glad_glUniform4i
-GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
-#define glUniform4iv glad_glUniform4iv
-GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
-#define glUniform4ui glad_glUniform4ui
-GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
-#define glUniform4uiv glad_glUniform4uiv
-GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
-#define glUniformBlockBinding glad_glUniformBlockBinding
-GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
-#define glUniformMatrix2fv glad_glUniformMatrix2fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
-#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
-#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
-#define glUniformMatrix3fv glad_glUniformMatrix3fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
-#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
-#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
-#define glUniformMatrix4fv glad_glUniformMatrix4fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
-#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
-GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
-#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
-GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
-#define glUnmapBuffer glad_glUnmapBuffer
-GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
-#define glUseProgram glad_glUseProgram
-GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
-#define glValidateProgram glad_glValidateProgram
-GLAD_API_CALL PFNGLVERTEX2DPROC glad_glVertex2d;
-#define glVertex2d glad_glVertex2d
-GLAD_API_CALL PFNGLVERTEX2DVPROC glad_glVertex2dv;
-#define glVertex2dv glad_glVertex2dv
-GLAD_API_CALL PFNGLVERTEX2FPROC glad_glVertex2f;
-#define glVertex2f glad_glVertex2f
-GLAD_API_CALL PFNGLVERTEX2FVPROC glad_glVertex2fv;
-#define glVertex2fv glad_glVertex2fv
-GLAD_API_CALL PFNGLVERTEX2IPROC glad_glVertex2i;
-#define glVertex2i glad_glVertex2i
-GLAD_API_CALL PFNGLVERTEX2IVPROC glad_glVertex2iv;
-#define glVertex2iv glad_glVertex2iv
-GLAD_API_CALL PFNGLVERTEX2SPROC glad_glVertex2s;
-#define glVertex2s glad_glVertex2s
-GLAD_API_CALL PFNGLVERTEX2SVPROC glad_glVertex2sv;
-#define glVertex2sv glad_glVertex2sv
-GLAD_API_CALL PFNGLVERTEX3DPROC glad_glVertex3d;
-#define glVertex3d glad_glVertex3d
-GLAD_API_CALL PFNGLVERTEX3DVPROC glad_glVertex3dv;
-#define glVertex3dv glad_glVertex3dv
-GLAD_API_CALL PFNGLVERTEX3FPROC glad_glVertex3f;
-#define glVertex3f glad_glVertex3f
-GLAD_API_CALL PFNGLVERTEX3FVPROC glad_glVertex3fv;
-#define glVertex3fv glad_glVertex3fv
-GLAD_API_CALL PFNGLVERTEX3IPROC glad_glVertex3i;
-#define glVertex3i glad_glVertex3i
-GLAD_API_CALL PFNGLVERTEX3IVPROC glad_glVertex3iv;
-#define glVertex3iv glad_glVertex3iv
-GLAD_API_CALL PFNGLVERTEX3SPROC glad_glVertex3s;
-#define glVertex3s glad_glVertex3s
-GLAD_API_CALL PFNGLVERTEX3SVPROC glad_glVertex3sv;
-#define glVertex3sv glad_glVertex3sv
-GLAD_API_CALL PFNGLVERTEX4DPROC glad_glVertex4d;
-#define glVertex4d glad_glVertex4d
-GLAD_API_CALL PFNGLVERTEX4DVPROC glad_glVertex4dv;
-#define glVertex4dv glad_glVertex4dv
-GLAD_API_CALL PFNGLVERTEX4FPROC glad_glVertex4f;
-#define glVertex4f glad_glVertex4f
-GLAD_API_CALL PFNGLVERTEX4FVPROC glad_glVertex4fv;
-#define glVertex4fv glad_glVertex4fv
-GLAD_API_CALL PFNGLVERTEX4IPROC glad_glVertex4i;
-#define glVertex4i glad_glVertex4i
-GLAD_API_CALL PFNGLVERTEX4IVPROC glad_glVertex4iv;
-#define glVertex4iv glad_glVertex4iv
-GLAD_API_CALL PFNGLVERTEX4SPROC glad_glVertex4s;
-#define glVertex4s glad_glVertex4s
-GLAD_API_CALL PFNGLVERTEX4SVPROC glad_glVertex4sv;
-#define glVertex4sv glad_glVertex4sv
-GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
-#define glVertexAttrib1d glad_glVertexAttrib1d
-GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
-#define glVertexAttrib1dv glad_glVertexAttrib1dv
-GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
-#define glVertexAttrib1f glad_glVertexAttrib1f
-GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
-#define glVertexAttrib1fv glad_glVertexAttrib1fv
-GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
-#define glVertexAttrib1s glad_glVertexAttrib1s
-GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
-#define glVertexAttrib1sv glad_glVertexAttrib1sv
-GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
-#define glVertexAttrib2d glad_glVertexAttrib2d
-GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
-#define glVertexAttrib2dv glad_glVertexAttrib2dv
-GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
-#define glVertexAttrib2f glad_glVertexAttrib2f
-GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
-#define glVertexAttrib2fv glad_glVertexAttrib2fv
-GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
-#define glVertexAttrib2s glad_glVertexAttrib2s
-GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
-#define glVertexAttrib2sv glad_glVertexAttrib2sv
-GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
-#define glVertexAttrib3d glad_glVertexAttrib3d
-GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
-#define glVertexAttrib3dv glad_glVertexAttrib3dv
-GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
-#define glVertexAttrib3f glad_glVertexAttrib3f
-GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
-#define glVertexAttrib3fv glad_glVertexAttrib3fv
-GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
-#define glVertexAttrib3s glad_glVertexAttrib3s
-GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
-#define glVertexAttrib3sv glad_glVertexAttrib3sv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
-#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
-#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
-#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
-#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
-GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
-#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
-#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
-GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
-#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
-GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
-#define glVertexAttrib4bv glad_glVertexAttrib4bv
-GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
-#define glVertexAttrib4d glad_glVertexAttrib4d
-GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
-#define glVertexAttrib4dv glad_glVertexAttrib4dv
-GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
-#define glVertexAttrib4f glad_glVertexAttrib4f
-GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
-#define glVertexAttrib4fv glad_glVertexAttrib4fv
-GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
-#define glVertexAttrib4iv glad_glVertexAttrib4iv
-GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
-#define glVertexAttrib4s glad_glVertexAttrib4s
-GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
-#define glVertexAttrib4sv glad_glVertexAttrib4sv
-GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
-#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
-GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
-#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
-GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
-#define glVertexAttrib4usv glad_glVertexAttrib4usv
-GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
-#define glVertexAttribDivisor glad_glVertexAttribDivisor
-GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
-#define glVertexAttribI1i glad_glVertexAttribI1i
-GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
-#define glVertexAttribI1iv glad_glVertexAttribI1iv
-GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
-#define glVertexAttribI1ui glad_glVertexAttribI1ui
-GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
-#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
-#define glVertexAttribI2i glad_glVertexAttribI2i
-GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
-#define glVertexAttribI2iv glad_glVertexAttribI2iv
-GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
-#define glVertexAttribI2ui glad_glVertexAttribI2ui
-GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
-#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
-#define glVertexAttribI3i glad_glVertexAttribI3i
-GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
-#define glVertexAttribI3iv glad_glVertexAttribI3iv
-GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
-#define glVertexAttribI3ui glad_glVertexAttribI3ui
-GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
-#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
-#define glVertexAttribI4bv glad_glVertexAttribI4bv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
-#define glVertexAttribI4i glad_glVertexAttribI4i
-GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
-#define glVertexAttribI4iv glad_glVertexAttribI4iv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
-#define glVertexAttribI4sv glad_glVertexAttribI4sv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
-#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
-#define glVertexAttribI4ui glad_glVertexAttribI4ui
-GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
-#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
-#define glVertexAttribI4usv glad_glVertexAttribI4usv
-GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
-#define glVertexAttribIPointer glad_glVertexAttribIPointer
-GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
-#define glVertexAttribP1ui glad_glVertexAttribP1ui
-GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
-#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
-#define glVertexAttribP2ui glad_glVertexAttribP2ui
-GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
-#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
-#define glVertexAttribP3ui glad_glVertexAttribP3ui
-GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
-#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
-#define glVertexAttribP4ui glad_glVertexAttribP4ui
-GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
-#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
-GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
-#define glVertexAttribPointer glad_glVertexAttribPointer
-GLAD_API_CALL PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
-#define glVertexP2ui glad_glVertexP2ui
-GLAD_API_CALL PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
-#define glVertexP2uiv glad_glVertexP2uiv
-GLAD_API_CALL PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
-#define glVertexP3ui glad_glVertexP3ui
-GLAD_API_CALL PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
-#define glVertexP3uiv glad_glVertexP3uiv
-GLAD_API_CALL PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
-#define glVertexP4ui glad_glVertexP4ui
-GLAD_API_CALL PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
-#define glVertexP4uiv glad_glVertexP4uiv
-GLAD_API_CALL PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
-#define glVertexPointer glad_glVertexPointer
-GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
-#define glViewport glad_glViewport
-GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
-#define glWaitSync glad_glWaitSync
-GLAD_API_CALL PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
-#define glWindowPos2d glad_glWindowPos2d
-GLAD_API_CALL PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
-#define glWindowPos2dv glad_glWindowPos2dv
-GLAD_API_CALL PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
-#define glWindowPos2f glad_glWindowPos2f
-GLAD_API_CALL PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
-#define glWindowPos2fv glad_glWindowPos2fv
-GLAD_API_CALL PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
-#define glWindowPos2i glad_glWindowPos2i
-GLAD_API_CALL PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
-#define glWindowPos2iv glad_glWindowPos2iv
-GLAD_API_CALL PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
-#define glWindowPos2s glad_glWindowPos2s
-GLAD_API_CALL PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
-#define glWindowPos2sv glad_glWindowPos2sv
-GLAD_API_CALL PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
-#define glWindowPos3d glad_glWindowPos3d
-GLAD_API_CALL PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
-#define glWindowPos3dv glad_glWindowPos3dv
-GLAD_API_CALL PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
-#define glWindowPos3f glad_glWindowPos3f
-GLAD_API_CALL PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
-#define glWindowPos3fv glad_glWindowPos3fv
-GLAD_API_CALL PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
-#define glWindowPos3i glad_glWindowPos3i
-GLAD_API_CALL PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
-#define glWindowPos3iv glad_glWindowPos3iv
-GLAD_API_CALL PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
-#define glWindowPos3s glad_glWindowPos3s
-GLAD_API_CALL PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
-#define glWindowPos3sv glad_glWindowPos3sv
-
-
-GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
-GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
-
-
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/**
+ * Loader generated by glad 2.0.0-beta on Sun Apr 14 17:03:32 2019
+ *
+ * Generator: C/C++
+ * Specification: gl
+ * Extensions: 3
+ *
+ * APIs:
+ *  - gl:compatibility=3.3
+ *
+ * Options:
+ *  - MX_GLOBAL = False
+ *  - LOADER = False
+ *  - ALIAS = False
+ *  - HEADER_ONLY = False
+ *  - DEBUG = False
+ *  - MX = False
+ *
+ * Commandline:
+ *    --api='gl:compatibility=3.3' --extensions='GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug' c
+ *
+ * Online:
+ *    http://glad.sh/#api=gl%3Acompatibility%3D3.3&extensions=GL_ARB_multisample%2CGL_ARB_robustness%2CGL_KHR_debug&generator=c&options=
+ *
+ */
+
+#ifndef GLAD_GL_H_
+#define GLAD_GL_H_
+
+#ifdef __gl_h_
+    #error OpenGL header already included (API: gl), remove previous include!
+#endif
+#define __gl_h_ 1
+
+
+#define GLAD_GL
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GLAD_PLATFORM_H_
+#define GLAD_PLATFORM_H_
+
+#ifndef GLAD_PLATFORM_WIN32
+  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)
+    #define GLAD_PLATFORM_WIN32 1
+  #else
+    #define GLAD_PLATFORM_WIN32 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_APPLE
+  #ifdef __APPLE__
+    #define GLAD_PLATFORM_APPLE 1
+  #else
+    #define GLAD_PLATFORM_APPLE 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_EMSCRIPTEN
+  #ifdef __EMSCRIPTEN__
+    #define GLAD_PLATFORM_EMSCRIPTEN 1
+  #else
+    #define GLAD_PLATFORM_EMSCRIPTEN 0
+  #endif
+#endif
+
+#ifndef GLAD_PLATFORM_UWP
+  #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY)
+    #ifdef __has_include
+      #if __has_include(<winapifamily.h>)
+        #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+      #endif
+    #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_
+      #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1
+    #endif
+  #endif
+
+  #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY
+    #include <winapifamily.h>
+    #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
+      #define GLAD_PLATFORM_UWP 1
+    #endif
+  #endif
+
+  #ifndef GLAD_PLATFORM_UWP
+    #define GLAD_PLATFORM_UWP 0
+  #endif
+#endif
+
+#ifdef __GNUC__
+  #define GLAD_GNUC_EXTENSION __extension__
+#else
+  #define GLAD_GNUC_EXTENSION
+#endif
+
+#ifndef GLAD_API_CALL
+  #if defined(GLAD_API_CALL_EXPORT)
+    #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__)
+      #if defined(GLAD_API_CALL_EXPORT_BUILD)
+        #if defined(__GNUC__)
+          #define GLAD_API_CALL __attribute__ ((dllexport)) extern
+        #else
+          #define GLAD_API_CALL __declspec(dllexport) extern
+        #endif
+      #else
+        #if defined(__GNUC__)
+          #define GLAD_API_CALL __attribute__ ((dllimport)) extern
+        #else
+          #define GLAD_API_CALL __declspec(dllimport) extern
+        #endif
+      #endif
+    #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD)
+      #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern
+    #else
+      #define GLAD_API_CALL extern
+    #endif
+  #else
+    #define GLAD_API_CALL extern
+  #endif
+#endif
+
+#ifdef APIENTRY
+  #define GLAD_API_PTR APIENTRY
+#elif GLAD_PLATFORM_WIN32
+  #define GLAD_API_PTR __stdcall
+#else
+  #define GLAD_API_PTR
+#endif
+
+#ifndef GLAPI
+#define GLAPI GLAD_API_CALL
+#endif
+
+#ifndef GLAPIENTRY
+#define GLAPIENTRY GLAD_API_PTR
+#endif
+
+
+#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor)
+#define GLAD_VERSION_MAJOR(version) (version / 10000)
+#define GLAD_VERSION_MINOR(version) (version % 10000)
+
+typedef void (*GLADapiproc)(void);
+
+typedef GLADapiproc (*GLADloadfunc)(const char *name);
+typedef GLADapiproc (*GLADuserptrloadfunc)(const char *name, void *userptr);
+
+typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...);
+typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...);
+
+#endif /* GLAD_PLATFORM_H_ */
+
+#define GL_2D 0x0600
+#define GL_2_BYTES 0x1407
+#define GL_3D 0x0601
+#define GL_3D_COLOR 0x0602
+#define GL_3D_COLOR_TEXTURE 0x0603
+#define GL_3_BYTES 0x1408
+#define GL_4D_COLOR_TEXTURE 0x0604
+#define GL_4_BYTES 0x1409
+#define GL_ACCUM 0x0100
+#define GL_ACCUM_ALPHA_BITS 0x0D5B
+#define GL_ACCUM_BLUE_BITS 0x0D5A
+#define GL_ACCUM_BUFFER_BIT 0x00000200
+#define GL_ACCUM_CLEAR_VALUE 0x0B80
+#define GL_ACCUM_GREEN_BITS 0x0D59
+#define GL_ACCUM_RED_BITS 0x0D58
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ADD 0x0104
+#define GL_ADD_SIGNED 0x8574
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_ALPHA 0x1906
+#define GL_ALPHA12 0x803D
+#define GL_ALPHA16 0x803E
+#define GL_ALPHA4 0x803B
+#define GL_ALPHA8 0x803C
+#define GL_ALPHA_BIAS 0x0D1D
+#define GL_ALPHA_BITS 0x0D55
+#define GL_ALPHA_INTEGER 0x8D97
+#define GL_ALPHA_SCALE 0x0D1C
+#define GL_ALPHA_TEST 0x0BC0
+#define GL_ALPHA_TEST_FUNC 0x0BC1
+#define GL_ALPHA_TEST_REF 0x0BC2
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_ALWAYS 0x0207
+#define GL_AMBIENT 0x1200
+#define GL_AMBIENT_AND_DIFFUSE 0x1602
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ATTRIB_STACK_DEPTH 0x0BB0
+#define GL_AUTO_NORMAL 0x0D80
+#define GL_AUX0 0x0409
+#define GL_AUX1 0x040A
+#define GL_AUX2 0x040B
+#define GL_AUX3 0x040C
+#define GL_AUX_BUFFERS 0x0C00
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BITMAP 0x1A00
+#define GL_BITMAP_TOKEN 0x0704
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLUE 0x1905
+#define GL_BLUE_BIAS 0x0D1B
+#define GL_BLUE_BITS 0x0D54
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BLUE_SCALE 0x0D1A
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_BUFFER 0x82E0
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_BYTE 0x1400
+#define GL_C3F_V3F 0x2A24
+#define GL_C4F_N3F_V3F 0x2A26
+#define GL_C4UB_V2F 0x2A22
+#define GL_C4UB_V3F 0x2A23
+#define GL_CCW 0x0901
+#define GL_CLAMP 0x2900
+#define GL_CLAMP_FRAGMENT_COLOR 0x891B
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_CLAMP_VERTEX_COLOR 0x891A
+#define GL_CLEAR 0x1500
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
+#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1
+#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
+#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_CLIP_PLANE0 0x3000
+#define GL_CLIP_PLANE1 0x3001
+#define GL_CLIP_PLANE2 0x3002
+#define GL_CLIP_PLANE3 0x3003
+#define GL_CLIP_PLANE4 0x3004
+#define GL_CLIP_PLANE5 0x3005
+#define GL_COEFF 0x0A00
+#define GL_COLOR 0x1800
+#define GL_COLOR_ARRAY 0x8076
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_COLOR_ARRAY_POINTER 0x8090
+#define GL_COLOR_ARRAY_SIZE 0x8081
+#define GL_COLOR_ARRAY_STRIDE 0x8083
+#define GL_COLOR_ARRAY_TYPE 0x8082
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT16 0x8CF0
+#define GL_COLOR_ATTACHMENT17 0x8CF1
+#define GL_COLOR_ATTACHMENT18 0x8CF2
+#define GL_COLOR_ATTACHMENT19 0x8CF3
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT20 0x8CF4
+#define GL_COLOR_ATTACHMENT21 0x8CF5
+#define GL_COLOR_ATTACHMENT22 0x8CF6
+#define GL_COLOR_ATTACHMENT23 0x8CF7
+#define GL_COLOR_ATTACHMENT24 0x8CF8
+#define GL_COLOR_ATTACHMENT25 0x8CF9
+#define GL_COLOR_ATTACHMENT26 0x8CFA
+#define GL_COLOR_ATTACHMENT27 0x8CFB
+#define GL_COLOR_ATTACHMENT28 0x8CFC
+#define GL_COLOR_ATTACHMENT29 0x8CFD
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT30 0x8CFE
+#define GL_COLOR_ATTACHMENT31 0x8CFF
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_INDEX 0x1900
+#define GL_COLOR_INDEXES 0x1603
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_MATERIAL 0x0B57
+#define GL_COLOR_MATERIAL_FACE 0x0B55
+#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
+#define GL_COLOR_SUM 0x8458
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+#define GL_COMPILE 0x1300
+#define GL_COMPILE_AND_EXECUTE 0x1301
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_COMPRESSED_SLUMINANCE 0x8C4A
+#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONSTANT 0x8576
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_ATTENUATION 0x1207
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_COORD_REPLACE 0x8862
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_COPY_PIXEL_TOKEN 0x0706
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CURRENT_BIT 0x00000001
+#define GL_CURRENT_COLOR 0x0B00
+#define GL_CURRENT_FOG_COORD 0x8453
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_CURRENT_INDEX 0x0B01
+#define GL_CURRENT_NORMAL 0x0B02
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_QUERY 0x8865
+#define GL_CURRENT_RASTER_COLOR 0x0B04
+#define GL_CURRENT_RASTER_DISTANCE 0x0B09
+#define GL_CURRENT_RASTER_INDEX 0x0B05
+#define GL_CURRENT_RASTER_POSITION 0x0B07
+#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08
+#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F
+#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_CURRENT_TEXTURE_COORDS 0x0B03
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_CW 0x0900
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DECAL 0x2101
+#define GL_DECR 0x1E03
+#define GL_DECR_WRAP 0x8508
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DEPTH 0x1801
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_BIAS 0x0D1F
+#define GL_DEPTH_BITS 0x0D56
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_SCALE 0x0D1E
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DIFFUSE 0x1201
+#define GL_DISPLAY_LIST 0x82E7
+#define GL_DITHER 0x0BD0
+#define GL_DOMAIN 0x0A02
+#define GL_DONT_CARE 0x1100
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_DRAW_PIXEL_TOKEN 0x0705
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_EDGE_FLAG 0x0B43
+#define GL_EDGE_FLAG_ARRAY 0x8079
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
+#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_EMISSION 0x1600
+#define GL_ENABLE_BIT 0x00002000
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EVAL_BIT 0x00010000
+#define GL_EXP 0x0800
+#define GL_EXP2 0x0801
+#define GL_EXTENSIONS 0x1F03
+#define GL_EYE_LINEAR 0x2400
+#define GL_EYE_PLANE 0x2502
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FEEDBACK 0x1C01
+#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
+#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1
+#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2
+#define GL_FILL 0x1B02
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLAT 0x1D00
+#define GL_FLOAT 0x1406
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FOG 0x0B60
+#define GL_FOG_BIT 0x00000080
+#define GL_FOG_COLOR 0x0B66
+#define GL_FOG_COORD 0x8451
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORD_ARRAY 0x8457
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
+#define GL_FOG_COORD_ARRAY_POINTER 0x8456
+#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORD_ARRAY_TYPE 0x8454
+#define GL_FOG_COORD_SRC 0x8450
+#define GL_FOG_DENSITY 0x0B62
+#define GL_FOG_END 0x0B64
+#define GL_FOG_HINT 0x0C54
+#define GL_FOG_INDEX 0x0B61
+#define GL_FOG_MODE 0x0B65
+#define GL_FOG_START 0x0B63
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_GREEN_BIAS 0x0D19
+#define GL_GREEN_BITS 0x0D53
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_GREEN_SCALE 0x0D18
+#define GL_GUILTY_CONTEXT_RESET_ARB 0x8253
+#define GL_HALF_FLOAT 0x140B
+#define GL_HINT_BIT 0x00008000
+#define GL_INCR 0x1E02
+#define GL_INCR_WRAP 0x8507
+#define GL_INDEX 0x8222
+#define GL_INDEX_ARRAY 0x8077
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_INDEX_ARRAY_POINTER 0x8091
+#define GL_INDEX_ARRAY_STRIDE 0x8086
+#define GL_INDEX_ARRAY_TYPE 0x8085
+#define GL_INDEX_BITS 0x0D51
+#define GL_INDEX_CLEAR_VALUE 0x0C20
+#define GL_INDEX_LOGIC_OP 0x0BF1
+#define GL_INDEX_MODE 0x0C30
+#define GL_INDEX_OFFSET 0x0D13
+#define GL_INDEX_SHIFT 0x0D12
+#define GL_INDEX_WRITEMASK 0x0C21
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INNOCENT_CONTEXT_RESET_ARB 0x8254
+#define GL_INT 0x1404
+#define GL_INTENSITY 0x8049
+#define GL_INTENSITY12 0x804C
+#define GL_INTENSITY16 0x804D
+#define GL_INTENSITY4 0x804A
+#define GL_INTENSITY8 0x804B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INTERPOLATE 0x8575
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_INVALID_INDEX 0xFFFFFFFF
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LIGHT0 0x4000
+#define GL_LIGHT1 0x4001
+#define GL_LIGHT2 0x4002
+#define GL_LIGHT3 0x4003
+#define GL_LIGHT4 0x4004
+#define GL_LIGHT5 0x4005
+#define GL_LIGHT6 0x4006
+#define GL_LIGHT7 0x4007
+#define GL_LIGHTING 0x0B50
+#define GL_LIGHTING_BIT 0x00000040
+#define GL_LIGHT_MODEL_AMBIENT 0x0B53
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
+#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_ATTENUATION 0x1208
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_BIT 0x00000004
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_RESET_TOKEN 0x0707
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STIPPLE 0x0B24
+#define GL_LINE_STIPPLE_PATTERN 0x0B25
+#define GL_LINE_STIPPLE_REPEAT 0x0B26
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_LINE_TOKEN 0x0702
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LINK_STATUS 0x8B82
+#define GL_LIST_BASE 0x0B32
+#define GL_LIST_BIT 0x00020000
+#define GL_LIST_INDEX 0x0B33
+#define GL_LIST_MODE 0x0B30
+#define GL_LOAD 0x0101
+#define GL_LOGIC_OP 0x0BF1
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE12 0x8041
+#define GL_LUMINANCE12_ALPHA12 0x8047
+#define GL_LUMINANCE12_ALPHA4 0x8046
+#define GL_LUMINANCE16 0x8042
+#define GL_LUMINANCE16_ALPHA16 0x8048
+#define GL_LUMINANCE4 0x803F
+#define GL_LUMINANCE4_ALPHA4 0x8043
+#define GL_LUMINANCE6_ALPHA2 0x8044
+#define GL_LUMINANCE8 0x8040
+#define GL_LUMINANCE8_ALPHA8 0x8045
+#define GL_LUMINANCE_ALPHA 0x190A
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP1_COLOR_4 0x0D90
+#define GL_MAP1_GRID_DOMAIN 0x0DD0
+#define GL_MAP1_GRID_SEGMENTS 0x0DD1
+#define GL_MAP1_INDEX 0x0D91
+#define GL_MAP1_NORMAL 0x0D92
+#define GL_MAP1_TEXTURE_COORD_1 0x0D93
+#define GL_MAP1_TEXTURE_COORD_2 0x0D94
+#define GL_MAP1_TEXTURE_COORD_3 0x0D95
+#define GL_MAP1_TEXTURE_COORD_4 0x0D96
+#define GL_MAP1_VERTEX_3 0x0D97
+#define GL_MAP1_VERTEX_4 0x0D98
+#define GL_MAP2_COLOR_4 0x0DB0
+#define GL_MAP2_GRID_DOMAIN 0x0DD2
+#define GL_MAP2_GRID_SEGMENTS 0x0DD3
+#define GL_MAP2_INDEX 0x0DB1
+#define GL_MAP2_NORMAL 0x0DB2
+#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
+#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
+#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
+#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
+#define GL_MAP2_VERTEX_3 0x0DB7
+#define GL_MAP2_VERTEX_4 0x0DB8
+#define GL_MAP_COLOR 0x0D10
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_STENCIL 0x0D11
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MATRIX_MODE 0x0BA0
+#define GL_MAX 0x8008
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35
+#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_CLIP_PLANES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_EVAL_ORDER 0x0D30
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_LIGHTS 0x0D31
+#define GL_MAX_LIST_NESTING 0x0B31
+#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36
+#define GL_MAX_NAME_STACK_DEPTH 0x0D37
+#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_MIN 0x8007
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_MODELVIEW 0x1700
+#define GL_MODELVIEW_MATRIX 0x0BA6
+#define GL_MODELVIEW_STACK_DEPTH 0x0BA3
+#define GL_MODULATE 0x2100
+#define GL_MULT 0x0103
+#define GL_MULTISAMPLE 0x809D
+#define GL_MULTISAMPLE_ARB 0x809D
+#define GL_MULTISAMPLE_BIT 0x20000000
+#define GL_MULTISAMPLE_BIT_ARB 0x20000000
+#define GL_N3F_V3F 0x2A25
+#define GL_NAME_STACK_DEPTH 0x0D70
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NORMALIZE 0x0BA1
+#define GL_NORMAL_ARRAY 0x8075
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_NORMAL_ARRAY_POINTER 0x808F
+#define GL_NORMAL_ARRAY_STRIDE 0x807F
+#define GL_NORMAL_ARRAY_TYPE 0x807E
+#define GL_NORMAL_MAP 0x8511
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_OBJECT_LINEAR 0x2401
+#define GL_OBJECT_PLANE 0x2501
+#define GL_OBJECT_TYPE 0x9112
+#define GL_ONE 1
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OR 0x1507
+#define GL_ORDER 0x0A01
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_PASS_THROUGH_TOKEN 0x0700
+#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50
+#define GL_PIXEL_MAP_A_TO_A 0x0C79
+#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
+#define GL_PIXEL_MAP_B_TO_B 0x0C78
+#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
+#define GL_PIXEL_MAP_G_TO_G 0x0C77
+#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
+#define GL_PIXEL_MAP_I_TO_A 0x0C75
+#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
+#define GL_PIXEL_MAP_I_TO_B 0x0C74
+#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
+#define GL_PIXEL_MAP_I_TO_G 0x0C73
+#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
+#define GL_PIXEL_MAP_I_TO_I 0x0C70
+#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
+#define GL_PIXEL_MAP_I_TO_R 0x0C72
+#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
+#define GL_PIXEL_MAP_R_TO_R 0x0C76
+#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
+#define GL_PIXEL_MAP_S_TO_S 0x0C71
+#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
+#define GL_PIXEL_MODE_BIT 0x00000020
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_BIT 0x00000002
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POINT_SMOOTH 0x0B10
+#define GL_POINT_SMOOTH_HINT 0x0C51
+#define GL_POINT_SPRITE 0x8861
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_POINT_TOKEN 0x0701
+#define GL_POLYGON 0x0009
+#define GL_POLYGON_BIT 0x00000008
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_POLYGON_STIPPLE 0x0B42
+#define GL_POLYGON_STIPPLE_BIT 0x00000010
+#define GL_POLYGON_TOKEN 0x0703
+#define GL_POSITION 0x1203
+#define GL_PREVIOUS 0x8578
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROGRAM 0x82E2
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROJECTION 0x1701
+#define GL_PROJECTION_MATRIX 0x0BA7
+#define GL_PROJECTION_STACK_DEPTH 0x0BA4
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_Q 0x2003
+#define GL_QUADRATIC_ATTENUATION 0x1209
+#define GL_QUADS 0x0007
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_QUAD_STRIP 0x0008
+#define GL_QUERY 0x82E3
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R 0x2002
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R16_SNORM 0x8F98
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R3_G3_B2 0x2A10
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_R8_SNORM 0x8F94
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_BUFFER 0x0C02
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_RED 0x1903
+#define GL_RED_BIAS 0x0D15
+#define GL_RED_BITS 0x0D52
+#define GL_RED_INTEGER 0x8D94
+#define GL_RED_SCALE 0x0D14
+#define GL_REFLECTION_MAP 0x8512
+#define GL_RENDER 0x1C00
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RENDERER 0x1F01
+#define GL_RENDER_MODE 0x0C40
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_RETURN 0x0102
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB10_A2UI 0x906F
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA2 0x8055
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGBA_MODE 0x0C31
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RGB_SCALE 0x8573
+#define GL_RG_INTEGER 0x8228
+#define GL_RIGHT 0x0407
+#define GL_S 0x2000
+#define GL_SAMPLER 0x82E6
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLES_ARB 0x80A9
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_COVERAGE_ARB 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_ALPHA_TO_ONE_ARB 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_BUFFERS_ARB 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_ARB 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SCISSOR_BIT 0x00080000
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SELECT 0x1C02
+#define GL_SELECTION_BUFFER_POINTER 0x0DF3
+#define GL_SELECTION_BUFFER_SIZE 0x0DF4
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_SET 0x150F
+#define GL_SHADER 0x82E1
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADE_MODEL 0x0B54
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_SHININESS 0x1601
+#define GL_SHORT 0x1402
+#define GL_SIGNALED 0x9119
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SLUMINANCE 0x8C46
+#define GL_SLUMINANCE8 0x8C47
+#define GL_SLUMINANCE8_ALPHA8 0x8C45
+#define GL_SLUMINANCE_ALPHA 0x8C44
+#define GL_SMOOTH 0x1D01
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SPECULAR 0x1202
+#define GL_SPHERE_MAP 0x2402
+#define GL_SPOT_CUTOFF 0x1206
+#define GL_SPOT_DIRECTION 0x1204
+#define GL_SPOT_EXPONENT 0x1205
+#define GL_SRC0_ALPHA 0x8588
+#define GL_SRC0_RGB 0x8580
+#define GL_SRC1_ALPHA 0x8589
+#define GL_SRC1_COLOR 0x88F9
+#define GL_SRC1_RGB 0x8581
+#define GL_SRC2_ALPHA 0x858A
+#define GL_SRC2_RGB 0x8582
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+#define GL_STACK_OVERFLOW 0x0503
+#define GL_STACK_UNDERFLOW 0x0504
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_STENCIL_BITS 0x0D57
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_SUBTRACT 0x84E7
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_T 0x2001
+#define GL_T2F_C3F_V3F 0x2A2A
+#define GL_T2F_C4F_N3F_V3F 0x2A2C
+#define GL_T2F_C4UB_V3F 0x2A29
+#define GL_T2F_N3F_V3F 0x2A2B
+#define GL_T2F_V3F 0x2A27
+#define GL_T4F_C4F_N3F_V4F 0x2A2D
+#define GL_T4F_V4F 0x2A28
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BIT 0x00040000
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_BORDER 0x1005
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPONENTS 0x1003
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092
+#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088
+#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A
+#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_ENV 0x2300
+#define GL_TEXTURE_ENV_COLOR 0x2201
+#define GL_TEXTURE_ENV_MODE 0x2200
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_GEN_MODE 0x2500
+#define GL_TEXTURE_GEN_Q 0x0C63
+#define GL_TEXTURE_GEN_R 0x0C62
+#define GL_TEXTURE_GEN_S 0x0C60
+#define GL_TEXTURE_GEN_T 0x0C61
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTENSITY_SIZE 0x8061
+#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
+#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MATRIX 0x0BA8
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_PRIORITY 0x8066
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_RESIDENT 0x8067
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STACK_DEPTH 0x0BA5
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_TRANSFORM_BIT 0x00001000
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_TRUE 1
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNKNOWN_CONTEXT_RESET_ARB 0x8255
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_V2F 0x2A20
+#define GL_V3F 0x2A21
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_VERTEX_ARRAY_POINTER 0x808E
+#define GL_VERTEX_ARRAY_SIZE 0x807A
+#define GL_VERTEX_ARRAY_STRIDE 0x807C
+#define GL_VERTEX_ARRAY_TYPE 0x807B
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_VIEWPORT 0x0BA2
+#define GL_VIEWPORT_BIT 0x00000800
+#define GL_WAIT_FAILED 0x911D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_WRITE_ONLY 0x88B9
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+#define GL_ZOOM_X 0x0D16
+#define GL_ZOOM_Y 0x0D17
+
+
+#include <glad/khrplatform.h>
+typedef unsigned int GLenum;
+typedef unsigned char GLboolean;
+typedef unsigned int GLbitfield;
+typedef void GLvoid;
+typedef khronos_int8_t GLbyte;
+typedef khronos_uint8_t GLubyte;
+typedef khronos_int16_t GLshort;
+typedef khronos_uint16_t GLushort;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef khronos_int32_t GLclampx;
+typedef int GLsizei;
+typedef khronos_float_t GLfloat;
+typedef khronos_float_t GLclampf;
+typedef double GLdouble;
+typedef double GLclampd;
+typedef void *GLeglClientBufferEXT;
+typedef void *GLeglImageOES;
+typedef char GLchar;
+typedef char GLcharARB;
+#ifdef __APPLE__
+typedef void *GLhandleARB;
+#else
+typedef unsigned int GLhandleARB;
+#endif
+typedef khronos_uint16_t GLhalf;
+typedef khronos_uint16_t GLhalfARB;
+typedef khronos_int32_t GLfixed;
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptr;
+#else
+typedef khronos_intptr_t GLintptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_intptr_t GLintptrARB;
+#else
+typedef khronos_intptr_t GLintptrARB;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptr;
+#else
+typedef khronos_ssize_t GLsizeiptr;
+#endif
+#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)
+typedef khronos_ssize_t GLsizeiptrARB;
+#else
+typedef khronos_ssize_t GLsizeiptrARB;
+#endif
+typedef khronos_int64_t GLint64;
+typedef khronos_int64_t GLint64EXT;
+typedef khronos_uint64_t GLuint64;
+typedef khronos_uint64_t GLuint64EXT;
+typedef struct __GLsync *GLsync;
+struct _cl_context;
+struct _cl_event;
+typedef void ( *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void ( *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void ( *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+typedef void ( *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam);
+typedef unsigned short GLhalfNV;
+typedef GLintptr GLvdpauSurfaceNV;
+typedef void ( *GLVULKANPROCNV)(void);
+
+
+#define GL_VERSION_1_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_0;
+#define GL_VERSION_1_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_1;
+#define GL_VERSION_1_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_2;
+#define GL_VERSION_1_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_3;
+#define GL_VERSION_1_4 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_4;
+#define GL_VERSION_1_5 1
+GLAD_API_CALL int GLAD_GL_VERSION_1_5;
+#define GL_VERSION_2_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_0;
+#define GL_VERSION_2_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_2_1;
+#define GL_VERSION_3_0 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_0;
+#define GL_VERSION_3_1 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_1;
+#define GL_VERSION_3_2 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_2;
+#define GL_VERSION_3_3 1
+GLAD_API_CALL int GLAD_GL_VERSION_3_3;
+#define GL_ARB_multisample 1
+GLAD_API_CALL int GLAD_GL_ARB_multisample;
+#define GL_ARB_robustness 1
+GLAD_API_CALL int GLAD_GL_ARB_robustness;
+#define GL_KHR_debug 1
+GLAD_API_CALL int GLAD_GL_KHR_debug;
+
+
+typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum   op, GLfloat   value);
+typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum   texture);
+typedef void (GLAD_API_PTR *PFNGLALPHAFUNCPROC)(GLenum   func, GLfloat   ref);
+typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTPROC)(GLsizei   n, const  GLuint  * textures, GLboolean  * residences);
+typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTPROC)(GLint   i);
+typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint   program, GLuint   shader);
+typedef void (GLAD_API_PTR *PFNGLBEGINPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint   id, GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum   target, GLuint   id);
+typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum   primitiveMode);
+typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint   program, GLuint   index, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum   target, GLuint   buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum   target, GLuint   index, GLuint   buffer);
+typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum   target, GLuint   index, GLuint   buffer, GLintptr   offset, GLsizeiptr   size);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint   program, GLuint   color, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint   program, GLuint   colorNumber, GLuint   index, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum   target, GLuint   framebuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum   target, GLuint   renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint   unit, GLuint   sampler);
+typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum   target, GLuint   texture);
+typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint   array);
+typedef void (GLAD_API_PTR *PFNGLBITMAPPROC)(GLsizei   width, GLsizei   height, GLfloat   xorig, GLfloat   yorig, GLfloat   xmove, GLfloat   ymove, const  GLubyte  * bitmap);
+typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum   modeRGB, GLenum   modeAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum   sfactor, GLenum   dfactor);
+typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum   sfactorRGB, GLenum   dfactorRGB, GLenum   sfactorAlpha, GLenum   dfactorAlpha);
+typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint   srcX0, GLint   srcY0, GLint   srcX1, GLint   srcY1, GLint   dstX0, GLint   dstY0, GLint   dstX1, GLint   dstY1, GLbitfield   mask, GLenum   filter);
+typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum   target, GLsizeiptr   size, const void * data, GLenum   usage);
+typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   size, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTPROC)(GLuint   list);
+typedef void (GLAD_API_PTR *PFNGLCALLLISTSPROC)(GLsizei   n, GLenum   type, const void * lists);
+typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum   target);
+typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum   target, GLenum   clamp);
+typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield   mask);
+typedef void (GLAD_API_PTR *PFNGLCLEARACCUMPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum   buffer, GLint   drawbuffer, GLfloat   depth, GLint   stencil);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLint  * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum   buffer, GLint   drawbuffer, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
+typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble   depth);
+typedef void (GLAD_API_PTR *PFNGLCLEARINDEXPROC)(GLfloat   c);
+typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint   s);
+typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREPROC)(GLenum   texture);
+typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync   sync, GLbitfield   flags, GLuint64   timeout);
+typedef void (GLAD_API_PTR *PFNGLCLIPPLANEPROC)(GLenum   plane, const  GLdouble  * equation);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3BVPROC)(const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IPROC)(GLint   red, GLint   green, GLint   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SPROC)(GLshort   red, GLshort   green, GLshort   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UBVPROC)(const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIPROC)(GLuint   red, GLuint   green, GLuint   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3UIVPROC)(const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USPROC)(GLushort   red, GLushort   green, GLushort   blue);
+typedef void (GLAD_API_PTR *PFNGLCOLOR3USVPROC)(const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue, GLbyte   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4BVPROC)(const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue, GLdouble   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue, GLfloat   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IPROC)(GLint   red, GLint   green, GLint   blue, GLint   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SPROC)(GLshort   red, GLshort   green, GLshort   blue, GLshort   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue, GLubyte   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UBVPROC)(const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIPROC)(GLuint   red, GLuint   green, GLuint   blue, GLuint   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4UIVPROC)(const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USPROC)(GLushort   red, GLushort   green, GLushort   blue, GLushort   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLOR4USVPROC)(const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean   red, GLboolean   green, GLboolean   blue, GLboolean   alpha);
+typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint   index, GLboolean   r, GLboolean   g, GLboolean   b, GLboolean   a);
+typedef void (GLAD_API_PTR *PFNGLCOLORMATERIALPROC)(GLenum   face, GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIPROC)(GLenum   type, GLuint   color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP3UIVPROC)(GLenum   type, const  GLuint  * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIPROC)(GLenum   type, GLuint   color);
+typedef void (GLAD_API_PTR *PFNGLCOLORP4UIVPROC)(GLenum   type, const  GLuint  * color);
+typedef void (GLAD_API_PTR *PFNGLCOLORPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint   shader);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLint   border, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLsizei   height, GLint   border, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLint   border, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLsizei   width, GLenum   format, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLsizei   width, GLsizei   height, GLenum   format, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLsizei   width, GLsizei   height, GLsizei   depth, GLenum   format, GLsizei   imageSize, const void * data);
+typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum   readTarget, GLenum   writeTarget, GLintptr   readOffset, GLintptr   writeOffset, GLsizeiptr   size);
+typedef void (GLAD_API_PTR *PFNGLCOPYPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   type);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLint   x, GLint   y, GLsizei   width, GLint   border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLenum   internalformat, GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLint   border);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   x, GLint   y, GLsizei   width);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   x, GLint   y, GLsizei   width, GLsizei   height);
+typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLint   x, GLint   y, GLsizei   width, GLsizei   height);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void);
+typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum   type);
+typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC   callback, const void * userParam);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum   source, GLenum   type, GLenum   severity, GLsizei   count, const  GLuint  * ids, GLboolean   enabled);
+typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum   source, GLenum   type, GLuint   id, GLenum   severity, GLsizei   length, const  GLchar  * buf);
+typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei   n, const  GLuint  * buffers);
+typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei   n, const  GLuint  * framebuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETELISTSPROC)(GLuint   list, GLsizei   range);
+typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint   program);
+typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei   n, const  GLuint  * ids);
+typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei   n, const  GLuint  * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei   count, const  GLuint  * samplers);
+typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint   shader);
+typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync   sync);
+typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei   n, const  GLuint  * textures);
+typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei   n, const  GLuint  * arrays);
+typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum   func);
+typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean   flag);
+typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble   n, GLdouble   f);
+typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint   program, GLuint   shader);
+typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum   cap);
+typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEPROC)(GLenum   array);
+typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum   target, GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum   mode, GLint   first, GLsizei   count);
+typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum   mode, GLint   first, GLsizei   count, GLsizei   instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum   buf);
+typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei   n, const  GLenum  * bufs);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLint   basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLsizei   instancecount);
+typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum   mode, GLsizei   count, GLenum   type, const void * indices, GLsizei   instancecount, GLint   basevertex);
+typedef void (GLAD_API_PTR *PFNGLDRAWPIXELSPROC)(GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum   mode, GLuint   start, GLuint   end, GLsizei   count, GLenum   type, const void * indices);
+typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum   mode, GLuint   start, GLuint   end, GLsizei   count, GLenum   type, const void * indices, GLint   basevertex);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPROC)(GLboolean   flag);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTERPROC)(GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLEDGEFLAGVPROC)(const  GLboolean  * flag);
+typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum   cap);
+typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEPROC)(GLenum   array);
+typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum   target, GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLENDPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDLISTPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum   target);
+typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DPROC)(GLdouble   u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DVPROC)(const  GLdouble  * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FPROC)(GLfloat   u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FVPROC)(const  GLfloat  * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DPROC)(GLdouble   u, GLdouble   v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DVPROC)(const  GLdouble  * u);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FPROC)(GLfloat   u, GLfloat   v);
+typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FVPROC)(const  GLfloat  * u);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH1PROC)(GLenum   mode, GLint   i1, GLint   i2);
+typedef void (GLAD_API_PTR *PFNGLEVALMESH2PROC)(GLenum   mode, GLint   i1, GLint   i2, GLint   j1, GLint   j2);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT1PROC)(GLint   i);
+typedef void (GLAD_API_PTR *PFNGLEVALPOINT2PROC)(GLint   i, GLint   j);
+typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERPROC)(GLsizei   size, GLenum   type, GLfloat  * buffer);
+typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum   condition, GLbitfield   flags);
+typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   length);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDPROC)(GLdouble   coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVPROC)(const  GLdouble  * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFPROC)(GLfloat   coord);
+typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVPROC)(const  GLfloat  * coord);
+typedef void (GLAD_API_PTR *PFNGLFOGFPROC)(GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLFOGFVPROC)(GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLFOGIPROC)(GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLFOGIVPROC)(GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum   target, GLenum   attachment, GLenum   renderbuffertarget, GLuint   renderbuffer);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum   target, GLenum   attachment, GLuint   texture, GLint   level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum   target, GLenum   attachment, GLenum   textarget, GLuint   texture, GLint   level, GLint   zoffset);
+typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum   target, GLenum   attachment, GLuint   texture, GLint   level, GLint   layer);
+typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLFRUSTUMPROC)(GLdouble   left, GLdouble   right, GLdouble   bottom, GLdouble   top, GLdouble   zNear, GLdouble   zFar);
+typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei   n, GLuint  * buffers);
+typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei   n, GLuint  * framebuffers);
+typedef GLuint (GLAD_API_PTR *PFNGLGENLISTSPROC)(GLsizei   range);
+typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei   n, GLuint  * ids);
+typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei   n, GLuint  * renderbuffers);
+typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei   count, GLuint  * samplers);
+typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei   n, GLuint  * textures);
+typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei   n, GLuint  * arrays);
+typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum   target);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLint  * size, GLenum  * type, GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLint  * size, GLenum  * type, GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint   program, GLuint   uniformBlockIndex, GLsizei   bufSize, GLsizei  * length, GLchar  * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint   program, GLuint   uniformBlockIndex, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint   program, GLuint   uniformIndex, GLsizei   bufSize, GLsizei  * length, GLchar  * uniformName);
+typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint   program, GLsizei   uniformCount, const  GLuint  * uniformIndices, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint   program, GLsizei   maxCount, GLsizei  * count, GLuint  * shaders);
+typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint   program, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum   target, GLuint   index, GLboolean  * data);
+typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum   pname, GLboolean  * data);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum   target, GLenum   pname, GLint64  * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum   target, GLenum   pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   size, void * data);
+typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEPROC)(GLenum   plane, GLdouble  * equation);
+typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum   target, GLint   level, void * img);
+typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint   count, GLsizei   bufSize, GLenum  * sources, GLenum  * types, GLuint  * ids, GLenum  * severities, GLsizei  * lengths, GLchar  * messageLog);
+typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum   pname, GLdouble  * data);
+typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum   pname, GLfloat  * data);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint   program, const  GLchar  * name);
+typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint   program, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum   target, GLenum   attachment, GLenum   pname, GLint  * params);
+typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSARBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum   target, GLuint   index, GLint64  * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum   pname, GLint64  * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum   target, GLuint   index, GLint  * data);
+typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum   pname, GLint  * data);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTFVPROC)(GLenum   light, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETLIGHTIVPROC)(GLenum   light, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETMAPDVPROC)(GLenum   target, GLenum   query, GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPFVPROC)(GLenum   target, GLenum   query, GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLGETMAPIVPROC)(GLenum   target, GLenum   query, GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALFVPROC)(GLenum   face, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETMATERIALIVPROC)(GLenum   face, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum   pname, GLuint   index, GLfloat  * val);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELPROC)(GLenum   identifier, GLuint   name, GLsizei   bufSize, GLsizei  * length, GLchar  * label);
+typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELPROC)(const void * ptr, GLsizei   bufSize, GLsizei  * length, GLchar  * label);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPFVPROC)(GLenum   map, GLfloat  * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUIVPROC)(GLenum   map, GLuint  * values);
+typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUSVPROC)(GLenum   map, GLushort  * values);
+typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum   pname, void ** params);
+typedef void (GLAD_API_PTR *PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte  * mask);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint   program, GLsizei   bufSize, GLsizei  * length, GLchar  * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint   program, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint   id, GLenum   pname, GLint64  * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint   id, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint   id, GLenum   pname, GLuint64  * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint   id, GLenum   pname, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint   sampler, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint   sampler, GLenum   pname, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint   sampler, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint   sampler, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint   shader, GLsizei   bufSize, GLsizei  * length, GLchar  * infoLog);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint   shader, GLsizei   bufSize, GLsizei  * length, GLchar  * source);
+typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint   shader, GLenum   pname, GLint  * params);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum   name);
+typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum   name, GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync   sync, GLenum   pname, GLsizei   bufSize, GLsizei  * length, GLint  * values);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVFVPROC)(GLenum   target, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXENVIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENDVPROC)(GLenum   coord, GLenum   pname, GLdouble  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENFVPROC)(GLenum   coord, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXGENIVPROC)(GLenum   coord, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum   target, GLint   level, GLenum   format, GLenum   type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum   target, GLint   level, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum   target, GLint   level, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum   target, GLenum   pname, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum   target, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum   target, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint   program, GLuint   index, GLsizei   bufSize, GLsizei  * length, GLsizei  * size, GLenum  * type, GLchar  * name);
+typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint   program, const  GLchar  * uniformBlockName);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint   program, GLsizei   uniformCount, const  GLchar  *const* uniformNames, GLuint  * uniformIndices);
+typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint   program, const  GLchar  * name);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint   program, GLint   location, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint   program, GLint   location, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint   program, GLint   location, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint   index, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint   index, GLenum   pname, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint   index, GLenum   pname, void ** pointer);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint   index, GLenum   pname, GLdouble  * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint   index, GLenum   pname, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint   index, GLenum   pname, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETNCOLORTABLEARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   bufSize, void * table);
+typedef void (GLAD_API_PTR *PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC)(GLenum   target, GLint   lod, GLsizei   bufSize, void * img);
+typedef void (GLAD_API_PTR *PFNGLGETNCONVOLUTIONFILTERARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   bufSize, void * image);
+typedef void (GLAD_API_PTR *PFNGLGETNHISTOGRAMARBPROC)(GLenum   target, GLboolean   reset, GLenum   format, GLenum   type, GLsizei   bufSize, void * values);
+typedef void (GLAD_API_PTR *PFNGLGETNMAPDVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLGETNMAPFVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLGETNMAPIVARBPROC)(GLenum   target, GLenum   query, GLsizei   bufSize, GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLGETNMINMAXARBPROC)(GLenum   target, GLboolean   reset, GLenum   format, GLenum   type, GLsizei   bufSize, void * values);
+typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPFVARBPROC)(GLenum   map, GLsizei   bufSize, GLfloat  * values);
+typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUIVARBPROC)(GLenum   map, GLsizei   bufSize, GLuint  * values);
+typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUSVARBPROC)(GLenum   map, GLsizei   bufSize, GLushort  * values);
+typedef void (GLAD_API_PTR *PFNGLGETNPOLYGONSTIPPLEARBPROC)(GLsizei   bufSize, GLubyte  * pattern);
+typedef void (GLAD_API_PTR *PFNGLGETNSEPARABLEFILTERARBPROC)(GLenum   target, GLenum   format, GLenum   type, GLsizei   rowBufSize, void * row, GLsizei   columnBufSize, void * column, void * span);
+typedef void (GLAD_API_PTR *PFNGLGETNTEXIMAGEARBPROC)(GLenum   target, GLint   level, GLenum   format, GLenum   type, GLsizei   bufSize, void * img);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMDVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLdouble  * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVARBPROC)(GLuint   program, GLint   location, GLsizei   bufSize, GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum   target, GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLINDEXMASKPROC)(GLuint   mask);
+typedef void (GLAD_API_PTR *PFNGLINDEXPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLINDEXDPROC)(GLdouble   c);
+typedef void (GLAD_API_PTR *PFNGLINDEXDVPROC)(const  GLdouble  * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFPROC)(GLfloat   c);
+typedef void (GLAD_API_PTR *PFNGLINDEXFVPROC)(const  GLfloat  * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIPROC)(GLint   c);
+typedef void (GLAD_API_PTR *PFNGLINDEXIVPROC)(const  GLint  * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSPROC)(GLshort   c);
+typedef void (GLAD_API_PTR *PFNGLINDEXSVPROC)(const  GLshort  * c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBPROC)(GLubyte   c);
+typedef void (GLAD_API_PTR *PFNGLINDEXUBVPROC)(const  GLubyte  * c);
+typedef void (GLAD_API_PTR *PFNGLINITNAMESPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLINTERLEAVEDARRAYSPROC)(GLenum   format, GLsizei   stride, const void * pointer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint   buffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum   cap);
+typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum   target, GLuint   index);
+typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint   framebuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISLISTPROC)(GLuint   list);
+typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint   program);
+typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint   id);
+typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint   renderbuffer);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint   sampler);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint   shader);
+typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync   sync);
+typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint   texture);
+typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint   array);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFPROC)(GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFVPROC)(GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIPROC)(GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIVPROC)(GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFPROC)(GLenum   light, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTFVPROC)(GLenum   light, GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIPROC)(GLenum   light, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLLIGHTIVPROC)(GLenum   light, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLLINESTIPPLEPROC)(GLint   factor, GLushort   pattern);
+typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat   width);
+typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint   program);
+typedef void (GLAD_API_PTR *PFNGLLISTBASEPROC)(GLuint   base);
+typedef void (GLAD_API_PTR *PFNGLLOADIDENTITYPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXDPROC)(const  GLdouble  * m);
+typedef void (GLAD_API_PTR *PFNGLLOADMATRIXFPROC)(const  GLfloat  * m);
+typedef void (GLAD_API_PTR *PFNGLLOADNAMEPROC)(GLuint   name);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDPROC)(const  GLdouble  * m);
+typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFPROC)(const  GLfloat  * m);
+typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum   opcode);
+typedef void (GLAD_API_PTR *PFNGLMAP1DPROC)(GLenum   target, GLdouble   u1, GLdouble   u2, GLint   stride, GLint   order, const  GLdouble  * points);
+typedef void (GLAD_API_PTR *PFNGLMAP1FPROC)(GLenum   target, GLfloat   u1, GLfloat   u2, GLint   stride, GLint   order, const  GLfloat  * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2DPROC)(GLenum   target, GLdouble   u1, GLdouble   u2, GLint   ustride, GLint   uorder, GLdouble   v1, GLdouble   v2, GLint   vstride, GLint   vorder, const  GLdouble  * points);
+typedef void (GLAD_API_PTR *PFNGLMAP2FPROC)(GLenum   target, GLfloat   u1, GLfloat   u2, GLint   ustride, GLint   uorder, GLfloat   v1, GLfloat   v2, GLint   vstride, GLint   vorder, const  GLfloat  * points);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum   target, GLenum   access);
+typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum   target, GLintptr   offset, GLsizeiptr   length, GLbitfield   access);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1DPROC)(GLint   un, GLdouble   u1, GLdouble   u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID1FPROC)(GLint   un, GLfloat   u1, GLfloat   u2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2DPROC)(GLint   un, GLdouble   u1, GLdouble   u2, GLint   vn, GLdouble   v1, GLdouble   v2);
+typedef void (GLAD_API_PTR *PFNGLMAPGRID2FPROC)(GLint   un, GLfloat   u1, GLfloat   u2, GLint   vn, GLfloat   v1, GLfloat   v2);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFPROC)(GLenum   face, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALFVPROC)(GLenum   face, GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIPROC)(GLenum   face, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLMATERIALIVPROC)(GLenum   face, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLMATRIXMODEPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXDPROC)(const  GLdouble  * m);
+typedef void (GLAD_API_PTR *PFNGLMULTMATRIXFPROC)(const  GLfloat  * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDPROC)(const  GLdouble  * m);
+typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFPROC)(const  GLfloat  * m);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum   mode, const  GLint  * first, const  GLsizei  * count, GLsizei   drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum   mode, const  GLsizei  * count, GLenum   type, const void *const* indices, GLsizei   drawcount);
+typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum   mode, const  GLsizei  * count, GLenum   type, const void *const* indices, GLsizei   drawcount, const  GLint  * basevertex);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DPROC)(GLenum   target, GLdouble   s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVPROC)(GLenum   target, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FPROC)(GLenum   target, GLfloat   s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVPROC)(GLenum   target, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IPROC)(GLenum   target, GLint   s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVPROC)(GLenum   target, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SPROC)(GLenum   target, GLshort   s);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVPROC)(GLenum   target, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DPROC)(GLenum   target, GLdouble   s, GLdouble   t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVPROC)(GLenum   target, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FPROC)(GLenum   target, GLfloat   s, GLfloat   t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVPROC)(GLenum   target, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IPROC)(GLenum   target, GLint   s, GLint   t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVPROC)(GLenum   target, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SPROC)(GLenum   target, GLshort   s, GLshort   t);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVPROC)(GLenum   target, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DPROC)(GLenum   target, GLdouble   s, GLdouble   t, GLdouble   r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVPROC)(GLenum   target, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FPROC)(GLenum   target, GLfloat   s, GLfloat   t, GLfloat   r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVPROC)(GLenum   target, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IPROC)(GLenum   target, GLint   s, GLint   t, GLint   r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVPROC)(GLenum   target, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SPROC)(GLenum   target, GLshort   s, GLshort   t, GLshort   r);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVPROC)(GLenum   target, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DPROC)(GLenum   target, GLdouble   s, GLdouble   t, GLdouble   r, GLdouble   q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVPROC)(GLenum   target, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FPROC)(GLenum   target, GLfloat   s, GLfloat   t, GLfloat   r, GLfloat   q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVPROC)(GLenum   target, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IPROC)(GLenum   target, GLint   s, GLint   t, GLint   r, GLint   q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVPROC)(GLenum   target, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SPROC)(GLenum   target, GLshort   s, GLshort   t, GLshort   r, GLshort   q);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVPROC)(GLenum   target, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum   texture, GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum   texture, GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint   list, GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte   nx, GLbyte   ny, GLbyte   nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DPROC)(GLdouble   nx, GLdouble   ny, GLdouble   nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FPROC)(GLfloat   nx, GLfloat   ny, GLfloat   nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IPROC)(GLint   nx, GLint   ny, GLint   nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SPROC)(GLshort   nx, GLshort   ny, GLshort   nz);
+typedef void (GLAD_API_PTR *PFNGLNORMAL3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIPROC)(GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALP3UIVPROC)(GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLNORMALPOINTERPROC)(GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLOBJECTLABELPROC)(GLenum   identifier, GLuint   name, GLsizei   length, const  GLchar  * label);
+typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELPROC)(const void * ptr, GLsizei   length, const  GLchar  * label);
+typedef void (GLAD_API_PTR *PFNGLORTHOPROC)(GLdouble   left, GLdouble   right, GLdouble   bottom, GLdouble   top, GLdouble   zNear, GLdouble   zFar);
+typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHPROC)(GLfloat   token);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPFVPROC)(GLenum   map, GLsizei   mapsize, const  GLfloat  * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUIVPROC)(GLenum   map, GLsizei   mapsize, const  GLuint  * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELMAPUSVPROC)(GLenum   map, GLsizei   mapsize, const  GLushort  * values);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERFPROC)(GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERIPROC)(GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLPIXELZOOMPROC)(GLfloat   xfactor, GLfloat   yfactor);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat   size);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum   face, GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat   factor, GLfloat   units);
+typedef void (GLAD_API_PTR *PFNGLPOLYGONSTIPPLEPROC)(const  GLubyte  * mask);
+typedef void (GLAD_API_PTR *PFNGLPOPATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPCLIENTATTRIBPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPOPNAMEPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint   index);
+typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESPROC)(GLsizei   n, const  GLuint  * textures, const  GLfloat  * priorities);
+typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLPUSHATTRIBPROC)(GLbitfield   mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield   mask);
+typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPPROC)(GLenum   source, GLuint   id, GLsizei   length, const  GLchar  * message);
+typedef void (GLAD_API_PTR *PFNGLPUSHMATRIXPROC)(void);
+typedef void (GLAD_API_PTR *PFNGLPUSHNAMEPROC)(GLuint   name);
+typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint   id, GLenum   target);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DPROC)(GLdouble   x, GLdouble   y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FPROC)(GLfloat   x, GLfloat   y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IPROC)(GLint   x, GLint   y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SPROC)(GLshort   x, GLshort   y);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IPROC)(GLint   x, GLint   y, GLint   z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SPROC)(GLshort   x, GLshort   y, GLshort   z);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DPROC)(GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FPROC)(GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IPROC)(GLint   x, GLint   y, GLint   z, GLint   w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SPROC)(GLshort   x, GLshort   y, GLshort   z, GLshort   w);
+typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum   src);
+typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, void * pixels);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, GLsizei   bufSize, void * data);
+typedef void (GLAD_API_PTR *PFNGLREADNPIXELSARBPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, GLsizei   bufSize, void * data);
+typedef void (GLAD_API_PTR *PFNGLRECTDPROC)(GLdouble   x1, GLdouble   y1, GLdouble   x2, GLdouble   y2);
+typedef void (GLAD_API_PTR *PFNGLRECTDVPROC)(const  GLdouble  * v1, const  GLdouble  * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTFPROC)(GLfloat   x1, GLfloat   y1, GLfloat   x2, GLfloat   y2);
+typedef void (GLAD_API_PTR *PFNGLRECTFVPROC)(const  GLfloat  * v1, const  GLfloat  * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTIPROC)(GLint   x1, GLint   y1, GLint   x2, GLint   y2);
+typedef void (GLAD_API_PTR *PFNGLRECTIVPROC)(const  GLint  * v1, const  GLint  * v2);
+typedef void (GLAD_API_PTR *PFNGLRECTSPROC)(GLshort   x1, GLshort   y1, GLshort   x2, GLshort   y2);
+typedef void (GLAD_API_PTR *PFNGLRECTSVPROC)(const  GLshort  * v1, const  GLshort  * v2);
+typedef GLint (GLAD_API_PTR *PFNGLRENDERMODEPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum   target, GLenum   internalformat, GLsizei   width, GLsizei   height);
+typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height);
+typedef void (GLAD_API_PTR *PFNGLROTATEDPROC)(GLdouble   angle, GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLROTATEFPROC)(GLfloat   angle, GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat   value, GLboolean   invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEARBPROC)(GLfloat   value, GLboolean   invert);
+typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint   maskNumber, GLbitfield   mask);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint   sampler, GLenum   pname, const  GLint  * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint   sampler, GLenum   pname, const  GLuint  * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint   sampler, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint   sampler, GLenum   pname, const  GLfloat  * param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint   sampler, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint   sampler, GLenum   pname, const  GLint  * param);
+typedef void (GLAD_API_PTR *PFNGLSCALEDPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLSCALEFPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BPROC)(GLbyte   red, GLbyte   green, GLbyte   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BVPROC)(const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DPROC)(GLdouble   red, GLdouble   green, GLdouble   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FPROC)(GLfloat   red, GLfloat   green, GLfloat   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IPROC)(GLint   red, GLint   green, GLint   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SPROC)(GLshort   red, GLshort   green, GLshort   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBPROC)(GLubyte   red, GLubyte   green, GLubyte   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBVPROC)(const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIPROC)(GLuint   red, GLuint   green, GLuint   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIVPROC)(const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USPROC)(GLushort   red, GLushort   green, GLushort   blue);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USVPROC)(const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIPROC)(GLenum   type, GLuint   color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIVPROC)(GLenum   type, const  GLuint  * color);
+typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLSELECTBUFFERPROC)(GLsizei   size, GLuint  * buffer);
+typedef void (GLAD_API_PTR *PFNGLSHADEMODELPROC)(GLenum   mode);
+typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint   shader, GLsizei   count, const  GLchar  *const* string, const  GLint  * length);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum   func, GLint   ref, GLuint   mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum   face, GLenum   func, GLint   ref, GLuint   mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint   mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum   face, GLuint   mask);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum   fail, GLenum   zfail, GLenum   zpass);
+typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum   face, GLenum   sfail, GLenum   dpfail, GLenum   dppass);
+typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum   target, GLenum   internalformat, GLuint   buffer);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DPROC)(GLdouble   s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FPROC)(GLfloat   s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IPROC)(GLint   s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SPROC)(GLshort   s);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DPROC)(GLdouble   s, GLdouble   t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FPROC)(GLfloat   s, GLfloat   t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IPROC)(GLint   s, GLint   t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SPROC)(GLshort   s, GLshort   t);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DPROC)(GLdouble   s, GLdouble   t, GLdouble   r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FPROC)(GLfloat   s, GLfloat   t, GLfloat   r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IPROC)(GLint   s, GLint   t, GLint   r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SPROC)(GLshort   s, GLshort   t, GLshort   r);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DPROC)(GLdouble   s, GLdouble   t, GLdouble   r, GLdouble   q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FPROC)(GLfloat   s, GLfloat   t, GLfloat   r, GLfloat   q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IPROC)(GLint   s, GLint   t, GLint   r, GLint   q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SPROC)(GLshort   s, GLshort   t, GLshort   r, GLshort   q);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIPROC)(GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIVPROC)(GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIPROC)(GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIVPROC)(GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIPROC)(GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIVPROC)(GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIPROC)(GLenum   type, GLuint   coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIVPROC)(GLenum   type, const  GLuint  * coords);
+typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFPROC)(GLenum   target, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVFVPROC)(GLenum   target, GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIPROC)(GLenum   target, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLTEXENVIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDPROC)(GLenum   coord, GLenum   pname, GLdouble   param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENDVPROC)(GLenum   coord, GLenum   pname, const  GLdouble  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFPROC)(GLenum   coord, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENFVPROC)(GLenum   coord, GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIPROC)(GLenum   coord, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLTEXGENIVPROC)(GLenum   coord, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLint   border, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLsizei   height, GLint   border, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height, GLboolean   fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum   target, GLint   level, GLint   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLint   border, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum   target, GLsizei   samples, GLenum   internalformat, GLsizei   width, GLsizei   height, GLsizei   depth, GLboolean   fixedsamplelocations);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum   target, GLenum   pname, const  GLuint  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum   target, GLenum   pname, GLfloat   param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum   target, GLenum   pname, const  GLfloat  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum   target, GLenum   pname, GLint   param);
+typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum   target, GLenum   pname, const  GLint  * params);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLsizei   width, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLsizei   width, GLsizei   height, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum   target, GLint   level, GLint   xoffset, GLint   yoffset, GLint   zoffset, GLsizei   width, GLsizei   height, GLsizei   depth, GLenum   format, GLenum   type, const void * pixels);
+typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint   program, GLsizei   count, const  GLchar  *const* varyings, GLenum   bufferMode);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEDPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLTRANSLATEFPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint   location, GLfloat   v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint   location, GLint   v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint   location, GLuint   v0);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint   location, GLfloat   v0, GLfloat   v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint   location, GLint   v0, GLint   v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint   location, GLuint   v0, GLuint   v1);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint   location, GLfloat   v0, GLfloat   v1, GLfloat   v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint   location, GLint   v0, GLint   v1, GLint   v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint   location, GLuint   v0, GLuint   v1, GLuint   v2);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint   location, GLfloat   v0, GLfloat   v1, GLfloat   v2, GLfloat   v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint   location, GLsizei   count, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint   location, GLint   v0, GLint   v1, GLint   v2, GLint   v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint   location, GLsizei   count, const  GLint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint   location, GLuint   v0, GLuint   v1, GLuint   v2, GLuint   v3);
+typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint   location, GLsizei   count, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint   program, GLuint   uniformBlockIndex, GLuint   uniformBlockBinding);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint   location, GLsizei   count, GLboolean   transpose, const  GLfloat  * value);
+typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum   target);
+typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint   program);
+typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint   program);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DPROC)(GLdouble   x, GLdouble   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FPROC)(GLfloat   x, GLfloat   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IPROC)(GLint   x, GLint   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SPROC)(GLshort   x, GLshort   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEX2SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IPROC)(GLint   x, GLint   y, GLint   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SPROC)(GLshort   x, GLshort   y, GLshort   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEX3SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DPROC)(GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FPROC)(GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IPROC)(GLint   x, GLint   y, GLint   z, GLint   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SPROC)(GLshort   x, GLshort   y, GLshort   z, GLshort   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEX4SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint   index, GLdouble   x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint   index, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint   index, GLfloat   x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint   index, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint   index, GLshort   x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint   index, GLdouble   x, GLdouble   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint   index, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint   index, GLfloat   x, GLfloat   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint   index, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint   index, GLshort   x, GLshort   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint   index, GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint   index, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint   index, GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint   index, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint   index, GLshort   x, GLshort   y, GLshort   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint   index, const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint   index, GLubyte   x, GLubyte   y, GLubyte   z, GLubyte   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint   index, const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint   index, const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint   index, const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint   index, GLdouble   x, GLdouble   y, GLdouble   z, GLdouble   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint   index, const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint   index, GLfloat   x, GLfloat   y, GLfloat   z, GLfloat   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint   index, const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint   index, GLshort   x, GLshort   y, GLshort   z, GLshort   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint   index, const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint   index, const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint   index, GLuint   divisor);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint   index, GLint   x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint   index, GLuint   x);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint   index, GLint   x, GLint   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint   index, GLuint   x, GLuint   y);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint   index, GLint   x, GLint   y, GLint   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint   index, GLuint   x, GLuint   y, GLuint   z);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint   index, const  GLbyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint   index, GLint   x, GLint   y, GLint   z, GLint   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint   index, const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint   index, const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint   index, const  GLubyte  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint   index, GLuint   x, GLuint   y, GLuint   z, GLuint   w);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint   index, const  GLuint  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint   index, const  GLushort  * v);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint   index, GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint   index, GLenum   type, GLboolean   normalized, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint   index, GLenum   type, GLboolean   normalized, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint   index, GLint   size, GLenum   type, GLboolean   normalized, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIPROC)(GLenum   type, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIVPROC)(GLenum   type, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIPROC)(GLenum   type, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIVPROC)(GLenum   type, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIPROC)(GLenum   type, GLuint   value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIVPROC)(GLenum   type, const  GLuint  * value);
+typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTERPROC)(GLint   size, GLenum   type, GLsizei   stride, const void * pointer);
+typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint   x, GLint   y, GLsizei   width, GLsizei   height);
+typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync   sync, GLbitfield   flags, GLuint64   timeout);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DPROC)(GLdouble   x, GLdouble   y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FPROC)(GLfloat   x, GLfloat   y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IPROC)(GLint   x, GLint   y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SPROC)(GLshort   x, GLshort   y);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SVPROC)(const  GLshort  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DPROC)(GLdouble   x, GLdouble   y, GLdouble   z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DVPROC)(const  GLdouble  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FPROC)(GLfloat   x, GLfloat   y, GLfloat   z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FVPROC)(const  GLfloat  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IPROC)(GLint   x, GLint   y, GLint   z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IVPROC)(const  GLint  * v);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SPROC)(GLshort   x, GLshort   y, GLshort   z);
+typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SVPROC)(const  GLshort  * v);
+
+GLAD_API_CALL PFNGLACCUMPROC glad_glAccum;
+#define glAccum glad_glAccum
+GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture;
+#define glActiveTexture glad_glActiveTexture
+GLAD_API_CALL PFNGLALPHAFUNCPROC glad_glAlphaFunc;
+#define glAlphaFunc glad_glAlphaFunc
+GLAD_API_CALL PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident;
+#define glAreTexturesResident glad_glAreTexturesResident
+GLAD_API_CALL PFNGLARRAYELEMENTPROC glad_glArrayElement;
+#define glArrayElement glad_glArrayElement
+GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader;
+#define glAttachShader glad_glAttachShader
+GLAD_API_CALL PFNGLBEGINPROC glad_glBegin;
+#define glBegin glad_glBegin
+GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender;
+#define glBeginConditionalRender glad_glBeginConditionalRender
+GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery;
+#define glBeginQuery glad_glBeginQuery
+GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback;
+#define glBeginTransformFeedback glad_glBeginTransformFeedback
+GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation;
+#define glBindAttribLocation glad_glBindAttribLocation
+GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer;
+#define glBindBuffer glad_glBindBuffer
+GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase;
+#define glBindBufferBase glad_glBindBufferBase
+GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange;
+#define glBindBufferRange glad_glBindBufferRange
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation;
+#define glBindFragDataLocation glad_glBindFragDataLocation
+GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed;
+#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed
+GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer;
+#define glBindFramebuffer glad_glBindFramebuffer
+GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer;
+#define glBindRenderbuffer glad_glBindRenderbuffer
+GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler;
+#define glBindSampler glad_glBindSampler
+GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture;
+#define glBindTexture glad_glBindTexture
+GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray;
+#define glBindVertexArray glad_glBindVertexArray
+GLAD_API_CALL PFNGLBITMAPPROC glad_glBitmap;
+#define glBitmap glad_glBitmap
+GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor;
+#define glBlendColor glad_glBlendColor
+GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation;
+#define glBlendEquation glad_glBlendEquation
+GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate;
+#define glBlendEquationSeparate glad_glBlendEquationSeparate
+GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc;
+#define glBlendFunc glad_glBlendFunc
+GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate;
+#define glBlendFuncSeparate glad_glBlendFuncSeparate
+GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer;
+#define glBlitFramebuffer glad_glBlitFramebuffer
+GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData;
+#define glBufferData glad_glBufferData
+GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData;
+#define glBufferSubData glad_glBufferSubData
+GLAD_API_CALL PFNGLCALLLISTPROC glad_glCallList;
+#define glCallList glad_glCallList
+GLAD_API_CALL PFNGLCALLLISTSPROC glad_glCallLists;
+#define glCallLists glad_glCallLists
+GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus;
+#define glCheckFramebufferStatus glad_glCheckFramebufferStatus
+GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor;
+#define glClampColor glad_glClampColor
+GLAD_API_CALL PFNGLCLEARPROC glad_glClear;
+#define glClear glad_glClear
+GLAD_API_CALL PFNGLCLEARACCUMPROC glad_glClearAccum;
+#define glClearAccum glad_glClearAccum
+GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi;
+#define glClearBufferfi glad_glClearBufferfi
+GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv;
+#define glClearBufferfv glad_glClearBufferfv
+GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv;
+#define glClearBufferiv glad_glClearBufferiv
+GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv;
+#define glClearBufferuiv glad_glClearBufferuiv
+GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor;
+#define glClearColor glad_glClearColor
+GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth;
+#define glClearDepth glad_glClearDepth
+GLAD_API_CALL PFNGLCLEARINDEXPROC glad_glClearIndex;
+#define glClearIndex glad_glClearIndex
+GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil;
+#define glClearStencil glad_glClearStencil
+GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture;
+#define glClientActiveTexture glad_glClientActiveTexture
+GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync;
+#define glClientWaitSync glad_glClientWaitSync
+GLAD_API_CALL PFNGLCLIPPLANEPROC glad_glClipPlane;
+#define glClipPlane glad_glClipPlane
+GLAD_API_CALL PFNGLCOLOR3BPROC glad_glColor3b;
+#define glColor3b glad_glColor3b
+GLAD_API_CALL PFNGLCOLOR3BVPROC glad_glColor3bv;
+#define glColor3bv glad_glColor3bv
+GLAD_API_CALL PFNGLCOLOR3DPROC glad_glColor3d;
+#define glColor3d glad_glColor3d
+GLAD_API_CALL PFNGLCOLOR3DVPROC glad_glColor3dv;
+#define glColor3dv glad_glColor3dv
+GLAD_API_CALL PFNGLCOLOR3FPROC glad_glColor3f;
+#define glColor3f glad_glColor3f
+GLAD_API_CALL PFNGLCOLOR3FVPROC glad_glColor3fv;
+#define glColor3fv glad_glColor3fv
+GLAD_API_CALL PFNGLCOLOR3IPROC glad_glColor3i;
+#define glColor3i glad_glColor3i
+GLAD_API_CALL PFNGLCOLOR3IVPROC glad_glColor3iv;
+#define glColor3iv glad_glColor3iv
+GLAD_API_CALL PFNGLCOLOR3SPROC glad_glColor3s;
+#define glColor3s glad_glColor3s
+GLAD_API_CALL PFNGLCOLOR3SVPROC glad_glColor3sv;
+#define glColor3sv glad_glColor3sv
+GLAD_API_CALL PFNGLCOLOR3UBPROC glad_glColor3ub;
+#define glColor3ub glad_glColor3ub
+GLAD_API_CALL PFNGLCOLOR3UBVPROC glad_glColor3ubv;
+#define glColor3ubv glad_glColor3ubv
+GLAD_API_CALL PFNGLCOLOR3UIPROC glad_glColor3ui;
+#define glColor3ui glad_glColor3ui
+GLAD_API_CALL PFNGLCOLOR3UIVPROC glad_glColor3uiv;
+#define glColor3uiv glad_glColor3uiv
+GLAD_API_CALL PFNGLCOLOR3USPROC glad_glColor3us;
+#define glColor3us glad_glColor3us
+GLAD_API_CALL PFNGLCOLOR3USVPROC glad_glColor3usv;
+#define glColor3usv glad_glColor3usv
+GLAD_API_CALL PFNGLCOLOR4BPROC glad_glColor4b;
+#define glColor4b glad_glColor4b
+GLAD_API_CALL PFNGLCOLOR4BVPROC glad_glColor4bv;
+#define glColor4bv glad_glColor4bv
+GLAD_API_CALL PFNGLCOLOR4DPROC glad_glColor4d;
+#define glColor4d glad_glColor4d
+GLAD_API_CALL PFNGLCOLOR4DVPROC glad_glColor4dv;
+#define glColor4dv glad_glColor4dv
+GLAD_API_CALL PFNGLCOLOR4FPROC glad_glColor4f;
+#define glColor4f glad_glColor4f
+GLAD_API_CALL PFNGLCOLOR4FVPROC glad_glColor4fv;
+#define glColor4fv glad_glColor4fv
+GLAD_API_CALL PFNGLCOLOR4IPROC glad_glColor4i;
+#define glColor4i glad_glColor4i
+GLAD_API_CALL PFNGLCOLOR4IVPROC glad_glColor4iv;
+#define glColor4iv glad_glColor4iv
+GLAD_API_CALL PFNGLCOLOR4SPROC glad_glColor4s;
+#define glColor4s glad_glColor4s
+GLAD_API_CALL PFNGLCOLOR4SVPROC glad_glColor4sv;
+#define glColor4sv glad_glColor4sv
+GLAD_API_CALL PFNGLCOLOR4UBPROC glad_glColor4ub;
+#define glColor4ub glad_glColor4ub
+GLAD_API_CALL PFNGLCOLOR4UBVPROC glad_glColor4ubv;
+#define glColor4ubv glad_glColor4ubv
+GLAD_API_CALL PFNGLCOLOR4UIPROC glad_glColor4ui;
+#define glColor4ui glad_glColor4ui
+GLAD_API_CALL PFNGLCOLOR4UIVPROC glad_glColor4uiv;
+#define glColor4uiv glad_glColor4uiv
+GLAD_API_CALL PFNGLCOLOR4USPROC glad_glColor4us;
+#define glColor4us glad_glColor4us
+GLAD_API_CALL PFNGLCOLOR4USVPROC glad_glColor4usv;
+#define glColor4usv glad_glColor4usv
+GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask;
+#define glColorMask glad_glColorMask
+GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski;
+#define glColorMaski glad_glColorMaski
+GLAD_API_CALL PFNGLCOLORMATERIALPROC glad_glColorMaterial;
+#define glColorMaterial glad_glColorMaterial
+GLAD_API_CALL PFNGLCOLORP3UIPROC glad_glColorP3ui;
+#define glColorP3ui glad_glColorP3ui
+GLAD_API_CALL PFNGLCOLORP3UIVPROC glad_glColorP3uiv;
+#define glColorP3uiv glad_glColorP3uiv
+GLAD_API_CALL PFNGLCOLORP4UIPROC glad_glColorP4ui;
+#define glColorP4ui glad_glColorP4ui
+GLAD_API_CALL PFNGLCOLORP4UIVPROC glad_glColorP4uiv;
+#define glColorP4uiv glad_glColorP4uiv
+GLAD_API_CALL PFNGLCOLORPOINTERPROC glad_glColorPointer;
+#define glColorPointer glad_glColorPointer
+GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader;
+#define glCompileShader glad_glCompileShader
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D;
+#define glCompressedTexImage1D glad_glCompressedTexImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D;
+#define glCompressedTexImage2D glad_glCompressedTexImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D;
+#define glCompressedTexImage3D glad_glCompressedTexImage3D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D;
+#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D;
+#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D
+GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D;
+#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D
+GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData;
+#define glCopyBufferSubData glad_glCopyBufferSubData
+GLAD_API_CALL PFNGLCOPYPIXELSPROC glad_glCopyPixels;
+#define glCopyPixels glad_glCopyPixels
+GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D;
+#define glCopyTexImage1D glad_glCopyTexImage1D
+GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D;
+#define glCopyTexImage2D glad_glCopyTexImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D;
+#define glCopyTexSubImage1D glad_glCopyTexSubImage1D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D;
+#define glCopyTexSubImage2D glad_glCopyTexSubImage2D
+GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D;
+#define glCopyTexSubImage3D glad_glCopyTexSubImage3D
+GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram;
+#define glCreateProgram glad_glCreateProgram
+GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader;
+#define glCreateShader glad_glCreateShader
+GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace;
+#define glCullFace glad_glCullFace
+GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback;
+#define glDebugMessageCallback glad_glDebugMessageCallback
+GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl;
+#define glDebugMessageControl glad_glDebugMessageControl
+GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert;
+#define glDebugMessageInsert glad_glDebugMessageInsert
+GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers;
+#define glDeleteBuffers glad_glDeleteBuffers
+GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers;
+#define glDeleteFramebuffers glad_glDeleteFramebuffers
+GLAD_API_CALL PFNGLDELETELISTSPROC glad_glDeleteLists;
+#define glDeleteLists glad_glDeleteLists
+GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram;
+#define glDeleteProgram glad_glDeleteProgram
+GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries;
+#define glDeleteQueries glad_glDeleteQueries
+GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers;
+#define glDeleteRenderbuffers glad_glDeleteRenderbuffers
+GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers;
+#define glDeleteSamplers glad_glDeleteSamplers
+GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader;
+#define glDeleteShader glad_glDeleteShader
+GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync;
+#define glDeleteSync glad_glDeleteSync
+GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures;
+#define glDeleteTextures glad_glDeleteTextures
+GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays;
+#define glDeleteVertexArrays glad_glDeleteVertexArrays
+GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc;
+#define glDepthFunc glad_glDepthFunc
+GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask;
+#define glDepthMask glad_glDepthMask
+GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange;
+#define glDepthRange glad_glDepthRange
+GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader;
+#define glDetachShader glad_glDetachShader
+GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable;
+#define glDisable glad_glDisable
+GLAD_API_CALL PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState;
+#define glDisableClientState glad_glDisableClientState
+GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray;
+#define glDisableVertexAttribArray glad_glDisableVertexAttribArray
+GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei;
+#define glDisablei glad_glDisablei
+GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays;
+#define glDrawArrays glad_glDrawArrays
+GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced;
+#define glDrawArraysInstanced glad_glDrawArraysInstanced
+GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer;
+#define glDrawBuffer glad_glDrawBuffer
+GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers;
+#define glDrawBuffers glad_glDrawBuffers
+GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements;
+#define glDrawElements glad_glDrawElements
+GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex;
+#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced;
+#define glDrawElementsInstanced glad_glDrawElementsInstanced
+GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex;
+#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex
+GLAD_API_CALL PFNGLDRAWPIXELSPROC glad_glDrawPixels;
+#define glDrawPixels glad_glDrawPixels
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements;
+#define glDrawRangeElements glad_glDrawRangeElements
+GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex;
+#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex
+GLAD_API_CALL PFNGLEDGEFLAGPROC glad_glEdgeFlag;
+#define glEdgeFlag glad_glEdgeFlag
+GLAD_API_CALL PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer;
+#define glEdgeFlagPointer glad_glEdgeFlagPointer
+GLAD_API_CALL PFNGLEDGEFLAGVPROC glad_glEdgeFlagv;
+#define glEdgeFlagv glad_glEdgeFlagv
+GLAD_API_CALL PFNGLENABLEPROC glad_glEnable;
+#define glEnable glad_glEnable
+GLAD_API_CALL PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState;
+#define glEnableClientState glad_glEnableClientState
+GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray;
+#define glEnableVertexAttribArray glad_glEnableVertexAttribArray
+GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei;
+#define glEnablei glad_glEnablei
+GLAD_API_CALL PFNGLENDPROC glad_glEnd;
+#define glEnd glad_glEnd
+GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender;
+#define glEndConditionalRender glad_glEndConditionalRender
+GLAD_API_CALL PFNGLENDLISTPROC glad_glEndList;
+#define glEndList glad_glEndList
+GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery;
+#define glEndQuery glad_glEndQuery
+GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback;
+#define glEndTransformFeedback glad_glEndTransformFeedback
+GLAD_API_CALL PFNGLEVALCOORD1DPROC glad_glEvalCoord1d;
+#define glEvalCoord1d glad_glEvalCoord1d
+GLAD_API_CALL PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv;
+#define glEvalCoord1dv glad_glEvalCoord1dv
+GLAD_API_CALL PFNGLEVALCOORD1FPROC glad_glEvalCoord1f;
+#define glEvalCoord1f glad_glEvalCoord1f
+GLAD_API_CALL PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv;
+#define glEvalCoord1fv glad_glEvalCoord1fv
+GLAD_API_CALL PFNGLEVALCOORD2DPROC glad_glEvalCoord2d;
+#define glEvalCoord2d glad_glEvalCoord2d
+GLAD_API_CALL PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv;
+#define glEvalCoord2dv glad_glEvalCoord2dv
+GLAD_API_CALL PFNGLEVALCOORD2FPROC glad_glEvalCoord2f;
+#define glEvalCoord2f glad_glEvalCoord2f
+GLAD_API_CALL PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv;
+#define glEvalCoord2fv glad_glEvalCoord2fv
+GLAD_API_CALL PFNGLEVALMESH1PROC glad_glEvalMesh1;
+#define glEvalMesh1 glad_glEvalMesh1
+GLAD_API_CALL PFNGLEVALMESH2PROC glad_glEvalMesh2;
+#define glEvalMesh2 glad_glEvalMesh2
+GLAD_API_CALL PFNGLEVALPOINT1PROC glad_glEvalPoint1;
+#define glEvalPoint1 glad_glEvalPoint1
+GLAD_API_CALL PFNGLEVALPOINT2PROC glad_glEvalPoint2;
+#define glEvalPoint2 glad_glEvalPoint2
+GLAD_API_CALL PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer;
+#define glFeedbackBuffer glad_glFeedbackBuffer
+GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync;
+#define glFenceSync glad_glFenceSync
+GLAD_API_CALL PFNGLFINISHPROC glad_glFinish;
+#define glFinish glad_glFinish
+GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush;
+#define glFlush glad_glFlush
+GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange;
+#define glFlushMappedBufferRange glad_glFlushMappedBufferRange
+GLAD_API_CALL PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer;
+#define glFogCoordPointer glad_glFogCoordPointer
+GLAD_API_CALL PFNGLFOGCOORDDPROC glad_glFogCoordd;
+#define glFogCoordd glad_glFogCoordd
+GLAD_API_CALL PFNGLFOGCOORDDVPROC glad_glFogCoorddv;
+#define glFogCoorddv glad_glFogCoorddv
+GLAD_API_CALL PFNGLFOGCOORDFPROC glad_glFogCoordf;
+#define glFogCoordf glad_glFogCoordf
+GLAD_API_CALL PFNGLFOGCOORDFVPROC glad_glFogCoordfv;
+#define glFogCoordfv glad_glFogCoordfv
+GLAD_API_CALL PFNGLFOGFPROC glad_glFogf;
+#define glFogf glad_glFogf
+GLAD_API_CALL PFNGLFOGFVPROC glad_glFogfv;
+#define glFogfv glad_glFogfv
+GLAD_API_CALL PFNGLFOGIPROC glad_glFogi;
+#define glFogi glad_glFogi
+GLAD_API_CALL PFNGLFOGIVPROC glad_glFogiv;
+#define glFogiv glad_glFogiv
+GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer;
+#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture;
+#define glFramebufferTexture glad_glFramebufferTexture
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D;
+#define glFramebufferTexture1D glad_glFramebufferTexture1D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D;
+#define glFramebufferTexture2D glad_glFramebufferTexture2D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D;
+#define glFramebufferTexture3D glad_glFramebufferTexture3D
+GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer;
+#define glFramebufferTextureLayer glad_glFramebufferTextureLayer
+GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace;
+#define glFrontFace glad_glFrontFace
+GLAD_API_CALL PFNGLFRUSTUMPROC glad_glFrustum;
+#define glFrustum glad_glFrustum
+GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers;
+#define glGenBuffers glad_glGenBuffers
+GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers;
+#define glGenFramebuffers glad_glGenFramebuffers
+GLAD_API_CALL PFNGLGENLISTSPROC glad_glGenLists;
+#define glGenLists glad_glGenLists
+GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries;
+#define glGenQueries glad_glGenQueries
+GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers;
+#define glGenRenderbuffers glad_glGenRenderbuffers
+GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers;
+#define glGenSamplers glad_glGenSamplers
+GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures;
+#define glGenTextures glad_glGenTextures
+GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays;
+#define glGenVertexArrays glad_glGenVertexArrays
+GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap;
+#define glGenerateMipmap glad_glGenerateMipmap
+GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib;
+#define glGetActiveAttrib glad_glGetActiveAttrib
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform;
+#define glGetActiveUniform glad_glGetActiveUniform
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName;
+#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv;
+#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName;
+#define glGetActiveUniformName glad_glGetActiveUniformName
+GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv;
+#define glGetActiveUniformsiv glad_glGetActiveUniformsiv
+GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders;
+#define glGetAttachedShaders glad_glGetAttachedShaders
+GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation;
+#define glGetAttribLocation glad_glGetAttribLocation
+GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v;
+#define glGetBooleani_v glad_glGetBooleani_v
+GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv;
+#define glGetBooleanv glad_glGetBooleanv
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v;
+#define glGetBufferParameteri64v glad_glGetBufferParameteri64v
+GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv;
+#define glGetBufferParameteriv glad_glGetBufferParameteriv
+GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv;
+#define glGetBufferPointerv glad_glGetBufferPointerv
+GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData;
+#define glGetBufferSubData glad_glGetBufferSubData
+GLAD_API_CALL PFNGLGETCLIPPLANEPROC glad_glGetClipPlane;
+#define glGetClipPlane glad_glGetClipPlane
+GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage;
+#define glGetCompressedTexImage glad_glGetCompressedTexImage
+GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog;
+#define glGetDebugMessageLog glad_glGetDebugMessageLog
+GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev;
+#define glGetDoublev glad_glGetDoublev
+GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError;
+#define glGetError glad_glGetError
+GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv;
+#define glGetFloatv glad_glGetFloatv
+GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex;
+#define glGetFragDataIndex glad_glGetFragDataIndex
+GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation;
+#define glGetFragDataLocation glad_glGetFragDataLocation
+GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv;
+#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv
+GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB;
+#define glGetGraphicsResetStatusARB glad_glGetGraphicsResetStatusARB
+GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v;
+#define glGetInteger64i_v glad_glGetInteger64i_v
+GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v;
+#define glGetInteger64v glad_glGetInteger64v
+GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v;
+#define glGetIntegeri_v glad_glGetIntegeri_v
+GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv;
+#define glGetIntegerv glad_glGetIntegerv
+GLAD_API_CALL PFNGLGETLIGHTFVPROC glad_glGetLightfv;
+#define glGetLightfv glad_glGetLightfv
+GLAD_API_CALL PFNGLGETLIGHTIVPROC glad_glGetLightiv;
+#define glGetLightiv glad_glGetLightiv
+GLAD_API_CALL PFNGLGETMAPDVPROC glad_glGetMapdv;
+#define glGetMapdv glad_glGetMapdv
+GLAD_API_CALL PFNGLGETMAPFVPROC glad_glGetMapfv;
+#define glGetMapfv glad_glGetMapfv
+GLAD_API_CALL PFNGLGETMAPIVPROC glad_glGetMapiv;
+#define glGetMapiv glad_glGetMapiv
+GLAD_API_CALL PFNGLGETMATERIALFVPROC glad_glGetMaterialfv;
+#define glGetMaterialfv glad_glGetMaterialfv
+GLAD_API_CALL PFNGLGETMATERIALIVPROC glad_glGetMaterialiv;
+#define glGetMaterialiv glad_glGetMaterialiv
+GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv;
+#define glGetMultisamplefv glad_glGetMultisamplefv
+GLAD_API_CALL PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel;
+#define glGetObjectLabel glad_glGetObjectLabel
+GLAD_API_CALL PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel;
+#define glGetObjectPtrLabel glad_glGetObjectPtrLabel
+GLAD_API_CALL PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv;
+#define glGetPixelMapfv glad_glGetPixelMapfv
+GLAD_API_CALL PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv;
+#define glGetPixelMapuiv glad_glGetPixelMapuiv
+GLAD_API_CALL PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv;
+#define glGetPixelMapusv glad_glGetPixelMapusv
+GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv;
+#define glGetPointerv glad_glGetPointerv
+GLAD_API_CALL PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple;
+#define glGetPolygonStipple glad_glGetPolygonStipple
+GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog;
+#define glGetProgramInfoLog glad_glGetProgramInfoLog
+GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv;
+#define glGetProgramiv glad_glGetProgramiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v;
+#define glGetQueryObjecti64v glad_glGetQueryObjecti64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv;
+#define glGetQueryObjectiv glad_glGetQueryObjectiv
+GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v;
+#define glGetQueryObjectui64v glad_glGetQueryObjectui64v
+GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv;
+#define glGetQueryObjectuiv glad_glGetQueryObjectuiv
+GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv;
+#define glGetQueryiv glad_glGetQueryiv
+GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv;
+#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv;
+#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv;
+#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv;
+#define glGetSamplerParameterfv glad_glGetSamplerParameterfv
+GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv;
+#define glGetSamplerParameteriv glad_glGetSamplerParameteriv
+GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog;
+#define glGetShaderInfoLog glad_glGetShaderInfoLog
+GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource;
+#define glGetShaderSource glad_glGetShaderSource
+GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv;
+#define glGetShaderiv glad_glGetShaderiv
+GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString;
+#define glGetString glad_glGetString
+GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi;
+#define glGetStringi glad_glGetStringi
+GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv;
+#define glGetSynciv glad_glGetSynciv
+GLAD_API_CALL PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv;
+#define glGetTexEnvfv glad_glGetTexEnvfv
+GLAD_API_CALL PFNGLGETTEXENVIVPROC glad_glGetTexEnviv;
+#define glGetTexEnviv glad_glGetTexEnviv
+GLAD_API_CALL PFNGLGETTEXGENDVPROC glad_glGetTexGendv;
+#define glGetTexGendv glad_glGetTexGendv
+GLAD_API_CALL PFNGLGETTEXGENFVPROC glad_glGetTexGenfv;
+#define glGetTexGenfv glad_glGetTexGenfv
+GLAD_API_CALL PFNGLGETTEXGENIVPROC glad_glGetTexGeniv;
+#define glGetTexGeniv glad_glGetTexGeniv
+GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage;
+#define glGetTexImage glad_glGetTexImage
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv;
+#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv
+GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv;
+#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv;
+#define glGetTexParameterIiv glad_glGetTexParameterIiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv;
+#define glGetTexParameterIuiv glad_glGetTexParameterIuiv
+GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv;
+#define glGetTexParameterfv glad_glGetTexParameterfv
+GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv;
+#define glGetTexParameteriv glad_glGetTexParameteriv
+GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying;
+#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying
+GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex;
+#define glGetUniformBlockIndex glad_glGetUniformBlockIndex
+GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices;
+#define glGetUniformIndices glad_glGetUniformIndices
+GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation;
+#define glGetUniformLocation glad_glGetUniformLocation
+GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv;
+#define glGetUniformfv glad_glGetUniformfv
+GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv;
+#define glGetUniformiv glad_glGetUniformiv
+GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv;
+#define glGetUniformuiv glad_glGetUniformuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv;
+#define glGetVertexAttribIiv glad_glGetVertexAttribIiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv;
+#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv;
+#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv;
+#define glGetVertexAttribdv glad_glGetVertexAttribdv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv;
+#define glGetVertexAttribfv glad_glGetVertexAttribfv
+GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv;
+#define glGetVertexAttribiv glad_glGetVertexAttribiv
+GLAD_API_CALL PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB;
+#define glGetnColorTableARB glad_glGetnColorTableARB
+GLAD_API_CALL PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB;
+#define glGetnCompressedTexImageARB glad_glGetnCompressedTexImageARB
+GLAD_API_CALL PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB;
+#define glGetnConvolutionFilterARB glad_glGetnConvolutionFilterARB
+GLAD_API_CALL PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB;
+#define glGetnHistogramARB glad_glGetnHistogramARB
+GLAD_API_CALL PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB;
+#define glGetnMapdvARB glad_glGetnMapdvARB
+GLAD_API_CALL PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB;
+#define glGetnMapfvARB glad_glGetnMapfvARB
+GLAD_API_CALL PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB;
+#define glGetnMapivARB glad_glGetnMapivARB
+GLAD_API_CALL PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB;
+#define glGetnMinmaxARB glad_glGetnMinmaxARB
+GLAD_API_CALL PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB;
+#define glGetnPixelMapfvARB glad_glGetnPixelMapfvARB
+GLAD_API_CALL PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB;
+#define glGetnPixelMapuivARB glad_glGetnPixelMapuivARB
+GLAD_API_CALL PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB;
+#define glGetnPixelMapusvARB glad_glGetnPixelMapusvARB
+GLAD_API_CALL PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB;
+#define glGetnPolygonStippleARB glad_glGetnPolygonStippleARB
+GLAD_API_CALL PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB;
+#define glGetnSeparableFilterARB glad_glGetnSeparableFilterARB
+GLAD_API_CALL PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB;
+#define glGetnTexImageARB glad_glGetnTexImageARB
+GLAD_API_CALL PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB;
+#define glGetnUniformdvARB glad_glGetnUniformdvARB
+GLAD_API_CALL PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB;
+#define glGetnUniformfvARB glad_glGetnUniformfvARB
+GLAD_API_CALL PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB;
+#define glGetnUniformivARB glad_glGetnUniformivARB
+GLAD_API_CALL PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB;
+#define glGetnUniformuivARB glad_glGetnUniformuivARB
+GLAD_API_CALL PFNGLHINTPROC glad_glHint;
+#define glHint glad_glHint
+GLAD_API_CALL PFNGLINDEXMASKPROC glad_glIndexMask;
+#define glIndexMask glad_glIndexMask
+GLAD_API_CALL PFNGLINDEXPOINTERPROC glad_glIndexPointer;
+#define glIndexPointer glad_glIndexPointer
+GLAD_API_CALL PFNGLINDEXDPROC glad_glIndexd;
+#define glIndexd glad_glIndexd
+GLAD_API_CALL PFNGLINDEXDVPROC glad_glIndexdv;
+#define glIndexdv glad_glIndexdv
+GLAD_API_CALL PFNGLINDEXFPROC glad_glIndexf;
+#define glIndexf glad_glIndexf
+GLAD_API_CALL PFNGLINDEXFVPROC glad_glIndexfv;
+#define glIndexfv glad_glIndexfv
+GLAD_API_CALL PFNGLINDEXIPROC glad_glIndexi;
+#define glIndexi glad_glIndexi
+GLAD_API_CALL PFNGLINDEXIVPROC glad_glIndexiv;
+#define glIndexiv glad_glIndexiv
+GLAD_API_CALL PFNGLINDEXSPROC glad_glIndexs;
+#define glIndexs glad_glIndexs
+GLAD_API_CALL PFNGLINDEXSVPROC glad_glIndexsv;
+#define glIndexsv glad_glIndexsv
+GLAD_API_CALL PFNGLINDEXUBPROC glad_glIndexub;
+#define glIndexub glad_glIndexub
+GLAD_API_CALL PFNGLINDEXUBVPROC glad_glIndexubv;
+#define glIndexubv glad_glIndexubv
+GLAD_API_CALL PFNGLINITNAMESPROC glad_glInitNames;
+#define glInitNames glad_glInitNames
+GLAD_API_CALL PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays;
+#define glInterleavedArrays glad_glInterleavedArrays
+GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer;
+#define glIsBuffer glad_glIsBuffer
+GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled;
+#define glIsEnabled glad_glIsEnabled
+GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi;
+#define glIsEnabledi glad_glIsEnabledi
+GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer;
+#define glIsFramebuffer glad_glIsFramebuffer
+GLAD_API_CALL PFNGLISLISTPROC glad_glIsList;
+#define glIsList glad_glIsList
+GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram;
+#define glIsProgram glad_glIsProgram
+GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery;
+#define glIsQuery glad_glIsQuery
+GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer;
+#define glIsRenderbuffer glad_glIsRenderbuffer
+GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler;
+#define glIsSampler glad_glIsSampler
+GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader;
+#define glIsShader glad_glIsShader
+GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync;
+#define glIsSync glad_glIsSync
+GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture;
+#define glIsTexture glad_glIsTexture
+GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray;
+#define glIsVertexArray glad_glIsVertexArray
+GLAD_API_CALL PFNGLLIGHTMODELFPROC glad_glLightModelf;
+#define glLightModelf glad_glLightModelf
+GLAD_API_CALL PFNGLLIGHTMODELFVPROC glad_glLightModelfv;
+#define glLightModelfv glad_glLightModelfv
+GLAD_API_CALL PFNGLLIGHTMODELIPROC glad_glLightModeli;
+#define glLightModeli glad_glLightModeli
+GLAD_API_CALL PFNGLLIGHTMODELIVPROC glad_glLightModeliv;
+#define glLightModeliv glad_glLightModeliv
+GLAD_API_CALL PFNGLLIGHTFPROC glad_glLightf;
+#define glLightf glad_glLightf
+GLAD_API_CALL PFNGLLIGHTFVPROC glad_glLightfv;
+#define glLightfv glad_glLightfv
+GLAD_API_CALL PFNGLLIGHTIPROC glad_glLighti;
+#define glLighti glad_glLighti
+GLAD_API_CALL PFNGLLIGHTIVPROC glad_glLightiv;
+#define glLightiv glad_glLightiv
+GLAD_API_CALL PFNGLLINESTIPPLEPROC glad_glLineStipple;
+#define glLineStipple glad_glLineStipple
+GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth;
+#define glLineWidth glad_glLineWidth
+GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram;
+#define glLinkProgram glad_glLinkProgram
+GLAD_API_CALL PFNGLLISTBASEPROC glad_glListBase;
+#define glListBase glad_glListBase
+GLAD_API_CALL PFNGLLOADIDENTITYPROC glad_glLoadIdentity;
+#define glLoadIdentity glad_glLoadIdentity
+GLAD_API_CALL PFNGLLOADMATRIXDPROC glad_glLoadMatrixd;
+#define glLoadMatrixd glad_glLoadMatrixd
+GLAD_API_CALL PFNGLLOADMATRIXFPROC glad_glLoadMatrixf;
+#define glLoadMatrixf glad_glLoadMatrixf
+GLAD_API_CALL PFNGLLOADNAMEPROC glad_glLoadName;
+#define glLoadName glad_glLoadName
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd;
+#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd
+GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf;
+#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf
+GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp;
+#define glLogicOp glad_glLogicOp
+GLAD_API_CALL PFNGLMAP1DPROC glad_glMap1d;
+#define glMap1d glad_glMap1d
+GLAD_API_CALL PFNGLMAP1FPROC glad_glMap1f;
+#define glMap1f glad_glMap1f
+GLAD_API_CALL PFNGLMAP2DPROC glad_glMap2d;
+#define glMap2d glad_glMap2d
+GLAD_API_CALL PFNGLMAP2FPROC glad_glMap2f;
+#define glMap2f glad_glMap2f
+GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer;
+#define glMapBuffer glad_glMapBuffer
+GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange;
+#define glMapBufferRange glad_glMapBufferRange
+GLAD_API_CALL PFNGLMAPGRID1DPROC glad_glMapGrid1d;
+#define glMapGrid1d glad_glMapGrid1d
+GLAD_API_CALL PFNGLMAPGRID1FPROC glad_glMapGrid1f;
+#define glMapGrid1f glad_glMapGrid1f
+GLAD_API_CALL PFNGLMAPGRID2DPROC glad_glMapGrid2d;
+#define glMapGrid2d glad_glMapGrid2d
+GLAD_API_CALL PFNGLMAPGRID2FPROC glad_glMapGrid2f;
+#define glMapGrid2f glad_glMapGrid2f
+GLAD_API_CALL PFNGLMATERIALFPROC glad_glMaterialf;
+#define glMaterialf glad_glMaterialf
+GLAD_API_CALL PFNGLMATERIALFVPROC glad_glMaterialfv;
+#define glMaterialfv glad_glMaterialfv
+GLAD_API_CALL PFNGLMATERIALIPROC glad_glMateriali;
+#define glMateriali glad_glMateriali
+GLAD_API_CALL PFNGLMATERIALIVPROC glad_glMaterialiv;
+#define glMaterialiv glad_glMaterialiv
+GLAD_API_CALL PFNGLMATRIXMODEPROC glad_glMatrixMode;
+#define glMatrixMode glad_glMatrixMode
+GLAD_API_CALL PFNGLMULTMATRIXDPROC glad_glMultMatrixd;
+#define glMultMatrixd glad_glMultMatrixd
+GLAD_API_CALL PFNGLMULTMATRIXFPROC glad_glMultMatrixf;
+#define glMultMatrixf glad_glMultMatrixf
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd;
+#define glMultTransposeMatrixd glad_glMultTransposeMatrixd
+GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf;
+#define glMultTransposeMatrixf glad_glMultTransposeMatrixf
+GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays;
+#define glMultiDrawArrays glad_glMultiDrawArrays
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements;
+#define glMultiDrawElements glad_glMultiDrawElements
+GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex;
+#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex
+GLAD_API_CALL PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d;
+#define glMultiTexCoord1d glad_glMultiTexCoord1d
+GLAD_API_CALL PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv;
+#define glMultiTexCoord1dv glad_glMultiTexCoord1dv
+GLAD_API_CALL PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f;
+#define glMultiTexCoord1f glad_glMultiTexCoord1f
+GLAD_API_CALL PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv;
+#define glMultiTexCoord1fv glad_glMultiTexCoord1fv
+GLAD_API_CALL PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i;
+#define glMultiTexCoord1i glad_glMultiTexCoord1i
+GLAD_API_CALL PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv;
+#define glMultiTexCoord1iv glad_glMultiTexCoord1iv
+GLAD_API_CALL PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s;
+#define glMultiTexCoord1s glad_glMultiTexCoord1s
+GLAD_API_CALL PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv;
+#define glMultiTexCoord1sv glad_glMultiTexCoord1sv
+GLAD_API_CALL PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d;
+#define glMultiTexCoord2d glad_glMultiTexCoord2d
+GLAD_API_CALL PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv;
+#define glMultiTexCoord2dv glad_glMultiTexCoord2dv
+GLAD_API_CALL PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f;
+#define glMultiTexCoord2f glad_glMultiTexCoord2f
+GLAD_API_CALL PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv;
+#define glMultiTexCoord2fv glad_glMultiTexCoord2fv
+GLAD_API_CALL PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i;
+#define glMultiTexCoord2i glad_glMultiTexCoord2i
+GLAD_API_CALL PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv;
+#define glMultiTexCoord2iv glad_glMultiTexCoord2iv
+GLAD_API_CALL PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s;
+#define glMultiTexCoord2s glad_glMultiTexCoord2s
+GLAD_API_CALL PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv;
+#define glMultiTexCoord2sv glad_glMultiTexCoord2sv
+GLAD_API_CALL PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d;
+#define glMultiTexCoord3d glad_glMultiTexCoord3d
+GLAD_API_CALL PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv;
+#define glMultiTexCoord3dv glad_glMultiTexCoord3dv
+GLAD_API_CALL PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f;
+#define glMultiTexCoord3f glad_glMultiTexCoord3f
+GLAD_API_CALL PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv;
+#define glMultiTexCoord3fv glad_glMultiTexCoord3fv
+GLAD_API_CALL PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i;
+#define glMultiTexCoord3i glad_glMultiTexCoord3i
+GLAD_API_CALL PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv;
+#define glMultiTexCoord3iv glad_glMultiTexCoord3iv
+GLAD_API_CALL PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s;
+#define glMultiTexCoord3s glad_glMultiTexCoord3s
+GLAD_API_CALL PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv;
+#define glMultiTexCoord3sv glad_glMultiTexCoord3sv
+GLAD_API_CALL PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d;
+#define glMultiTexCoord4d glad_glMultiTexCoord4d
+GLAD_API_CALL PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv;
+#define glMultiTexCoord4dv glad_glMultiTexCoord4dv
+GLAD_API_CALL PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f;
+#define glMultiTexCoord4f glad_glMultiTexCoord4f
+GLAD_API_CALL PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv;
+#define glMultiTexCoord4fv glad_glMultiTexCoord4fv
+GLAD_API_CALL PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i;
+#define glMultiTexCoord4i glad_glMultiTexCoord4i
+GLAD_API_CALL PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv;
+#define glMultiTexCoord4iv glad_glMultiTexCoord4iv
+GLAD_API_CALL PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s;
+#define glMultiTexCoord4s glad_glMultiTexCoord4s
+GLAD_API_CALL PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv;
+#define glMultiTexCoord4sv glad_glMultiTexCoord4sv
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui;
+#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv;
+#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui;
+#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv;
+#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui;
+#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv;
+#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui;
+#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui
+GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv;
+#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv
+GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList;
+#define glNewList glad_glNewList
+GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b;
+#define glNormal3b glad_glNormal3b
+GLAD_API_CALL PFNGLNORMAL3BVPROC glad_glNormal3bv;
+#define glNormal3bv glad_glNormal3bv
+GLAD_API_CALL PFNGLNORMAL3DPROC glad_glNormal3d;
+#define glNormal3d glad_glNormal3d
+GLAD_API_CALL PFNGLNORMAL3DVPROC glad_glNormal3dv;
+#define glNormal3dv glad_glNormal3dv
+GLAD_API_CALL PFNGLNORMAL3FPROC glad_glNormal3f;
+#define glNormal3f glad_glNormal3f
+GLAD_API_CALL PFNGLNORMAL3FVPROC glad_glNormal3fv;
+#define glNormal3fv glad_glNormal3fv
+GLAD_API_CALL PFNGLNORMAL3IPROC glad_glNormal3i;
+#define glNormal3i glad_glNormal3i
+GLAD_API_CALL PFNGLNORMAL3IVPROC glad_glNormal3iv;
+#define glNormal3iv glad_glNormal3iv
+GLAD_API_CALL PFNGLNORMAL3SPROC glad_glNormal3s;
+#define glNormal3s glad_glNormal3s
+GLAD_API_CALL PFNGLNORMAL3SVPROC glad_glNormal3sv;
+#define glNormal3sv glad_glNormal3sv
+GLAD_API_CALL PFNGLNORMALP3UIPROC glad_glNormalP3ui;
+#define glNormalP3ui glad_glNormalP3ui
+GLAD_API_CALL PFNGLNORMALP3UIVPROC glad_glNormalP3uiv;
+#define glNormalP3uiv glad_glNormalP3uiv
+GLAD_API_CALL PFNGLNORMALPOINTERPROC glad_glNormalPointer;
+#define glNormalPointer glad_glNormalPointer
+GLAD_API_CALL PFNGLOBJECTLABELPROC glad_glObjectLabel;
+#define glObjectLabel glad_glObjectLabel
+GLAD_API_CALL PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel;
+#define glObjectPtrLabel glad_glObjectPtrLabel
+GLAD_API_CALL PFNGLORTHOPROC glad_glOrtho;
+#define glOrtho glad_glOrtho
+GLAD_API_CALL PFNGLPASSTHROUGHPROC glad_glPassThrough;
+#define glPassThrough glad_glPassThrough
+GLAD_API_CALL PFNGLPIXELMAPFVPROC glad_glPixelMapfv;
+#define glPixelMapfv glad_glPixelMapfv
+GLAD_API_CALL PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv;
+#define glPixelMapuiv glad_glPixelMapuiv
+GLAD_API_CALL PFNGLPIXELMAPUSVPROC glad_glPixelMapusv;
+#define glPixelMapusv glad_glPixelMapusv
+GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref;
+#define glPixelStoref glad_glPixelStoref
+GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei;
+#define glPixelStorei glad_glPixelStorei
+GLAD_API_CALL PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf;
+#define glPixelTransferf glad_glPixelTransferf
+GLAD_API_CALL PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi;
+#define glPixelTransferi glad_glPixelTransferi
+GLAD_API_CALL PFNGLPIXELZOOMPROC glad_glPixelZoom;
+#define glPixelZoom glad_glPixelZoom
+GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf;
+#define glPointParameterf glad_glPointParameterf
+GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv;
+#define glPointParameterfv glad_glPointParameterfv
+GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri;
+#define glPointParameteri glad_glPointParameteri
+GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv;
+#define glPointParameteriv glad_glPointParameteriv
+GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize;
+#define glPointSize glad_glPointSize
+GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode;
+#define glPolygonMode glad_glPolygonMode
+GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset;
+#define glPolygonOffset glad_glPolygonOffset
+GLAD_API_CALL PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple;
+#define glPolygonStipple glad_glPolygonStipple
+GLAD_API_CALL PFNGLPOPATTRIBPROC glad_glPopAttrib;
+#define glPopAttrib glad_glPopAttrib
+GLAD_API_CALL PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib;
+#define glPopClientAttrib glad_glPopClientAttrib
+GLAD_API_CALL PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup;
+#define glPopDebugGroup glad_glPopDebugGroup
+GLAD_API_CALL PFNGLPOPMATRIXPROC glad_glPopMatrix;
+#define glPopMatrix glad_glPopMatrix
+GLAD_API_CALL PFNGLPOPNAMEPROC glad_glPopName;
+#define glPopName glad_glPopName
+GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex;
+#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex
+GLAD_API_CALL PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures;
+#define glPrioritizeTextures glad_glPrioritizeTextures
+GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex;
+#define glProvokingVertex glad_glProvokingVertex
+GLAD_API_CALL PFNGLPUSHATTRIBPROC glad_glPushAttrib;
+#define glPushAttrib glad_glPushAttrib
+GLAD_API_CALL PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib;
+#define glPushClientAttrib glad_glPushClientAttrib
+GLAD_API_CALL PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup;
+#define glPushDebugGroup glad_glPushDebugGroup
+GLAD_API_CALL PFNGLPUSHMATRIXPROC glad_glPushMatrix;
+#define glPushMatrix glad_glPushMatrix
+GLAD_API_CALL PFNGLPUSHNAMEPROC glad_glPushName;
+#define glPushName glad_glPushName
+GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter;
+#define glQueryCounter glad_glQueryCounter
+GLAD_API_CALL PFNGLRASTERPOS2DPROC glad_glRasterPos2d;
+#define glRasterPos2d glad_glRasterPos2d
+GLAD_API_CALL PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv;
+#define glRasterPos2dv glad_glRasterPos2dv
+GLAD_API_CALL PFNGLRASTERPOS2FPROC glad_glRasterPos2f;
+#define glRasterPos2f glad_glRasterPos2f
+GLAD_API_CALL PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv;
+#define glRasterPos2fv glad_glRasterPos2fv
+GLAD_API_CALL PFNGLRASTERPOS2IPROC glad_glRasterPos2i;
+#define glRasterPos2i glad_glRasterPos2i
+GLAD_API_CALL PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv;
+#define glRasterPos2iv glad_glRasterPos2iv
+GLAD_API_CALL PFNGLRASTERPOS2SPROC glad_glRasterPos2s;
+#define glRasterPos2s glad_glRasterPos2s
+GLAD_API_CALL PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv;
+#define glRasterPos2sv glad_glRasterPos2sv
+GLAD_API_CALL PFNGLRASTERPOS3DPROC glad_glRasterPos3d;
+#define glRasterPos3d glad_glRasterPos3d
+GLAD_API_CALL PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv;
+#define glRasterPos3dv glad_glRasterPos3dv
+GLAD_API_CALL PFNGLRASTERPOS3FPROC glad_glRasterPos3f;
+#define glRasterPos3f glad_glRasterPos3f
+GLAD_API_CALL PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv;
+#define glRasterPos3fv glad_glRasterPos3fv
+GLAD_API_CALL PFNGLRASTERPOS3IPROC glad_glRasterPos3i;
+#define glRasterPos3i glad_glRasterPos3i
+GLAD_API_CALL PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv;
+#define glRasterPos3iv glad_glRasterPos3iv
+GLAD_API_CALL PFNGLRASTERPOS3SPROC glad_glRasterPos3s;
+#define glRasterPos3s glad_glRasterPos3s
+GLAD_API_CALL PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv;
+#define glRasterPos3sv glad_glRasterPos3sv
+GLAD_API_CALL PFNGLRASTERPOS4DPROC glad_glRasterPos4d;
+#define glRasterPos4d glad_glRasterPos4d
+GLAD_API_CALL PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv;
+#define glRasterPos4dv glad_glRasterPos4dv
+GLAD_API_CALL PFNGLRASTERPOS4FPROC glad_glRasterPos4f;
+#define glRasterPos4f glad_glRasterPos4f
+GLAD_API_CALL PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv;
+#define glRasterPos4fv glad_glRasterPos4fv
+GLAD_API_CALL PFNGLRASTERPOS4IPROC glad_glRasterPos4i;
+#define glRasterPos4i glad_glRasterPos4i
+GLAD_API_CALL PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv;
+#define glRasterPos4iv glad_glRasterPos4iv
+GLAD_API_CALL PFNGLRASTERPOS4SPROC glad_glRasterPos4s;
+#define glRasterPos4s glad_glRasterPos4s
+GLAD_API_CALL PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv;
+#define glRasterPos4sv glad_glRasterPos4sv
+GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer;
+#define glReadBuffer glad_glReadBuffer
+GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels;
+#define glReadPixels glad_glReadPixels
+GLAD_API_CALL PFNGLREADNPIXELSPROC glad_glReadnPixels;
+#define glReadnPixels glad_glReadnPixels
+GLAD_API_CALL PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB;
+#define glReadnPixelsARB glad_glReadnPixelsARB
+GLAD_API_CALL PFNGLRECTDPROC glad_glRectd;
+#define glRectd glad_glRectd
+GLAD_API_CALL PFNGLRECTDVPROC glad_glRectdv;
+#define glRectdv glad_glRectdv
+GLAD_API_CALL PFNGLRECTFPROC glad_glRectf;
+#define glRectf glad_glRectf
+GLAD_API_CALL PFNGLRECTFVPROC glad_glRectfv;
+#define glRectfv glad_glRectfv
+GLAD_API_CALL PFNGLRECTIPROC glad_glRecti;
+#define glRecti glad_glRecti
+GLAD_API_CALL PFNGLRECTIVPROC glad_glRectiv;
+#define glRectiv glad_glRectiv
+GLAD_API_CALL PFNGLRECTSPROC glad_glRects;
+#define glRects glad_glRects
+GLAD_API_CALL PFNGLRECTSVPROC glad_glRectsv;
+#define glRectsv glad_glRectsv
+GLAD_API_CALL PFNGLRENDERMODEPROC glad_glRenderMode;
+#define glRenderMode glad_glRenderMode
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage;
+#define glRenderbufferStorage glad_glRenderbufferStorage
+GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample;
+#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample
+GLAD_API_CALL PFNGLROTATEDPROC glad_glRotated;
+#define glRotated glad_glRotated
+GLAD_API_CALL PFNGLROTATEFPROC glad_glRotatef;
+#define glRotatef glad_glRotatef
+GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage;
+#define glSampleCoverage glad_glSampleCoverage
+GLAD_API_CALL PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB;
+#define glSampleCoverageARB glad_glSampleCoverageARB
+GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski;
+#define glSampleMaski glad_glSampleMaski
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv;
+#define glSamplerParameterIiv glad_glSamplerParameterIiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv;
+#define glSamplerParameterIuiv glad_glSamplerParameterIuiv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf;
+#define glSamplerParameterf glad_glSamplerParameterf
+GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv;
+#define glSamplerParameterfv glad_glSamplerParameterfv
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri;
+#define glSamplerParameteri glad_glSamplerParameteri
+GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv;
+#define glSamplerParameteriv glad_glSamplerParameteriv
+GLAD_API_CALL PFNGLSCALEDPROC glad_glScaled;
+#define glScaled glad_glScaled
+GLAD_API_CALL PFNGLSCALEFPROC glad_glScalef;
+#define glScalef glad_glScalef
+GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor;
+#define glScissor glad_glScissor
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b;
+#define glSecondaryColor3b glad_glSecondaryColor3b
+GLAD_API_CALL PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv;
+#define glSecondaryColor3bv glad_glSecondaryColor3bv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d;
+#define glSecondaryColor3d glad_glSecondaryColor3d
+GLAD_API_CALL PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv;
+#define glSecondaryColor3dv glad_glSecondaryColor3dv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f;
+#define glSecondaryColor3f glad_glSecondaryColor3f
+GLAD_API_CALL PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv;
+#define glSecondaryColor3fv glad_glSecondaryColor3fv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i;
+#define glSecondaryColor3i glad_glSecondaryColor3i
+GLAD_API_CALL PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv;
+#define glSecondaryColor3iv glad_glSecondaryColor3iv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s;
+#define glSecondaryColor3s glad_glSecondaryColor3s
+GLAD_API_CALL PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv;
+#define glSecondaryColor3sv glad_glSecondaryColor3sv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub;
+#define glSecondaryColor3ub glad_glSecondaryColor3ub
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv;
+#define glSecondaryColor3ubv glad_glSecondaryColor3ubv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui;
+#define glSecondaryColor3ui glad_glSecondaryColor3ui
+GLAD_API_CALL PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv;
+#define glSecondaryColor3uiv glad_glSecondaryColor3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us;
+#define glSecondaryColor3us glad_glSecondaryColor3us
+GLAD_API_CALL PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv;
+#define glSecondaryColor3usv glad_glSecondaryColor3usv
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui;
+#define glSecondaryColorP3ui glad_glSecondaryColorP3ui
+GLAD_API_CALL PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv;
+#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv
+GLAD_API_CALL PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer;
+#define glSecondaryColorPointer glad_glSecondaryColorPointer
+GLAD_API_CALL PFNGLSELECTBUFFERPROC glad_glSelectBuffer;
+#define glSelectBuffer glad_glSelectBuffer
+GLAD_API_CALL PFNGLSHADEMODELPROC glad_glShadeModel;
+#define glShadeModel glad_glShadeModel
+GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource;
+#define glShaderSource glad_glShaderSource
+GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc;
+#define glStencilFunc glad_glStencilFunc
+GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate;
+#define glStencilFuncSeparate glad_glStencilFuncSeparate
+GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask;
+#define glStencilMask glad_glStencilMask
+GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate;
+#define glStencilMaskSeparate glad_glStencilMaskSeparate
+GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp;
+#define glStencilOp glad_glStencilOp
+GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate;
+#define glStencilOpSeparate glad_glStencilOpSeparate
+GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer;
+#define glTexBuffer glad_glTexBuffer
+GLAD_API_CALL PFNGLTEXCOORD1DPROC glad_glTexCoord1d;
+#define glTexCoord1d glad_glTexCoord1d
+GLAD_API_CALL PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv;
+#define glTexCoord1dv glad_glTexCoord1dv
+GLAD_API_CALL PFNGLTEXCOORD1FPROC glad_glTexCoord1f;
+#define glTexCoord1f glad_glTexCoord1f
+GLAD_API_CALL PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv;
+#define glTexCoord1fv glad_glTexCoord1fv
+GLAD_API_CALL PFNGLTEXCOORD1IPROC glad_glTexCoord1i;
+#define glTexCoord1i glad_glTexCoord1i
+GLAD_API_CALL PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv;
+#define glTexCoord1iv glad_glTexCoord1iv
+GLAD_API_CALL PFNGLTEXCOORD1SPROC glad_glTexCoord1s;
+#define glTexCoord1s glad_glTexCoord1s
+GLAD_API_CALL PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv;
+#define glTexCoord1sv glad_glTexCoord1sv
+GLAD_API_CALL PFNGLTEXCOORD2DPROC glad_glTexCoord2d;
+#define glTexCoord2d glad_glTexCoord2d
+GLAD_API_CALL PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv;
+#define glTexCoord2dv glad_glTexCoord2dv
+GLAD_API_CALL PFNGLTEXCOORD2FPROC glad_glTexCoord2f;
+#define glTexCoord2f glad_glTexCoord2f
+GLAD_API_CALL PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv;
+#define glTexCoord2fv glad_glTexCoord2fv
+GLAD_API_CALL PFNGLTEXCOORD2IPROC glad_glTexCoord2i;
+#define glTexCoord2i glad_glTexCoord2i
+GLAD_API_CALL PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv;
+#define glTexCoord2iv glad_glTexCoord2iv
+GLAD_API_CALL PFNGLTEXCOORD2SPROC glad_glTexCoord2s;
+#define glTexCoord2s glad_glTexCoord2s
+GLAD_API_CALL PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv;
+#define glTexCoord2sv glad_glTexCoord2sv
+GLAD_API_CALL PFNGLTEXCOORD3DPROC glad_glTexCoord3d;
+#define glTexCoord3d glad_glTexCoord3d
+GLAD_API_CALL PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv;
+#define glTexCoord3dv glad_glTexCoord3dv
+GLAD_API_CALL PFNGLTEXCOORD3FPROC glad_glTexCoord3f;
+#define glTexCoord3f glad_glTexCoord3f
+GLAD_API_CALL PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv;
+#define glTexCoord3fv glad_glTexCoord3fv
+GLAD_API_CALL PFNGLTEXCOORD3IPROC glad_glTexCoord3i;
+#define glTexCoord3i glad_glTexCoord3i
+GLAD_API_CALL PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv;
+#define glTexCoord3iv glad_glTexCoord3iv
+GLAD_API_CALL PFNGLTEXCOORD3SPROC glad_glTexCoord3s;
+#define glTexCoord3s glad_glTexCoord3s
+GLAD_API_CALL PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv;
+#define glTexCoord3sv glad_glTexCoord3sv
+GLAD_API_CALL PFNGLTEXCOORD4DPROC glad_glTexCoord4d;
+#define glTexCoord4d glad_glTexCoord4d
+GLAD_API_CALL PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv;
+#define glTexCoord4dv glad_glTexCoord4dv
+GLAD_API_CALL PFNGLTEXCOORD4FPROC glad_glTexCoord4f;
+#define glTexCoord4f glad_glTexCoord4f
+GLAD_API_CALL PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv;
+#define glTexCoord4fv glad_glTexCoord4fv
+GLAD_API_CALL PFNGLTEXCOORD4IPROC glad_glTexCoord4i;
+#define glTexCoord4i glad_glTexCoord4i
+GLAD_API_CALL PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv;
+#define glTexCoord4iv glad_glTexCoord4iv
+GLAD_API_CALL PFNGLTEXCOORD4SPROC glad_glTexCoord4s;
+#define glTexCoord4s glad_glTexCoord4s
+GLAD_API_CALL PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv;
+#define glTexCoord4sv glad_glTexCoord4sv
+GLAD_API_CALL PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui;
+#define glTexCoordP1ui glad_glTexCoordP1ui
+GLAD_API_CALL PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv;
+#define glTexCoordP1uiv glad_glTexCoordP1uiv
+GLAD_API_CALL PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui;
+#define glTexCoordP2ui glad_glTexCoordP2ui
+GLAD_API_CALL PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv;
+#define glTexCoordP2uiv glad_glTexCoordP2uiv
+GLAD_API_CALL PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui;
+#define glTexCoordP3ui glad_glTexCoordP3ui
+GLAD_API_CALL PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv;
+#define glTexCoordP3uiv glad_glTexCoordP3uiv
+GLAD_API_CALL PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui;
+#define glTexCoordP4ui glad_glTexCoordP4ui
+GLAD_API_CALL PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv;
+#define glTexCoordP4uiv glad_glTexCoordP4uiv
+GLAD_API_CALL PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer;
+#define glTexCoordPointer glad_glTexCoordPointer
+GLAD_API_CALL PFNGLTEXENVFPROC glad_glTexEnvf;
+#define glTexEnvf glad_glTexEnvf
+GLAD_API_CALL PFNGLTEXENVFVPROC glad_glTexEnvfv;
+#define glTexEnvfv glad_glTexEnvfv
+GLAD_API_CALL PFNGLTEXENVIPROC glad_glTexEnvi;
+#define glTexEnvi glad_glTexEnvi
+GLAD_API_CALL PFNGLTEXENVIVPROC glad_glTexEnviv;
+#define glTexEnviv glad_glTexEnviv
+GLAD_API_CALL PFNGLTEXGENDPROC glad_glTexGend;
+#define glTexGend glad_glTexGend
+GLAD_API_CALL PFNGLTEXGENDVPROC glad_glTexGendv;
+#define glTexGendv glad_glTexGendv
+GLAD_API_CALL PFNGLTEXGENFPROC glad_glTexGenf;
+#define glTexGenf glad_glTexGenf
+GLAD_API_CALL PFNGLTEXGENFVPROC glad_glTexGenfv;
+#define glTexGenfv glad_glTexGenfv
+GLAD_API_CALL PFNGLTEXGENIPROC glad_glTexGeni;
+#define glTexGeni glad_glTexGeni
+GLAD_API_CALL PFNGLTEXGENIVPROC glad_glTexGeniv;
+#define glTexGeniv glad_glTexGeniv
+GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D;
+#define glTexImage1D glad_glTexImage1D
+GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D;
+#define glTexImage2D glad_glTexImage2D
+GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample;
+#define glTexImage2DMultisample glad_glTexImage2DMultisample
+GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D;
+#define glTexImage3D glad_glTexImage3D
+GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample;
+#define glTexImage3DMultisample glad_glTexImage3DMultisample
+GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv;
+#define glTexParameterIiv glad_glTexParameterIiv
+GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv;
+#define glTexParameterIuiv glad_glTexParameterIuiv
+GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf;
+#define glTexParameterf glad_glTexParameterf
+GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv;
+#define glTexParameterfv glad_glTexParameterfv
+GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri;
+#define glTexParameteri glad_glTexParameteri
+GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv;
+#define glTexParameteriv glad_glTexParameteriv
+GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D;
+#define glTexSubImage1D glad_glTexSubImage1D
+GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D;
+#define glTexSubImage2D glad_glTexSubImage2D
+GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D;
+#define glTexSubImage3D glad_glTexSubImage3D
+GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings;
+#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings
+GLAD_API_CALL PFNGLTRANSLATEDPROC glad_glTranslated;
+#define glTranslated glad_glTranslated
+GLAD_API_CALL PFNGLTRANSLATEFPROC glad_glTranslatef;
+#define glTranslatef glad_glTranslatef
+GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f;
+#define glUniform1f glad_glUniform1f
+GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv;
+#define glUniform1fv glad_glUniform1fv
+GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i;
+#define glUniform1i glad_glUniform1i
+GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv;
+#define glUniform1iv glad_glUniform1iv
+GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui;
+#define glUniform1ui glad_glUniform1ui
+GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv;
+#define glUniform1uiv glad_glUniform1uiv
+GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f;
+#define glUniform2f glad_glUniform2f
+GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv;
+#define glUniform2fv glad_glUniform2fv
+GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i;
+#define glUniform2i glad_glUniform2i
+GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv;
+#define glUniform2iv glad_glUniform2iv
+GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui;
+#define glUniform2ui glad_glUniform2ui
+GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv;
+#define glUniform2uiv glad_glUniform2uiv
+GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f;
+#define glUniform3f glad_glUniform3f
+GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv;
+#define glUniform3fv glad_glUniform3fv
+GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i;
+#define glUniform3i glad_glUniform3i
+GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv;
+#define glUniform3iv glad_glUniform3iv
+GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui;
+#define glUniform3ui glad_glUniform3ui
+GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv;
+#define glUniform3uiv glad_glUniform3uiv
+GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f;
+#define glUniform4f glad_glUniform4f
+GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv;
+#define glUniform4fv glad_glUniform4fv
+GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i;
+#define glUniform4i glad_glUniform4i
+GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv;
+#define glUniform4iv glad_glUniform4iv
+GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui;
+#define glUniform4ui glad_glUniform4ui
+GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv;
+#define glUniform4uiv glad_glUniform4uiv
+GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding;
+#define glUniformBlockBinding glad_glUniformBlockBinding
+GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv;
+#define glUniformMatrix2fv glad_glUniformMatrix2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv;
+#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv;
+#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv;
+#define glUniformMatrix3fv glad_glUniformMatrix3fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv;
+#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv;
+#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv;
+#define glUniformMatrix4fv glad_glUniformMatrix4fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv;
+#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv
+GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv;
+#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv
+GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer;
+#define glUnmapBuffer glad_glUnmapBuffer
+GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram;
+#define glUseProgram glad_glUseProgram
+GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram;
+#define glValidateProgram glad_glValidateProgram
+GLAD_API_CALL PFNGLVERTEX2DPROC glad_glVertex2d;
+#define glVertex2d glad_glVertex2d
+GLAD_API_CALL PFNGLVERTEX2DVPROC glad_glVertex2dv;
+#define glVertex2dv glad_glVertex2dv
+GLAD_API_CALL PFNGLVERTEX2FPROC glad_glVertex2f;
+#define glVertex2f glad_glVertex2f
+GLAD_API_CALL PFNGLVERTEX2FVPROC glad_glVertex2fv;
+#define glVertex2fv glad_glVertex2fv
+GLAD_API_CALL PFNGLVERTEX2IPROC glad_glVertex2i;
+#define glVertex2i glad_glVertex2i
+GLAD_API_CALL PFNGLVERTEX2IVPROC glad_glVertex2iv;
+#define glVertex2iv glad_glVertex2iv
+GLAD_API_CALL PFNGLVERTEX2SPROC glad_glVertex2s;
+#define glVertex2s glad_glVertex2s
+GLAD_API_CALL PFNGLVERTEX2SVPROC glad_glVertex2sv;
+#define glVertex2sv glad_glVertex2sv
+GLAD_API_CALL PFNGLVERTEX3DPROC glad_glVertex3d;
+#define glVertex3d glad_glVertex3d
+GLAD_API_CALL PFNGLVERTEX3DVPROC glad_glVertex3dv;
+#define glVertex3dv glad_glVertex3dv
+GLAD_API_CALL PFNGLVERTEX3FPROC glad_glVertex3f;
+#define glVertex3f glad_glVertex3f
+GLAD_API_CALL PFNGLVERTEX3FVPROC glad_glVertex3fv;
+#define glVertex3fv glad_glVertex3fv
+GLAD_API_CALL PFNGLVERTEX3IPROC glad_glVertex3i;
+#define glVertex3i glad_glVertex3i
+GLAD_API_CALL PFNGLVERTEX3IVPROC glad_glVertex3iv;
+#define glVertex3iv glad_glVertex3iv
+GLAD_API_CALL PFNGLVERTEX3SPROC glad_glVertex3s;
+#define glVertex3s glad_glVertex3s
+GLAD_API_CALL PFNGLVERTEX3SVPROC glad_glVertex3sv;
+#define glVertex3sv glad_glVertex3sv
+GLAD_API_CALL PFNGLVERTEX4DPROC glad_glVertex4d;
+#define glVertex4d glad_glVertex4d
+GLAD_API_CALL PFNGLVERTEX4DVPROC glad_glVertex4dv;
+#define glVertex4dv glad_glVertex4dv
+GLAD_API_CALL PFNGLVERTEX4FPROC glad_glVertex4f;
+#define glVertex4f glad_glVertex4f
+GLAD_API_CALL PFNGLVERTEX4FVPROC glad_glVertex4fv;
+#define glVertex4fv glad_glVertex4fv
+GLAD_API_CALL PFNGLVERTEX4IPROC glad_glVertex4i;
+#define glVertex4i glad_glVertex4i
+GLAD_API_CALL PFNGLVERTEX4IVPROC glad_glVertex4iv;
+#define glVertex4iv glad_glVertex4iv
+GLAD_API_CALL PFNGLVERTEX4SPROC glad_glVertex4s;
+#define glVertex4s glad_glVertex4s
+GLAD_API_CALL PFNGLVERTEX4SVPROC glad_glVertex4sv;
+#define glVertex4sv glad_glVertex4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d;
+#define glVertexAttrib1d glad_glVertexAttrib1d
+GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv;
+#define glVertexAttrib1dv glad_glVertexAttrib1dv
+GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f;
+#define glVertexAttrib1f glad_glVertexAttrib1f
+GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv;
+#define glVertexAttrib1fv glad_glVertexAttrib1fv
+GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s;
+#define glVertexAttrib1s glad_glVertexAttrib1s
+GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv;
+#define glVertexAttrib1sv glad_glVertexAttrib1sv
+GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d;
+#define glVertexAttrib2d glad_glVertexAttrib2d
+GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv;
+#define glVertexAttrib2dv glad_glVertexAttrib2dv
+GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f;
+#define glVertexAttrib2f glad_glVertexAttrib2f
+GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv;
+#define glVertexAttrib2fv glad_glVertexAttrib2fv
+GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s;
+#define glVertexAttrib2s glad_glVertexAttrib2s
+GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv;
+#define glVertexAttrib2sv glad_glVertexAttrib2sv
+GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d;
+#define glVertexAttrib3d glad_glVertexAttrib3d
+GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv;
+#define glVertexAttrib3dv glad_glVertexAttrib3dv
+GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f;
+#define glVertexAttrib3f glad_glVertexAttrib3f
+GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv;
+#define glVertexAttrib3fv glad_glVertexAttrib3fv
+GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s;
+#define glVertexAttrib3s glad_glVertexAttrib3s
+GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv;
+#define glVertexAttrib3sv glad_glVertexAttrib3sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv;
+#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv;
+#define glVertexAttrib4Niv glad_glVertexAttrib4Niv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv;
+#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub;
+#define glVertexAttrib4Nub glad_glVertexAttrib4Nub
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv;
+#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv;
+#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv;
+#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv
+GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv;
+#define glVertexAttrib4bv glad_glVertexAttrib4bv
+GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d;
+#define glVertexAttrib4d glad_glVertexAttrib4d
+GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv;
+#define glVertexAttrib4dv glad_glVertexAttrib4dv
+GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f;
+#define glVertexAttrib4f glad_glVertexAttrib4f
+GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv;
+#define glVertexAttrib4fv glad_glVertexAttrib4fv
+GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv;
+#define glVertexAttrib4iv glad_glVertexAttrib4iv
+GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s;
+#define glVertexAttrib4s glad_glVertexAttrib4s
+GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv;
+#define glVertexAttrib4sv glad_glVertexAttrib4sv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv;
+#define glVertexAttrib4ubv glad_glVertexAttrib4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv;
+#define glVertexAttrib4uiv glad_glVertexAttrib4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv;
+#define glVertexAttrib4usv glad_glVertexAttrib4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor;
+#define glVertexAttribDivisor glad_glVertexAttribDivisor
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i;
+#define glVertexAttribI1i glad_glVertexAttribI1i
+GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv;
+#define glVertexAttribI1iv glad_glVertexAttribI1iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui;
+#define glVertexAttribI1ui glad_glVertexAttribI1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv;
+#define glVertexAttribI1uiv glad_glVertexAttribI1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i;
+#define glVertexAttribI2i glad_glVertexAttribI2i
+GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv;
+#define glVertexAttribI2iv glad_glVertexAttribI2iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui;
+#define glVertexAttribI2ui glad_glVertexAttribI2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv;
+#define glVertexAttribI2uiv glad_glVertexAttribI2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i;
+#define glVertexAttribI3i glad_glVertexAttribI3i
+GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv;
+#define glVertexAttribI3iv glad_glVertexAttribI3iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui;
+#define glVertexAttribI3ui glad_glVertexAttribI3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv;
+#define glVertexAttribI3uiv glad_glVertexAttribI3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv;
+#define glVertexAttribI4bv glad_glVertexAttribI4bv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i;
+#define glVertexAttribI4i glad_glVertexAttribI4i
+GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv;
+#define glVertexAttribI4iv glad_glVertexAttribI4iv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv;
+#define glVertexAttribI4sv glad_glVertexAttribI4sv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv;
+#define glVertexAttribI4ubv glad_glVertexAttribI4ubv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui;
+#define glVertexAttribI4ui glad_glVertexAttribI4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv;
+#define glVertexAttribI4uiv glad_glVertexAttribI4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv;
+#define glVertexAttribI4usv glad_glVertexAttribI4usv
+GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer;
+#define glVertexAttribIPointer glad_glVertexAttribIPointer
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui;
+#define glVertexAttribP1ui glad_glVertexAttribP1ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv;
+#define glVertexAttribP1uiv glad_glVertexAttribP1uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui;
+#define glVertexAttribP2ui glad_glVertexAttribP2ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv;
+#define glVertexAttribP2uiv glad_glVertexAttribP2uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui;
+#define glVertexAttribP3ui glad_glVertexAttribP3ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv;
+#define glVertexAttribP3uiv glad_glVertexAttribP3uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui;
+#define glVertexAttribP4ui glad_glVertexAttribP4ui
+GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv;
+#define glVertexAttribP4uiv glad_glVertexAttribP4uiv
+GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer;
+#define glVertexAttribPointer glad_glVertexAttribPointer
+GLAD_API_CALL PFNGLVERTEXP2UIPROC glad_glVertexP2ui;
+#define glVertexP2ui glad_glVertexP2ui
+GLAD_API_CALL PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv;
+#define glVertexP2uiv glad_glVertexP2uiv
+GLAD_API_CALL PFNGLVERTEXP3UIPROC glad_glVertexP3ui;
+#define glVertexP3ui glad_glVertexP3ui
+GLAD_API_CALL PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv;
+#define glVertexP3uiv glad_glVertexP3uiv
+GLAD_API_CALL PFNGLVERTEXP4UIPROC glad_glVertexP4ui;
+#define glVertexP4ui glad_glVertexP4ui
+GLAD_API_CALL PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv;
+#define glVertexP4uiv glad_glVertexP4uiv
+GLAD_API_CALL PFNGLVERTEXPOINTERPROC glad_glVertexPointer;
+#define glVertexPointer glad_glVertexPointer
+GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport;
+#define glViewport glad_glViewport
+GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync;
+#define glWaitSync glad_glWaitSync
+GLAD_API_CALL PFNGLWINDOWPOS2DPROC glad_glWindowPos2d;
+#define glWindowPos2d glad_glWindowPos2d
+GLAD_API_CALL PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv;
+#define glWindowPos2dv glad_glWindowPos2dv
+GLAD_API_CALL PFNGLWINDOWPOS2FPROC glad_glWindowPos2f;
+#define glWindowPos2f glad_glWindowPos2f
+GLAD_API_CALL PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv;
+#define glWindowPos2fv glad_glWindowPos2fv
+GLAD_API_CALL PFNGLWINDOWPOS2IPROC glad_glWindowPos2i;
+#define glWindowPos2i glad_glWindowPos2i
+GLAD_API_CALL PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv;
+#define glWindowPos2iv glad_glWindowPos2iv
+GLAD_API_CALL PFNGLWINDOWPOS2SPROC glad_glWindowPos2s;
+#define glWindowPos2s glad_glWindowPos2s
+GLAD_API_CALL PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv;
+#define glWindowPos2sv glad_glWindowPos2sv
+GLAD_API_CALL PFNGLWINDOWPOS3DPROC glad_glWindowPos3d;
+#define glWindowPos3d glad_glWindowPos3d
+GLAD_API_CALL PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv;
+#define glWindowPos3dv glad_glWindowPos3dv
+GLAD_API_CALL PFNGLWINDOWPOS3FPROC glad_glWindowPos3f;
+#define glWindowPos3f glad_glWindowPos3f
+GLAD_API_CALL PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv;
+#define glWindowPos3fv glad_glWindowPos3fv
+GLAD_API_CALL PFNGLWINDOWPOS3IPROC glad_glWindowPos3i;
+#define glWindowPos3i glad_glWindowPos3i
+GLAD_API_CALL PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv;
+#define glWindowPos3iv glad_glWindowPos3iv
+GLAD_API_CALL PFNGLWINDOWPOS3SPROC glad_glWindowPos3s;
+#define glWindowPos3s glad_glWindowPos3s
+GLAD_API_CALL PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv;
+#define glWindowPos3sv glad_glWindowPos3sv
+
+
+GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr);
+GLAD_API_CALL int gladLoadGL( GLADloadfunc load);
+
+
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/glfw/deps/glad_gl.c b/glfw/deps/glad_gl.c
--- a/glfw/deps/glad_gl.c
+++ b/glfw/deps/glad_gl.c
@@ -1,1791 +1,1791 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <glad/gl.h>
-
-#ifndef GLAD_IMPL_UTIL_C_
-#define GLAD_IMPL_UTIL_C_
-
-#ifdef _MSC_VER
-#define GLAD_IMPL_UTIL_SSCANF sscanf_s
-#else
-#define GLAD_IMPL_UTIL_SSCANF sscanf
-#endif
-
-#endif /* GLAD_IMPL_UTIL_C_ */
-
-
-int GLAD_GL_VERSION_1_0 = 0;
-int GLAD_GL_VERSION_1_1 = 0;
-int GLAD_GL_VERSION_1_2 = 0;
-int GLAD_GL_VERSION_1_3 = 0;
-int GLAD_GL_VERSION_1_4 = 0;
-int GLAD_GL_VERSION_1_5 = 0;
-int GLAD_GL_VERSION_2_0 = 0;
-int GLAD_GL_VERSION_2_1 = 0;
-int GLAD_GL_VERSION_3_0 = 0;
-int GLAD_GL_VERSION_3_1 = 0;
-int GLAD_GL_VERSION_3_2 = 0;
-int GLAD_GL_VERSION_3_3 = 0;
-int GLAD_GL_ARB_multisample = 0;
-int GLAD_GL_ARB_robustness = 0;
-int GLAD_GL_KHR_debug = 0;
-
-
-
-PFNGLACCUMPROC glad_glAccum = NULL;
-PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
-PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
-PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
-PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
-PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
-PFNGLBEGINPROC glad_glBegin = NULL;
-PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
-PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
-PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
-PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
-PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
-PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
-PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
-PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
-PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
-PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
-PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
-PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
-PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
-PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
-PFNGLBITMAPPROC glad_glBitmap = NULL;
-PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
-PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
-PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
-PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
-PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
-PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
-PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
-PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
-PFNGLCALLLISTPROC glad_glCallList = NULL;
-PFNGLCALLLISTSPROC glad_glCallLists = NULL;
-PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
-PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
-PFNGLCLEARPROC glad_glClear = NULL;
-PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
-PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
-PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
-PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
-PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
-PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
-PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
-PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
-PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
-PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
-PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
-PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
-PFNGLCOLOR3BPROC glad_glColor3b = NULL;
-PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
-PFNGLCOLOR3DPROC glad_glColor3d = NULL;
-PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
-PFNGLCOLOR3FPROC glad_glColor3f = NULL;
-PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
-PFNGLCOLOR3IPROC glad_glColor3i = NULL;
-PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
-PFNGLCOLOR3SPROC glad_glColor3s = NULL;
-PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
-PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
-PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
-PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
-PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
-PFNGLCOLOR3USPROC glad_glColor3us = NULL;
-PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
-PFNGLCOLOR4BPROC glad_glColor4b = NULL;
-PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
-PFNGLCOLOR4DPROC glad_glColor4d = NULL;
-PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
-PFNGLCOLOR4FPROC glad_glColor4f = NULL;
-PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
-PFNGLCOLOR4IPROC glad_glColor4i = NULL;
-PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
-PFNGLCOLOR4SPROC glad_glColor4s = NULL;
-PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
-PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
-PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
-PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
-PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
-PFNGLCOLOR4USPROC glad_glColor4us = NULL;
-PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
-PFNGLCOLORMASKPROC glad_glColorMask = NULL;
-PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
-PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
-PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
-PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
-PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
-PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
-PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
-PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
-PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
-PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
-PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
-PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
-PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
-PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
-PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
-PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
-PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
-PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
-PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
-PFNGLCULLFACEPROC glad_glCullFace = NULL;
-PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
-PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
-PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL;
-PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
-PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
-PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
-PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
-PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
-PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
-PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
-PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
-PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
-PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
-PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
-PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
-PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
-PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
-PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
-PFNGLDISABLEPROC glad_glDisable = NULL;
-PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
-PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
-PFNGLDISABLEIPROC glad_glDisablei = NULL;
-PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
-PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
-PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
-PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
-PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
-PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
-PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
-PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
-PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
-PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
-PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
-PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
-PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
-PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
-PFNGLENABLEPROC glad_glEnable = NULL;
-PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
-PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
-PFNGLENABLEIPROC glad_glEnablei = NULL;
-PFNGLENDPROC glad_glEnd = NULL;
-PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
-PFNGLENDLISTPROC glad_glEndList = NULL;
-PFNGLENDQUERYPROC glad_glEndQuery = NULL;
-PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
-PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
-PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
-PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
-PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
-PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
-PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
-PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
-PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
-PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
-PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
-PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
-PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
-PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
-PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
-PFNGLFINISHPROC glad_glFinish = NULL;
-PFNGLFLUSHPROC glad_glFlush = NULL;
-PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
-PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
-PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
-PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
-PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
-PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
-PFNGLFOGFPROC glad_glFogf = NULL;
-PFNGLFOGFVPROC glad_glFogfv = NULL;
-PFNGLFOGIPROC glad_glFogi = NULL;
-PFNGLFOGIVPROC glad_glFogiv = NULL;
-PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
-PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
-PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
-PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
-PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
-PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
-PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
-PFNGLFRUSTUMPROC glad_glFrustum = NULL;
-PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
-PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
-PFNGLGENLISTSPROC glad_glGenLists = NULL;
-PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
-PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
-PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
-PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
-PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
-PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
-PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
-PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
-PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
-PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
-PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
-PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
-PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
-PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
-PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
-PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
-PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
-PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
-PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
-PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
-PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
-PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
-PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
-PFNGLGETERRORPROC glad_glGetError = NULL;
-PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
-PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
-PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
-PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
-PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB = NULL;
-PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
-PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
-PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
-PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
-PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
-PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
-PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
-PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
-PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
-PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
-PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
-PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
-PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
-PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
-PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
-PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
-PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
-PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
-PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
-PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
-PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
-PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
-PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
-PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
-PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
-PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
-PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
-PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
-PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
-PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
-PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
-PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
-PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
-PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
-PFNGLGETSTRINGPROC glad_glGetString = NULL;
-PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
-PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
-PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
-PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
-PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
-PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
-PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
-PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
-PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
-PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
-PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
-PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
-PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
-PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
-PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
-PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
-PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
-PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
-PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
-PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
-PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
-PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
-PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
-PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
-PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
-PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
-PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
-PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB = NULL;
-PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB = NULL;
-PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB = NULL;
-PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB = NULL;
-PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB = NULL;
-PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB = NULL;
-PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB = NULL;
-PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB = NULL;
-PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB = NULL;
-PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB = NULL;
-PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB = NULL;
-PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB = NULL;
-PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB = NULL;
-PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB = NULL;
-PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB = NULL;
-PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB = NULL;
-PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB = NULL;
-PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB = NULL;
-PFNGLHINTPROC glad_glHint = NULL;
-PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
-PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
-PFNGLINDEXDPROC glad_glIndexd = NULL;
-PFNGLINDEXDVPROC glad_glIndexdv = NULL;
-PFNGLINDEXFPROC glad_glIndexf = NULL;
-PFNGLINDEXFVPROC glad_glIndexfv = NULL;
-PFNGLINDEXIPROC glad_glIndexi = NULL;
-PFNGLINDEXIVPROC glad_glIndexiv = NULL;
-PFNGLINDEXSPROC glad_glIndexs = NULL;
-PFNGLINDEXSVPROC glad_glIndexsv = NULL;
-PFNGLINDEXUBPROC glad_glIndexub = NULL;
-PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
-PFNGLINITNAMESPROC glad_glInitNames = NULL;
-PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
-PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
-PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
-PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
-PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
-PFNGLISLISTPROC glad_glIsList = NULL;
-PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
-PFNGLISQUERYPROC glad_glIsQuery = NULL;
-PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
-PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
-PFNGLISSHADERPROC glad_glIsShader = NULL;
-PFNGLISSYNCPROC glad_glIsSync = NULL;
-PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
-PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
-PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
-PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
-PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
-PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
-PFNGLLIGHTFPROC glad_glLightf = NULL;
-PFNGLLIGHTFVPROC glad_glLightfv = NULL;
-PFNGLLIGHTIPROC glad_glLighti = NULL;
-PFNGLLIGHTIVPROC glad_glLightiv = NULL;
-PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
-PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
-PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
-PFNGLLISTBASEPROC glad_glListBase = NULL;
-PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
-PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
-PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
-PFNGLLOADNAMEPROC glad_glLoadName = NULL;
-PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
-PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
-PFNGLLOGICOPPROC glad_glLogicOp = NULL;
-PFNGLMAP1DPROC glad_glMap1d = NULL;
-PFNGLMAP1FPROC glad_glMap1f = NULL;
-PFNGLMAP2DPROC glad_glMap2d = NULL;
-PFNGLMAP2FPROC glad_glMap2f = NULL;
-PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
-PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
-PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
-PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
-PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
-PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
-PFNGLMATERIALFPROC glad_glMaterialf = NULL;
-PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
-PFNGLMATERIALIPROC glad_glMateriali = NULL;
-PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
-PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
-PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
-PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
-PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
-PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
-PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
-PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
-PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
-PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
-PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
-PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
-PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
-PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
-PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
-PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
-PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
-PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
-PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
-PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
-PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
-PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
-PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
-PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
-PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
-PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
-PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
-PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
-PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
-PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
-PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
-PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
-PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
-PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
-PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
-PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
-PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
-PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
-PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
-PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
-PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
-PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
-PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
-PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
-PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
-PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
-PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
-PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
-PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
-PFNGLNEWLISTPROC glad_glNewList = NULL;
-PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
-PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
-PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
-PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
-PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
-PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
-PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
-PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
-PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
-PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
-PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
-PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
-PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
-PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
-PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL;
-PFNGLORTHOPROC glad_glOrtho = NULL;
-PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
-PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
-PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
-PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
-PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
-PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
-PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
-PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
-PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
-PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
-PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
-PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
-PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
-PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
-PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
-PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
-PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
-PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
-PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
-PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
-PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
-PFNGLPOPNAMEPROC glad_glPopName = NULL;
-PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
-PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
-PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
-PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
-PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
-PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL;
-PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
-PFNGLPUSHNAMEPROC glad_glPushName = NULL;
-PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
-PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
-PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
-PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
-PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
-PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
-PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
-PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
-PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
-PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
-PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
-PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
-PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
-PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
-PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
-PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
-PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
-PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
-PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
-PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
-PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
-PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
-PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
-PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
-PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
-PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
-PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
-PFNGLREADNPIXELSPROC glad_glReadnPixels = NULL;
-PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB = NULL;
-PFNGLRECTDPROC glad_glRectd = NULL;
-PFNGLRECTDVPROC glad_glRectdv = NULL;
-PFNGLRECTFPROC glad_glRectf = NULL;
-PFNGLRECTFVPROC glad_glRectfv = NULL;
-PFNGLRECTIPROC glad_glRecti = NULL;
-PFNGLRECTIVPROC glad_glRectiv = NULL;
-PFNGLRECTSPROC glad_glRects = NULL;
-PFNGLRECTSVPROC glad_glRectsv = NULL;
-PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
-PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
-PFNGLROTATEDPROC glad_glRotated = NULL;
-PFNGLROTATEFPROC glad_glRotatef = NULL;
-PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
-PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB = NULL;
-PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
-PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
-PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
-PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
-PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
-PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
-PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
-PFNGLSCALEDPROC glad_glScaled = NULL;
-PFNGLSCALEFPROC glad_glScalef = NULL;
-PFNGLSCISSORPROC glad_glScissor = NULL;
-PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
-PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
-PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
-PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
-PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
-PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
-PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
-PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
-PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
-PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
-PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
-PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
-PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
-PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
-PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
-PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
-PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
-PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
-PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
-PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
-PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
-PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
-PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
-PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
-PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
-PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
-PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
-PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
-PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
-PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
-PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
-PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
-PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
-PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
-PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
-PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
-PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
-PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
-PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
-PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
-PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
-PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
-PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
-PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
-PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
-PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
-PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
-PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
-PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
-PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
-PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
-PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
-PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
-PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
-PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
-PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
-PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
-PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
-PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
-PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
-PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
-PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
-PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
-PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
-PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
-PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
-PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
-PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
-PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
-PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
-PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
-PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
-PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
-PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
-PFNGLTEXGENDPROC glad_glTexGend = NULL;
-PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
-PFNGLTEXGENFPROC glad_glTexGenf = NULL;
-PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
-PFNGLTEXGENIPROC glad_glTexGeni = NULL;
-PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
-PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
-PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
-PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
-PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
-PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
-PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
-PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
-PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
-PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
-PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
-PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
-PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
-PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
-PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
-PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
-PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
-PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
-PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
-PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
-PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
-PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
-PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
-PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
-PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
-PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
-PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
-PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
-PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
-PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
-PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
-PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
-PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
-PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
-PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
-PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
-PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
-PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
-PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
-PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
-PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
-PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
-PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
-PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
-PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
-PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
-PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
-PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
-PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
-PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
-PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
-PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
-PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
-PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
-PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
-PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
-PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
-PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
-PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
-PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
-PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
-PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
-PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
-PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
-PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
-PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
-PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
-PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
-PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
-PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
-PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
-PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
-PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
-PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
-PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
-PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
-PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
-PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
-PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
-PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
-PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
-PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
-PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
-PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
-PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
-PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
-PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
-PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
-PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
-PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
-PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
-PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
-PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
-PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
-PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
-PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
-PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
-PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
-PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
-PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
-PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
-PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
-PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
-PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
-PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
-PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
-PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
-PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
-PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
-PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
-PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
-PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
-PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
-PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
-PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
-PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
-PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
-PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
-PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
-PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
-PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
-PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
-PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
-PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
-PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
-PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
-PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
-PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
-PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
-PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
-PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
-PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
-PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
-PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
-PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
-PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
-PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
-PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
-PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
-PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
-PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
-PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
-PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
-PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
-PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
-PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
-PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
-PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
-PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
-PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
-PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
-PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
-PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
-PFNGLVIEWPORTPROC glad_glViewport = NULL;
-PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
-PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
-PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
-PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
-PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
-PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
-PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
-PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
-PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
-PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
-PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
-PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
-PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
-PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
-PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
-PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
-PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
-
-
-static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_0) return;
-    glAccum = (PFNGLACCUMPROC) load("glAccum", userptr);
-    glAlphaFunc = (PFNGLALPHAFUNCPROC) load("glAlphaFunc", userptr);
-    glBegin = (PFNGLBEGINPROC) load("glBegin", userptr);
-    glBitmap = (PFNGLBITMAPPROC) load("glBitmap", userptr);
-    glBlendFunc = (PFNGLBLENDFUNCPROC) load("glBlendFunc", userptr);
-    glCallList = (PFNGLCALLLISTPROC) load("glCallList", userptr);
-    glCallLists = (PFNGLCALLLISTSPROC) load("glCallLists", userptr);
-    glClear = (PFNGLCLEARPROC) load("glClear", userptr);
-    glClearAccum = (PFNGLCLEARACCUMPROC) load("glClearAccum", userptr);
-    glClearColor = (PFNGLCLEARCOLORPROC) load("glClearColor", userptr);
-    glClearDepth = (PFNGLCLEARDEPTHPROC) load("glClearDepth", userptr);
-    glClearIndex = (PFNGLCLEARINDEXPROC) load("glClearIndex", userptr);
-    glClearStencil = (PFNGLCLEARSTENCILPROC) load("glClearStencil", userptr);
-    glClipPlane = (PFNGLCLIPPLANEPROC) load("glClipPlane", userptr);
-    glColor3b = (PFNGLCOLOR3BPROC) load("glColor3b", userptr);
-    glColor3bv = (PFNGLCOLOR3BVPROC) load("glColor3bv", userptr);
-    glColor3d = (PFNGLCOLOR3DPROC) load("glColor3d", userptr);
-    glColor3dv = (PFNGLCOLOR3DVPROC) load("glColor3dv", userptr);
-    glColor3f = (PFNGLCOLOR3FPROC) load("glColor3f", userptr);
-    glColor3fv = (PFNGLCOLOR3FVPROC) load("glColor3fv", userptr);
-    glColor3i = (PFNGLCOLOR3IPROC) load("glColor3i", userptr);
-    glColor3iv = (PFNGLCOLOR3IVPROC) load("glColor3iv", userptr);
-    glColor3s = (PFNGLCOLOR3SPROC) load("glColor3s", userptr);
-    glColor3sv = (PFNGLCOLOR3SVPROC) load("glColor3sv", userptr);
-    glColor3ub = (PFNGLCOLOR3UBPROC) load("glColor3ub", userptr);
-    glColor3ubv = (PFNGLCOLOR3UBVPROC) load("glColor3ubv", userptr);
-    glColor3ui = (PFNGLCOLOR3UIPROC) load("glColor3ui", userptr);
-    glColor3uiv = (PFNGLCOLOR3UIVPROC) load("glColor3uiv", userptr);
-    glColor3us = (PFNGLCOLOR3USPROC) load("glColor3us", userptr);
-    glColor3usv = (PFNGLCOLOR3USVPROC) load("glColor3usv", userptr);
-    glColor4b = (PFNGLCOLOR4BPROC) load("glColor4b", userptr);
-    glColor4bv = (PFNGLCOLOR4BVPROC) load("glColor4bv", userptr);
-    glColor4d = (PFNGLCOLOR4DPROC) load("glColor4d", userptr);
-    glColor4dv = (PFNGLCOLOR4DVPROC) load("glColor4dv", userptr);
-    glColor4f = (PFNGLCOLOR4FPROC) load("glColor4f", userptr);
-    glColor4fv = (PFNGLCOLOR4FVPROC) load("glColor4fv", userptr);
-    glColor4i = (PFNGLCOLOR4IPROC) load("glColor4i", userptr);
-    glColor4iv = (PFNGLCOLOR4IVPROC) load("glColor4iv", userptr);
-    glColor4s = (PFNGLCOLOR4SPROC) load("glColor4s", userptr);
-    glColor4sv = (PFNGLCOLOR4SVPROC) load("glColor4sv", userptr);
-    glColor4ub = (PFNGLCOLOR4UBPROC) load("glColor4ub", userptr);
-    glColor4ubv = (PFNGLCOLOR4UBVPROC) load("glColor4ubv", userptr);
-    glColor4ui = (PFNGLCOLOR4UIPROC) load("glColor4ui", userptr);
-    glColor4uiv = (PFNGLCOLOR4UIVPROC) load("glColor4uiv", userptr);
-    glColor4us = (PFNGLCOLOR4USPROC) load("glColor4us", userptr);
-    glColor4usv = (PFNGLCOLOR4USVPROC) load("glColor4usv", userptr);
-    glColorMask = (PFNGLCOLORMASKPROC) load("glColorMask", userptr);
-    glColorMaterial = (PFNGLCOLORMATERIALPROC) load("glColorMaterial", userptr);
-    glCopyPixels = (PFNGLCOPYPIXELSPROC) load("glCopyPixels", userptr);
-    glCullFace = (PFNGLCULLFACEPROC) load("glCullFace", userptr);
-    glDeleteLists = (PFNGLDELETELISTSPROC) load("glDeleteLists", userptr);
-    glDepthFunc = (PFNGLDEPTHFUNCPROC) load("glDepthFunc", userptr);
-    glDepthMask = (PFNGLDEPTHMASKPROC) load("glDepthMask", userptr);
-    glDepthRange = (PFNGLDEPTHRANGEPROC) load("glDepthRange", userptr);
-    glDisable = (PFNGLDISABLEPROC) load("glDisable", userptr);
-    glDrawBuffer = (PFNGLDRAWBUFFERPROC) load("glDrawBuffer", userptr);
-    glDrawPixels = (PFNGLDRAWPIXELSPROC) load("glDrawPixels", userptr);
-    glEdgeFlag = (PFNGLEDGEFLAGPROC) load("glEdgeFlag", userptr);
-    glEdgeFlagv = (PFNGLEDGEFLAGVPROC) load("glEdgeFlagv", userptr);
-    glEnable = (PFNGLENABLEPROC) load("glEnable", userptr);
-    glEnd = (PFNGLENDPROC) load("glEnd", userptr);
-    glEndList = (PFNGLENDLISTPROC) load("glEndList", userptr);
-    glEvalCoord1d = (PFNGLEVALCOORD1DPROC) load("glEvalCoord1d", userptr);
-    glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC) load("glEvalCoord1dv", userptr);
-    glEvalCoord1f = (PFNGLEVALCOORD1FPROC) load("glEvalCoord1f", userptr);
-    glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC) load("glEvalCoord1fv", userptr);
-    glEvalCoord2d = (PFNGLEVALCOORD2DPROC) load("glEvalCoord2d", userptr);
-    glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC) load("glEvalCoord2dv", userptr);
-    glEvalCoord2f = (PFNGLEVALCOORD2FPROC) load("glEvalCoord2f", userptr);
-    glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC) load("glEvalCoord2fv", userptr);
-    glEvalMesh1 = (PFNGLEVALMESH1PROC) load("glEvalMesh1", userptr);
-    glEvalMesh2 = (PFNGLEVALMESH2PROC) load("glEvalMesh2", userptr);
-    glEvalPoint1 = (PFNGLEVALPOINT1PROC) load("glEvalPoint1", userptr);
-    glEvalPoint2 = (PFNGLEVALPOINT2PROC) load("glEvalPoint2", userptr);
-    glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) load("glFeedbackBuffer", userptr);
-    glFinish = (PFNGLFINISHPROC) load("glFinish", userptr);
-    glFlush = (PFNGLFLUSHPROC) load("glFlush", userptr);
-    glFogf = (PFNGLFOGFPROC) load("glFogf", userptr);
-    glFogfv = (PFNGLFOGFVPROC) load("glFogfv", userptr);
-    glFogi = (PFNGLFOGIPROC) load("glFogi", userptr);
-    glFogiv = (PFNGLFOGIVPROC) load("glFogiv", userptr);
-    glFrontFace = (PFNGLFRONTFACEPROC) load("glFrontFace", userptr);
-    glFrustum = (PFNGLFRUSTUMPROC) load("glFrustum", userptr);
-    glGenLists = (PFNGLGENLISTSPROC) load("glGenLists", userptr);
-    glGetBooleanv = (PFNGLGETBOOLEANVPROC) load("glGetBooleanv", userptr);
-    glGetClipPlane = (PFNGLGETCLIPPLANEPROC) load("glGetClipPlane", userptr);
-    glGetDoublev = (PFNGLGETDOUBLEVPROC) load("glGetDoublev", userptr);
-    glGetError = (PFNGLGETERRORPROC) load("glGetError", userptr);
-    glGetFloatv = (PFNGLGETFLOATVPROC) load("glGetFloatv", userptr);
-    glGetIntegerv = (PFNGLGETINTEGERVPROC) load("glGetIntegerv", userptr);
-    glGetLightfv = (PFNGLGETLIGHTFVPROC) load("glGetLightfv", userptr);
-    glGetLightiv = (PFNGLGETLIGHTIVPROC) load("glGetLightiv", userptr);
-    glGetMapdv = (PFNGLGETMAPDVPROC) load("glGetMapdv", userptr);
-    glGetMapfv = (PFNGLGETMAPFVPROC) load("glGetMapfv", userptr);
-    glGetMapiv = (PFNGLGETMAPIVPROC) load("glGetMapiv", userptr);
-    glGetMaterialfv = (PFNGLGETMATERIALFVPROC) load("glGetMaterialfv", userptr);
-    glGetMaterialiv = (PFNGLGETMATERIALIVPROC) load("glGetMaterialiv", userptr);
-    glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC) load("glGetPixelMapfv", userptr);
-    glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC) load("glGetPixelMapuiv", userptr);
-    glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC) load("glGetPixelMapusv", userptr);
-    glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC) load("glGetPolygonStipple", userptr);
-    glGetString = (PFNGLGETSTRINGPROC) load("glGetString", userptr);
-    glGetTexEnvfv = (PFNGLGETTEXENVFVPROC) load("glGetTexEnvfv", userptr);
-    glGetTexEnviv = (PFNGLGETTEXENVIVPROC) load("glGetTexEnviv", userptr);
-    glGetTexGendv = (PFNGLGETTEXGENDVPROC) load("glGetTexGendv", userptr);
-    glGetTexGenfv = (PFNGLGETTEXGENFVPROC) load("glGetTexGenfv", userptr);
-    glGetTexGeniv = (PFNGLGETTEXGENIVPROC) load("glGetTexGeniv", userptr);
-    glGetTexImage = (PFNGLGETTEXIMAGEPROC) load("glGetTexImage", userptr);
-    glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load("glGetTexLevelParameterfv", userptr);
-    glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load("glGetTexLevelParameteriv", userptr);
-    glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load("glGetTexParameterfv", userptr);
-    glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load("glGetTexParameteriv", userptr);
-    glHint = (PFNGLHINTPROC) load("glHint", userptr);
-    glIndexMask = (PFNGLINDEXMASKPROC) load("glIndexMask", userptr);
-    glIndexd = (PFNGLINDEXDPROC) load("glIndexd", userptr);
-    glIndexdv = (PFNGLINDEXDVPROC) load("glIndexdv", userptr);
-    glIndexf = (PFNGLINDEXFPROC) load("glIndexf", userptr);
-    glIndexfv = (PFNGLINDEXFVPROC) load("glIndexfv", userptr);
-    glIndexi = (PFNGLINDEXIPROC) load("glIndexi", userptr);
-    glIndexiv = (PFNGLINDEXIVPROC) load("glIndexiv", userptr);
-    glIndexs = (PFNGLINDEXSPROC) load("glIndexs", userptr);
-    glIndexsv = (PFNGLINDEXSVPROC) load("glIndexsv", userptr);
-    glInitNames = (PFNGLINITNAMESPROC) load("glInitNames", userptr);
-    glIsEnabled = (PFNGLISENABLEDPROC) load("glIsEnabled", userptr);
-    glIsList = (PFNGLISLISTPROC) load("glIsList", userptr);
-    glLightModelf = (PFNGLLIGHTMODELFPROC) load("glLightModelf", userptr);
-    glLightModelfv = (PFNGLLIGHTMODELFVPROC) load("glLightModelfv", userptr);
-    glLightModeli = (PFNGLLIGHTMODELIPROC) load("glLightModeli", userptr);
-    glLightModeliv = (PFNGLLIGHTMODELIVPROC) load("glLightModeliv", userptr);
-    glLightf = (PFNGLLIGHTFPROC) load("glLightf", userptr);
-    glLightfv = (PFNGLLIGHTFVPROC) load("glLightfv", userptr);
-    glLighti = (PFNGLLIGHTIPROC) load("glLighti", userptr);
-    glLightiv = (PFNGLLIGHTIVPROC) load("glLightiv", userptr);
-    glLineStipple = (PFNGLLINESTIPPLEPROC) load("glLineStipple", userptr);
-    glLineWidth = (PFNGLLINEWIDTHPROC) load("glLineWidth", userptr);
-    glListBase = (PFNGLLISTBASEPROC) load("glListBase", userptr);
-    glLoadIdentity = (PFNGLLOADIDENTITYPROC) load("glLoadIdentity", userptr);
-    glLoadMatrixd = (PFNGLLOADMATRIXDPROC) load("glLoadMatrixd", userptr);
-    glLoadMatrixf = (PFNGLLOADMATRIXFPROC) load("glLoadMatrixf", userptr);
-    glLoadName = (PFNGLLOADNAMEPROC) load("glLoadName", userptr);
-    glLogicOp = (PFNGLLOGICOPPROC) load("glLogicOp", userptr);
-    glMap1d = (PFNGLMAP1DPROC) load("glMap1d", userptr);
-    glMap1f = (PFNGLMAP1FPROC) load("glMap1f", userptr);
-    glMap2d = (PFNGLMAP2DPROC) load("glMap2d", userptr);
-    glMap2f = (PFNGLMAP2FPROC) load("glMap2f", userptr);
-    glMapGrid1d = (PFNGLMAPGRID1DPROC) load("glMapGrid1d", userptr);
-    glMapGrid1f = (PFNGLMAPGRID1FPROC) load("glMapGrid1f", userptr);
-    glMapGrid2d = (PFNGLMAPGRID2DPROC) load("glMapGrid2d", userptr);
-    glMapGrid2f = (PFNGLMAPGRID2FPROC) load("glMapGrid2f", userptr);
-    glMaterialf = (PFNGLMATERIALFPROC) load("glMaterialf", userptr);
-    glMaterialfv = (PFNGLMATERIALFVPROC) load("glMaterialfv", userptr);
-    glMateriali = (PFNGLMATERIALIPROC) load("glMateriali", userptr);
-    glMaterialiv = (PFNGLMATERIALIVPROC) load("glMaterialiv", userptr);
-    glMatrixMode = (PFNGLMATRIXMODEPROC) load("glMatrixMode", userptr);
-    glMultMatrixd = (PFNGLMULTMATRIXDPROC) load("glMultMatrixd", userptr);
-    glMultMatrixf = (PFNGLMULTMATRIXFPROC) load("glMultMatrixf", userptr);
-    glNewList = (PFNGLNEWLISTPROC) load("glNewList", userptr);
-    glNormal3b = (PFNGLNORMAL3BPROC) load("glNormal3b", userptr);
-    glNormal3bv = (PFNGLNORMAL3BVPROC) load("glNormal3bv", userptr);
-    glNormal3d = (PFNGLNORMAL3DPROC) load("glNormal3d", userptr);
-    glNormal3dv = (PFNGLNORMAL3DVPROC) load("glNormal3dv", userptr);
-    glNormal3f = (PFNGLNORMAL3FPROC) load("glNormal3f", userptr);
-    glNormal3fv = (PFNGLNORMAL3FVPROC) load("glNormal3fv", userptr);
-    glNormal3i = (PFNGLNORMAL3IPROC) load("glNormal3i", userptr);
-    glNormal3iv = (PFNGLNORMAL3IVPROC) load("glNormal3iv", userptr);
-    glNormal3s = (PFNGLNORMAL3SPROC) load("glNormal3s", userptr);
-    glNormal3sv = (PFNGLNORMAL3SVPROC) load("glNormal3sv", userptr);
-    glOrtho = (PFNGLORTHOPROC) load("glOrtho", userptr);
-    glPassThrough = (PFNGLPASSTHROUGHPROC) load("glPassThrough", userptr);
-    glPixelMapfv = (PFNGLPIXELMAPFVPROC) load("glPixelMapfv", userptr);
-    glPixelMapuiv = (PFNGLPIXELMAPUIVPROC) load("glPixelMapuiv", userptr);
-    glPixelMapusv = (PFNGLPIXELMAPUSVPROC) load("glPixelMapusv", userptr);
-    glPixelStoref = (PFNGLPIXELSTOREFPROC) load("glPixelStoref", userptr);
-    glPixelStorei = (PFNGLPIXELSTOREIPROC) load("glPixelStorei", userptr);
-    glPixelTransferf = (PFNGLPIXELTRANSFERFPROC) load("glPixelTransferf", userptr);
-    glPixelTransferi = (PFNGLPIXELTRANSFERIPROC) load("glPixelTransferi", userptr);
-    glPixelZoom = (PFNGLPIXELZOOMPROC) load("glPixelZoom", userptr);
-    glPointSize = (PFNGLPOINTSIZEPROC) load("glPointSize", userptr);
-    glPolygonMode = (PFNGLPOLYGONMODEPROC) load("glPolygonMode", userptr);
-    glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC) load("glPolygonStipple", userptr);
-    glPopAttrib = (PFNGLPOPATTRIBPROC) load("glPopAttrib", userptr);
-    glPopMatrix = (PFNGLPOPMATRIXPROC) load("glPopMatrix", userptr);
-    glPopName = (PFNGLPOPNAMEPROC) load("glPopName", userptr);
-    glPushAttrib = (PFNGLPUSHATTRIBPROC) load("glPushAttrib", userptr);
-    glPushMatrix = (PFNGLPUSHMATRIXPROC) load("glPushMatrix", userptr);
-    glPushName = (PFNGLPUSHNAMEPROC) load("glPushName", userptr);
-    glRasterPos2d = (PFNGLRASTERPOS2DPROC) load("glRasterPos2d", userptr);
-    glRasterPos2dv = (PFNGLRASTERPOS2DVPROC) load("glRasterPos2dv", userptr);
-    glRasterPos2f = (PFNGLRASTERPOS2FPROC) load("glRasterPos2f", userptr);
-    glRasterPos2fv = (PFNGLRASTERPOS2FVPROC) load("glRasterPos2fv", userptr);
-    glRasterPos2i = (PFNGLRASTERPOS2IPROC) load("glRasterPos2i", userptr);
-    glRasterPos2iv = (PFNGLRASTERPOS2IVPROC) load("glRasterPos2iv", userptr);
-    glRasterPos2s = (PFNGLRASTERPOS2SPROC) load("glRasterPos2s", userptr);
-    glRasterPos2sv = (PFNGLRASTERPOS2SVPROC) load("glRasterPos2sv", userptr);
-    glRasterPos3d = (PFNGLRASTERPOS3DPROC) load("glRasterPos3d", userptr);
-    glRasterPos3dv = (PFNGLRASTERPOS3DVPROC) load("glRasterPos3dv", userptr);
-    glRasterPos3f = (PFNGLRASTERPOS3FPROC) load("glRasterPos3f", userptr);
-    glRasterPos3fv = (PFNGLRASTERPOS3FVPROC) load("glRasterPos3fv", userptr);
-    glRasterPos3i = (PFNGLRASTERPOS3IPROC) load("glRasterPos3i", userptr);
-    glRasterPos3iv = (PFNGLRASTERPOS3IVPROC) load("glRasterPos3iv", userptr);
-    glRasterPos3s = (PFNGLRASTERPOS3SPROC) load("glRasterPos3s", userptr);
-    glRasterPos3sv = (PFNGLRASTERPOS3SVPROC) load("glRasterPos3sv", userptr);
-    glRasterPos4d = (PFNGLRASTERPOS4DPROC) load("glRasterPos4d", userptr);
-    glRasterPos4dv = (PFNGLRASTERPOS4DVPROC) load("glRasterPos4dv", userptr);
-    glRasterPos4f = (PFNGLRASTERPOS4FPROC) load("glRasterPos4f", userptr);
-    glRasterPos4fv = (PFNGLRASTERPOS4FVPROC) load("glRasterPos4fv", userptr);
-    glRasterPos4i = (PFNGLRASTERPOS4IPROC) load("glRasterPos4i", userptr);
-    glRasterPos4iv = (PFNGLRASTERPOS4IVPROC) load("glRasterPos4iv", userptr);
-    glRasterPos4s = (PFNGLRASTERPOS4SPROC) load("glRasterPos4s", userptr);
-    glRasterPos4sv = (PFNGLRASTERPOS4SVPROC) load("glRasterPos4sv", userptr);
-    glReadBuffer = (PFNGLREADBUFFERPROC) load("glReadBuffer", userptr);
-    glReadPixels = (PFNGLREADPIXELSPROC) load("glReadPixels", userptr);
-    glRectd = (PFNGLRECTDPROC) load("glRectd", userptr);
-    glRectdv = (PFNGLRECTDVPROC) load("glRectdv", userptr);
-    glRectf = (PFNGLRECTFPROC) load("glRectf", userptr);
-    glRectfv = (PFNGLRECTFVPROC) load("glRectfv", userptr);
-    glRecti = (PFNGLRECTIPROC) load("glRecti", userptr);
-    glRectiv = (PFNGLRECTIVPROC) load("glRectiv", userptr);
-    glRects = (PFNGLRECTSPROC) load("glRects", userptr);
-    glRectsv = (PFNGLRECTSVPROC) load("glRectsv", userptr);
-    glRenderMode = (PFNGLRENDERMODEPROC) load("glRenderMode", userptr);
-    glRotated = (PFNGLROTATEDPROC) load("glRotated", userptr);
-    glRotatef = (PFNGLROTATEFPROC) load("glRotatef", userptr);
-    glScaled = (PFNGLSCALEDPROC) load("glScaled", userptr);
-    glScalef = (PFNGLSCALEFPROC) load("glScalef", userptr);
-    glScissor = (PFNGLSCISSORPROC) load("glScissor", userptr);
-    glSelectBuffer = (PFNGLSELECTBUFFERPROC) load("glSelectBuffer", userptr);
-    glShadeModel = (PFNGLSHADEMODELPROC) load("glShadeModel", userptr);
-    glStencilFunc = (PFNGLSTENCILFUNCPROC) load("glStencilFunc", userptr);
-    glStencilMask = (PFNGLSTENCILMASKPROC) load("glStencilMask", userptr);
-    glStencilOp = (PFNGLSTENCILOPPROC) load("glStencilOp", userptr);
-    glTexCoord1d = (PFNGLTEXCOORD1DPROC) load("glTexCoord1d", userptr);
-    glTexCoord1dv = (PFNGLTEXCOORD1DVPROC) load("glTexCoord1dv", userptr);
-    glTexCoord1f = (PFNGLTEXCOORD1FPROC) load("glTexCoord1f", userptr);
-    glTexCoord1fv = (PFNGLTEXCOORD1FVPROC) load("glTexCoord1fv", userptr);
-    glTexCoord1i = (PFNGLTEXCOORD1IPROC) load("glTexCoord1i", userptr);
-    glTexCoord1iv = (PFNGLTEXCOORD1IVPROC) load("glTexCoord1iv", userptr);
-    glTexCoord1s = (PFNGLTEXCOORD1SPROC) load("glTexCoord1s", userptr);
-    glTexCoord1sv = (PFNGLTEXCOORD1SVPROC) load("glTexCoord1sv", userptr);
-    glTexCoord2d = (PFNGLTEXCOORD2DPROC) load("glTexCoord2d", userptr);
-    glTexCoord2dv = (PFNGLTEXCOORD2DVPROC) load("glTexCoord2dv", userptr);
-    glTexCoord2f = (PFNGLTEXCOORD2FPROC) load("glTexCoord2f", userptr);
-    glTexCoord2fv = (PFNGLTEXCOORD2FVPROC) load("glTexCoord2fv", userptr);
-    glTexCoord2i = (PFNGLTEXCOORD2IPROC) load("glTexCoord2i", userptr);
-    glTexCoord2iv = (PFNGLTEXCOORD2IVPROC) load("glTexCoord2iv", userptr);
-    glTexCoord2s = (PFNGLTEXCOORD2SPROC) load("glTexCoord2s", userptr);
-    glTexCoord2sv = (PFNGLTEXCOORD2SVPROC) load("glTexCoord2sv", userptr);
-    glTexCoord3d = (PFNGLTEXCOORD3DPROC) load("glTexCoord3d", userptr);
-    glTexCoord3dv = (PFNGLTEXCOORD3DVPROC) load("glTexCoord3dv", userptr);
-    glTexCoord3f = (PFNGLTEXCOORD3FPROC) load("glTexCoord3f", userptr);
-    glTexCoord3fv = (PFNGLTEXCOORD3FVPROC) load("glTexCoord3fv", userptr);
-    glTexCoord3i = (PFNGLTEXCOORD3IPROC) load("glTexCoord3i", userptr);
-    glTexCoord3iv = (PFNGLTEXCOORD3IVPROC) load("glTexCoord3iv", userptr);
-    glTexCoord3s = (PFNGLTEXCOORD3SPROC) load("glTexCoord3s", userptr);
-    glTexCoord3sv = (PFNGLTEXCOORD3SVPROC) load("glTexCoord3sv", userptr);
-    glTexCoord4d = (PFNGLTEXCOORD4DPROC) load("glTexCoord4d", userptr);
-    glTexCoord4dv = (PFNGLTEXCOORD4DVPROC) load("glTexCoord4dv", userptr);
-    glTexCoord4f = (PFNGLTEXCOORD4FPROC) load("glTexCoord4f", userptr);
-    glTexCoord4fv = (PFNGLTEXCOORD4FVPROC) load("glTexCoord4fv", userptr);
-    glTexCoord4i = (PFNGLTEXCOORD4IPROC) load("glTexCoord4i", userptr);
-    glTexCoord4iv = (PFNGLTEXCOORD4IVPROC) load("glTexCoord4iv", userptr);
-    glTexCoord4s = (PFNGLTEXCOORD4SPROC) load("glTexCoord4s", userptr);
-    glTexCoord4sv = (PFNGLTEXCOORD4SVPROC) load("glTexCoord4sv", userptr);
-    glTexEnvf = (PFNGLTEXENVFPROC) load("glTexEnvf", userptr);
-    glTexEnvfv = (PFNGLTEXENVFVPROC) load("glTexEnvfv", userptr);
-    glTexEnvi = (PFNGLTEXENVIPROC) load("glTexEnvi", userptr);
-    glTexEnviv = (PFNGLTEXENVIVPROC) load("glTexEnviv", userptr);
-    glTexGend = (PFNGLTEXGENDPROC) load("glTexGend", userptr);
-    glTexGendv = (PFNGLTEXGENDVPROC) load("glTexGendv", userptr);
-    glTexGenf = (PFNGLTEXGENFPROC) load("glTexGenf", userptr);
-    glTexGenfv = (PFNGLTEXGENFVPROC) load("glTexGenfv", userptr);
-    glTexGeni = (PFNGLTEXGENIPROC) load("glTexGeni", userptr);
-    glTexGeniv = (PFNGLTEXGENIVPROC) load("glTexGeniv", userptr);
-    glTexImage1D = (PFNGLTEXIMAGE1DPROC) load("glTexImage1D", userptr);
-    glTexImage2D = (PFNGLTEXIMAGE2DPROC) load("glTexImage2D", userptr);
-    glTexParameterf = (PFNGLTEXPARAMETERFPROC) load("glTexParameterf", userptr);
-    glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load("glTexParameterfv", userptr);
-    glTexParameteri = (PFNGLTEXPARAMETERIPROC) load("glTexParameteri", userptr);
-    glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load("glTexParameteriv", userptr);
-    glTranslated = (PFNGLTRANSLATEDPROC) load("glTranslated", userptr);
-    glTranslatef = (PFNGLTRANSLATEFPROC) load("glTranslatef", userptr);
-    glVertex2d = (PFNGLVERTEX2DPROC) load("glVertex2d", userptr);
-    glVertex2dv = (PFNGLVERTEX2DVPROC) load("glVertex2dv", userptr);
-    glVertex2f = (PFNGLVERTEX2FPROC) load("glVertex2f", userptr);
-    glVertex2fv = (PFNGLVERTEX2FVPROC) load("glVertex2fv", userptr);
-    glVertex2i = (PFNGLVERTEX2IPROC) load("glVertex2i", userptr);
-    glVertex2iv = (PFNGLVERTEX2IVPROC) load("glVertex2iv", userptr);
-    glVertex2s = (PFNGLVERTEX2SPROC) load("glVertex2s", userptr);
-    glVertex2sv = (PFNGLVERTEX2SVPROC) load("glVertex2sv", userptr);
-    glVertex3d = (PFNGLVERTEX3DPROC) load("glVertex3d", userptr);
-    glVertex3dv = (PFNGLVERTEX3DVPROC) load("glVertex3dv", userptr);
-    glVertex3f = (PFNGLVERTEX3FPROC) load("glVertex3f", userptr);
-    glVertex3fv = (PFNGLVERTEX3FVPROC) load("glVertex3fv", userptr);
-    glVertex3i = (PFNGLVERTEX3IPROC) load("glVertex3i", userptr);
-    glVertex3iv = (PFNGLVERTEX3IVPROC) load("glVertex3iv", userptr);
-    glVertex3s = (PFNGLVERTEX3SPROC) load("glVertex3s", userptr);
-    glVertex3sv = (PFNGLVERTEX3SVPROC) load("glVertex3sv", userptr);
-    glVertex4d = (PFNGLVERTEX4DPROC) load("glVertex4d", userptr);
-    glVertex4dv = (PFNGLVERTEX4DVPROC) load("glVertex4dv", userptr);
-    glVertex4f = (PFNGLVERTEX4FPROC) load("glVertex4f", userptr);
-    glVertex4fv = (PFNGLVERTEX4FVPROC) load("glVertex4fv", userptr);
-    glVertex4i = (PFNGLVERTEX4IPROC) load("glVertex4i", userptr);
-    glVertex4iv = (PFNGLVERTEX4IVPROC) load("glVertex4iv", userptr);
-    glVertex4s = (PFNGLVERTEX4SPROC) load("glVertex4s", userptr);
-    glVertex4sv = (PFNGLVERTEX4SVPROC) load("glVertex4sv", userptr);
-    glViewport = (PFNGLVIEWPORTPROC) load("glViewport", userptr);
-}
-static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_1) return;
-    glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC) load("glAreTexturesResident", userptr);
-    glArrayElement = (PFNGLARRAYELEMENTPROC) load("glArrayElement", userptr);
-    glBindTexture = (PFNGLBINDTEXTUREPROC) load("glBindTexture", userptr);
-    glColorPointer = (PFNGLCOLORPOINTERPROC) load("glColorPointer", userptr);
-    glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load("glCopyTexImage1D", userptr);
-    glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load("glCopyTexImage2D", userptr);
-    glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load("glCopyTexSubImage1D", userptr);
-    glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load("glCopyTexSubImage2D", userptr);
-    glDeleteTextures = (PFNGLDELETETEXTURESPROC) load("glDeleteTextures", userptr);
-    glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC) load("glDisableClientState", userptr);
-    glDrawArrays = (PFNGLDRAWARRAYSPROC) load("glDrawArrays", userptr);
-    glDrawElements = (PFNGLDRAWELEMENTSPROC) load("glDrawElements", userptr);
-    glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC) load("glEdgeFlagPointer", userptr);
-    glEnableClientState = (PFNGLENABLECLIENTSTATEPROC) load("glEnableClientState", userptr);
-    glGenTextures = (PFNGLGENTEXTURESPROC) load("glGenTextures", userptr);
-    glGetPointerv = (PFNGLGETPOINTERVPROC) load("glGetPointerv", userptr);
-    glIndexPointer = (PFNGLINDEXPOINTERPROC) load("glIndexPointer", userptr);
-    glIndexub = (PFNGLINDEXUBPROC) load("glIndexub", userptr);
-    glIndexubv = (PFNGLINDEXUBVPROC) load("glIndexubv", userptr);
-    glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC) load("glInterleavedArrays", userptr);
-    glIsTexture = (PFNGLISTEXTUREPROC) load("glIsTexture", userptr);
-    glNormalPointer = (PFNGLNORMALPOINTERPROC) load("glNormalPointer", userptr);
-    glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load("glPolygonOffset", userptr);
-    glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC) load("glPopClientAttrib", userptr);
-    glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC) load("glPrioritizeTextures", userptr);
-    glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC) load("glPushClientAttrib", userptr);
-    glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC) load("glTexCoordPointer", userptr);
-    glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load("glTexSubImage1D", userptr);
-    glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load("glTexSubImage2D", userptr);
-    glVertexPointer = (PFNGLVERTEXPOINTERPROC) load("glVertexPointer", userptr);
-}
-static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_2) return;
-    glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load("glCopyTexSubImage3D", userptr);
-    glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load("glDrawRangeElements", userptr);
-    glTexImage3D = (PFNGLTEXIMAGE3DPROC) load("glTexImage3D", userptr);
-    glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load("glTexSubImage3D", userptr);
-}
-static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_3) return;
-    glActiveTexture = (PFNGLACTIVETEXTUREPROC) load("glActiveTexture", userptr);
-    glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC) load("glClientActiveTexture", userptr);
-    glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load("glCompressedTexImage1D", userptr);
-    glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load("glCompressedTexImage2D", userptr);
-    glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load("glCompressedTexImage3D", userptr);
-    glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load("glCompressedTexSubImage1D", userptr);
-    glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load("glCompressedTexSubImage2D", userptr);
-    glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load("glCompressedTexSubImage3D", userptr);
-    glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load("glGetCompressedTexImage", userptr);
-    glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC) load("glLoadTransposeMatrixd", userptr);
-    glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC) load("glLoadTransposeMatrixf", userptr);
-    glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC) load("glMultTransposeMatrixd", userptr);
-    glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC) load("glMultTransposeMatrixf", userptr);
-    glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) load("glMultiTexCoord1d", userptr);
-    glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC) load("glMultiTexCoord1dv", userptr);
-    glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) load("glMultiTexCoord1f", userptr);
-    glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC) load("glMultiTexCoord1fv", userptr);
-    glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC) load("glMultiTexCoord1i", userptr);
-    glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC) load("glMultiTexCoord1iv", userptr);
-    glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC) load("glMultiTexCoord1s", userptr);
-    glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC) load("glMultiTexCoord1sv", userptr);
-    glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) load("glMultiTexCoord2d", userptr);
-    glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC) load("glMultiTexCoord2dv", userptr);
-    glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) load("glMultiTexCoord2f", userptr);
-    glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC) load("glMultiTexCoord2fv", userptr);
-    glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC) load("glMultiTexCoord2i", userptr);
-    glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC) load("glMultiTexCoord2iv", userptr);
-    glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC) load("glMultiTexCoord2s", userptr);
-    glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC) load("glMultiTexCoord2sv", userptr);
-    glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) load("glMultiTexCoord3d", userptr);
-    glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC) load("glMultiTexCoord3dv", userptr);
-    glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) load("glMultiTexCoord3f", userptr);
-    glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC) load("glMultiTexCoord3fv", userptr);
-    glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC) load("glMultiTexCoord3i", userptr);
-    glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC) load("glMultiTexCoord3iv", userptr);
-    glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC) load("glMultiTexCoord3s", userptr);
-    glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC) load("glMultiTexCoord3sv", userptr);
-    glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) load("glMultiTexCoord4d", userptr);
-    glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC) load("glMultiTexCoord4dv", userptr);
-    glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) load("glMultiTexCoord4f", userptr);
-    glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC) load("glMultiTexCoord4fv", userptr);
-    glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC) load("glMultiTexCoord4i", userptr);
-    glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC) load("glMultiTexCoord4iv", userptr);
-    glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC) load("glMultiTexCoord4s", userptr);
-    glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC) load("glMultiTexCoord4sv", userptr);
-    glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load("glSampleCoverage", userptr);
-}
-static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_4) return;
-    glBlendColor = (PFNGLBLENDCOLORPROC) load("glBlendColor", userptr);
-    glBlendEquation = (PFNGLBLENDEQUATIONPROC) load("glBlendEquation", userptr);
-    glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load("glBlendFuncSeparate", userptr);
-    glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC) load("glFogCoordPointer", userptr);
-    glFogCoordd = (PFNGLFOGCOORDDPROC) load("glFogCoordd", userptr);
-    glFogCoorddv = (PFNGLFOGCOORDDVPROC) load("glFogCoorddv", userptr);
-    glFogCoordf = (PFNGLFOGCOORDFPROC) load("glFogCoordf", userptr);
-    glFogCoordfv = (PFNGLFOGCOORDFVPROC) load("glFogCoordfv", userptr);
-    glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load("glMultiDrawArrays", userptr);
-    glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load("glMultiDrawElements", userptr);
-    glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load("glPointParameterf", userptr);
-    glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load("glPointParameterfv", userptr);
-    glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load("glPointParameteri", userptr);
-    glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load("glPointParameteriv", userptr);
-    glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC) load("glSecondaryColor3b", userptr);
-    glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC) load("glSecondaryColor3bv", userptr);
-    glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC) load("glSecondaryColor3d", userptr);
-    glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC) load("glSecondaryColor3dv", userptr);
-    glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC) load("glSecondaryColor3f", userptr);
-    glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC) load("glSecondaryColor3fv", userptr);
-    glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC) load("glSecondaryColor3i", userptr);
-    glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC) load("glSecondaryColor3iv", userptr);
-    glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC) load("glSecondaryColor3s", userptr);
-    glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC) load("glSecondaryColor3sv", userptr);
-    glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC) load("glSecondaryColor3ub", userptr);
-    glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC) load("glSecondaryColor3ubv", userptr);
-    glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC) load("glSecondaryColor3ui", userptr);
-    glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC) load("glSecondaryColor3uiv", userptr);
-    glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC) load("glSecondaryColor3us", userptr);
-    glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC) load("glSecondaryColor3usv", userptr);
-    glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC) load("glSecondaryColorPointer", userptr);
-    glWindowPos2d = (PFNGLWINDOWPOS2DPROC) load("glWindowPos2d", userptr);
-    glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC) load("glWindowPos2dv", userptr);
-    glWindowPos2f = (PFNGLWINDOWPOS2FPROC) load("glWindowPos2f", userptr);
-    glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC) load("glWindowPos2fv", userptr);
-    glWindowPos2i = (PFNGLWINDOWPOS2IPROC) load("glWindowPos2i", userptr);
-    glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC) load("glWindowPos2iv", userptr);
-    glWindowPos2s = (PFNGLWINDOWPOS2SPROC) load("glWindowPos2s", userptr);
-    glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC) load("glWindowPos2sv", userptr);
-    glWindowPos3d = (PFNGLWINDOWPOS3DPROC) load("glWindowPos3d", userptr);
-    glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC) load("glWindowPos3dv", userptr);
-    glWindowPos3f = (PFNGLWINDOWPOS3FPROC) load("glWindowPos3f", userptr);
-    glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC) load("glWindowPos3fv", userptr);
-    glWindowPos3i = (PFNGLWINDOWPOS3IPROC) load("glWindowPos3i", userptr);
-    glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC) load("glWindowPos3iv", userptr);
-    glWindowPos3s = (PFNGLWINDOWPOS3SPROC) load("glWindowPos3s", userptr);
-    glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC) load("glWindowPos3sv", userptr);
-}
-static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_1_5) return;
-    glBeginQuery = (PFNGLBEGINQUERYPROC) load("glBeginQuery", userptr);
-    glBindBuffer = (PFNGLBINDBUFFERPROC) load("glBindBuffer", userptr);
-    glBufferData = (PFNGLBUFFERDATAPROC) load("glBufferData", userptr);
-    glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load("glBufferSubData", userptr);
-    glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load("glDeleteBuffers", userptr);
-    glDeleteQueries = (PFNGLDELETEQUERIESPROC) load("glDeleteQueries", userptr);
-    glEndQuery = (PFNGLENDQUERYPROC) load("glEndQuery", userptr);
-    glGenBuffers = (PFNGLGENBUFFERSPROC) load("glGenBuffers", userptr);
-    glGenQueries = (PFNGLGENQUERIESPROC) load("glGenQueries", userptr);
-    glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load("glGetBufferParameteriv", userptr);
-    glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load("glGetBufferPointerv", userptr);
-    glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load("glGetBufferSubData", userptr);
-    glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load("glGetQueryObjectiv", userptr);
-    glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load("glGetQueryObjectuiv", userptr);
-    glGetQueryiv = (PFNGLGETQUERYIVPROC) load("glGetQueryiv", userptr);
-    glIsBuffer = (PFNGLISBUFFERPROC) load("glIsBuffer", userptr);
-    glIsQuery = (PFNGLISQUERYPROC) load("glIsQuery", userptr);
-    glMapBuffer = (PFNGLMAPBUFFERPROC) load("glMapBuffer", userptr);
-    glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load("glUnmapBuffer", userptr);
-}
-static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_2_0) return;
-    glAttachShader = (PFNGLATTACHSHADERPROC) load("glAttachShader", userptr);
-    glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load("glBindAttribLocation", userptr);
-    glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load("glBlendEquationSeparate", userptr);
-    glCompileShader = (PFNGLCOMPILESHADERPROC) load("glCompileShader", userptr);
-    glCreateProgram = (PFNGLCREATEPROGRAMPROC) load("glCreateProgram", userptr);
-    glCreateShader = (PFNGLCREATESHADERPROC) load("glCreateShader", userptr);
-    glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load("glDeleteProgram", userptr);
-    glDeleteShader = (PFNGLDELETESHADERPROC) load("glDeleteShader", userptr);
-    glDetachShader = (PFNGLDETACHSHADERPROC) load("glDetachShader", userptr);
-    glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load("glDisableVertexAttribArray", userptr);
-    glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load("glDrawBuffers", userptr);
-    glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load("glEnableVertexAttribArray", userptr);
-    glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load("glGetActiveAttrib", userptr);
-    glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load("glGetActiveUniform", userptr);
-    glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load("glGetAttachedShaders", userptr);
-    glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load("glGetAttribLocation", userptr);
-    glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load("glGetProgramInfoLog", userptr);
-    glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load("glGetProgramiv", userptr);
-    glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load("glGetShaderInfoLog", userptr);
-    glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load("glGetShaderSource", userptr);
-    glGetShaderiv = (PFNGLGETSHADERIVPROC) load("glGetShaderiv", userptr);
-    glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load("glGetUniformLocation", userptr);
-    glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load("glGetUniformfv", userptr);
-    glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load("glGetUniformiv", userptr);
-    glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load("glGetVertexAttribPointerv", userptr);
-    glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load("glGetVertexAttribdv", userptr);
-    glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load("glGetVertexAttribfv", userptr);
-    glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load("glGetVertexAttribiv", userptr);
-    glIsProgram = (PFNGLISPROGRAMPROC) load("glIsProgram", userptr);
-    glIsShader = (PFNGLISSHADERPROC) load("glIsShader", userptr);
-    glLinkProgram = (PFNGLLINKPROGRAMPROC) load("glLinkProgram", userptr);
-    glShaderSource = (PFNGLSHADERSOURCEPROC) load("glShaderSource", userptr);
-    glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load("glStencilFuncSeparate", userptr);
-    glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load("glStencilMaskSeparate", userptr);
-    glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load("glStencilOpSeparate", userptr);
-    glUniform1f = (PFNGLUNIFORM1FPROC) load("glUniform1f", userptr);
-    glUniform1fv = (PFNGLUNIFORM1FVPROC) load("glUniform1fv", userptr);
-    glUniform1i = (PFNGLUNIFORM1IPROC) load("glUniform1i", userptr);
-    glUniform1iv = (PFNGLUNIFORM1IVPROC) load("glUniform1iv", userptr);
-    glUniform2f = (PFNGLUNIFORM2FPROC) load("glUniform2f", userptr);
-    glUniform2fv = (PFNGLUNIFORM2FVPROC) load("glUniform2fv", userptr);
-    glUniform2i = (PFNGLUNIFORM2IPROC) load("glUniform2i", userptr);
-    glUniform2iv = (PFNGLUNIFORM2IVPROC) load("glUniform2iv", userptr);
-    glUniform3f = (PFNGLUNIFORM3FPROC) load("glUniform3f", userptr);
-    glUniform3fv = (PFNGLUNIFORM3FVPROC) load("glUniform3fv", userptr);
-    glUniform3i = (PFNGLUNIFORM3IPROC) load("glUniform3i", userptr);
-    glUniform3iv = (PFNGLUNIFORM3IVPROC) load("glUniform3iv", userptr);
-    glUniform4f = (PFNGLUNIFORM4FPROC) load("glUniform4f", userptr);
-    glUniform4fv = (PFNGLUNIFORM4FVPROC) load("glUniform4fv", userptr);
-    glUniform4i = (PFNGLUNIFORM4IPROC) load("glUniform4i", userptr);
-    glUniform4iv = (PFNGLUNIFORM4IVPROC) load("glUniform4iv", userptr);
-    glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load("glUniformMatrix2fv", userptr);
-    glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load("glUniformMatrix3fv", userptr);
-    glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load("glUniformMatrix4fv", userptr);
-    glUseProgram = (PFNGLUSEPROGRAMPROC) load("glUseProgram", userptr);
-    glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load("glValidateProgram", userptr);
-    glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load("glVertexAttrib1d", userptr);
-    glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load("glVertexAttrib1dv", userptr);
-    glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load("glVertexAttrib1f", userptr);
-    glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load("glVertexAttrib1fv", userptr);
-    glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load("glVertexAttrib1s", userptr);
-    glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load("glVertexAttrib1sv", userptr);
-    glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load("glVertexAttrib2d", userptr);
-    glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load("glVertexAttrib2dv", userptr);
-    glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load("glVertexAttrib2f", userptr);
-    glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load("glVertexAttrib2fv", userptr);
-    glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load("glVertexAttrib2s", userptr);
-    glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load("glVertexAttrib2sv", userptr);
-    glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load("glVertexAttrib3d", userptr);
-    glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load("glVertexAttrib3dv", userptr);
-    glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load("glVertexAttrib3f", userptr);
-    glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load("glVertexAttrib3fv", userptr);
-    glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load("glVertexAttrib3s", userptr);
-    glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load("glVertexAttrib3sv", userptr);
-    glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load("glVertexAttrib4Nbv", userptr);
-    glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load("glVertexAttrib4Niv", userptr);
-    glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load("glVertexAttrib4Nsv", userptr);
-    glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load("glVertexAttrib4Nub", userptr);
-    glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load("glVertexAttrib4Nubv", userptr);
-    glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load("glVertexAttrib4Nuiv", userptr);
-    glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load("glVertexAttrib4Nusv", userptr);
-    glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load("glVertexAttrib4bv", userptr);
-    glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load("glVertexAttrib4d", userptr);
-    glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load("glVertexAttrib4dv", userptr);
-    glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load("glVertexAttrib4f", userptr);
-    glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load("glVertexAttrib4fv", userptr);
-    glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load("glVertexAttrib4iv", userptr);
-    glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load("glVertexAttrib4s", userptr);
-    glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load("glVertexAttrib4sv", userptr);
-    glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load("glVertexAttrib4ubv", userptr);
-    glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load("glVertexAttrib4uiv", userptr);
-    glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load("glVertexAttrib4usv", userptr);
-    glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load("glVertexAttribPointer", userptr);
-}
-static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_2_1) return;
-    glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load("glUniformMatrix2x3fv", userptr);
-    glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load("glUniformMatrix2x4fv", userptr);
-    glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load("glUniformMatrix3x2fv", userptr);
-    glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load("glUniformMatrix3x4fv", userptr);
-    glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load("glUniformMatrix4x2fv", userptr);
-    glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load("glUniformMatrix4x3fv", userptr);
-}
-static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_3_0) return;
-    glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load("glBeginConditionalRender", userptr);
-    glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load("glBeginTransformFeedback", userptr);
-    glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load("glBindBufferBase", userptr);
-    glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load("glBindBufferRange", userptr);
-    glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load("glBindFragDataLocation", userptr);
-    glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load("glBindFramebuffer", userptr);
-    glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load("glBindRenderbuffer", userptr);
-    glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load("glBindVertexArray", userptr);
-    glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load("glBlitFramebuffer", userptr);
-    glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load("glCheckFramebufferStatus", userptr);
-    glClampColor = (PFNGLCLAMPCOLORPROC) load("glClampColor", userptr);
-    glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load("glClearBufferfi", userptr);
-    glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load("glClearBufferfv", userptr);
-    glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load("glClearBufferiv", userptr);
-    glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load("glClearBufferuiv", userptr);
-    glColorMaski = (PFNGLCOLORMASKIPROC) load("glColorMaski", userptr);
-    glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load("glDeleteFramebuffers", userptr);
-    glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load("glDeleteRenderbuffers", userptr);
-    glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load("glDeleteVertexArrays", userptr);
-    glDisablei = (PFNGLDISABLEIPROC) load("glDisablei", userptr);
-    glEnablei = (PFNGLENABLEIPROC) load("glEnablei", userptr);
-    glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load("glEndConditionalRender", userptr);
-    glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load("glEndTransformFeedback", userptr);
-    glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load("glFlushMappedBufferRange", userptr);
-    glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load("glFramebufferRenderbuffer", userptr);
-    glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load("glFramebufferTexture1D", userptr);
-    glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load("glFramebufferTexture2D", userptr);
-    glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load("glFramebufferTexture3D", userptr);
-    glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load("glFramebufferTextureLayer", userptr);
-    glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load("glGenFramebuffers", userptr);
-    glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load("glGenRenderbuffers", userptr);
-    glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load("glGenVertexArrays", userptr);
-    glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load("glGenerateMipmap", userptr);
-    glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load("glGetBooleani_v", userptr);
-    glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load("glGetFragDataLocation", userptr);
-    glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load("glGetFramebufferAttachmentParameteriv", userptr);
-    glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load("glGetIntegeri_v", userptr);
-    glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load("glGetRenderbufferParameteriv", userptr);
-    glGetStringi = (PFNGLGETSTRINGIPROC) load("glGetStringi", userptr);
-    glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load("glGetTexParameterIiv", userptr);
-    glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load("glGetTexParameterIuiv", userptr);
-    glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load("glGetTransformFeedbackVarying", userptr);
-    glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load("glGetUniformuiv", userptr);
-    glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load("glGetVertexAttribIiv", userptr);
-    glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load("glGetVertexAttribIuiv", userptr);
-    glIsEnabledi = (PFNGLISENABLEDIPROC) load("glIsEnabledi", userptr);
-    glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load("glIsFramebuffer", userptr);
-    glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load("glIsRenderbuffer", userptr);
-    glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load("glIsVertexArray", userptr);
-    glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load("glMapBufferRange", userptr);
-    glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load("glRenderbufferStorage", userptr);
-    glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load("glRenderbufferStorageMultisample", userptr);
-    glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load("glTexParameterIiv", userptr);
-    glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load("glTexParameterIuiv", userptr);
-    glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load("glTransformFeedbackVaryings", userptr);
-    glUniform1ui = (PFNGLUNIFORM1UIPROC) load("glUniform1ui", userptr);
-    glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load("glUniform1uiv", userptr);
-    glUniform2ui = (PFNGLUNIFORM2UIPROC) load("glUniform2ui", userptr);
-    glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load("glUniform2uiv", userptr);
-    glUniform3ui = (PFNGLUNIFORM3UIPROC) load("glUniform3ui", userptr);
-    glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load("glUniform3uiv", userptr);
-    glUniform4ui = (PFNGLUNIFORM4UIPROC) load("glUniform4ui", userptr);
-    glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load("glUniform4uiv", userptr);
-    glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load("glVertexAttribI1i", userptr);
-    glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load("glVertexAttribI1iv", userptr);
-    glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load("glVertexAttribI1ui", userptr);
-    glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load("glVertexAttribI1uiv", userptr);
-    glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load("glVertexAttribI2i", userptr);
-    glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load("glVertexAttribI2iv", userptr);
-    glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load("glVertexAttribI2ui", userptr);
-    glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load("glVertexAttribI2uiv", userptr);
-    glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load("glVertexAttribI3i", userptr);
-    glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load("glVertexAttribI3iv", userptr);
-    glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load("glVertexAttribI3ui", userptr);
-    glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load("glVertexAttribI3uiv", userptr);
-    glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load("glVertexAttribI4bv", userptr);
-    glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load("glVertexAttribI4i", userptr);
-    glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load("glVertexAttribI4iv", userptr);
-    glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load("glVertexAttribI4sv", userptr);
-    glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load("glVertexAttribI4ubv", userptr);
-    glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load("glVertexAttribI4ui", userptr);
-    glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load("glVertexAttribI4uiv", userptr);
-    glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load("glVertexAttribI4usv", userptr);
-    glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load("glVertexAttribIPointer", userptr);
-}
-static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_3_1) return;
-    glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load("glBindBufferBase", userptr);
-    glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load("glBindBufferRange", userptr);
-    glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load("glCopyBufferSubData", userptr);
-    glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load("glDrawArraysInstanced", userptr);
-    glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load("glDrawElementsInstanced", userptr);
-    glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load("glGetActiveUniformBlockName", userptr);
-    glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load("glGetActiveUniformBlockiv", userptr);
-    glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load("glGetActiveUniformName", userptr);
-    glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load("glGetActiveUniformsiv", userptr);
-    glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load("glGetIntegeri_v", userptr);
-    glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load("glGetUniformBlockIndex", userptr);
-    glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load("glGetUniformIndices", userptr);
-    glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load("glPrimitiveRestartIndex", userptr);
-    glTexBuffer = (PFNGLTEXBUFFERPROC) load("glTexBuffer", userptr);
-    glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load("glUniformBlockBinding", userptr);
-}
-static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_3_2) return;
-    glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load("glClientWaitSync", userptr);
-    glDeleteSync = (PFNGLDELETESYNCPROC) load("glDeleteSync", userptr);
-    glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load("glDrawElementsBaseVertex", userptr);
-    glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load("glDrawElementsInstancedBaseVertex", userptr);
-    glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load("glDrawRangeElementsBaseVertex", userptr);
-    glFenceSync = (PFNGLFENCESYNCPROC) load("glFenceSync", userptr);
-    glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load("glFramebufferTexture", userptr);
-    glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load("glGetBufferParameteri64v", userptr);
-    glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load("glGetInteger64i_v", userptr);
-    glGetInteger64v = (PFNGLGETINTEGER64VPROC) load("glGetInteger64v", userptr);
-    glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load("glGetMultisamplefv", userptr);
-    glGetSynciv = (PFNGLGETSYNCIVPROC) load("glGetSynciv", userptr);
-    glIsSync = (PFNGLISSYNCPROC) load("glIsSync", userptr);
-    glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load("glMultiDrawElementsBaseVertex", userptr);
-    glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load("glProvokingVertex", userptr);
-    glSampleMaski = (PFNGLSAMPLEMASKIPROC) load("glSampleMaski", userptr);
-    glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load("glTexImage2DMultisample", userptr);
-    glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load("glTexImage3DMultisample", userptr);
-    glWaitSync = (PFNGLWAITSYNCPROC) load("glWaitSync", userptr);
-}
-static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_VERSION_3_3) return;
-    glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load("glBindFragDataLocationIndexed", userptr);
-    glBindSampler = (PFNGLBINDSAMPLERPROC) load("glBindSampler", userptr);
-    glColorP3ui = (PFNGLCOLORP3UIPROC) load("glColorP3ui", userptr);
-    glColorP3uiv = (PFNGLCOLORP3UIVPROC) load("glColorP3uiv", userptr);
-    glColorP4ui = (PFNGLCOLORP4UIPROC) load("glColorP4ui", userptr);
-    glColorP4uiv = (PFNGLCOLORP4UIVPROC) load("glColorP4uiv", userptr);
-    glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load("glDeleteSamplers", userptr);
-    glGenSamplers = (PFNGLGENSAMPLERSPROC) load("glGenSamplers", userptr);
-    glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load("glGetFragDataIndex", userptr);
-    glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load("glGetQueryObjecti64v", userptr);
-    glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load("glGetQueryObjectui64v", userptr);
-    glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load("glGetSamplerParameterIiv", userptr);
-    glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load("glGetSamplerParameterIuiv", userptr);
-    glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load("glGetSamplerParameterfv", userptr);
-    glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load("glGetSamplerParameteriv", userptr);
-    glIsSampler = (PFNGLISSAMPLERPROC) load("glIsSampler", userptr);
-    glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load("glMultiTexCoordP1ui", userptr);
-    glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load("glMultiTexCoordP1uiv", userptr);
-    glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load("glMultiTexCoordP2ui", userptr);
-    glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load("glMultiTexCoordP2uiv", userptr);
-    glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load("glMultiTexCoordP3ui", userptr);
-    glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load("glMultiTexCoordP3uiv", userptr);
-    glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load("glMultiTexCoordP4ui", userptr);
-    glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load("glMultiTexCoordP4uiv", userptr);
-    glNormalP3ui = (PFNGLNORMALP3UIPROC) load("glNormalP3ui", userptr);
-    glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load("glNormalP3uiv", userptr);
-    glQueryCounter = (PFNGLQUERYCOUNTERPROC) load("glQueryCounter", userptr);
-    glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load("glSamplerParameterIiv", userptr);
-    glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load("glSamplerParameterIuiv", userptr);
-    glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load("glSamplerParameterf", userptr);
-    glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load("glSamplerParameterfv", userptr);
-    glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load("glSamplerParameteri", userptr);
-    glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load("glSamplerParameteriv", userptr);
-    glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load("glSecondaryColorP3ui", userptr);
-    glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load("glSecondaryColorP3uiv", userptr);
-    glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load("glTexCoordP1ui", userptr);
-    glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load("glTexCoordP1uiv", userptr);
-    glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load("glTexCoordP2ui", userptr);
-    glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load("glTexCoordP2uiv", userptr);
-    glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load("glTexCoordP3ui", userptr);
-    glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load("glTexCoordP3uiv", userptr);
-    glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load("glTexCoordP4ui", userptr);
-    glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load("glTexCoordP4uiv", userptr);
-    glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load("glVertexAttribDivisor", userptr);
-    glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load("glVertexAttribP1ui", userptr);
-    glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load("glVertexAttribP1uiv", userptr);
-    glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load("glVertexAttribP2ui", userptr);
-    glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load("glVertexAttribP2uiv", userptr);
-    glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load("glVertexAttribP3ui", userptr);
-    glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load("glVertexAttribP3uiv", userptr);
-    glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load("glVertexAttribP4ui", userptr);
-    glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load("glVertexAttribP4uiv", userptr);
-    glVertexP2ui = (PFNGLVERTEXP2UIPROC) load("glVertexP2ui", userptr);
-    glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load("glVertexP2uiv", userptr);
-    glVertexP3ui = (PFNGLVERTEXP3UIPROC) load("glVertexP3ui", userptr);
-    glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load("glVertexP3uiv", userptr);
-    glVertexP4ui = (PFNGLVERTEXP4UIPROC) load("glVertexP4ui", userptr);
-    glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load("glVertexP4uiv", userptr);
-}
-static void glad_gl_load_GL_ARB_multisample( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_ARB_multisample) return;
-    glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load("glSampleCoverage", userptr);
-    glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC) load("glSampleCoverageARB", userptr);
-}
-static void glad_gl_load_GL_ARB_robustness( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_ARB_robustness) return;
-    glGetGraphicsResetStatusARB = (PFNGLGETGRAPHICSRESETSTATUSARBPROC) load("glGetGraphicsResetStatusARB", userptr);
-    glGetnColorTableARB = (PFNGLGETNCOLORTABLEARBPROC) load("glGetnColorTableARB", userptr);
-    glGetnCompressedTexImageARB = (PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) load("glGetnCompressedTexImageARB", userptr);
-    glGetnConvolutionFilterARB = (PFNGLGETNCONVOLUTIONFILTERARBPROC) load("glGetnConvolutionFilterARB", userptr);
-    glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC) load("glGetnHistogramARB", userptr);
-    glGetnMapdvARB = (PFNGLGETNMAPDVARBPROC) load("glGetnMapdvARB", userptr);
-    glGetnMapfvARB = (PFNGLGETNMAPFVARBPROC) load("glGetnMapfvARB", userptr);
-    glGetnMapivARB = (PFNGLGETNMAPIVARBPROC) load("glGetnMapivARB", userptr);
-    glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC) load("glGetnMinmaxARB", userptr);
-    glGetnPixelMapfvARB = (PFNGLGETNPIXELMAPFVARBPROC) load("glGetnPixelMapfvARB", userptr);
-    glGetnPixelMapuivARB = (PFNGLGETNPIXELMAPUIVARBPROC) load("glGetnPixelMapuivARB", userptr);
-    glGetnPixelMapusvARB = (PFNGLGETNPIXELMAPUSVARBPROC) load("glGetnPixelMapusvARB", userptr);
-    glGetnPolygonStippleARB = (PFNGLGETNPOLYGONSTIPPLEARBPROC) load("glGetnPolygonStippleARB", userptr);
-    glGetnSeparableFilterARB = (PFNGLGETNSEPARABLEFILTERARBPROC) load("glGetnSeparableFilterARB", userptr);
-    glGetnTexImageARB = (PFNGLGETNTEXIMAGEARBPROC) load("glGetnTexImageARB", userptr);
-    glGetnUniformdvARB = (PFNGLGETNUNIFORMDVARBPROC) load("glGetnUniformdvARB", userptr);
-    glGetnUniformfvARB = (PFNGLGETNUNIFORMFVARBPROC) load("glGetnUniformfvARB", userptr);
-    glGetnUniformivARB = (PFNGLGETNUNIFORMIVARBPROC) load("glGetnUniformivARB", userptr);
-    glGetnUniformuivARB = (PFNGLGETNUNIFORMUIVARBPROC) load("glGetnUniformuivARB", userptr);
-    glReadnPixels = (PFNGLREADNPIXELSPROC) load("glReadnPixels", userptr);
-    glReadnPixelsARB = (PFNGLREADNPIXELSARBPROC) load("glReadnPixelsARB", userptr);
-}
-static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
-    if(!GLAD_GL_KHR_debug) return;
-    glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load("glDebugMessageCallback", userptr);
-    glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load("glDebugMessageControl", userptr);
-    glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load("glDebugMessageInsert", userptr);
-    glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load("glGetDebugMessageLog", userptr);
-    glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load("glGetObjectLabel", userptr);
-    glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load("glGetObjectPtrLabel", userptr);
-    glGetPointerv = (PFNGLGETPOINTERVPROC) load("glGetPointerv", userptr);
-    glObjectLabel = (PFNGLOBJECTLABELPROC) load("glObjectLabel", userptr);
-    glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load("glObjectPtrLabel", userptr);
-    glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load("glPopDebugGroup", userptr);
-    glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load("glPushDebugGroup", userptr);
-}
-
-
-
-#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
-#define GLAD_GL_IS_SOME_NEW_VERSION 1
-#else
-#define GLAD_GL_IS_SOME_NEW_VERSION 0
-#endif
-
-static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
-#if GLAD_GL_IS_SOME_NEW_VERSION
-    if(GLAD_VERSION_MAJOR(version) < 3) {
-#else
-    (void) version;
-    (void) out_num_exts_i;
-    (void) out_exts_i;
-#endif
-        if (glGetString == NULL) {
-            return 0;
-        }
-        *out_exts = (const char *)glGetString(GL_EXTENSIONS);
-#if GLAD_GL_IS_SOME_NEW_VERSION
-    } else {
-        unsigned int index = 0;
-        unsigned int num_exts_i = 0;
-        char **exts_i = NULL;
-        if (glGetStringi == NULL || glGetIntegerv == NULL) {
-            return 0;
-        }
-        glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
-        if (num_exts_i > 0) {
-            exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
-        }
-        if (exts_i == NULL) {
-            return 0;
-        }
-        for(index = 0; index < num_exts_i; index++) {
-            const char *gl_str_tmp = (const char*) glGetStringi(GL_EXTENSIONS, index);
-            size_t len = strlen(gl_str_tmp) + 1;
-
-            char *local_str = (char*) malloc(len * sizeof(char));
-            if(local_str != NULL) {
-                memcpy(local_str, gl_str_tmp, len * sizeof(char));
-            }
-
-            exts_i[index] = local_str;
-        }
-
-        *out_num_exts_i = num_exts_i;
-        *out_exts_i = exts_i;
-    }
-#endif
-    return 1;
-}
-static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
-    if (exts_i != NULL) {
-        unsigned int index;
-        for(index = 0; index < num_exts_i; index++) {
-            free((void *) (exts_i[index]));
-        }
-        free((void *)exts_i);
-        exts_i = NULL;
-    }
-}
-static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
-    if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
-        const char *extensions;
-        const char *loc;
-        const char *terminator;
-        extensions = exts;
-        if(extensions == NULL || ext == NULL) {
-            return 0;
-        }
-        while(1) {
-            loc = strstr(extensions, ext);
-            if(loc == NULL) {
-                return 0;
-            }
-            terminator = loc + strlen(ext);
-            if((loc == extensions || *(loc - 1) == ' ') &&
-                (*terminator == ' ' || *terminator == '\0')) {
-                return 1;
-            }
-            extensions = terminator;
-        }
-    } else {
-        unsigned int index;
-        for(index = 0; index < num_exts_i; index++) {
-            const char *e = exts_i[index];
-            if(strcmp(e, ext) == 0) {
-                return 1;
-            }
-        }
-    }
-    return 0;
-}
-
-static GLADapiproc glad_gl_get_proc_from_userptr(const char* name, void *userptr) {
-    return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
-}
-
-static int glad_gl_find_extensions_gl( int version) {
-    const char *exts = NULL;
-    unsigned int num_exts_i = 0;
-    char **exts_i = NULL;
-    if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
-
-    GLAD_GL_ARB_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multisample");
-    GLAD_GL_ARB_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_robustness");
-    GLAD_GL_KHR_debug = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_debug");
-
-    glad_gl_free_extensions(exts_i, num_exts_i);
-
-    return 1;
-}
-
-static int glad_gl_find_core_gl(void) {
-    int i, major, minor;
-    const char* version;
-    const char* prefixes[] = {
-        "OpenGL ES-CM ",
-        "OpenGL ES-CL ",
-        "OpenGL ES ",
-        NULL
-    };
-    version = (const char*) glGetString(GL_VERSION);
-    if (!version) return 0;
-    for (i = 0;  prefixes[i];  i++) {
-        const size_t length = strlen(prefixes[i]);
-        if (strncmp(version, prefixes[i], length) == 0) {
-            version += length;
-            break;
-        }
-    }
-
-    GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
-
-    GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
-    GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
-    GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
-    GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
-    GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
-    GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
-    GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
-    GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
-    GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
-    GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
-    GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
-    GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
-
-    return GLAD_MAKE_VERSION(major, minor);
-}
-
-int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
-    int version;
-
-    glGetString = (PFNGLGETSTRINGPROC) load("glGetString", userptr);
-    if(glGetString == NULL) return 0;
-    if(glGetString(GL_VERSION) == NULL) return 0;
-    version = glad_gl_find_core_gl();
-
-    glad_gl_load_GL_VERSION_1_0(load, userptr);
-    glad_gl_load_GL_VERSION_1_1(load, userptr);
-    glad_gl_load_GL_VERSION_1_2(load, userptr);
-    glad_gl_load_GL_VERSION_1_3(load, userptr);
-    glad_gl_load_GL_VERSION_1_4(load, userptr);
-    glad_gl_load_GL_VERSION_1_5(load, userptr);
-    glad_gl_load_GL_VERSION_2_0(load, userptr);
-    glad_gl_load_GL_VERSION_2_1(load, userptr);
-    glad_gl_load_GL_VERSION_3_0(load, userptr);
-    glad_gl_load_GL_VERSION_3_1(load, userptr);
-    glad_gl_load_GL_VERSION_3_2(load, userptr);
-    glad_gl_load_GL_VERSION_3_3(load, userptr);
-
-    if (!glad_gl_find_extensions_gl(version)) return 0;
-    glad_gl_load_GL_ARB_multisample(load, userptr);
-    glad_gl_load_GL_ARB_robustness(load, userptr);
-    glad_gl_load_GL_KHR_debug(load, userptr);
-
-
-
-    return version;
-}
-
-
-int gladLoadGL( GLADloadfunc load) {
-    return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
-}
-
-
-
-
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <glad/gl.h>
+
+#ifndef GLAD_IMPL_UTIL_C_
+#define GLAD_IMPL_UTIL_C_
+
+#ifdef _MSC_VER
+#define GLAD_IMPL_UTIL_SSCANF sscanf_s
+#else
+#define GLAD_IMPL_UTIL_SSCANF sscanf
+#endif
+
+#endif /* GLAD_IMPL_UTIL_C_ */
+
+
+int GLAD_GL_VERSION_1_0 = 0;
+int GLAD_GL_VERSION_1_1 = 0;
+int GLAD_GL_VERSION_1_2 = 0;
+int GLAD_GL_VERSION_1_3 = 0;
+int GLAD_GL_VERSION_1_4 = 0;
+int GLAD_GL_VERSION_1_5 = 0;
+int GLAD_GL_VERSION_2_0 = 0;
+int GLAD_GL_VERSION_2_1 = 0;
+int GLAD_GL_VERSION_3_0 = 0;
+int GLAD_GL_VERSION_3_1 = 0;
+int GLAD_GL_VERSION_3_2 = 0;
+int GLAD_GL_VERSION_3_3 = 0;
+int GLAD_GL_ARB_multisample = 0;
+int GLAD_GL_ARB_robustness = 0;
+int GLAD_GL_KHR_debug = 0;
+
+
+
+PFNGLACCUMPROC glad_glAccum = NULL;
+PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL;
+PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL;
+PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL;
+PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL;
+PFNGLATTACHSHADERPROC glad_glAttachShader = NULL;
+PFNGLBEGINPROC glad_glBegin = NULL;
+PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL;
+PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL;
+PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL;
+PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL;
+PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL;
+PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL;
+PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL;
+PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL;
+PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL;
+PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL;
+PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
+PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
+PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
+PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
+PFNGLBITMAPPROC glad_glBitmap = NULL;
+PFNGLBLENDCOLORPROC glad_glBlendColor = NULL;
+PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL;
+PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL;
+PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL;
+PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
+PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
+PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
+PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
+PFNGLCALLLISTPROC glad_glCallList = NULL;
+PFNGLCALLLISTSPROC glad_glCallLists = NULL;
+PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
+PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
+PFNGLCLEARPROC glad_glClear = NULL;
+PFNGLCLEARACCUMPROC glad_glClearAccum = NULL;
+PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL;
+PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL;
+PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL;
+PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
+PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
+PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
+PFNGLCLEARINDEXPROC glad_glClearIndex = NULL;
+PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
+PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL;
+PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
+PFNGLCLIPPLANEPROC glad_glClipPlane = NULL;
+PFNGLCOLOR3BPROC glad_glColor3b = NULL;
+PFNGLCOLOR3BVPROC glad_glColor3bv = NULL;
+PFNGLCOLOR3DPROC glad_glColor3d = NULL;
+PFNGLCOLOR3DVPROC glad_glColor3dv = NULL;
+PFNGLCOLOR3FPROC glad_glColor3f = NULL;
+PFNGLCOLOR3FVPROC glad_glColor3fv = NULL;
+PFNGLCOLOR3IPROC glad_glColor3i = NULL;
+PFNGLCOLOR3IVPROC glad_glColor3iv = NULL;
+PFNGLCOLOR3SPROC glad_glColor3s = NULL;
+PFNGLCOLOR3SVPROC glad_glColor3sv = NULL;
+PFNGLCOLOR3UBPROC glad_glColor3ub = NULL;
+PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL;
+PFNGLCOLOR3UIPROC glad_glColor3ui = NULL;
+PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL;
+PFNGLCOLOR3USPROC glad_glColor3us = NULL;
+PFNGLCOLOR3USVPROC glad_glColor3usv = NULL;
+PFNGLCOLOR4BPROC glad_glColor4b = NULL;
+PFNGLCOLOR4BVPROC glad_glColor4bv = NULL;
+PFNGLCOLOR4DPROC glad_glColor4d = NULL;
+PFNGLCOLOR4DVPROC glad_glColor4dv = NULL;
+PFNGLCOLOR4FPROC glad_glColor4f = NULL;
+PFNGLCOLOR4FVPROC glad_glColor4fv = NULL;
+PFNGLCOLOR4IPROC glad_glColor4i = NULL;
+PFNGLCOLOR4IVPROC glad_glColor4iv = NULL;
+PFNGLCOLOR4SPROC glad_glColor4s = NULL;
+PFNGLCOLOR4SVPROC glad_glColor4sv = NULL;
+PFNGLCOLOR4UBPROC glad_glColor4ub = NULL;
+PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL;
+PFNGLCOLOR4UIPROC glad_glColor4ui = NULL;
+PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL;
+PFNGLCOLOR4USPROC glad_glColor4us = NULL;
+PFNGLCOLOR4USVPROC glad_glColor4usv = NULL;
+PFNGLCOLORMASKPROC glad_glColorMask = NULL;
+PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
+PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL;
+PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
+PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL;
+PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL;
+PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL;
+PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL;
+PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL;
+PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL;
+PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
+PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
+PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
+PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL;
+PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
+PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
+PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
+PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
+PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
+PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
+PFNGLCULLFACEPROC glad_glCullFace = NULL;
+PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
+PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
+PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL;
+PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL;
+PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL;
+PFNGLDELETELISTSPROC glad_glDeleteLists = NULL;
+PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL;
+PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL;
+PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL;
+PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL;
+PFNGLDELETESHADERPROC glad_glDeleteShader = NULL;
+PFNGLDELETESYNCPROC glad_glDeleteSync = NULL;
+PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL;
+PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL;
+PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL;
+PFNGLDEPTHMASKPROC glad_glDepthMask = NULL;
+PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL;
+PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
+PFNGLDISABLEPROC glad_glDisable = NULL;
+PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL;
+PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
+PFNGLDISABLEIPROC glad_glDisablei = NULL;
+PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL;
+PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL;
+PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL;
+PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL;
+PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL;
+PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL;
+PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL;
+PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL;
+PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL;
+PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL;
+PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL;
+PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL;
+PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL;
+PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL;
+PFNGLENABLEPROC glad_glEnable = NULL;
+PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL;
+PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
+PFNGLENABLEIPROC glad_glEnablei = NULL;
+PFNGLENDPROC glad_glEnd = NULL;
+PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
+PFNGLENDLISTPROC glad_glEndList = NULL;
+PFNGLENDQUERYPROC glad_glEndQuery = NULL;
+PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL;
+PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL;
+PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL;
+PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL;
+PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL;
+PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL;
+PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL;
+PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL;
+PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL;
+PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL;
+PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL;
+PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL;
+PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL;
+PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL;
+PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
+PFNGLFINISHPROC glad_glFinish = NULL;
+PFNGLFLUSHPROC glad_glFlush = NULL;
+PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
+PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL;
+PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL;
+PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL;
+PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL;
+PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL;
+PFNGLFOGFPROC glad_glFogf = NULL;
+PFNGLFOGFVPROC glad_glFogfv = NULL;
+PFNGLFOGIPROC glad_glFogi = NULL;
+PFNGLFOGIVPROC glad_glFogiv = NULL;
+PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
+PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
+PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL;
+PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL;
+PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL;
+PFNGLFRONTFACEPROC glad_glFrontFace = NULL;
+PFNGLFRUSTUMPROC glad_glFrustum = NULL;
+PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL;
+PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL;
+PFNGLGENLISTSPROC glad_glGenLists = NULL;
+PFNGLGENQUERIESPROC glad_glGenQueries = NULL;
+PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL;
+PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL;
+PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
+PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
+PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
+PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
+PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL;
+PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL;
+PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL;
+PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL;
+PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL;
+PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL;
+PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL;
+PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL;
+PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL;
+PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
+PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
+PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
+PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL;
+PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
+PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
+PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
+PFNGLGETERRORPROC glad_glGetError = NULL;
+PFNGLGETFLOATVPROC glad_glGetFloatv = NULL;
+PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL;
+PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL;
+PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL;
+PFNGLGETGRAPHICSRESETSTATUSARBPROC glad_glGetGraphicsResetStatusARB = NULL;
+PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL;
+PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL;
+PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL;
+PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
+PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL;
+PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL;
+PFNGLGETMAPDVPROC glad_glGetMapdv = NULL;
+PFNGLGETMAPFVPROC glad_glGetMapfv = NULL;
+PFNGLGETMAPIVPROC glad_glGetMapiv = NULL;
+PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL;
+PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL;
+PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
+PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
+PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
+PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL;
+PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL;
+PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL;
+PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
+PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL;
+PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL;
+PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
+PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
+PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
+PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL;
+PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL;
+PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL;
+PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL;
+PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL;
+PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL;
+PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL;
+PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL;
+PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL;
+PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL;
+PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL;
+PFNGLGETSTRINGPROC glad_glGetString = NULL;
+PFNGLGETSTRINGIPROC glad_glGetStringi = NULL;
+PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL;
+PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL;
+PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL;
+PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL;
+PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL;
+PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL;
+PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL;
+PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL;
+PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL;
+PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
+PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
+PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
+PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
+PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
+PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
+PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
+PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
+PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
+PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
+PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
+PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
+PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
+PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
+PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
+PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
+PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
+PFNGLGETNCOLORTABLEARBPROC glad_glGetnColorTableARB = NULL;
+PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC glad_glGetnCompressedTexImageARB = NULL;
+PFNGLGETNCONVOLUTIONFILTERARBPROC glad_glGetnConvolutionFilterARB = NULL;
+PFNGLGETNHISTOGRAMARBPROC glad_glGetnHistogramARB = NULL;
+PFNGLGETNMAPDVARBPROC glad_glGetnMapdvARB = NULL;
+PFNGLGETNMAPFVARBPROC glad_glGetnMapfvARB = NULL;
+PFNGLGETNMAPIVARBPROC glad_glGetnMapivARB = NULL;
+PFNGLGETNMINMAXARBPROC glad_glGetnMinmaxARB = NULL;
+PFNGLGETNPIXELMAPFVARBPROC glad_glGetnPixelMapfvARB = NULL;
+PFNGLGETNPIXELMAPUIVARBPROC glad_glGetnPixelMapuivARB = NULL;
+PFNGLGETNPIXELMAPUSVARBPROC glad_glGetnPixelMapusvARB = NULL;
+PFNGLGETNPOLYGONSTIPPLEARBPROC glad_glGetnPolygonStippleARB = NULL;
+PFNGLGETNSEPARABLEFILTERARBPROC glad_glGetnSeparableFilterARB = NULL;
+PFNGLGETNTEXIMAGEARBPROC glad_glGetnTexImageARB = NULL;
+PFNGLGETNUNIFORMDVARBPROC glad_glGetnUniformdvARB = NULL;
+PFNGLGETNUNIFORMFVARBPROC glad_glGetnUniformfvARB = NULL;
+PFNGLGETNUNIFORMIVARBPROC glad_glGetnUniformivARB = NULL;
+PFNGLGETNUNIFORMUIVARBPROC glad_glGetnUniformuivARB = NULL;
+PFNGLHINTPROC glad_glHint = NULL;
+PFNGLINDEXMASKPROC glad_glIndexMask = NULL;
+PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL;
+PFNGLINDEXDPROC glad_glIndexd = NULL;
+PFNGLINDEXDVPROC glad_glIndexdv = NULL;
+PFNGLINDEXFPROC glad_glIndexf = NULL;
+PFNGLINDEXFVPROC glad_glIndexfv = NULL;
+PFNGLINDEXIPROC glad_glIndexi = NULL;
+PFNGLINDEXIVPROC glad_glIndexiv = NULL;
+PFNGLINDEXSPROC glad_glIndexs = NULL;
+PFNGLINDEXSVPROC glad_glIndexsv = NULL;
+PFNGLINDEXUBPROC glad_glIndexub = NULL;
+PFNGLINDEXUBVPROC glad_glIndexubv = NULL;
+PFNGLINITNAMESPROC glad_glInitNames = NULL;
+PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL;
+PFNGLISBUFFERPROC glad_glIsBuffer = NULL;
+PFNGLISENABLEDPROC glad_glIsEnabled = NULL;
+PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL;
+PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL;
+PFNGLISLISTPROC glad_glIsList = NULL;
+PFNGLISPROGRAMPROC glad_glIsProgram = NULL;
+PFNGLISQUERYPROC glad_glIsQuery = NULL;
+PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL;
+PFNGLISSAMPLERPROC glad_glIsSampler = NULL;
+PFNGLISSHADERPROC glad_glIsShader = NULL;
+PFNGLISSYNCPROC glad_glIsSync = NULL;
+PFNGLISTEXTUREPROC glad_glIsTexture = NULL;
+PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL;
+PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL;
+PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL;
+PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL;
+PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL;
+PFNGLLIGHTFPROC glad_glLightf = NULL;
+PFNGLLIGHTFVPROC glad_glLightfv = NULL;
+PFNGLLIGHTIPROC glad_glLighti = NULL;
+PFNGLLIGHTIVPROC glad_glLightiv = NULL;
+PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL;
+PFNGLLINEWIDTHPROC glad_glLineWidth = NULL;
+PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
+PFNGLLISTBASEPROC glad_glListBase = NULL;
+PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL;
+PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL;
+PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL;
+PFNGLLOADNAMEPROC glad_glLoadName = NULL;
+PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL;
+PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL;
+PFNGLLOGICOPPROC glad_glLogicOp = NULL;
+PFNGLMAP1DPROC glad_glMap1d = NULL;
+PFNGLMAP1FPROC glad_glMap1f = NULL;
+PFNGLMAP2DPROC glad_glMap2d = NULL;
+PFNGLMAP2FPROC glad_glMap2f = NULL;
+PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
+PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
+PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL;
+PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL;
+PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL;
+PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL;
+PFNGLMATERIALFPROC glad_glMaterialf = NULL;
+PFNGLMATERIALFVPROC glad_glMaterialfv = NULL;
+PFNGLMATERIALIPROC glad_glMateriali = NULL;
+PFNGLMATERIALIVPROC glad_glMaterialiv = NULL;
+PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL;
+PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL;
+PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL;
+PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL;
+PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL;
+PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
+PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
+PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
+PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL;
+PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL;
+PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL;
+PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL;
+PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL;
+PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL;
+PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL;
+PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL;
+PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL;
+PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL;
+PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL;
+PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL;
+PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL;
+PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL;
+PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL;
+PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL;
+PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL;
+PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL;
+PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL;
+PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL;
+PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL;
+PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL;
+PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL;
+PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL;
+PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL;
+PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL;
+PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL;
+PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL;
+PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL;
+PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL;
+PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL;
+PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL;
+PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
+PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
+PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
+PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL;
+PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
+PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
+PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
+PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
+PFNGLNEWLISTPROC glad_glNewList = NULL;
+PFNGLNORMAL3BPROC glad_glNormal3b = NULL;
+PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL;
+PFNGLNORMAL3DPROC glad_glNormal3d = NULL;
+PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL;
+PFNGLNORMAL3FPROC glad_glNormal3f = NULL;
+PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL;
+PFNGLNORMAL3IPROC glad_glNormal3i = NULL;
+PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL;
+PFNGLNORMAL3SPROC glad_glNormal3s = NULL;
+PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL;
+PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
+PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
+PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL;
+PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
+PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL;
+PFNGLORTHOPROC glad_glOrtho = NULL;
+PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL;
+PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL;
+PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL;
+PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL;
+PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL;
+PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL;
+PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL;
+PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL;
+PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL;
+PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL;
+PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL;
+PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL;
+PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
+PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
+PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
+PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
+PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL;
+PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL;
+PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL;
+PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
+PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL;
+PFNGLPOPNAMEPROC glad_glPopName = NULL;
+PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
+PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL;
+PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL;
+PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL;
+PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL;
+PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL;
+PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL;
+PFNGLPUSHNAMEPROC glad_glPushName = NULL;
+PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL;
+PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL;
+PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL;
+PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL;
+PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL;
+PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL;
+PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL;
+PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL;
+PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL;
+PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL;
+PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL;
+PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL;
+PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL;
+PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL;
+PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL;
+PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL;
+PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL;
+PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL;
+PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL;
+PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL;
+PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL;
+PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL;
+PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL;
+PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL;
+PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL;
+PFNGLREADBUFFERPROC glad_glReadBuffer = NULL;
+PFNGLREADPIXELSPROC glad_glReadPixels = NULL;
+PFNGLREADNPIXELSPROC glad_glReadnPixels = NULL;
+PFNGLREADNPIXELSARBPROC glad_glReadnPixelsARB = NULL;
+PFNGLRECTDPROC glad_glRectd = NULL;
+PFNGLRECTDVPROC glad_glRectdv = NULL;
+PFNGLRECTFPROC glad_glRectf = NULL;
+PFNGLRECTFVPROC glad_glRectfv = NULL;
+PFNGLRECTIPROC glad_glRecti = NULL;
+PFNGLRECTIVPROC glad_glRectiv = NULL;
+PFNGLRECTSPROC glad_glRects = NULL;
+PFNGLRECTSVPROC glad_glRectsv = NULL;
+PFNGLRENDERMODEPROC glad_glRenderMode = NULL;
+PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL;
+PFNGLROTATEDPROC glad_glRotated = NULL;
+PFNGLROTATEFPROC glad_glRotatef = NULL;
+PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL;
+PFNGLSAMPLECOVERAGEARBPROC glad_glSampleCoverageARB = NULL;
+PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL;
+PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL;
+PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL;
+PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL;
+PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL;
+PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL;
+PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL;
+PFNGLSCALEDPROC glad_glScaled = NULL;
+PFNGLSCALEFPROC glad_glScalef = NULL;
+PFNGLSCISSORPROC glad_glScissor = NULL;
+PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL;
+PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL;
+PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL;
+PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL;
+PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL;
+PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL;
+PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL;
+PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL;
+PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL;
+PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL;
+PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL;
+PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL;
+PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL;
+PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL;
+PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL;
+PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL;
+PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL;
+PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
+PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL;
+PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL;
+PFNGLSHADEMODELPROC glad_glShadeModel = NULL;
+PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
+PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
+PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
+PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
+PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL;
+PFNGLSTENCILOPPROC glad_glStencilOp = NULL;
+PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL;
+PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL;
+PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL;
+PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL;
+PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL;
+PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL;
+PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL;
+PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL;
+PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL;
+PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL;
+PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL;
+PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL;
+PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL;
+PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL;
+PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL;
+PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL;
+PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL;
+PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL;
+PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL;
+PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL;
+PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL;
+PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL;
+PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL;
+PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL;
+PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL;
+PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL;
+PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL;
+PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL;
+PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL;
+PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL;
+PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL;
+PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL;
+PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL;
+PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL;
+PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL;
+PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL;
+PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL;
+PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL;
+PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL;
+PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL;
+PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL;
+PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL;
+PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL;
+PFNGLTEXENVFPROC glad_glTexEnvf = NULL;
+PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL;
+PFNGLTEXENVIPROC glad_glTexEnvi = NULL;
+PFNGLTEXENVIVPROC glad_glTexEnviv = NULL;
+PFNGLTEXGENDPROC glad_glTexGend = NULL;
+PFNGLTEXGENDVPROC glad_glTexGendv = NULL;
+PFNGLTEXGENFPROC glad_glTexGenf = NULL;
+PFNGLTEXGENFVPROC glad_glTexGenfv = NULL;
+PFNGLTEXGENIPROC glad_glTexGeni = NULL;
+PFNGLTEXGENIVPROC glad_glTexGeniv = NULL;
+PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL;
+PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL;
+PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL;
+PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL;
+PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL;
+PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL;
+PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL;
+PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL;
+PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL;
+PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL;
+PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL;
+PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
+PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
+PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
+PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
+PFNGLTRANSLATEDPROC glad_glTranslated = NULL;
+PFNGLTRANSLATEFPROC glad_glTranslatef = NULL;
+PFNGLUNIFORM1FPROC glad_glUniform1f = NULL;
+PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL;
+PFNGLUNIFORM1IPROC glad_glUniform1i = NULL;
+PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL;
+PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL;
+PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL;
+PFNGLUNIFORM2FPROC glad_glUniform2f = NULL;
+PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL;
+PFNGLUNIFORM2IPROC glad_glUniform2i = NULL;
+PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL;
+PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL;
+PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL;
+PFNGLUNIFORM3FPROC glad_glUniform3f = NULL;
+PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL;
+PFNGLUNIFORM3IPROC glad_glUniform3i = NULL;
+PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL;
+PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL;
+PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL;
+PFNGLUNIFORM4FPROC glad_glUniform4f = NULL;
+PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL;
+PFNGLUNIFORM4IPROC glad_glUniform4i = NULL;
+PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL;
+PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL;
+PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL;
+PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL;
+PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL;
+PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL;
+PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL;
+PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL;
+PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL;
+PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL;
+PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL;
+PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL;
+PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
+PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
+PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
+PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
+PFNGLVERTEX2DPROC glad_glVertex2d = NULL;
+PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL;
+PFNGLVERTEX2FPROC glad_glVertex2f = NULL;
+PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL;
+PFNGLVERTEX2IPROC glad_glVertex2i = NULL;
+PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL;
+PFNGLVERTEX2SPROC glad_glVertex2s = NULL;
+PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL;
+PFNGLVERTEX3DPROC glad_glVertex3d = NULL;
+PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL;
+PFNGLVERTEX3FPROC glad_glVertex3f = NULL;
+PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL;
+PFNGLVERTEX3IPROC glad_glVertex3i = NULL;
+PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL;
+PFNGLVERTEX3SPROC glad_glVertex3s = NULL;
+PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL;
+PFNGLVERTEX4DPROC glad_glVertex4d = NULL;
+PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL;
+PFNGLVERTEX4FPROC glad_glVertex4f = NULL;
+PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL;
+PFNGLVERTEX4IPROC glad_glVertex4i = NULL;
+PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL;
+PFNGLVERTEX4SPROC glad_glVertex4s = NULL;
+PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL;
+PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
+PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
+PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
+PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL;
+PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL;
+PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL;
+PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL;
+PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL;
+PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL;
+PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL;
+PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL;
+PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL;
+PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL;
+PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL;
+PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL;
+PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL;
+PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL;
+PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL;
+PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL;
+PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL;
+PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL;
+PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL;
+PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL;
+PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL;
+PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL;
+PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL;
+PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL;
+PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL;
+PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL;
+PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL;
+PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL;
+PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL;
+PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL;
+PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL;
+PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL;
+PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL;
+PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL;
+PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL;
+PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL;
+PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL;
+PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL;
+PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL;
+PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL;
+PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL;
+PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL;
+PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL;
+PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL;
+PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL;
+PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL;
+PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL;
+PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL;
+PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL;
+PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL;
+PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL;
+PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL;
+PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL;
+PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL;
+PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL;
+PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL;
+PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL;
+PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL;
+PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL;
+PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL;
+PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL;
+PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL;
+PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL;
+PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL;
+PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL;
+PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL;
+PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL;
+PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL;
+PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL;
+PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL;
+PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL;
+PFNGLVIEWPORTPROC glad_glViewport = NULL;
+PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
+PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL;
+PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL;
+PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL;
+PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL;
+PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL;
+PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL;
+PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL;
+PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL;
+PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL;
+PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL;
+PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL;
+PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL;
+PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL;
+PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL;
+PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL;
+PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL;
+
+
+static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_0) return;
+    glAccum = (PFNGLACCUMPROC) load("glAccum", userptr);
+    glAlphaFunc = (PFNGLALPHAFUNCPROC) load("glAlphaFunc", userptr);
+    glBegin = (PFNGLBEGINPROC) load("glBegin", userptr);
+    glBitmap = (PFNGLBITMAPPROC) load("glBitmap", userptr);
+    glBlendFunc = (PFNGLBLENDFUNCPROC) load("glBlendFunc", userptr);
+    glCallList = (PFNGLCALLLISTPROC) load("glCallList", userptr);
+    glCallLists = (PFNGLCALLLISTSPROC) load("glCallLists", userptr);
+    glClear = (PFNGLCLEARPROC) load("glClear", userptr);
+    glClearAccum = (PFNGLCLEARACCUMPROC) load("glClearAccum", userptr);
+    glClearColor = (PFNGLCLEARCOLORPROC) load("glClearColor", userptr);
+    glClearDepth = (PFNGLCLEARDEPTHPROC) load("glClearDepth", userptr);
+    glClearIndex = (PFNGLCLEARINDEXPROC) load("glClearIndex", userptr);
+    glClearStencil = (PFNGLCLEARSTENCILPROC) load("glClearStencil", userptr);
+    glClipPlane = (PFNGLCLIPPLANEPROC) load("glClipPlane", userptr);
+    glColor3b = (PFNGLCOLOR3BPROC) load("glColor3b", userptr);
+    glColor3bv = (PFNGLCOLOR3BVPROC) load("glColor3bv", userptr);
+    glColor3d = (PFNGLCOLOR3DPROC) load("glColor3d", userptr);
+    glColor3dv = (PFNGLCOLOR3DVPROC) load("glColor3dv", userptr);
+    glColor3f = (PFNGLCOLOR3FPROC) load("glColor3f", userptr);
+    glColor3fv = (PFNGLCOLOR3FVPROC) load("glColor3fv", userptr);
+    glColor3i = (PFNGLCOLOR3IPROC) load("glColor3i", userptr);
+    glColor3iv = (PFNGLCOLOR3IVPROC) load("glColor3iv", userptr);
+    glColor3s = (PFNGLCOLOR3SPROC) load("glColor3s", userptr);
+    glColor3sv = (PFNGLCOLOR3SVPROC) load("glColor3sv", userptr);
+    glColor3ub = (PFNGLCOLOR3UBPROC) load("glColor3ub", userptr);
+    glColor3ubv = (PFNGLCOLOR3UBVPROC) load("glColor3ubv", userptr);
+    glColor3ui = (PFNGLCOLOR3UIPROC) load("glColor3ui", userptr);
+    glColor3uiv = (PFNGLCOLOR3UIVPROC) load("glColor3uiv", userptr);
+    glColor3us = (PFNGLCOLOR3USPROC) load("glColor3us", userptr);
+    glColor3usv = (PFNGLCOLOR3USVPROC) load("glColor3usv", userptr);
+    glColor4b = (PFNGLCOLOR4BPROC) load("glColor4b", userptr);
+    glColor4bv = (PFNGLCOLOR4BVPROC) load("glColor4bv", userptr);
+    glColor4d = (PFNGLCOLOR4DPROC) load("glColor4d", userptr);
+    glColor4dv = (PFNGLCOLOR4DVPROC) load("glColor4dv", userptr);
+    glColor4f = (PFNGLCOLOR4FPROC) load("glColor4f", userptr);
+    glColor4fv = (PFNGLCOLOR4FVPROC) load("glColor4fv", userptr);
+    glColor4i = (PFNGLCOLOR4IPROC) load("glColor4i", userptr);
+    glColor4iv = (PFNGLCOLOR4IVPROC) load("glColor4iv", userptr);
+    glColor4s = (PFNGLCOLOR4SPROC) load("glColor4s", userptr);
+    glColor4sv = (PFNGLCOLOR4SVPROC) load("glColor4sv", userptr);
+    glColor4ub = (PFNGLCOLOR4UBPROC) load("glColor4ub", userptr);
+    glColor4ubv = (PFNGLCOLOR4UBVPROC) load("glColor4ubv", userptr);
+    glColor4ui = (PFNGLCOLOR4UIPROC) load("glColor4ui", userptr);
+    glColor4uiv = (PFNGLCOLOR4UIVPROC) load("glColor4uiv", userptr);
+    glColor4us = (PFNGLCOLOR4USPROC) load("glColor4us", userptr);
+    glColor4usv = (PFNGLCOLOR4USVPROC) load("glColor4usv", userptr);
+    glColorMask = (PFNGLCOLORMASKPROC) load("glColorMask", userptr);
+    glColorMaterial = (PFNGLCOLORMATERIALPROC) load("glColorMaterial", userptr);
+    glCopyPixels = (PFNGLCOPYPIXELSPROC) load("glCopyPixels", userptr);
+    glCullFace = (PFNGLCULLFACEPROC) load("glCullFace", userptr);
+    glDeleteLists = (PFNGLDELETELISTSPROC) load("glDeleteLists", userptr);
+    glDepthFunc = (PFNGLDEPTHFUNCPROC) load("glDepthFunc", userptr);
+    glDepthMask = (PFNGLDEPTHMASKPROC) load("glDepthMask", userptr);
+    glDepthRange = (PFNGLDEPTHRANGEPROC) load("glDepthRange", userptr);
+    glDisable = (PFNGLDISABLEPROC) load("glDisable", userptr);
+    glDrawBuffer = (PFNGLDRAWBUFFERPROC) load("glDrawBuffer", userptr);
+    glDrawPixels = (PFNGLDRAWPIXELSPROC) load("glDrawPixels", userptr);
+    glEdgeFlag = (PFNGLEDGEFLAGPROC) load("glEdgeFlag", userptr);
+    glEdgeFlagv = (PFNGLEDGEFLAGVPROC) load("glEdgeFlagv", userptr);
+    glEnable = (PFNGLENABLEPROC) load("glEnable", userptr);
+    glEnd = (PFNGLENDPROC) load("glEnd", userptr);
+    glEndList = (PFNGLENDLISTPROC) load("glEndList", userptr);
+    glEvalCoord1d = (PFNGLEVALCOORD1DPROC) load("glEvalCoord1d", userptr);
+    glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC) load("glEvalCoord1dv", userptr);
+    glEvalCoord1f = (PFNGLEVALCOORD1FPROC) load("glEvalCoord1f", userptr);
+    glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC) load("glEvalCoord1fv", userptr);
+    glEvalCoord2d = (PFNGLEVALCOORD2DPROC) load("glEvalCoord2d", userptr);
+    glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC) load("glEvalCoord2dv", userptr);
+    glEvalCoord2f = (PFNGLEVALCOORD2FPROC) load("glEvalCoord2f", userptr);
+    glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC) load("glEvalCoord2fv", userptr);
+    glEvalMesh1 = (PFNGLEVALMESH1PROC) load("glEvalMesh1", userptr);
+    glEvalMesh2 = (PFNGLEVALMESH2PROC) load("glEvalMesh2", userptr);
+    glEvalPoint1 = (PFNGLEVALPOINT1PROC) load("glEvalPoint1", userptr);
+    glEvalPoint2 = (PFNGLEVALPOINT2PROC) load("glEvalPoint2", userptr);
+    glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) load("glFeedbackBuffer", userptr);
+    glFinish = (PFNGLFINISHPROC) load("glFinish", userptr);
+    glFlush = (PFNGLFLUSHPROC) load("glFlush", userptr);
+    glFogf = (PFNGLFOGFPROC) load("glFogf", userptr);
+    glFogfv = (PFNGLFOGFVPROC) load("glFogfv", userptr);
+    glFogi = (PFNGLFOGIPROC) load("glFogi", userptr);
+    glFogiv = (PFNGLFOGIVPROC) load("glFogiv", userptr);
+    glFrontFace = (PFNGLFRONTFACEPROC) load("glFrontFace", userptr);
+    glFrustum = (PFNGLFRUSTUMPROC) load("glFrustum", userptr);
+    glGenLists = (PFNGLGENLISTSPROC) load("glGenLists", userptr);
+    glGetBooleanv = (PFNGLGETBOOLEANVPROC) load("glGetBooleanv", userptr);
+    glGetClipPlane = (PFNGLGETCLIPPLANEPROC) load("glGetClipPlane", userptr);
+    glGetDoublev = (PFNGLGETDOUBLEVPROC) load("glGetDoublev", userptr);
+    glGetError = (PFNGLGETERRORPROC) load("glGetError", userptr);
+    glGetFloatv = (PFNGLGETFLOATVPROC) load("glGetFloatv", userptr);
+    glGetIntegerv = (PFNGLGETINTEGERVPROC) load("glGetIntegerv", userptr);
+    glGetLightfv = (PFNGLGETLIGHTFVPROC) load("glGetLightfv", userptr);
+    glGetLightiv = (PFNGLGETLIGHTIVPROC) load("glGetLightiv", userptr);
+    glGetMapdv = (PFNGLGETMAPDVPROC) load("glGetMapdv", userptr);
+    glGetMapfv = (PFNGLGETMAPFVPROC) load("glGetMapfv", userptr);
+    glGetMapiv = (PFNGLGETMAPIVPROC) load("glGetMapiv", userptr);
+    glGetMaterialfv = (PFNGLGETMATERIALFVPROC) load("glGetMaterialfv", userptr);
+    glGetMaterialiv = (PFNGLGETMATERIALIVPROC) load("glGetMaterialiv", userptr);
+    glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC) load("glGetPixelMapfv", userptr);
+    glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC) load("glGetPixelMapuiv", userptr);
+    glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC) load("glGetPixelMapusv", userptr);
+    glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC) load("glGetPolygonStipple", userptr);
+    glGetString = (PFNGLGETSTRINGPROC) load("glGetString", userptr);
+    glGetTexEnvfv = (PFNGLGETTEXENVFVPROC) load("glGetTexEnvfv", userptr);
+    glGetTexEnviv = (PFNGLGETTEXENVIVPROC) load("glGetTexEnviv", userptr);
+    glGetTexGendv = (PFNGLGETTEXGENDVPROC) load("glGetTexGendv", userptr);
+    glGetTexGenfv = (PFNGLGETTEXGENFVPROC) load("glGetTexGenfv", userptr);
+    glGetTexGeniv = (PFNGLGETTEXGENIVPROC) load("glGetTexGeniv", userptr);
+    glGetTexImage = (PFNGLGETTEXIMAGEPROC) load("glGetTexImage", userptr);
+    glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load("glGetTexLevelParameterfv", userptr);
+    glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load("glGetTexLevelParameteriv", userptr);
+    glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load("glGetTexParameterfv", userptr);
+    glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load("glGetTexParameteriv", userptr);
+    glHint = (PFNGLHINTPROC) load("glHint", userptr);
+    glIndexMask = (PFNGLINDEXMASKPROC) load("glIndexMask", userptr);
+    glIndexd = (PFNGLINDEXDPROC) load("glIndexd", userptr);
+    glIndexdv = (PFNGLINDEXDVPROC) load("glIndexdv", userptr);
+    glIndexf = (PFNGLINDEXFPROC) load("glIndexf", userptr);
+    glIndexfv = (PFNGLINDEXFVPROC) load("glIndexfv", userptr);
+    glIndexi = (PFNGLINDEXIPROC) load("glIndexi", userptr);
+    glIndexiv = (PFNGLINDEXIVPROC) load("glIndexiv", userptr);
+    glIndexs = (PFNGLINDEXSPROC) load("glIndexs", userptr);
+    glIndexsv = (PFNGLINDEXSVPROC) load("glIndexsv", userptr);
+    glInitNames = (PFNGLINITNAMESPROC) load("glInitNames", userptr);
+    glIsEnabled = (PFNGLISENABLEDPROC) load("glIsEnabled", userptr);
+    glIsList = (PFNGLISLISTPROC) load("glIsList", userptr);
+    glLightModelf = (PFNGLLIGHTMODELFPROC) load("glLightModelf", userptr);
+    glLightModelfv = (PFNGLLIGHTMODELFVPROC) load("glLightModelfv", userptr);
+    glLightModeli = (PFNGLLIGHTMODELIPROC) load("glLightModeli", userptr);
+    glLightModeliv = (PFNGLLIGHTMODELIVPROC) load("glLightModeliv", userptr);
+    glLightf = (PFNGLLIGHTFPROC) load("glLightf", userptr);
+    glLightfv = (PFNGLLIGHTFVPROC) load("glLightfv", userptr);
+    glLighti = (PFNGLLIGHTIPROC) load("glLighti", userptr);
+    glLightiv = (PFNGLLIGHTIVPROC) load("glLightiv", userptr);
+    glLineStipple = (PFNGLLINESTIPPLEPROC) load("glLineStipple", userptr);
+    glLineWidth = (PFNGLLINEWIDTHPROC) load("glLineWidth", userptr);
+    glListBase = (PFNGLLISTBASEPROC) load("glListBase", userptr);
+    glLoadIdentity = (PFNGLLOADIDENTITYPROC) load("glLoadIdentity", userptr);
+    glLoadMatrixd = (PFNGLLOADMATRIXDPROC) load("glLoadMatrixd", userptr);
+    glLoadMatrixf = (PFNGLLOADMATRIXFPROC) load("glLoadMatrixf", userptr);
+    glLoadName = (PFNGLLOADNAMEPROC) load("glLoadName", userptr);
+    glLogicOp = (PFNGLLOGICOPPROC) load("glLogicOp", userptr);
+    glMap1d = (PFNGLMAP1DPROC) load("glMap1d", userptr);
+    glMap1f = (PFNGLMAP1FPROC) load("glMap1f", userptr);
+    glMap2d = (PFNGLMAP2DPROC) load("glMap2d", userptr);
+    glMap2f = (PFNGLMAP2FPROC) load("glMap2f", userptr);
+    glMapGrid1d = (PFNGLMAPGRID1DPROC) load("glMapGrid1d", userptr);
+    glMapGrid1f = (PFNGLMAPGRID1FPROC) load("glMapGrid1f", userptr);
+    glMapGrid2d = (PFNGLMAPGRID2DPROC) load("glMapGrid2d", userptr);
+    glMapGrid2f = (PFNGLMAPGRID2FPROC) load("glMapGrid2f", userptr);
+    glMaterialf = (PFNGLMATERIALFPROC) load("glMaterialf", userptr);
+    glMaterialfv = (PFNGLMATERIALFVPROC) load("glMaterialfv", userptr);
+    glMateriali = (PFNGLMATERIALIPROC) load("glMateriali", userptr);
+    glMaterialiv = (PFNGLMATERIALIVPROC) load("glMaterialiv", userptr);
+    glMatrixMode = (PFNGLMATRIXMODEPROC) load("glMatrixMode", userptr);
+    glMultMatrixd = (PFNGLMULTMATRIXDPROC) load("glMultMatrixd", userptr);
+    glMultMatrixf = (PFNGLMULTMATRIXFPROC) load("glMultMatrixf", userptr);
+    glNewList = (PFNGLNEWLISTPROC) load("glNewList", userptr);
+    glNormal3b = (PFNGLNORMAL3BPROC) load("glNormal3b", userptr);
+    glNormal3bv = (PFNGLNORMAL3BVPROC) load("glNormal3bv", userptr);
+    glNormal3d = (PFNGLNORMAL3DPROC) load("glNormal3d", userptr);
+    glNormal3dv = (PFNGLNORMAL3DVPROC) load("glNormal3dv", userptr);
+    glNormal3f = (PFNGLNORMAL3FPROC) load("glNormal3f", userptr);
+    glNormal3fv = (PFNGLNORMAL3FVPROC) load("glNormal3fv", userptr);
+    glNormal3i = (PFNGLNORMAL3IPROC) load("glNormal3i", userptr);
+    glNormal3iv = (PFNGLNORMAL3IVPROC) load("glNormal3iv", userptr);
+    glNormal3s = (PFNGLNORMAL3SPROC) load("glNormal3s", userptr);
+    glNormal3sv = (PFNGLNORMAL3SVPROC) load("glNormal3sv", userptr);
+    glOrtho = (PFNGLORTHOPROC) load("glOrtho", userptr);
+    glPassThrough = (PFNGLPASSTHROUGHPROC) load("glPassThrough", userptr);
+    glPixelMapfv = (PFNGLPIXELMAPFVPROC) load("glPixelMapfv", userptr);
+    glPixelMapuiv = (PFNGLPIXELMAPUIVPROC) load("glPixelMapuiv", userptr);
+    glPixelMapusv = (PFNGLPIXELMAPUSVPROC) load("glPixelMapusv", userptr);
+    glPixelStoref = (PFNGLPIXELSTOREFPROC) load("glPixelStoref", userptr);
+    glPixelStorei = (PFNGLPIXELSTOREIPROC) load("glPixelStorei", userptr);
+    glPixelTransferf = (PFNGLPIXELTRANSFERFPROC) load("glPixelTransferf", userptr);
+    glPixelTransferi = (PFNGLPIXELTRANSFERIPROC) load("glPixelTransferi", userptr);
+    glPixelZoom = (PFNGLPIXELZOOMPROC) load("glPixelZoom", userptr);
+    glPointSize = (PFNGLPOINTSIZEPROC) load("glPointSize", userptr);
+    glPolygonMode = (PFNGLPOLYGONMODEPROC) load("glPolygonMode", userptr);
+    glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC) load("glPolygonStipple", userptr);
+    glPopAttrib = (PFNGLPOPATTRIBPROC) load("glPopAttrib", userptr);
+    glPopMatrix = (PFNGLPOPMATRIXPROC) load("glPopMatrix", userptr);
+    glPopName = (PFNGLPOPNAMEPROC) load("glPopName", userptr);
+    glPushAttrib = (PFNGLPUSHATTRIBPROC) load("glPushAttrib", userptr);
+    glPushMatrix = (PFNGLPUSHMATRIXPROC) load("glPushMatrix", userptr);
+    glPushName = (PFNGLPUSHNAMEPROC) load("glPushName", userptr);
+    glRasterPos2d = (PFNGLRASTERPOS2DPROC) load("glRasterPos2d", userptr);
+    glRasterPos2dv = (PFNGLRASTERPOS2DVPROC) load("glRasterPos2dv", userptr);
+    glRasterPos2f = (PFNGLRASTERPOS2FPROC) load("glRasterPos2f", userptr);
+    glRasterPos2fv = (PFNGLRASTERPOS2FVPROC) load("glRasterPos2fv", userptr);
+    glRasterPos2i = (PFNGLRASTERPOS2IPROC) load("glRasterPos2i", userptr);
+    glRasterPos2iv = (PFNGLRASTERPOS2IVPROC) load("glRasterPos2iv", userptr);
+    glRasterPos2s = (PFNGLRASTERPOS2SPROC) load("glRasterPos2s", userptr);
+    glRasterPos2sv = (PFNGLRASTERPOS2SVPROC) load("glRasterPos2sv", userptr);
+    glRasterPos3d = (PFNGLRASTERPOS3DPROC) load("glRasterPos3d", userptr);
+    glRasterPos3dv = (PFNGLRASTERPOS3DVPROC) load("glRasterPos3dv", userptr);
+    glRasterPos3f = (PFNGLRASTERPOS3FPROC) load("glRasterPos3f", userptr);
+    glRasterPos3fv = (PFNGLRASTERPOS3FVPROC) load("glRasterPos3fv", userptr);
+    glRasterPos3i = (PFNGLRASTERPOS3IPROC) load("glRasterPos3i", userptr);
+    glRasterPos3iv = (PFNGLRASTERPOS3IVPROC) load("glRasterPos3iv", userptr);
+    glRasterPos3s = (PFNGLRASTERPOS3SPROC) load("glRasterPos3s", userptr);
+    glRasterPos3sv = (PFNGLRASTERPOS3SVPROC) load("glRasterPos3sv", userptr);
+    glRasterPos4d = (PFNGLRASTERPOS4DPROC) load("glRasterPos4d", userptr);
+    glRasterPos4dv = (PFNGLRASTERPOS4DVPROC) load("glRasterPos4dv", userptr);
+    glRasterPos4f = (PFNGLRASTERPOS4FPROC) load("glRasterPos4f", userptr);
+    glRasterPos4fv = (PFNGLRASTERPOS4FVPROC) load("glRasterPos4fv", userptr);
+    glRasterPos4i = (PFNGLRASTERPOS4IPROC) load("glRasterPos4i", userptr);
+    glRasterPos4iv = (PFNGLRASTERPOS4IVPROC) load("glRasterPos4iv", userptr);
+    glRasterPos4s = (PFNGLRASTERPOS4SPROC) load("glRasterPos4s", userptr);
+    glRasterPos4sv = (PFNGLRASTERPOS4SVPROC) load("glRasterPos4sv", userptr);
+    glReadBuffer = (PFNGLREADBUFFERPROC) load("glReadBuffer", userptr);
+    glReadPixels = (PFNGLREADPIXELSPROC) load("glReadPixels", userptr);
+    glRectd = (PFNGLRECTDPROC) load("glRectd", userptr);
+    glRectdv = (PFNGLRECTDVPROC) load("glRectdv", userptr);
+    glRectf = (PFNGLRECTFPROC) load("glRectf", userptr);
+    glRectfv = (PFNGLRECTFVPROC) load("glRectfv", userptr);
+    glRecti = (PFNGLRECTIPROC) load("glRecti", userptr);
+    glRectiv = (PFNGLRECTIVPROC) load("glRectiv", userptr);
+    glRects = (PFNGLRECTSPROC) load("glRects", userptr);
+    glRectsv = (PFNGLRECTSVPROC) load("glRectsv", userptr);
+    glRenderMode = (PFNGLRENDERMODEPROC) load("glRenderMode", userptr);
+    glRotated = (PFNGLROTATEDPROC) load("glRotated", userptr);
+    glRotatef = (PFNGLROTATEFPROC) load("glRotatef", userptr);
+    glScaled = (PFNGLSCALEDPROC) load("glScaled", userptr);
+    glScalef = (PFNGLSCALEFPROC) load("glScalef", userptr);
+    glScissor = (PFNGLSCISSORPROC) load("glScissor", userptr);
+    glSelectBuffer = (PFNGLSELECTBUFFERPROC) load("glSelectBuffer", userptr);
+    glShadeModel = (PFNGLSHADEMODELPROC) load("glShadeModel", userptr);
+    glStencilFunc = (PFNGLSTENCILFUNCPROC) load("glStencilFunc", userptr);
+    glStencilMask = (PFNGLSTENCILMASKPROC) load("glStencilMask", userptr);
+    glStencilOp = (PFNGLSTENCILOPPROC) load("glStencilOp", userptr);
+    glTexCoord1d = (PFNGLTEXCOORD1DPROC) load("glTexCoord1d", userptr);
+    glTexCoord1dv = (PFNGLTEXCOORD1DVPROC) load("glTexCoord1dv", userptr);
+    glTexCoord1f = (PFNGLTEXCOORD1FPROC) load("glTexCoord1f", userptr);
+    glTexCoord1fv = (PFNGLTEXCOORD1FVPROC) load("glTexCoord1fv", userptr);
+    glTexCoord1i = (PFNGLTEXCOORD1IPROC) load("glTexCoord1i", userptr);
+    glTexCoord1iv = (PFNGLTEXCOORD1IVPROC) load("glTexCoord1iv", userptr);
+    glTexCoord1s = (PFNGLTEXCOORD1SPROC) load("glTexCoord1s", userptr);
+    glTexCoord1sv = (PFNGLTEXCOORD1SVPROC) load("glTexCoord1sv", userptr);
+    glTexCoord2d = (PFNGLTEXCOORD2DPROC) load("glTexCoord2d", userptr);
+    glTexCoord2dv = (PFNGLTEXCOORD2DVPROC) load("glTexCoord2dv", userptr);
+    glTexCoord2f = (PFNGLTEXCOORD2FPROC) load("glTexCoord2f", userptr);
+    glTexCoord2fv = (PFNGLTEXCOORD2FVPROC) load("glTexCoord2fv", userptr);
+    glTexCoord2i = (PFNGLTEXCOORD2IPROC) load("glTexCoord2i", userptr);
+    glTexCoord2iv = (PFNGLTEXCOORD2IVPROC) load("glTexCoord2iv", userptr);
+    glTexCoord2s = (PFNGLTEXCOORD2SPROC) load("glTexCoord2s", userptr);
+    glTexCoord2sv = (PFNGLTEXCOORD2SVPROC) load("glTexCoord2sv", userptr);
+    glTexCoord3d = (PFNGLTEXCOORD3DPROC) load("glTexCoord3d", userptr);
+    glTexCoord3dv = (PFNGLTEXCOORD3DVPROC) load("glTexCoord3dv", userptr);
+    glTexCoord3f = (PFNGLTEXCOORD3FPROC) load("glTexCoord3f", userptr);
+    glTexCoord3fv = (PFNGLTEXCOORD3FVPROC) load("glTexCoord3fv", userptr);
+    glTexCoord3i = (PFNGLTEXCOORD3IPROC) load("glTexCoord3i", userptr);
+    glTexCoord3iv = (PFNGLTEXCOORD3IVPROC) load("glTexCoord3iv", userptr);
+    glTexCoord3s = (PFNGLTEXCOORD3SPROC) load("glTexCoord3s", userptr);
+    glTexCoord3sv = (PFNGLTEXCOORD3SVPROC) load("glTexCoord3sv", userptr);
+    glTexCoord4d = (PFNGLTEXCOORD4DPROC) load("glTexCoord4d", userptr);
+    glTexCoord4dv = (PFNGLTEXCOORD4DVPROC) load("glTexCoord4dv", userptr);
+    glTexCoord4f = (PFNGLTEXCOORD4FPROC) load("glTexCoord4f", userptr);
+    glTexCoord4fv = (PFNGLTEXCOORD4FVPROC) load("glTexCoord4fv", userptr);
+    glTexCoord4i = (PFNGLTEXCOORD4IPROC) load("glTexCoord4i", userptr);
+    glTexCoord4iv = (PFNGLTEXCOORD4IVPROC) load("glTexCoord4iv", userptr);
+    glTexCoord4s = (PFNGLTEXCOORD4SPROC) load("glTexCoord4s", userptr);
+    glTexCoord4sv = (PFNGLTEXCOORD4SVPROC) load("glTexCoord4sv", userptr);
+    glTexEnvf = (PFNGLTEXENVFPROC) load("glTexEnvf", userptr);
+    glTexEnvfv = (PFNGLTEXENVFVPROC) load("glTexEnvfv", userptr);
+    glTexEnvi = (PFNGLTEXENVIPROC) load("glTexEnvi", userptr);
+    glTexEnviv = (PFNGLTEXENVIVPROC) load("glTexEnviv", userptr);
+    glTexGend = (PFNGLTEXGENDPROC) load("glTexGend", userptr);
+    glTexGendv = (PFNGLTEXGENDVPROC) load("glTexGendv", userptr);
+    glTexGenf = (PFNGLTEXGENFPROC) load("glTexGenf", userptr);
+    glTexGenfv = (PFNGLTEXGENFVPROC) load("glTexGenfv", userptr);
+    glTexGeni = (PFNGLTEXGENIPROC) load("glTexGeni", userptr);
+    glTexGeniv = (PFNGLTEXGENIVPROC) load("glTexGeniv", userptr);
+    glTexImage1D = (PFNGLTEXIMAGE1DPROC) load("glTexImage1D", userptr);
+    glTexImage2D = (PFNGLTEXIMAGE2DPROC) load("glTexImage2D", userptr);
+    glTexParameterf = (PFNGLTEXPARAMETERFPROC) load("glTexParameterf", userptr);
+    glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load("glTexParameterfv", userptr);
+    glTexParameteri = (PFNGLTEXPARAMETERIPROC) load("glTexParameteri", userptr);
+    glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load("glTexParameteriv", userptr);
+    glTranslated = (PFNGLTRANSLATEDPROC) load("glTranslated", userptr);
+    glTranslatef = (PFNGLTRANSLATEFPROC) load("glTranslatef", userptr);
+    glVertex2d = (PFNGLVERTEX2DPROC) load("glVertex2d", userptr);
+    glVertex2dv = (PFNGLVERTEX2DVPROC) load("glVertex2dv", userptr);
+    glVertex2f = (PFNGLVERTEX2FPROC) load("glVertex2f", userptr);
+    glVertex2fv = (PFNGLVERTEX2FVPROC) load("glVertex2fv", userptr);
+    glVertex2i = (PFNGLVERTEX2IPROC) load("glVertex2i", userptr);
+    glVertex2iv = (PFNGLVERTEX2IVPROC) load("glVertex2iv", userptr);
+    glVertex2s = (PFNGLVERTEX2SPROC) load("glVertex2s", userptr);
+    glVertex2sv = (PFNGLVERTEX2SVPROC) load("glVertex2sv", userptr);
+    glVertex3d = (PFNGLVERTEX3DPROC) load("glVertex3d", userptr);
+    glVertex3dv = (PFNGLVERTEX3DVPROC) load("glVertex3dv", userptr);
+    glVertex3f = (PFNGLVERTEX3FPROC) load("glVertex3f", userptr);
+    glVertex3fv = (PFNGLVERTEX3FVPROC) load("glVertex3fv", userptr);
+    glVertex3i = (PFNGLVERTEX3IPROC) load("glVertex3i", userptr);
+    glVertex3iv = (PFNGLVERTEX3IVPROC) load("glVertex3iv", userptr);
+    glVertex3s = (PFNGLVERTEX3SPROC) load("glVertex3s", userptr);
+    glVertex3sv = (PFNGLVERTEX3SVPROC) load("glVertex3sv", userptr);
+    glVertex4d = (PFNGLVERTEX4DPROC) load("glVertex4d", userptr);
+    glVertex4dv = (PFNGLVERTEX4DVPROC) load("glVertex4dv", userptr);
+    glVertex4f = (PFNGLVERTEX4FPROC) load("glVertex4f", userptr);
+    glVertex4fv = (PFNGLVERTEX4FVPROC) load("glVertex4fv", userptr);
+    glVertex4i = (PFNGLVERTEX4IPROC) load("glVertex4i", userptr);
+    glVertex4iv = (PFNGLVERTEX4IVPROC) load("glVertex4iv", userptr);
+    glVertex4s = (PFNGLVERTEX4SPROC) load("glVertex4s", userptr);
+    glVertex4sv = (PFNGLVERTEX4SVPROC) load("glVertex4sv", userptr);
+    glViewport = (PFNGLVIEWPORTPROC) load("glViewport", userptr);
+}
+static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_1) return;
+    glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC) load("glAreTexturesResident", userptr);
+    glArrayElement = (PFNGLARRAYELEMENTPROC) load("glArrayElement", userptr);
+    glBindTexture = (PFNGLBINDTEXTUREPROC) load("glBindTexture", userptr);
+    glColorPointer = (PFNGLCOLORPOINTERPROC) load("glColorPointer", userptr);
+    glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load("glCopyTexImage1D", userptr);
+    glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load("glCopyTexImage2D", userptr);
+    glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load("glCopyTexSubImage1D", userptr);
+    glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load("glCopyTexSubImage2D", userptr);
+    glDeleteTextures = (PFNGLDELETETEXTURESPROC) load("glDeleteTextures", userptr);
+    glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC) load("glDisableClientState", userptr);
+    glDrawArrays = (PFNGLDRAWARRAYSPROC) load("glDrawArrays", userptr);
+    glDrawElements = (PFNGLDRAWELEMENTSPROC) load("glDrawElements", userptr);
+    glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC) load("glEdgeFlagPointer", userptr);
+    glEnableClientState = (PFNGLENABLECLIENTSTATEPROC) load("glEnableClientState", userptr);
+    glGenTextures = (PFNGLGENTEXTURESPROC) load("glGenTextures", userptr);
+    glGetPointerv = (PFNGLGETPOINTERVPROC) load("glGetPointerv", userptr);
+    glIndexPointer = (PFNGLINDEXPOINTERPROC) load("glIndexPointer", userptr);
+    glIndexub = (PFNGLINDEXUBPROC) load("glIndexub", userptr);
+    glIndexubv = (PFNGLINDEXUBVPROC) load("glIndexubv", userptr);
+    glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC) load("glInterleavedArrays", userptr);
+    glIsTexture = (PFNGLISTEXTUREPROC) load("glIsTexture", userptr);
+    glNormalPointer = (PFNGLNORMALPOINTERPROC) load("glNormalPointer", userptr);
+    glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load("glPolygonOffset", userptr);
+    glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC) load("glPopClientAttrib", userptr);
+    glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC) load("glPrioritizeTextures", userptr);
+    glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC) load("glPushClientAttrib", userptr);
+    glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC) load("glTexCoordPointer", userptr);
+    glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load("glTexSubImage1D", userptr);
+    glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load("glTexSubImage2D", userptr);
+    glVertexPointer = (PFNGLVERTEXPOINTERPROC) load("glVertexPointer", userptr);
+}
+static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_2) return;
+    glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load("glCopyTexSubImage3D", userptr);
+    glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load("glDrawRangeElements", userptr);
+    glTexImage3D = (PFNGLTEXIMAGE3DPROC) load("glTexImage3D", userptr);
+    glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load("glTexSubImage3D", userptr);
+}
+static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_3) return;
+    glActiveTexture = (PFNGLACTIVETEXTUREPROC) load("glActiveTexture", userptr);
+    glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC) load("glClientActiveTexture", userptr);
+    glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load("glCompressedTexImage1D", userptr);
+    glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load("glCompressedTexImage2D", userptr);
+    glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load("glCompressedTexImage3D", userptr);
+    glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load("glCompressedTexSubImage1D", userptr);
+    glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load("glCompressedTexSubImage2D", userptr);
+    glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load("glCompressedTexSubImage3D", userptr);
+    glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load("glGetCompressedTexImage", userptr);
+    glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC) load("glLoadTransposeMatrixd", userptr);
+    glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC) load("glLoadTransposeMatrixf", userptr);
+    glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC) load("glMultTransposeMatrixd", userptr);
+    glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC) load("glMultTransposeMatrixf", userptr);
+    glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) load("glMultiTexCoord1d", userptr);
+    glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC) load("glMultiTexCoord1dv", userptr);
+    glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) load("glMultiTexCoord1f", userptr);
+    glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC) load("glMultiTexCoord1fv", userptr);
+    glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC) load("glMultiTexCoord1i", userptr);
+    glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC) load("glMultiTexCoord1iv", userptr);
+    glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC) load("glMultiTexCoord1s", userptr);
+    glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC) load("glMultiTexCoord1sv", userptr);
+    glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) load("glMultiTexCoord2d", userptr);
+    glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC) load("glMultiTexCoord2dv", userptr);
+    glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) load("glMultiTexCoord2f", userptr);
+    glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC) load("glMultiTexCoord2fv", userptr);
+    glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC) load("glMultiTexCoord2i", userptr);
+    glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC) load("glMultiTexCoord2iv", userptr);
+    glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC) load("glMultiTexCoord2s", userptr);
+    glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC) load("glMultiTexCoord2sv", userptr);
+    glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) load("glMultiTexCoord3d", userptr);
+    glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC) load("glMultiTexCoord3dv", userptr);
+    glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) load("glMultiTexCoord3f", userptr);
+    glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC) load("glMultiTexCoord3fv", userptr);
+    glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC) load("glMultiTexCoord3i", userptr);
+    glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC) load("glMultiTexCoord3iv", userptr);
+    glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC) load("glMultiTexCoord3s", userptr);
+    glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC) load("glMultiTexCoord3sv", userptr);
+    glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) load("glMultiTexCoord4d", userptr);
+    glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC) load("glMultiTexCoord4dv", userptr);
+    glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) load("glMultiTexCoord4f", userptr);
+    glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC) load("glMultiTexCoord4fv", userptr);
+    glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC) load("glMultiTexCoord4i", userptr);
+    glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC) load("glMultiTexCoord4iv", userptr);
+    glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC) load("glMultiTexCoord4s", userptr);
+    glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC) load("glMultiTexCoord4sv", userptr);
+    glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load("glSampleCoverage", userptr);
+}
+static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_4) return;
+    glBlendColor = (PFNGLBLENDCOLORPROC) load("glBlendColor", userptr);
+    glBlendEquation = (PFNGLBLENDEQUATIONPROC) load("glBlendEquation", userptr);
+    glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load("glBlendFuncSeparate", userptr);
+    glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC) load("glFogCoordPointer", userptr);
+    glFogCoordd = (PFNGLFOGCOORDDPROC) load("glFogCoordd", userptr);
+    glFogCoorddv = (PFNGLFOGCOORDDVPROC) load("glFogCoorddv", userptr);
+    glFogCoordf = (PFNGLFOGCOORDFPROC) load("glFogCoordf", userptr);
+    glFogCoordfv = (PFNGLFOGCOORDFVPROC) load("glFogCoordfv", userptr);
+    glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load("glMultiDrawArrays", userptr);
+    glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load("glMultiDrawElements", userptr);
+    glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load("glPointParameterf", userptr);
+    glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load("glPointParameterfv", userptr);
+    glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load("glPointParameteri", userptr);
+    glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load("glPointParameteriv", userptr);
+    glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC) load("glSecondaryColor3b", userptr);
+    glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC) load("glSecondaryColor3bv", userptr);
+    glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC) load("glSecondaryColor3d", userptr);
+    glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC) load("glSecondaryColor3dv", userptr);
+    glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC) load("glSecondaryColor3f", userptr);
+    glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC) load("glSecondaryColor3fv", userptr);
+    glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC) load("glSecondaryColor3i", userptr);
+    glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC) load("glSecondaryColor3iv", userptr);
+    glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC) load("glSecondaryColor3s", userptr);
+    glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC) load("glSecondaryColor3sv", userptr);
+    glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC) load("glSecondaryColor3ub", userptr);
+    glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC) load("glSecondaryColor3ubv", userptr);
+    glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC) load("glSecondaryColor3ui", userptr);
+    glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC) load("glSecondaryColor3uiv", userptr);
+    glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC) load("glSecondaryColor3us", userptr);
+    glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC) load("glSecondaryColor3usv", userptr);
+    glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC) load("glSecondaryColorPointer", userptr);
+    glWindowPos2d = (PFNGLWINDOWPOS2DPROC) load("glWindowPos2d", userptr);
+    glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC) load("glWindowPos2dv", userptr);
+    glWindowPos2f = (PFNGLWINDOWPOS2FPROC) load("glWindowPos2f", userptr);
+    glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC) load("glWindowPos2fv", userptr);
+    glWindowPos2i = (PFNGLWINDOWPOS2IPROC) load("glWindowPos2i", userptr);
+    glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC) load("glWindowPos2iv", userptr);
+    glWindowPos2s = (PFNGLWINDOWPOS2SPROC) load("glWindowPos2s", userptr);
+    glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC) load("glWindowPos2sv", userptr);
+    glWindowPos3d = (PFNGLWINDOWPOS3DPROC) load("glWindowPos3d", userptr);
+    glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC) load("glWindowPos3dv", userptr);
+    glWindowPos3f = (PFNGLWINDOWPOS3FPROC) load("glWindowPos3f", userptr);
+    glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC) load("glWindowPos3fv", userptr);
+    glWindowPos3i = (PFNGLWINDOWPOS3IPROC) load("glWindowPos3i", userptr);
+    glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC) load("glWindowPos3iv", userptr);
+    glWindowPos3s = (PFNGLWINDOWPOS3SPROC) load("glWindowPos3s", userptr);
+    glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC) load("glWindowPos3sv", userptr);
+}
+static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_1_5) return;
+    glBeginQuery = (PFNGLBEGINQUERYPROC) load("glBeginQuery", userptr);
+    glBindBuffer = (PFNGLBINDBUFFERPROC) load("glBindBuffer", userptr);
+    glBufferData = (PFNGLBUFFERDATAPROC) load("glBufferData", userptr);
+    glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load("glBufferSubData", userptr);
+    glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load("glDeleteBuffers", userptr);
+    glDeleteQueries = (PFNGLDELETEQUERIESPROC) load("glDeleteQueries", userptr);
+    glEndQuery = (PFNGLENDQUERYPROC) load("glEndQuery", userptr);
+    glGenBuffers = (PFNGLGENBUFFERSPROC) load("glGenBuffers", userptr);
+    glGenQueries = (PFNGLGENQUERIESPROC) load("glGenQueries", userptr);
+    glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load("glGetBufferParameteriv", userptr);
+    glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load("glGetBufferPointerv", userptr);
+    glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load("glGetBufferSubData", userptr);
+    glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load("glGetQueryObjectiv", userptr);
+    glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load("glGetQueryObjectuiv", userptr);
+    glGetQueryiv = (PFNGLGETQUERYIVPROC) load("glGetQueryiv", userptr);
+    glIsBuffer = (PFNGLISBUFFERPROC) load("glIsBuffer", userptr);
+    glIsQuery = (PFNGLISQUERYPROC) load("glIsQuery", userptr);
+    glMapBuffer = (PFNGLMAPBUFFERPROC) load("glMapBuffer", userptr);
+    glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load("glUnmapBuffer", userptr);
+}
+static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_2_0) return;
+    glAttachShader = (PFNGLATTACHSHADERPROC) load("glAttachShader", userptr);
+    glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load("glBindAttribLocation", userptr);
+    glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load("glBlendEquationSeparate", userptr);
+    glCompileShader = (PFNGLCOMPILESHADERPROC) load("glCompileShader", userptr);
+    glCreateProgram = (PFNGLCREATEPROGRAMPROC) load("glCreateProgram", userptr);
+    glCreateShader = (PFNGLCREATESHADERPROC) load("glCreateShader", userptr);
+    glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load("glDeleteProgram", userptr);
+    glDeleteShader = (PFNGLDELETESHADERPROC) load("glDeleteShader", userptr);
+    glDetachShader = (PFNGLDETACHSHADERPROC) load("glDetachShader", userptr);
+    glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load("glDisableVertexAttribArray", userptr);
+    glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load("glDrawBuffers", userptr);
+    glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load("glEnableVertexAttribArray", userptr);
+    glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load("glGetActiveAttrib", userptr);
+    glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load("glGetActiveUniform", userptr);
+    glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load("glGetAttachedShaders", userptr);
+    glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load("glGetAttribLocation", userptr);
+    glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load("glGetProgramInfoLog", userptr);
+    glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load("glGetProgramiv", userptr);
+    glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load("glGetShaderInfoLog", userptr);
+    glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load("glGetShaderSource", userptr);
+    glGetShaderiv = (PFNGLGETSHADERIVPROC) load("glGetShaderiv", userptr);
+    glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load("glGetUniformLocation", userptr);
+    glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load("glGetUniformfv", userptr);
+    glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load("glGetUniformiv", userptr);
+    glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load("glGetVertexAttribPointerv", userptr);
+    glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load("glGetVertexAttribdv", userptr);
+    glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load("glGetVertexAttribfv", userptr);
+    glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load("glGetVertexAttribiv", userptr);
+    glIsProgram = (PFNGLISPROGRAMPROC) load("glIsProgram", userptr);
+    glIsShader = (PFNGLISSHADERPROC) load("glIsShader", userptr);
+    glLinkProgram = (PFNGLLINKPROGRAMPROC) load("glLinkProgram", userptr);
+    glShaderSource = (PFNGLSHADERSOURCEPROC) load("glShaderSource", userptr);
+    glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load("glStencilFuncSeparate", userptr);
+    glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load("glStencilMaskSeparate", userptr);
+    glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load("glStencilOpSeparate", userptr);
+    glUniform1f = (PFNGLUNIFORM1FPROC) load("glUniform1f", userptr);
+    glUniform1fv = (PFNGLUNIFORM1FVPROC) load("glUniform1fv", userptr);
+    glUniform1i = (PFNGLUNIFORM1IPROC) load("glUniform1i", userptr);
+    glUniform1iv = (PFNGLUNIFORM1IVPROC) load("glUniform1iv", userptr);
+    glUniform2f = (PFNGLUNIFORM2FPROC) load("glUniform2f", userptr);
+    glUniform2fv = (PFNGLUNIFORM2FVPROC) load("glUniform2fv", userptr);
+    glUniform2i = (PFNGLUNIFORM2IPROC) load("glUniform2i", userptr);
+    glUniform2iv = (PFNGLUNIFORM2IVPROC) load("glUniform2iv", userptr);
+    glUniform3f = (PFNGLUNIFORM3FPROC) load("glUniform3f", userptr);
+    glUniform3fv = (PFNGLUNIFORM3FVPROC) load("glUniform3fv", userptr);
+    glUniform3i = (PFNGLUNIFORM3IPROC) load("glUniform3i", userptr);
+    glUniform3iv = (PFNGLUNIFORM3IVPROC) load("glUniform3iv", userptr);
+    glUniform4f = (PFNGLUNIFORM4FPROC) load("glUniform4f", userptr);
+    glUniform4fv = (PFNGLUNIFORM4FVPROC) load("glUniform4fv", userptr);
+    glUniform4i = (PFNGLUNIFORM4IPROC) load("glUniform4i", userptr);
+    glUniform4iv = (PFNGLUNIFORM4IVPROC) load("glUniform4iv", userptr);
+    glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load("glUniformMatrix2fv", userptr);
+    glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load("glUniformMatrix3fv", userptr);
+    glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load("glUniformMatrix4fv", userptr);
+    glUseProgram = (PFNGLUSEPROGRAMPROC) load("glUseProgram", userptr);
+    glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load("glValidateProgram", userptr);
+    glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load("glVertexAttrib1d", userptr);
+    glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load("glVertexAttrib1dv", userptr);
+    glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load("glVertexAttrib1f", userptr);
+    glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load("glVertexAttrib1fv", userptr);
+    glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load("glVertexAttrib1s", userptr);
+    glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load("glVertexAttrib1sv", userptr);
+    glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load("glVertexAttrib2d", userptr);
+    glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load("glVertexAttrib2dv", userptr);
+    glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load("glVertexAttrib2f", userptr);
+    glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load("glVertexAttrib2fv", userptr);
+    glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load("glVertexAttrib2s", userptr);
+    glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load("glVertexAttrib2sv", userptr);
+    glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load("glVertexAttrib3d", userptr);
+    glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load("glVertexAttrib3dv", userptr);
+    glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load("glVertexAttrib3f", userptr);
+    glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load("glVertexAttrib3fv", userptr);
+    glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load("glVertexAttrib3s", userptr);
+    glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load("glVertexAttrib3sv", userptr);
+    glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load("glVertexAttrib4Nbv", userptr);
+    glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load("glVertexAttrib4Niv", userptr);
+    glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load("glVertexAttrib4Nsv", userptr);
+    glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load("glVertexAttrib4Nub", userptr);
+    glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load("glVertexAttrib4Nubv", userptr);
+    glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load("glVertexAttrib4Nuiv", userptr);
+    glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load("glVertexAttrib4Nusv", userptr);
+    glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load("glVertexAttrib4bv", userptr);
+    glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load("glVertexAttrib4d", userptr);
+    glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load("glVertexAttrib4dv", userptr);
+    glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load("glVertexAttrib4f", userptr);
+    glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load("glVertexAttrib4fv", userptr);
+    glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load("glVertexAttrib4iv", userptr);
+    glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load("glVertexAttrib4s", userptr);
+    glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load("glVertexAttrib4sv", userptr);
+    glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load("glVertexAttrib4ubv", userptr);
+    glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load("glVertexAttrib4uiv", userptr);
+    glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load("glVertexAttrib4usv", userptr);
+    glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load("glVertexAttribPointer", userptr);
+}
+static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_2_1) return;
+    glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load("glUniformMatrix2x3fv", userptr);
+    glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load("glUniformMatrix2x4fv", userptr);
+    glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load("glUniformMatrix3x2fv", userptr);
+    glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load("glUniformMatrix3x4fv", userptr);
+    glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load("glUniformMatrix4x2fv", userptr);
+    glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load("glUniformMatrix4x3fv", userptr);
+}
+static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_3_0) return;
+    glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load("glBeginConditionalRender", userptr);
+    glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load("glBeginTransformFeedback", userptr);
+    glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load("glBindBufferBase", userptr);
+    glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load("glBindBufferRange", userptr);
+    glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load("glBindFragDataLocation", userptr);
+    glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load("glBindFramebuffer", userptr);
+    glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load("glBindRenderbuffer", userptr);
+    glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load("glBindVertexArray", userptr);
+    glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load("glBlitFramebuffer", userptr);
+    glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load("glCheckFramebufferStatus", userptr);
+    glClampColor = (PFNGLCLAMPCOLORPROC) load("glClampColor", userptr);
+    glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load("glClearBufferfi", userptr);
+    glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load("glClearBufferfv", userptr);
+    glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load("glClearBufferiv", userptr);
+    glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load("glClearBufferuiv", userptr);
+    glColorMaski = (PFNGLCOLORMASKIPROC) load("glColorMaski", userptr);
+    glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load("glDeleteFramebuffers", userptr);
+    glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load("glDeleteRenderbuffers", userptr);
+    glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load("glDeleteVertexArrays", userptr);
+    glDisablei = (PFNGLDISABLEIPROC) load("glDisablei", userptr);
+    glEnablei = (PFNGLENABLEIPROC) load("glEnablei", userptr);
+    glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load("glEndConditionalRender", userptr);
+    glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load("glEndTransformFeedback", userptr);
+    glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load("glFlushMappedBufferRange", userptr);
+    glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load("glFramebufferRenderbuffer", userptr);
+    glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load("glFramebufferTexture1D", userptr);
+    glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load("glFramebufferTexture2D", userptr);
+    glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load("glFramebufferTexture3D", userptr);
+    glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load("glFramebufferTextureLayer", userptr);
+    glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load("glGenFramebuffers", userptr);
+    glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load("glGenRenderbuffers", userptr);
+    glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load("glGenVertexArrays", userptr);
+    glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load("glGenerateMipmap", userptr);
+    glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load("glGetBooleani_v", userptr);
+    glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load("glGetFragDataLocation", userptr);
+    glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load("glGetFramebufferAttachmentParameteriv", userptr);
+    glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load("glGetIntegeri_v", userptr);
+    glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load("glGetRenderbufferParameteriv", userptr);
+    glGetStringi = (PFNGLGETSTRINGIPROC) load("glGetStringi", userptr);
+    glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load("glGetTexParameterIiv", userptr);
+    glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load("glGetTexParameterIuiv", userptr);
+    glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load("glGetTransformFeedbackVarying", userptr);
+    glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load("glGetUniformuiv", userptr);
+    glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load("glGetVertexAttribIiv", userptr);
+    glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load("glGetVertexAttribIuiv", userptr);
+    glIsEnabledi = (PFNGLISENABLEDIPROC) load("glIsEnabledi", userptr);
+    glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load("glIsFramebuffer", userptr);
+    glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load("glIsRenderbuffer", userptr);
+    glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load("glIsVertexArray", userptr);
+    glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load("glMapBufferRange", userptr);
+    glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load("glRenderbufferStorage", userptr);
+    glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load("glRenderbufferStorageMultisample", userptr);
+    glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load("glTexParameterIiv", userptr);
+    glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load("glTexParameterIuiv", userptr);
+    glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load("glTransformFeedbackVaryings", userptr);
+    glUniform1ui = (PFNGLUNIFORM1UIPROC) load("glUniform1ui", userptr);
+    glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load("glUniform1uiv", userptr);
+    glUniform2ui = (PFNGLUNIFORM2UIPROC) load("glUniform2ui", userptr);
+    glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load("glUniform2uiv", userptr);
+    glUniform3ui = (PFNGLUNIFORM3UIPROC) load("glUniform3ui", userptr);
+    glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load("glUniform3uiv", userptr);
+    glUniform4ui = (PFNGLUNIFORM4UIPROC) load("glUniform4ui", userptr);
+    glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load("glUniform4uiv", userptr);
+    glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load("glVertexAttribI1i", userptr);
+    glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load("glVertexAttribI1iv", userptr);
+    glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load("glVertexAttribI1ui", userptr);
+    glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load("glVertexAttribI1uiv", userptr);
+    glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load("glVertexAttribI2i", userptr);
+    glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load("glVertexAttribI2iv", userptr);
+    glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load("glVertexAttribI2ui", userptr);
+    glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load("glVertexAttribI2uiv", userptr);
+    glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load("glVertexAttribI3i", userptr);
+    glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load("glVertexAttribI3iv", userptr);
+    glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load("glVertexAttribI3ui", userptr);
+    glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load("glVertexAttribI3uiv", userptr);
+    glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load("glVertexAttribI4bv", userptr);
+    glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load("glVertexAttribI4i", userptr);
+    glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load("glVertexAttribI4iv", userptr);
+    glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load("glVertexAttribI4sv", userptr);
+    glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load("glVertexAttribI4ubv", userptr);
+    glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load("glVertexAttribI4ui", userptr);
+    glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load("glVertexAttribI4uiv", userptr);
+    glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load("glVertexAttribI4usv", userptr);
+    glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load("glVertexAttribIPointer", userptr);
+}
+static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_3_1) return;
+    glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load("glBindBufferBase", userptr);
+    glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load("glBindBufferRange", userptr);
+    glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load("glCopyBufferSubData", userptr);
+    glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load("glDrawArraysInstanced", userptr);
+    glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load("glDrawElementsInstanced", userptr);
+    glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load("glGetActiveUniformBlockName", userptr);
+    glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load("glGetActiveUniformBlockiv", userptr);
+    glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load("glGetActiveUniformName", userptr);
+    glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load("glGetActiveUniformsiv", userptr);
+    glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load("glGetIntegeri_v", userptr);
+    glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load("glGetUniformBlockIndex", userptr);
+    glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load("glGetUniformIndices", userptr);
+    glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load("glPrimitiveRestartIndex", userptr);
+    glTexBuffer = (PFNGLTEXBUFFERPROC) load("glTexBuffer", userptr);
+    glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load("glUniformBlockBinding", userptr);
+}
+static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_3_2) return;
+    glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load("glClientWaitSync", userptr);
+    glDeleteSync = (PFNGLDELETESYNCPROC) load("glDeleteSync", userptr);
+    glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load("glDrawElementsBaseVertex", userptr);
+    glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load("glDrawElementsInstancedBaseVertex", userptr);
+    glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load("glDrawRangeElementsBaseVertex", userptr);
+    glFenceSync = (PFNGLFENCESYNCPROC) load("glFenceSync", userptr);
+    glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load("glFramebufferTexture", userptr);
+    glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load("glGetBufferParameteri64v", userptr);
+    glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load("glGetInteger64i_v", userptr);
+    glGetInteger64v = (PFNGLGETINTEGER64VPROC) load("glGetInteger64v", userptr);
+    glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load("glGetMultisamplefv", userptr);
+    glGetSynciv = (PFNGLGETSYNCIVPROC) load("glGetSynciv", userptr);
+    glIsSync = (PFNGLISSYNCPROC) load("glIsSync", userptr);
+    glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load("glMultiDrawElementsBaseVertex", userptr);
+    glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load("glProvokingVertex", userptr);
+    glSampleMaski = (PFNGLSAMPLEMASKIPROC) load("glSampleMaski", userptr);
+    glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load("glTexImage2DMultisample", userptr);
+    glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load("glTexImage3DMultisample", userptr);
+    glWaitSync = (PFNGLWAITSYNCPROC) load("glWaitSync", userptr);
+}
+static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_VERSION_3_3) return;
+    glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load("glBindFragDataLocationIndexed", userptr);
+    glBindSampler = (PFNGLBINDSAMPLERPROC) load("glBindSampler", userptr);
+    glColorP3ui = (PFNGLCOLORP3UIPROC) load("glColorP3ui", userptr);
+    glColorP3uiv = (PFNGLCOLORP3UIVPROC) load("glColorP3uiv", userptr);
+    glColorP4ui = (PFNGLCOLORP4UIPROC) load("glColorP4ui", userptr);
+    glColorP4uiv = (PFNGLCOLORP4UIVPROC) load("glColorP4uiv", userptr);
+    glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load("glDeleteSamplers", userptr);
+    glGenSamplers = (PFNGLGENSAMPLERSPROC) load("glGenSamplers", userptr);
+    glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load("glGetFragDataIndex", userptr);
+    glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load("glGetQueryObjecti64v", userptr);
+    glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load("glGetQueryObjectui64v", userptr);
+    glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load("glGetSamplerParameterIiv", userptr);
+    glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load("glGetSamplerParameterIuiv", userptr);
+    glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load("glGetSamplerParameterfv", userptr);
+    glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load("glGetSamplerParameteriv", userptr);
+    glIsSampler = (PFNGLISSAMPLERPROC) load("glIsSampler", userptr);
+    glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load("glMultiTexCoordP1ui", userptr);
+    glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load("glMultiTexCoordP1uiv", userptr);
+    glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load("glMultiTexCoordP2ui", userptr);
+    glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load("glMultiTexCoordP2uiv", userptr);
+    glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load("glMultiTexCoordP3ui", userptr);
+    glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load("glMultiTexCoordP3uiv", userptr);
+    glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load("glMultiTexCoordP4ui", userptr);
+    glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load("glMultiTexCoordP4uiv", userptr);
+    glNormalP3ui = (PFNGLNORMALP3UIPROC) load("glNormalP3ui", userptr);
+    glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load("glNormalP3uiv", userptr);
+    glQueryCounter = (PFNGLQUERYCOUNTERPROC) load("glQueryCounter", userptr);
+    glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load("glSamplerParameterIiv", userptr);
+    glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load("glSamplerParameterIuiv", userptr);
+    glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load("glSamplerParameterf", userptr);
+    glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load("glSamplerParameterfv", userptr);
+    glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load("glSamplerParameteri", userptr);
+    glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load("glSamplerParameteriv", userptr);
+    glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load("glSecondaryColorP3ui", userptr);
+    glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load("glSecondaryColorP3uiv", userptr);
+    glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load("glTexCoordP1ui", userptr);
+    glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load("glTexCoordP1uiv", userptr);
+    glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load("glTexCoordP2ui", userptr);
+    glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load("glTexCoordP2uiv", userptr);
+    glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load("glTexCoordP3ui", userptr);
+    glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load("glTexCoordP3uiv", userptr);
+    glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load("glTexCoordP4ui", userptr);
+    glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load("glTexCoordP4uiv", userptr);
+    glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load("glVertexAttribDivisor", userptr);
+    glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load("glVertexAttribP1ui", userptr);
+    glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load("glVertexAttribP1uiv", userptr);
+    glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load("glVertexAttribP2ui", userptr);
+    glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load("glVertexAttribP2uiv", userptr);
+    glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load("glVertexAttribP3ui", userptr);
+    glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load("glVertexAttribP3uiv", userptr);
+    glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load("glVertexAttribP4ui", userptr);
+    glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load("glVertexAttribP4uiv", userptr);
+    glVertexP2ui = (PFNGLVERTEXP2UIPROC) load("glVertexP2ui", userptr);
+    glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load("glVertexP2uiv", userptr);
+    glVertexP3ui = (PFNGLVERTEXP3UIPROC) load("glVertexP3ui", userptr);
+    glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load("glVertexP3uiv", userptr);
+    glVertexP4ui = (PFNGLVERTEXP4UIPROC) load("glVertexP4ui", userptr);
+    glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load("glVertexP4uiv", userptr);
+}
+static void glad_gl_load_GL_ARB_multisample( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_ARB_multisample) return;
+    glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load("glSampleCoverage", userptr);
+    glSampleCoverageARB = (PFNGLSAMPLECOVERAGEARBPROC) load("glSampleCoverageARB", userptr);
+}
+static void glad_gl_load_GL_ARB_robustness( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_ARB_robustness) return;
+    glGetGraphicsResetStatusARB = (PFNGLGETGRAPHICSRESETSTATUSARBPROC) load("glGetGraphicsResetStatusARB", userptr);
+    glGetnColorTableARB = (PFNGLGETNCOLORTABLEARBPROC) load("glGetnColorTableARB", userptr);
+    glGetnCompressedTexImageARB = (PFNGLGETNCOMPRESSEDTEXIMAGEARBPROC) load("glGetnCompressedTexImageARB", userptr);
+    glGetnConvolutionFilterARB = (PFNGLGETNCONVOLUTIONFILTERARBPROC) load("glGetnConvolutionFilterARB", userptr);
+    glGetnHistogramARB = (PFNGLGETNHISTOGRAMARBPROC) load("glGetnHistogramARB", userptr);
+    glGetnMapdvARB = (PFNGLGETNMAPDVARBPROC) load("glGetnMapdvARB", userptr);
+    glGetnMapfvARB = (PFNGLGETNMAPFVARBPROC) load("glGetnMapfvARB", userptr);
+    glGetnMapivARB = (PFNGLGETNMAPIVARBPROC) load("glGetnMapivARB", userptr);
+    glGetnMinmaxARB = (PFNGLGETNMINMAXARBPROC) load("glGetnMinmaxARB", userptr);
+    glGetnPixelMapfvARB = (PFNGLGETNPIXELMAPFVARBPROC) load("glGetnPixelMapfvARB", userptr);
+    glGetnPixelMapuivARB = (PFNGLGETNPIXELMAPUIVARBPROC) load("glGetnPixelMapuivARB", userptr);
+    glGetnPixelMapusvARB = (PFNGLGETNPIXELMAPUSVARBPROC) load("glGetnPixelMapusvARB", userptr);
+    glGetnPolygonStippleARB = (PFNGLGETNPOLYGONSTIPPLEARBPROC) load("glGetnPolygonStippleARB", userptr);
+    glGetnSeparableFilterARB = (PFNGLGETNSEPARABLEFILTERARBPROC) load("glGetnSeparableFilterARB", userptr);
+    glGetnTexImageARB = (PFNGLGETNTEXIMAGEARBPROC) load("glGetnTexImageARB", userptr);
+    glGetnUniformdvARB = (PFNGLGETNUNIFORMDVARBPROC) load("glGetnUniformdvARB", userptr);
+    glGetnUniformfvARB = (PFNGLGETNUNIFORMFVARBPROC) load("glGetnUniformfvARB", userptr);
+    glGetnUniformivARB = (PFNGLGETNUNIFORMIVARBPROC) load("glGetnUniformivARB", userptr);
+    glGetnUniformuivARB = (PFNGLGETNUNIFORMUIVARBPROC) load("glGetnUniformuivARB", userptr);
+    glReadnPixels = (PFNGLREADNPIXELSPROC) load("glReadnPixels", userptr);
+    glReadnPixelsARB = (PFNGLREADNPIXELSARBPROC) load("glReadnPixelsARB", userptr);
+}
+static void glad_gl_load_GL_KHR_debug( GLADuserptrloadfunc load, void* userptr) {
+    if(!GLAD_GL_KHR_debug) return;
+    glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load("glDebugMessageCallback", userptr);
+    glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load("glDebugMessageControl", userptr);
+    glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load("glDebugMessageInsert", userptr);
+    glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load("glGetDebugMessageLog", userptr);
+    glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load("glGetObjectLabel", userptr);
+    glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load("glGetObjectPtrLabel", userptr);
+    glGetPointerv = (PFNGLGETPOINTERVPROC) load("glGetPointerv", userptr);
+    glObjectLabel = (PFNGLOBJECTLABELPROC) load("glObjectLabel", userptr);
+    glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load("glObjectPtrLabel", userptr);
+    glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load("glPopDebugGroup", userptr);
+    glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load("glPushDebugGroup", userptr);
+}
+
+
+
+#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
+#define GLAD_GL_IS_SOME_NEW_VERSION 1
+#else
+#define GLAD_GL_IS_SOME_NEW_VERSION 0
+#endif
+
+static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) {
+#if GLAD_GL_IS_SOME_NEW_VERSION
+    if(GLAD_VERSION_MAJOR(version) < 3) {
+#else
+    (void) version;
+    (void) out_num_exts_i;
+    (void) out_exts_i;
+#endif
+        if (glGetString == NULL) {
+            return 0;
+        }
+        *out_exts = (const char *)glGetString(GL_EXTENSIONS);
+#if GLAD_GL_IS_SOME_NEW_VERSION
+    } else {
+        unsigned int index = 0;
+        unsigned int num_exts_i = 0;
+        char **exts_i = NULL;
+        if (glGetStringi == NULL || glGetIntegerv == NULL) {
+            return 0;
+        }
+        glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i);
+        if (num_exts_i > 0) {
+            exts_i = (char **) malloc(num_exts_i * (sizeof *exts_i));
+        }
+        if (exts_i == NULL) {
+            return 0;
+        }
+        for(index = 0; index < num_exts_i; index++) {
+            const char *gl_str_tmp = (const char*) glGetStringi(GL_EXTENSIONS, index);
+            size_t len = strlen(gl_str_tmp) + 1;
+
+            char *local_str = (char*) malloc(len * sizeof(char));
+            if(local_str != NULL) {
+                memcpy(local_str, gl_str_tmp, len * sizeof(char));
+            }
+
+            exts_i[index] = local_str;
+        }
+
+        *out_num_exts_i = num_exts_i;
+        *out_exts_i = exts_i;
+    }
+#endif
+    return 1;
+}
+static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) {
+    if (exts_i != NULL) {
+        unsigned int index;
+        for(index = 0; index < num_exts_i; index++) {
+            free((void *) (exts_i[index]));
+        }
+        free((void *)exts_i);
+        exts_i = NULL;
+    }
+}
+static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) {
+    if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) {
+        const char *extensions;
+        const char *loc;
+        const char *terminator;
+        extensions = exts;
+        if(extensions == NULL || ext == NULL) {
+            return 0;
+        }
+        while(1) {
+            loc = strstr(extensions, ext);
+            if(loc == NULL) {
+                return 0;
+            }
+            terminator = loc + strlen(ext);
+            if((loc == extensions || *(loc - 1) == ' ') &&
+                (*terminator == ' ' || *terminator == '\0')) {
+                return 1;
+            }
+            extensions = terminator;
+        }
+    } else {
+        unsigned int index;
+        for(index = 0; index < num_exts_i; index++) {
+            const char *e = exts_i[index];
+            if(strcmp(e, ext) == 0) {
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+static GLADapiproc glad_gl_get_proc_from_userptr(const char* name, void *userptr) {
+    return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name);
+}
+
+static int glad_gl_find_extensions_gl( int version) {
+    const char *exts = NULL;
+    unsigned int num_exts_i = 0;
+    char **exts_i = NULL;
+    if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0;
+
+    GLAD_GL_ARB_multisample = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_multisample");
+    GLAD_GL_ARB_robustness = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_ARB_robustness");
+    GLAD_GL_KHR_debug = glad_gl_has_extension(version, exts, num_exts_i, exts_i, "GL_KHR_debug");
+
+    glad_gl_free_extensions(exts_i, num_exts_i);
+
+    return 1;
+}
+
+static int glad_gl_find_core_gl(void) {
+    int i, major, minor;
+    const char* version;
+    const char* prefixes[] = {
+        "OpenGL ES-CM ",
+        "OpenGL ES-CL ",
+        "OpenGL ES ",
+        NULL
+    };
+    version = (const char*) glGetString(GL_VERSION);
+    if (!version) return 0;
+    for (i = 0;  prefixes[i];  i++) {
+        const size_t length = strlen(prefixes[i]);
+        if (strncmp(version, prefixes[i], length) == 0) {
+            version += length;
+            break;
+        }
+    }
+
+    GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor);
+
+    GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1;
+    GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1;
+    GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1;
+    GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1;
+    GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1;
+    GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1;
+    GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2;
+    GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2;
+    GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3;
+    GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3;
+    GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3;
+    GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3;
+
+    return GLAD_MAKE_VERSION(major, minor);
+}
+
+int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) {
+    int version;
+
+    glGetString = (PFNGLGETSTRINGPROC) load("glGetString", userptr);
+    if(glGetString == NULL) return 0;
+    if(glGetString(GL_VERSION) == NULL) return 0;
+    version = glad_gl_find_core_gl();
+
+    glad_gl_load_GL_VERSION_1_0(load, userptr);
+    glad_gl_load_GL_VERSION_1_1(load, userptr);
+    glad_gl_load_GL_VERSION_1_2(load, userptr);
+    glad_gl_load_GL_VERSION_1_3(load, userptr);
+    glad_gl_load_GL_VERSION_1_4(load, userptr);
+    glad_gl_load_GL_VERSION_1_5(load, userptr);
+    glad_gl_load_GL_VERSION_2_0(load, userptr);
+    glad_gl_load_GL_VERSION_2_1(load, userptr);
+    glad_gl_load_GL_VERSION_3_0(load, userptr);
+    glad_gl_load_GL_VERSION_3_1(load, userptr);
+    glad_gl_load_GL_VERSION_3_2(load, userptr);
+    glad_gl_load_GL_VERSION_3_3(load, userptr);
+
+    if (!glad_gl_find_extensions_gl(version)) return 0;
+    glad_gl_load_GL_ARB_multisample(load, userptr);
+    glad_gl_load_GL_ARB_robustness(load, userptr);
+    glad_gl_load_GL_KHR_debug(load, userptr);
+
+
+
+    return version;
+}
+
+
+int gladLoadGL( GLADloadfunc load) {
+    return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load);
+}
+
+
+
+
diff --git a/glfw/include/GLFW/glfw3.h b/glfw/include/GLFW/glfw3.h
--- a/glfw/include/GLFW/glfw3.h
+++ b/glfw/include/GLFW/glfw3.h
@@ -1,5873 +1,5874 @@
-/*************************************************************************
- * GLFW 3.3 - www.glfw.org
- * A library for OpenGL, window and input
- *------------------------------------------------------------------------
- * Copyright (c) 2002-2006 Marcus Geelnard
- * Copyright (c) 2006-2019 Camilla Löwy <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
- *  @brief Functions and types related to OpenGL and OpenGL ES contexts.
- *
- *  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
- *  @brief Functions and types related to Vulkan.
- *
- *  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
- *  @brief Functions and types related to initialization and error handling.
- *
- *  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
- *  @brief Functions and types related to input handling.
- *
- *  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
- *  @brief Functions and types related to monitors.
- *
- *  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
- *  @brief Functions and types related to windows.
- *
- *  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 */
-
-/* Include because most Windows GLU headers need wchar_t and
- * the macOS 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 it unconditionally to avoid surprising side-effects.
- */
-#include <stdint.h>
-
-#if defined(GLFW_INCLUDE_VULKAN)
-  #include <vulkan/vulkan.h>
-#endif /* Vulkan header */
-
-/* The Vulkan header may have indirectly included windows.h (because of
- * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it.
- */
-
-/* It is customary to use APIENTRY for OpenGL function pointer declarations on
- * all platforms.  Additionally, the Windows OpenGL header needs APIENTRY.
- */
-#if !defined(APIENTRY)
- #if defined(_WIN32)
-  #define APIENTRY __stdcall
- #else
-  #define APIENTRY
- #endif
- #define GLFW_APIENTRY_DEFINED
-#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 the chosen OpenGL or OpenGL ES headers.
- */
-#if 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_ES32)
-
- #include <GLES3/gl32.h>
- #if defined(GLFW_INCLUDE_GLEXT)
-  #include <GLES2/gl2ext.h>
- #endif
-
-#elif defined(GLFW_INCLUDE_GLCOREARB)
-
- #if defined(__APPLE__)
-
-  #include <OpenGL/gl3.h>
-  #if defined(GLFW_INCLUDE_GLEXT)
-   #include <OpenGL/gl3ext.h>
-  #endif /*GLFW_INCLUDE_GLEXT*/
-
- #else /*__APPLE__*/
-
-  #include <GL/glcorearb.h>
-
- #endif /*__APPLE__*/
-
-#elif !defined(GLFW_INCLUDE_NONE)
-
- #if defined(__APPLE__)
-
-  #if !defined(GLFW_INCLUDE_GLEXT)
-   #define GL_GLEXT_LEGACY
-  #endif
-  #include <OpenGL/gl.h>
-  #if defined(GLFW_INCLUDE_GLU)
-   #include <OpenGL/glu.h>
-  #endif
-
- #else /*__APPLE__*/
-
-  #include <GL/gl.h>
-  #if defined(GLFW_INCLUDE_GLEXT)
-   #include <GL/glext.h>
-  #endif
-  #if defined(GLFW_INCLUDE_GLU)
-   #include <GL/glu.h>
-  #endif
-
- #endif /*__APPLE__*/
-
-#endif /* OpenGL and OpenGL ES headers */
-
-#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          3
-/*! @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
-/*! @} */
-
-/*! @brief One.
- *
- *  This is only semantic sugar for the number 1.  You can instead use `1` or
- *  `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal
- *  to one.
- *
- *  @ingroup init
- */
-#define GLFW_TRUE                   1
-/*! @brief Zero.
- *
- *  This is only semantic sugar for the number 0.  You can instead use `0` or
- *  `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is
- *  equal to zero.
- *
- *  @ingroup init
- */
-#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 hat_state Joystick hat states
- *  @brief Joystick hat states.
- *
- *  See [joystick hat input](@ref joystick_hat) for how these are used.
- *
- *  @ingroup input
- *  @{ */
-#define GLFW_HAT_CENTERED           0
-#define GLFW_HAT_UP                 1
-#define GLFW_HAT_RIGHT              2
-#define GLFW_HAT_DOWN               4
-#define GLFW_HAT_LEFT               8
-#define GLFW_HAT_RIGHT_UP           (GLFW_HAT_RIGHT | GLFW_HAT_UP)
-#define GLFW_HAT_RIGHT_DOWN         (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
-#define GLFW_HAT_LEFT_UP            (GLFW_HAT_LEFT  | GLFW_HAT_UP)
-#define GLFW_HAT_LEFT_DOWN          (GLFW_HAT_LEFT  | GLFW_HAT_DOWN)
-/*! @} */
-
-/*! @defgroup keys Keyboard keys
- *  @brief Keyboard key IDs.
- *
- *  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
- *  @brief 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.
- *
- *  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.
- *
- *  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.
- *
- *  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.
- *
- *  If this bit is set one or more Super keys were held down.
- */
-#define GLFW_MOD_SUPER           0x0008
-/*! @brief If this bit is set the Caps Lock key is enabled.
- *
- *  If this bit is set the Caps Lock key is enabled and the @ref
- *  GLFW_LOCK_KEY_MODS input mode is set.
- */
-#define GLFW_MOD_CAPS_LOCK       0x0010
-/*! @brief If this bit is set the Num Lock key is enabled.
- *
- *  If this bit is set the Num Lock key is enabled and the @ref
- *  GLFW_LOCK_KEY_MODS input mode is set.
- */
-#define GLFW_MOD_NUM_LOCK        0x0020
-
-/*! @} */
-
-/*! @defgroup buttons Mouse buttons
- *  @brief Mouse button IDs.
- *
- *  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
- *  @brief Joystick IDs.
- *
- *  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 gamepad_buttons Gamepad buttons
- *  @brief Gamepad buttons.
- *
- *  See @ref gamepad for how these are used.
- *
- *  @ingroup input
- *  @{ */
-#define GLFW_GAMEPAD_BUTTON_A               0
-#define GLFW_GAMEPAD_BUTTON_B               1
-#define GLFW_GAMEPAD_BUTTON_X               2
-#define GLFW_GAMEPAD_BUTTON_Y               3
-#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER     4
-#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER    5
-#define GLFW_GAMEPAD_BUTTON_BACK            6
-#define GLFW_GAMEPAD_BUTTON_START           7
-#define GLFW_GAMEPAD_BUTTON_GUIDE           8
-#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB      9
-#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB     10
-#define GLFW_GAMEPAD_BUTTON_DPAD_UP         11
-#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT      12
-#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN       13
-#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT       14
-#define GLFW_GAMEPAD_BUTTON_LAST            GLFW_GAMEPAD_BUTTON_DPAD_LEFT
-
-#define GLFW_GAMEPAD_BUTTON_CROSS       GLFW_GAMEPAD_BUTTON_A
-#define GLFW_GAMEPAD_BUTTON_CIRCLE      GLFW_GAMEPAD_BUTTON_B
-#define GLFW_GAMEPAD_BUTTON_SQUARE      GLFW_GAMEPAD_BUTTON_X
-#define GLFW_GAMEPAD_BUTTON_TRIANGLE    GLFW_GAMEPAD_BUTTON_Y
-/*! @} */
-
-/*! @defgroup gamepad_axes Gamepad axes
- *  @brief Gamepad axes.
- *
- *  See @ref gamepad for how these are used.
- *
- *  @ingroup input
- *  @{ */
-#define GLFW_GAMEPAD_AXIS_LEFT_X        0
-#define GLFW_GAMEPAD_AXIS_LEFT_Y        1
-#define GLFW_GAMEPAD_AXIS_RIGHT_X       2
-#define GLFW_GAMEPAD_AXIS_RIGHT_Y       3
-#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER  4
-#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5
-#define GLFW_GAMEPAD_AXIS_LAST          GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
-/*! @} */
-
-/*! @defgroup errors Error codes
- *  @brief Error codes.
- *
- *  See [error handling](@ref error_handling) for how these are used.
- *
- *  @ingroup init
- *  @{ */
-/*! @brief No error has occurred.
- *
- *  No error has occurred.
- *
- *  @analysis Yay.
- */
-#define GLFW_NO_ERROR               0
-/*! @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 @ref GLFW_RED_BITS 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.  macOS 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
-/*! @} */
-
-/*! @addtogroup window
- *  @{ */
-/*! @brief Input focus window hint and attribute
- *
- *  Input focus [window hint](@ref GLFW_FOCUSED_hint) or
- *  [window attribute](@ref GLFW_FOCUSED_attrib).
- */
-#define GLFW_FOCUSED                0x00020001
-/*! @brief Window iconification window attribute
- *
- *  Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib).
- */
-#define GLFW_ICONIFIED              0x00020002
-/*! @brief Window resize-ability window hint and attribute
- *
- *  Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and
- *  [window attribute](@ref GLFW_RESIZABLE_attrib).
- */
-#define GLFW_RESIZABLE              0x00020003
-/*! @brief Window visibility window hint and attribute
- *
- *  Window visibility [window hint](@ref GLFW_VISIBLE_hint) and
- *  [window attribute](@ref GLFW_VISIBLE_attrib).
- */
-#define GLFW_VISIBLE                0x00020004
-/*! @brief Window decoration window hint and attribute
- *
- *  Window decoration [window hint](@ref GLFW_DECORATED_hint) and
- *  [window attribute](@ref GLFW_DECORATED_attrib).
- */
-#define GLFW_DECORATED              0x00020005
-/*! @brief Window auto-iconification window hint and attribute
- *
- *  Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and
- *  [window attribute](@ref GLFW_AUTO_ICONIFY_attrib).
- */
-#define GLFW_AUTO_ICONIFY           0x00020006
-/*! @brief Window decoration window hint and attribute
- *
- *  Window decoration [window hint](@ref GLFW_FLOATING_hint) and
- *  [window attribute](@ref GLFW_FLOATING_attrib).
- */
-#define GLFW_FLOATING               0x00020007
-/*! @brief Window maximization window hint and attribute
- *
- *  Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and
- *  [window attribute](@ref GLFW_MAXIMIZED_attrib).
- */
-#define GLFW_MAXIMIZED              0x00020008
-/*! @brief Cursor centering window hint
- *
- *  Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
- */
-#define GLFW_CENTER_CURSOR          0x00020009
-/*! @brief Window framebuffer transparency hint and attribute
- *
- *  Window framebuffer transparency
- *  [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and
- *  [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
- */
-#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
-/*! @brief Mouse cursor hover window attribute.
- *
- *  Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
- */
-#define GLFW_HOVERED                0x0002000B
-/*! @brief Input focus on calling show window hint and attribute
- *
- *  Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
- *  [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
- */
-#define GLFW_FOCUS_ON_SHOW          0x0002000C
-
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
- */
-#define GLFW_RED_BITS               0x00021001
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS).
- */
-#define GLFW_GREEN_BITS             0x00021002
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS).
- */
-#define GLFW_BLUE_BITS              0x00021003
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS).
- */
-#define GLFW_ALPHA_BITS             0x00021004
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS).
- */
-#define GLFW_DEPTH_BITS             0x00021005
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS).
- */
-#define GLFW_STENCIL_BITS           0x00021006
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS).
- */
-#define GLFW_ACCUM_RED_BITS         0x00021007
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS).
- */
-#define GLFW_ACCUM_GREEN_BITS       0x00021008
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS).
- */
-#define GLFW_ACCUM_BLUE_BITS        0x00021009
-/*! @brief Framebuffer bit depth hint.
- *
- *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
- */
-#define GLFW_ACCUM_ALPHA_BITS       0x0002100A
-/*! @brief Framebuffer auxiliary buffer hint.
- *
- *  Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS).
- */
-#define GLFW_AUX_BUFFERS            0x0002100B
-/*! @brief OpenGL stereoscopic rendering hint.
- *
- *  OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO).
- */
-#define GLFW_STEREO                 0x0002100C
-/*! @brief Framebuffer MSAA samples hint.
- *
- *  Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES).
- */
-#define GLFW_SAMPLES                0x0002100D
-/*! @brief Framebuffer sRGB hint.
- *
- *  Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE).
- */
-#define GLFW_SRGB_CAPABLE           0x0002100E
-/*! @brief Monitor refresh rate hint.
- *
- *  Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE).
- */
-#define GLFW_REFRESH_RATE           0x0002100F
-/*! @brief Framebuffer double buffering hint.
- *
- *  Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
- */
-#define GLFW_DOUBLEBUFFER           0x00021010
-
-/*! @brief Context client API hint and attribute.
- *
- *  Context client API [hint](@ref GLFW_CLIENT_API_hint) and
- *  [attribute](@ref GLFW_CLIENT_API_attrib).
- */
-#define GLFW_CLIENT_API             0x00022001
-/*! @brief Context client API major version hint and attribute.
- *
- *  Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint)
- *  and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib).
- */
-#define GLFW_CONTEXT_VERSION_MAJOR  0x00022002
-/*! @brief Context client API minor version hint and attribute.
- *
- *  Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint)
- *  and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
- */
-#define GLFW_CONTEXT_VERSION_MINOR  0x00022003
-/*! @brief Context client API revision number hint and attribute.
- *
- *  Context client API revision number
- *  [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
- */
-#define GLFW_CONTEXT_REVISION       0x00022004
-/*! @brief Context robustness hint and attribute.
- *
- *  Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint)
- *  and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib).
- */
-#define GLFW_CONTEXT_ROBUSTNESS     0x00022005
-/*! @brief OpenGL forward-compatibility hint and attribute.
- *
- *  OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
- *  and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
- */
-#define GLFW_OPENGL_FORWARD_COMPAT  0x00022006
-/*! @brief OpenGL debug context hint and attribute.
- *
- *  OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and
- *  [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).
- */
-#define GLFW_OPENGL_DEBUG_CONTEXT   0x00022007
-/*! @brief OpenGL profile hint and attribute.
- *
- *  OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
- *  [attribute](@ref GLFW_OPENGL_PROFILE_attrib).
- */
-#define GLFW_OPENGL_PROFILE         0x00022008
-/*! @brief Context flush-on-release hint and attribute.
- *
- *  Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and
- *  [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib).
- */
-#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
-/*! @brief Context error suppression hint and attribute.
- *
- *  Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and
- *  [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib).
- */
-#define GLFW_CONTEXT_NO_ERROR       0x0002200A
-/*! @brief Context creation API hint and attribute.
- *
- *  Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and
- *  [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib).
- */
-#define GLFW_CONTEXT_CREATION_API   0x0002200B
-/*! @brief Window content area scaling window
- *  [window hint](@ref GLFW_SCALE_TO_MONITOR).
- */
-#define GLFW_SCALE_TO_MONITOR       0x0002200C
-/*! @brief macOS specific
- *  [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint).
- */
-#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
-/*! @brief macOS specific
- *  [window hint](@ref GLFW_COCOA_FRAME_NAME_hint).
- */
-#define GLFW_COCOA_FRAME_NAME         0x00023002
-/*! @brief macOS specific
- *  [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
- */
-#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
-/*! @brief X11 specific
- *  [window hint](@ref GLFW_X11_CLASS_NAME_hint).
- */
-#define GLFW_X11_CLASS_NAME         0x00024001
-/*! @brief X11 specific
- *  [window hint](@ref GLFW_X11_CLASS_NAME_hint).
- */
-#define GLFW_X11_INSTANCE_NAME      0x00024002
-/*! @} */
-
-#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_LOCK_KEY_MODS          0x00033004
-#define GLFW_RAW_MOUSE_MOTION       0x00033005
-
-#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
-#define GLFW_OSMESA_CONTEXT_API     0x00036003
-
-/*! @defgroup shapes Standard cursor shapes
- *  @brief Standard system 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
-
-/*! @addtogroup init
- *  @{ */
-/*! @brief Joystick hat buttons init hint.
- *
- *  Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS).
- */
-#define GLFW_JOYSTICK_HAT_BUTTONS   0x00050001
-/*! @brief macOS specific init hint.
- *
- *  macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint).
- */
-#define GLFW_COCOA_CHDIR_RESOURCES  0x00051001
-/*! @brief macOS specific init hint.
- *
- *  macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
- */
-#define GLFW_COCOA_MENUBAR          0x00051002
-/*! @} */
-
-#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 @ref 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 @ref 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 input
- */
-typedef struct GLFWcursor GLFWcursor;
-
-/*! @brief The function pointer type for error callbacks.
- *
- *  This is the function pointer type for error callbacks.  An error callback
- *  function has the following signature:
- *  @code
- *  void callback_name(int error_code, const char* description)
- *  @endcode
- *
- *  @param[in] error_code An [error code](@ref errors).  Future releases may add
- *  more error codes.
- *  @param[in] description A UTF-8 encoded string describing the error.
- *
- *  @pointer_lifetime The error description string is valid until the callback
- *  function returns.
- *
- *  @sa @ref error_handling
- *  @sa @ref glfwSetErrorCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup init
- */
-typedef void (* GLFWerrorfun)(int,const char*);
-
-/*! @brief The function pointer type for window position callbacks.
- *
- *  This is the function pointer type for window position callbacks.  A window
- *  position callback function has the following signature:
- *  @code
- *  void callback_name(GLFWwindow* window, int xpos, int ypos)
- *  @endcode
- *
- *  @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 content area of the window.
- *  @param[in] ypos The new y-coordinate, in screen coordinates, of the
- *  upper-left corner of the content area of the window.
- *
- *  @sa @ref window_pos
- *  @sa @ref glfwSetWindowPosCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
-
-/*! @brief The function pointer type for window size callbacks.
- *
- *  This is the function pointer type for window size callbacks.  A window size
- *  callback function has the following signature:
- *  @code
- *  void callback_name(GLFWwindow* window, int width, int height)
- *  @endcode
- *
- *  @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 @ref glfwSetWindowSizeCallback
- *
- *  @since Added in version 1.0.
- *  @glfw3 Added window handle parameter.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
-
-/*! @brief The function pointer type for window close callbacks.
- *
- *  This is the function pointer type for window close callbacks.  A window
- *  close callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window)
- *  @endcode
- *
- *  @param[in] window The window that the user attempted to close.
- *
- *  @sa @ref window_close
- *  @sa @ref glfwSetWindowCloseCallback
- *
- *  @since Added in version 2.5.
- *  @glfw3 Added window handle parameter.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowclosefun)(GLFWwindow*);
-
-/*! @brief The function pointer type for window content refresh callbacks.
- *
- *  This is the function pointer type for window content refresh callbacks.
- *  A window content refresh callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window);
- *  @endcode
- *
- *  @param[in] window The window whose content needs to be refreshed.
- *
- *  @sa @ref window_refresh
- *  @sa @ref glfwSetWindowRefreshCallback
- *
- *  @since Added in version 2.5.
- *  @glfw3 Added window handle parameter.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
-
-/*! @brief The function pointer type for window focus callbacks.
- *
- *  This is the function pointer type for window focus callbacks.  A window
- *  focus callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int focused)
- *  @endcode
- *
- *  @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 @ref glfwSetWindowFocusCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
-
-/*! @brief The function pointer type for window iconify callbacks.
- *
- *  This is the function pointer type for window iconify callbacks.  A window
- *  iconify callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int iconified)
- *  @endcode
- *
- *  @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 @ref glfwSetWindowIconifyCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
-
-/*! @brief The function pointer type for window maximize callbacks.
- *
- *  This is the function pointer type for window maximize callbacks.  A window
- *  maximize callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int maximized)
- *  @endcode
- *
- *  @param[in] window The window that was maximized or restored.
- *  @param[in] iconified `GLFW_TRUE` if the window was maximized, or
- *  `GLFW_FALSE` if it was restored.
- *
- *  @sa @ref window_maximize
- *  @sa glfwSetWindowMaximizeCallback
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
-
-/*! @brief The function pointer type for framebuffer size callbacks.
- *
- *  This is the function pointer type for framebuffer size callbacks.
- *  A framebuffer size callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int width, int height)
- *  @endcode
- *
- *  @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 @ref glfwSetFramebufferSizeCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup window
- */
-typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
-
-/*! @brief The function pointer type for window content scale callbacks.
- *
- *  This is the function pointer type for window content scale callbacks.
- *  A window content scale callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, float xscale, float yscale)
- *  @endcode
- *
- *  @param[in] window The window whose content scale changed.
- *  @param[in] xscale The new x-axis content scale of the window.
- *  @param[in] yscale The new y-axis content scale of the window.
- *
- *  @sa @ref window_scale
- *  @sa @ref glfwSetWindowContentScaleCallback
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
-
-/*! @brief The function pointer type for mouse button callbacks.
- *
- *  This is the function pointer type for mouse button callback functions.
- *  A mouse button callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int button, int action, int mods)
- *  @endcode
- *
- *  @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`.  Future releases
- *  may add more actions.
- *  @param[in] mods Bit field describing which [modifier keys](@ref mods) were
- *  held down.
- *
- *  @sa @ref input_mouse_button
- *  @sa @ref 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 pointer type for cursor position callbacks.
- *
- *  This is the function pointer type for cursor position callbacks.  A cursor
- *  position callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, double xpos, double ypos);
- *  @endcode
- *
- *  @param[in] window The window that received the event.
- *  @param[in] xpos The new cursor x-coordinate, relative to the left edge of
- *  the content area.
- *  @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
- *  content area.
- *
- *  @sa @ref cursor_pos
- *  @sa @ref glfwSetCursorPosCallback
- *
- *  @since Added in version 3.0.  Replaces `GLFWmouseposfun`.
- *
- *  @ingroup input
- */
-typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
-
-/*! @brief The function pointer type for cursor enter/leave callbacks.
- *
- *  This is the function pointer type for cursor enter/leave callbacks.
- *  A cursor enter/leave callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int entered)
- *  @endcode
- *
- *  @param[in] window The window that received the event.
- *  @param[in] entered `GLFW_TRUE` if the cursor entered the window's content
- *  area, or `GLFW_FALSE` if it left it.
- *
- *  @sa @ref cursor_enter
- *  @sa @ref glfwSetCursorEnterCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup input
- */
-typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
-
-/*! @brief The function pointer type for scroll callbacks.
- *
- *  This is the function pointer type for scroll callbacks.  A scroll callback
- *  function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, double xoffset, double yoffset)
- *  @endcode
- *
- *  @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 @ref glfwSetScrollCallback
- *
- *  @since Added in version 3.0.  Replaces `GLFWmousewheelfun`.
- *
- *  @ingroup input
- */
-typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
-
-/*! @brief The function pointer type for keyboard key callbacks.
- *
- *  This is the function pointer type for keyboard key callbacks.  A keyboard
- *  key callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
- *  @endcode
- *
- *  @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`.  Future
- *  releases may add more actions.
- *  @param[in] mods Bit field describing which [modifier keys](@ref mods) were
- *  held down.
- *
- *  @sa @ref input_key
- *  @sa @ref 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 pointer type for Unicode character callbacks.
- *
- *  This is the function pointer type for Unicode character callbacks.
- *  A Unicode character callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, unsigned int codepoint)
- *  @endcode
- *
- *  @param[in] window The window that received the event.
- *  @param[in] codepoint The Unicode code point of the character.
- *
- *  @sa @ref input_char
- *  @sa @ref glfwSetCharCallback
- *
- *  @since Added in version 2.4.
- *  @glfw3 Added window handle parameter.
- *
- *  @ingroup input
- */
-typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
-
-/*! @brief The function pointer type for Unicode character with modifiers
- *  callbacks.
- *
- *  This is the function pointer type for Unicode character with modifiers
- *  callbacks.  It is called for each input character, regardless of what
- *  modifier keys are held down.  A Unicode character with modifiers callback
- *  function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
- *  @endcode
- *
- *  @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 @ref glfwSetCharModsCallback
- *
- *  @deprecated Scheduled for removal in version 4.0.
- *
- *  @since Added in version 3.1.
- *
- *  @ingroup input
- */
-typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
-
-/*! @brief The function pointer type for path drop callbacks.
- *
- *  This is the function pointer type for path drop callbacks.  A path drop
- *  callback function has the following signature:
- *  @code
- *  void function_name(GLFWwindow* window, int path_count, const char* paths[])
- *  @endcode
- *
- *  @param[in] window The window that received the event.
- *  @param[in] path_count The number of dropped paths.
- *  @param[in] paths The UTF-8 encoded file and/or directory path names.
- *
- *  @pointer_lifetime The path array and its strings are valid until the
- *  callback function returns.
- *
- *  @sa @ref path_drop
- *  @sa @ref glfwSetDropCallback
- *
- *  @since Added in version 3.1.
- *
- *  @ingroup input
- */
-typedef void (* GLFWdropfun)(GLFWwindow*,int,const char*[]);
-
-/*! @brief The function pointer type for monitor configuration callbacks.
- *
- *  This is the function pointer type for monitor configuration callbacks.
- *  A monitor callback function has the following signature:
- *  @code
- *  void function_name(GLFWmonitor* monitor, int event)
- *  @endcode
- *
- *  @param[in] monitor The monitor that was connected or disconnected.
- *  @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.  Future
- *  releases may add more events.
- *
- *  @sa @ref monitor_event
- *  @sa @ref glfwSetMonitorCallback
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup monitor
- */
-typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
-
-/*! @brief The function pointer type for joystick configuration callbacks.
- *
- *  This is the function pointer type for joystick configuration callbacks.
- *  A joystick configuration callback function has the following signature:
- *  @code
- *  void function_name(int jid, int event)
- *  @endcode
- *
- *  @param[in] jid The joystick that was connected or disconnected.
- *  @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.  Future
- *  releases may add more events.
- *
- *  @sa @ref joystick_event
- *  @sa @ref 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 @ref glfwGetVideoMode
- *  @sa @ref 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 @ref glfwGetGammaRamp
- *  @sa @ref 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.
- *
- *  This describes a single 2D image.  See the documentation for each related
- *  function what the expected pixel format is.
- *
- *  @sa @ref cursor_custom
- *  @sa @ref window_icon
- *
- *  @since Added in version 2.1.
- *  @glfw3 Removed format and bytes-per-pixel members.
- *
- *  @ingroup window
- */
-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;
-
-/*! @brief Gamepad input state
- *
- *  This describes the input state of a gamepad.
- *
- *  @sa @ref gamepad
- *  @sa @ref glfwGetGamepadState
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-typedef struct GLFWgamepadstate
-{
-    /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS`
-     *  or `GLFW_RELEASE`.
-     */
-    unsigned char buttons[15];
-    /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0
-     *  to 1.0 inclusive.
-     */
-    float axes[6];
-} GLFWgamepadstate;
-
-
-/*************************************************************************
- * 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 @macos 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 the @ref
- *  GLFW_COCOA_CHDIR_RESOURCES init hint.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref intro_init
- *  @sa @ref 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 @ref glfwInit
- *
- *  @since Added in version 1.0.
- *
- *  @ingroup init
- */
-GLFWAPI void glfwTerminate(void);
-
-/*! @brief Sets the specified init hint to the desired value.
- *
- *  This function sets hints for the next initialization of GLFW.
- *
- *  The values you set hints to are never reset by GLFW, but they only take
- *  effect during initialization.  Once GLFW has been initialized, any values
- *  you set will be ignored until the library is terminated and initialized
- *  again.
- *
- *  Some hints are platform specific.  These may be set on any platform but they
- *  will only affect their specific platform.  Other platforms will ignore them.
- *  Setting these hints requires no platform specific headers or functions.
- *
- *  @param[in] hint The [init hint](@ref init_hints) to set.
- *  @param[in] value The new value of the init hint.
- *
- *  @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
- *  GLFW_INVALID_VALUE.
- *
- *  @remarks This function may be called before @ref glfwInit.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa init_hints
- *  @sa glfwInit
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup init
- */
-GLFWAPI void glfwInitHint(int hint, int value);
-
-/*! @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 @ref 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 @ref glfwGetVersion
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup init
- */
-GLFWAPI const char* glfwGetVersionString(void);
-
-/*! @brief Returns and clears the last error for the calling thread.
- *
- *  This function returns and clears the [error code](@ref errors) of the last
- *  error that occurred on the calling thread, and optionally a UTF-8 encoded
- *  human-readable description of it.  If no error has occurred since the last
- *  call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is
- *  set to `NULL`.
- *
- *  @param[in] description Where to store the error description pointer, or `NULL`.
- *  @return The last error code for the calling thread, or @ref GLFW_NO_ERROR
- *  (zero).
- *
- *  @errors None.
- *
- *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You
- *  should not free it yourself.  It is guaranteed to be valid only until the
- *  next error occurs or the library is terminated.
- *
- *  @remark This function may be called before @ref glfwInit.
- *
- *  @thread_safety This function may be called from any thread.
- *
- *  @sa @ref error_handling
- *  @sa @ref glfwSetErrorCallback
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup init
- */
-GLFWAPI int glfwGetError(const char** description);
-
-/*! @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 code is set before the callback is called.  Calling @ref
- *  glfwGetError from the error callback will return the same value as the error
- *  code argument.
- *
- *  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] callback The new callback, or `NULL` to remove the currently set
- *  callback.
- *  @return The previously set callback, or `NULL` if no callback was set.
- *
- *  @callback_signature
- *  @code
- *  void callback_name(int error_code, const char* description)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [callback pointer type](@ref GLFWerrorfun).
- *
- *  @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
- *  @sa @ref glfwGetError
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup init
- */
-GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback);
-
-/*! @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 @ref 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 @ref 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 Retrieves the work area of the monitor.
- *
- *  This function returns the position, in screen coordinates, of the upper-left
- *  corner of the work area of the specified monitor along with the work area
- *  size in screen coordinates. The work area is defined as the area of the
- *  monitor not occluded by the operating system task bar where present. If no
- *  task bar exists then the work area is the monitor resolution in screen
- *  coordinates.
- *
- *  Any or all of the position and size arguments may be `NULL`.  If an error
- *  occurs, all non-`NULL` position and size 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`.
- *  @param[out] width Where to store the monitor width, or `NULL`.
- *  @param[out] height Where to store the monitor height, 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_workarea
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup monitor
- */
-GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height);
-
-/*! @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 Retrieves the content scale for the specified monitor.
- *
- *  This function retrieves the content scale for the specified monitor.  The
- *  content scale is the ratio between the current DPI and the platform's
- *  default DPI.  This is especially important for text and any UI elements.  If
- *  the pixel dimensions of your UI scaled by this look appropriate on your
- *  machine then it should appear at a reasonable size on other machines
- *  regardless of their DPI and scaling settings.  This relies on the system DPI
- *  and scaling settings being somewhat correct.
- *
- *  The content scale may depend on both the monitor resolution and pixel
- *  density and on user settings.  It may be very different from the raw DPI
- *  calculated from the physical size and current resolution.
- *
- *  @param[in] monitor The monitor to query.
- *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
- *  @param[out] yscale Where to store the y-axis content scale, 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_scale
- *  @sa @ref glfwGetWindowContentScale
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup monitor
- */
-GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale);
-
-/*! @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 user pointer of the specified monitor.
- *
- *  This function sets the user-defined pointer of the specified monitor.  The
- *  current value is retained until the monitor is disconnected.  The initial
- *  value is `NULL`.
- *
- *  This function may be called from the monitor callback, even for a monitor
- *  that is being disconnected.
- *
- *  @param[in] monitor The monitor 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 monitor_userptr
- *  @sa @ref glfwGetMonitorUserPointer
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup monitor
- */
-GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
-
-/*! @brief Returns the user pointer of the specified monitor.
- *
- *  This function returns the current value of the user-defined pointer of the
- *  specified monitor.  The initial value is `NULL`.
- *
- *  This function may be called from the monitor callback, even for a monitor
- *  that is being disconnected.
- *
- *  @param[in] monitor The monitor 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 monitor_userptr
- *  @sa @ref glfwSetMonitorUserPointer
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup monitor
- */
-GLFWAPI void* glfwGetMonitorUserPointer(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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWmonitor* monitor, int event)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWmonitorfun).
- *
- *  @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 callback);
-
-/*! @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 @ref 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 @ref 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 an appropriately sized gamma ramp from the specified
- *  exponent and then calls @ref glfwSetGammaRamp with it.  The value must be
- *  a finite number greater than zero.
- *
- *  The software controlled gamma ramp is applied _in addition_ to the hardware
- *  gamma correction, which today is usually an approximation of sRGB gamma.
- *  This means that setting a perfectly linear ramp, or gamma 1.0, will produce
- *  the default (usually sRGB-like) behavior.
- *
- *  For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
- *  GLFW_SRGB_CAPABLE hint.
- *
- *  @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.
- *
- *  @remark @wayland Gamma handling is a privileged protocol, this function
- *  will thus never be implemented and emits @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.
- *
- *  @remark @wayland Gamma handling is a privileged protocol, this function
- *  will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
- *  returning `NULL`.
- *
- *  @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.
- *
- *  The software controlled gamma ramp is applied _in addition_ to the hardware
- *  gamma correction, which today is usually an approximation of sRGB gamma.
- *  This means that setting a perfectly linear ramp, or gamma 1.0, will produce
- *  the default (usually sRGB-like) behavior.
- *
- *  For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
- *  GLFW_SRGB_CAPABLE hint.
- *
- *  @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 The size of the specified gamma ramp should match the size of the
- *  current ramp for that monitor.
- *
- *  @remark @win32 The gamma ramp size must be 256.
- *
- *  @remark @wayland Gamma handling is a privileged protocol, this function
- *  will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
- *
- *  @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 @ref glfwWindowHint
- *  @sa @ref glfwWindowHintString
- *
- *  @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 this
- *  function or @ref glfwDefaultWindowHints, or until the library is terminated.
- *
- *  Only integer value hints can be set with this function.  String value hints
- *  are set with @ref glfwWindowHintString.
- *
- *  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.
- *
- *  Some hints are platform specific.  These may be set on any platform but they
- *  will only affect their specific platform.  Other platforms will ignore them.
- *  Setting these hints requires no platform specific headers or functions.
- *
- *  @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 @ref glfwWindowHintString
- *  @sa @ref glfwDefaultWindowHints
- *
- *  @since Added in version 3.0.  Replaces `glfwOpenWindowHint`.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwWindowHint(int hint, int value);
-
-/*! @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 this
- *  function or @ref glfwDefaultWindowHints, or until the library is terminated.
- *
- *  Only string type hints can be set with this function.  Integer value hints
- *  are set with @ref glfwWindowHint.
- *
- *  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.
- *
- *  Some hints are platform specific.  These may be set on any platform but they
- *  will only affect their specific platform.  Other platforms will ignore them.
- *  Setting these hints requires no platform specific headers or functions.
- *
- *  @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.
- *
- *  @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 window_hints
- *  @sa @ref glfwWindowHint
- *  @sa @ref glfwDefaultWindowHints
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwWindowHintString(int hint, const char* 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.  This will not affect its
- *  OpenGL or OpenGL ES context.
- *
- *  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 GLFW_VISIBLE_hint) 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_APPLICATION` 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 @macos The OS only supports forward-compatible core profile contexts
- *  for OpenGL versions 3.2 and later.  Before creating an OpenGL context of
- *  version 3.2 or later you must set the
- *  [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and
- *  [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly.
- *  OpenGL 3.0 and 3.1 contexts are not supported at all on macOS.
- *
- *  @remark @macos 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 @macos The first time a window is created the menu bar is created.
- *  If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
- *  bar.  Otherwise a minimal menu bar is created manually with common commands
- *  like Hide, Quit and About.  The About entry opens a minimal about dialog
- *  with information from the application's bundle.  Menu bar creation can be
- *  disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
- *
- *  @remark @macos On OS X 10.10 and later the window frame will not be rendered
- *  at full resolution on Retina displays unless the
- *  [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
- *  hint is `GLFW_TRUE` and 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 @macos When activating frame autosaving with
- *  [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
- *  window size and position may be overridden by previously saved values.
- *
- *  @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.
- *
- *  @remark @x11 The class part of the `WM_CLASS` window property will by
- *  default be set to the window title passed to this function.  The instance
- *  part will use the contents of the `RESOURCE_NAME` environment variable, if
- *  present and not empty, or fall back to the window title.  Set the
- *  [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and
- *  [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to
- *  override this.
- *
- *  @remark @wayland Compositors should implement the xdg-decoration protocol
- *  for GLFW to decorate the window properly.  If this protocol isn't
- *  supported, or if the compositor prefers client-side decorations, a very
- *  simple fallback frame will be drawn using the wp_viewporter protocol.  A
- *  compositor can still emit close, maximize or fullscreen events, using for
- *  instance a keybind mechanism.  If neither of these protocols is supported,
- *  the window won't be decorated.
- *
- *  @remark @wayland A full screen window will not attempt to change the mode,
- *  no matter what the requested size or refresh rate.
- *
- *  @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
- *  to be implemented in the user's compositor.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_creation
- *  @sa @ref 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 @ref 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 @macos 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 pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
- *  bits per channel with the red channel first.  They are arranged canonically
- *  as packed sequential rows, starting from the top-left corner.
- *
- *  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 @macos 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.
- *
- *  @remark @wayland There is no existing protocol to change an icon, the
- *  window will thus inherit the one defined in the application's desktop file.
- *  This function always emits @ref GLFW_PLATFORM_ERROR.
- *
- *  @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 content area of the specified window.
- *
- *  This function retrieves the position, in screen coordinates, of the
- *  upper-left corner of the content 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 content area, or `NULL`.
- *  @param[out] ypos Where to store the y-coordinate of the upper-left corner of
- *  the content area, or `NULL`.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @wayland There is no way for an application to retrieve the global
- *  position of its windows, this function will always emit @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_pos
- *  @sa @ref glfwSetWindowPos
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
-
-/*! @brief Sets the position of the content area of the specified window.
- *
- *  This function sets the position, in screen coordinates, of the upper-left
- *  corner of the content 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 content area.
- *  @param[in] ypos The y-coordinate of the upper-left corner of the content area.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @wayland There is no way for an application to set the global
- *  position of its windows, this function will always emit @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_pos
- *  @sa @ref 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 content area of the specified window.
- *
- *  This function retrieves the size, in screen coordinates, of the content 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
- *  content area, or `NULL`.
- *  @param[out] height Where to store the height, in screen coordinates, of the
- *  content 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 @ref 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 content 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 content
- *  area, or `GLFW_DONT_CARE`.
- *  @param[in] minheight The minimum height, in screen coordinates, of the
- *  content area, or `GLFW_DONT_CARE`.
- *  @param[in] maxwidth The maximum width, in screen coordinates, of the content
- *  area, or `GLFW_DONT_CARE`.
- *  @param[in] maxheight The maximum height, in screen coordinates, of the
- *  content 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.
- *
- *  @remark @wayland The size limits will not be applied until the window is
- *  actually resized, either by the user or by the compositor.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_sizelimits
- *  @sa @ref 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 content 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.
- *
- *  @remark @wayland The aspect ratio will not be applied until the window is
- *  actually resized, either by the user or by the compositor.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_sizelimits
- *  @sa @ref glfwSetWindowSizeLimits
- *
- *  @since Added in version 3.2.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
-
-/*! @brief Sets the size of the content area of the specified window.
- *
- *  This function sets the size, in screen coordinates, of the content 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
- *  content area.
- *  @param[in] height The desired height, in screen coordinates, of the window
- *  content area.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @wayland A full screen window will not attempt to change the mode,
- *  no matter what the requested size.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_size
- *  @sa @ref glfwGetWindowSize
- *  @sa @ref 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 @ref 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 Retrieves the content scale for the specified window.
- *
- *  This function retrieves the content scale for the specified window.  The
- *  content scale is the ratio between the current DPI and the platform's
- *  default DPI.  This is especially important for text and any UI elements.  If
- *  the pixel dimensions of your UI scaled by this look appropriate on your
- *  machine then it should appear at a reasonable size on other machines
- *  regardless of their DPI and scaling settings.  This relies on the system DPI
- *  and scaling settings being somewhat correct.
- *
- *  On systems where each monitors can have its own content scale, the window
- *  content scale will depend on which monitor the system considers the window
- *  to be on.
- *
- *  @param[in] window The window to query.
- *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
- *  @param[out] yscale Where to store the y-axis content scale, 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_scale
- *  @sa @ref glfwSetWindowContentScaleCallback
- *  @sa @ref glfwGetMonitorContentScale
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
-
-/*! @brief Returns the opacity of the whole window.
- *
- *  This function returns the opacity of the window, including any decorations.
- *
- *  The opacity (or alpha) value is a positive finite number between zero and
- *  one, where zero is fully transparent and one is fully opaque.  If the system
- *  does not support whole window transparency, this function always returns one.
- *
- *  The initial opacity value for newly created windows is one.
- *
- *  @param[in] window The window to query.
- *  @return The opacity value of the specified window.
- *
- *  @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_transparency
- *  @sa @ref glfwSetWindowOpacity
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
-
-/*! @brief Sets the opacity of the whole window.
- *
- *  This function sets the opacity of the window, including any decorations.
- *
- *  The opacity (or alpha) value is a positive finite number between zero and
- *  one, where zero is fully transparent and one is fully opaque.
- *
- *  The initial opacity value for newly created windows is one.
- *
- *  A window created with framebuffer transparency may not use whole window
- *  transparency.  The results of doing this are undefined.
- *
- *  @param[in] window The window to set the opacity for.
- *  @param[in] opacity The desired opacity of the specified window.
- *
- *  @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_transparency
- *  @sa @ref glfwGetWindowOpacity
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
-
-/*! @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.
- *
- *  @remark @wayland There is no concept of iconification in wl_shell, this
- *  function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
- *  protocol.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_iconify
- *  @sa @ref glfwRestoreWindow
- *  @sa @ref 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 @ref glfwIconifyWindow
- *  @sa @ref 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 @ref glfwIconifyWindow
- *  @sa @ref 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.
- *
- *  By default, windowed mode windows are focused when shown
- *  Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
- *  to change this behavior for all newly created windows, or change the
- *  behavior for an existing window with @ref glfwSetWindowAttrib.
- *
- *  @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 @ref 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 @ref 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 GLFW_FOCUSED_hint) to
- *  disable this behavior.
- *
- *  Also by default, windowed mode windows are focused when shown
- *  with @ref glfwShowWindow. Set the
- *  [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) 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.
- *
- *  For a less disruptive way of getting the user's attention, see
- *  [attention requests](@ref window_attention).
- *
- *  @param[in] window The window to give input focus.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @wayland It is not possible for an application to bring its windows
- *  to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_focus
- *  @sa @ref window_attention
- *
- *  @since Added in version 3.2.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwFocusWindow(GLFWwindow* window);
-
-/*! @brief Requests user attention to the specified window.
- *
- *  This function requests user attention to the specified window.  On
- *  platforms where this is not supported, attention is requested to the
- *  application as a whole.
- *
- *  Once the user has given attention, usually by focusing the window or
- *  application, the system will end the request automatically.
- *
- *  @param[in] window The window to request attention to.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @macos Attention is requested to the application as a whole, not the
- *  specific window.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_attention
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwRequestWindowAttention(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 @ref 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 content 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
- *  content area.
- *  @param[in] ypos The desired y-coordinate of the upper-left corner of the
- *  content area.
- *  @param[in] width The desired with, in screen coordinates, of the content
- *  area or video mode.
- *  @param[in] height The desired height, in screen coordinates, of the content
- *  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.
- *
- *  @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise
- *  affected by any resizing or mode switching, although you may need to update
- *  your viewport if the framebuffer size has changed.
- *
- *  @remark @wayland The desired window position is ignored, as there is no way
- *  for an application to set this property.
- *
- *  @remark @wayland Setting the window to full screen will not attempt to
- *  change the mode, no matter what the requested size or refresh rate.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_monitor
- *  @sa @ref window_full_screen
- *  @sa @ref glfwGetWindowMonitor
- *  @sa @ref 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
- *  @sa @ref glfwSetWindowAttrib
- *
- *  @since Added in version 3.0.  Replaces `glfwGetWindowParam` and
- *  `glfwGetGLVersion`.
- *
- *  @ingroup window
- */
-GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
-
-/*! @brief Sets an attribute of the specified window.
- *
- *  This function sets the value of an attribute of the specified window.
- *
- *  The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
- *  [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
- *  [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
- *  [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
- *  [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
- *
- *  Some of these attributes are ignored for full screen windows.  The new
- *  value will take effect if the window is later made windowed.
- *
- *  Some of these attributes are ignored for windowed mode windows.  The new
- *  value will take effect if the window is later made full screen.
- *
- *  @param[in] window The window to set the attribute for.
- *  @param[in] attrib A supported window attribute.
- *  @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
- *  GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
- *
- *  @remark Calling @ref glfwGetWindowAttrib will always return the latest
- *  value, even if that value is ignored by the current mode of the window.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_attribs
- *  @sa @ref glfwGetWindowAttrib
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value);
-
-/*! @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 @ref 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 @ref 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
- *  position, in screen coordinates, of the upper-left corner of the content
- *  area of the window.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int xpos, int ypos)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowposfun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @remark @wayland This callback will never be called, as there is no way for
- *  an application to know its global position.
- *
- *  @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 callback);
-
-/*! @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 content area of the window.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int width, int height)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowsizefun).
- *
- *  @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 callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowclosefun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @remark @macos 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 callback);
-
-/*! @brief Sets the refresh callback for the specified window.
- *
- *  This function sets the refresh callback of the specified window, which is
- *  called when the content 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, Aqua or Wayland, 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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window);
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowrefreshfun).
- *
- *  @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 callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int focused)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowfocusfun).
- *
- *  @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 callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int iconified)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowiconifyfun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @remark @wayland The wl_shell protocol has no concept of iconification,
- *  this callback will never be called when using this deprecated protocol.
- *
- *  @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 callback);
-
-/*! @brief Sets the maximize callback for the specified window.
- *
- *  This function sets the maximization callback of the specified window, which
- *  is called when the window is maximized or restored.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int maximized)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowmaximizefun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_maximize
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int width, int height)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWframebuffersizefun).
- *
- *  @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 callback);
-
-/*! @brief Sets the window content scale callback for the specified window.
- *
- *  This function sets the window content scale callback of the specified window,
- *  which is called when the content scale of the specified window changes.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, float xscale, float yscale)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWwindowcontentscalefun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref window_scale
- *  @sa @ref glfwGetWindowContentScale
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup window
- */
-GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback);
-
-/*! @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.
- *
- *  Do not assume that callbacks you set will _only_ be called in response to
- *  event processing functions like this one.  While it is necessary to poll for
- *  events, window systems that require GLFW to register callbacks of its own
- *  can pass events to GLFW in response to many window system function calls.
- *  GLFW will pass those events on to the application callbacks before
- *  returning.
- *
- *  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 @ref glfwWaitEvents
- *  @sa @ref 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.
- *
- *  Do not assume that callbacks you set will _only_ be called in response to
- *  event processing functions like this one.  While it is necessary to poll for
- *  events, window systems that require GLFW to register callbacks of its own
- *  can pass events to GLFW in response to many window system function calls.
- *  GLFW will pass those events on to the application callbacks before
- *  returning.
- *
- *  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 @ref glfwPollEvents
- *  @sa @ref 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.
- *
- *  Do not assume that callbacks you set will _only_ be called in response to
- *  event processing functions like this one.  While it is necessary to poll for
- *  events, window systems that require GLFW to register callbacks of its own
- *  can pass events to GLFW in response to many window system function calls.
- *  GLFW will pass those events on to the application callbacks before
- *  returning.
- *
- *  Event processing is not required for joystick input to work.
- *
- *  @param[in] timeout The maximum amount of time, in seconds, to wait.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
- *  GLFW_INVALID_VALUE 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 @ref glfwPollEvents
- *  @sa @ref 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.
- *
- *  @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 @ref glfwWaitEvents
- *  @sa @ref 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 @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
- *  @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
- *  @ref GLFW_RAW_MOUSE_MOTION.
- *
- *  @param[in] window The window to query.
- *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
- *  `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
- *  `GLFW_RAW_MOUSE_MOTION`.
- *
- *  @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 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 @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
- *  @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
- *  @ref GLFW_RAW_MOUSE_MOTION.
- *
- *  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
- *    content 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.
- *
- *  If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
- *  enable lock key modifier bits, or `GLFW_FALSE` to disable them.  If enabled,
- *  callbacks that receive modifier bits will also have the @ref
- *  GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
- *  and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
- *
- *  If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE`
- *  to enable raw (unscaled and unaccelerated) mouse motion when the cursor is
- *  disabled, or `GLFW_FALSE` to disable it.  If raw motion is not supported,
- *  attempting to set this will emit @ref GLFW_PLATFORM_ERROR.  Call @ref
- *  glfwRawMouseMotionSupported to check for support.
- *
- *  @param[in] window The window whose input mode to set.
- *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
- *  `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
- *  `GLFW_RAW_MOUSE_MOTION`.
- *  @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 @ref glfwGetInputMode
- *
- *  @since Added in version 3.0.  Replaces `glfwEnable` and `glfwDisable`.
- *
- *  @ingroup input
- */
-GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
-
-/*! @brief Returns whether raw mouse motion is supported.
- *
- *  This function returns whether raw mouse motion is supported on the current
- *  system.  This status does not change after GLFW has been initialized so you
- *  only need to check this once.  If you attempt to enable raw motion on
- *  a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted.
- *
- *  Raw mouse motion is closer to the actual motion of the mouse across
- *  a surface.  It is not affected by the scaling and acceleration applied to
- *  the motion of the desktop cursor.  That processing is suitable for a cursor
- *  while raw motion is better for controlling for example a 3D camera.  Because
- *  of this, raw mouse motion is only provided when the cursor is disabled.
- *
- *  @return `GLFW_TRUE` if raw mouse motion is supported on the current machine,
- *  or `GLFW_FALSE` otherwise.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref raw_mouse_motion
- *  @sa @ref glfwSetInputMode
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI int glfwRawMouseMotionSupported(void);
-
-/*! @brief Returns the layout-specific name of the specified printable key.
- *
- *  This function returns the name of the specified printable key, encoded as
- *  UTF-8.  This is typically the character that key would produce without any
- *  modifier keys, intended for displaying key bindings to the user.  For dead
- *  keys, it is typically the diacritic it would add to a character.
- *
- *  __Do not use this function__ for [text input](@ref input_char).  You will
- *  break text input for many languages even if it happens to work for yours.
- *
- *  If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key,
- *  otherwise the scancode is ignored.  If you specify a non-printable key, or
- *  `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this
- *  function returns `NULL` but does not emit an error.
- *
- *  This behavior allows you to always pass in the arguments in 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`
- *
- *  Names for printable keys depend on keyboard layout, while names for
- *  non-printable keys are the same across layouts but depend on the application
- *  language and should be localized along with other user interface text.
- *
- *  @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
- *  @param[in] scancode The scancode of the key to query.
- *  @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark The contents of the returned string may change when a keyboard
- *  layout change event is received.
- *
- *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You
- *  should not free it yourself.  It is valid 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 platform-specific scancode of the specified key.
- *
- *  This function returns the platform-specific scancode of the specified key.
- *
- *  If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
- *  method will return `-1`.
- *
- *  @param[in] key Any [named key](@ref keys).
- *  @return The platform-specific scancode for the key, or `-1` if an
- *  [error](@ref error_handling) occurred.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
- *  GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
- *
- *  @thread_safety This function may be called from any thread.
- *
- *  @sa @ref input_key
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI int glfwGetKeyScancode(int key);
-
-/*! @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 @ref 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 @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
- *  returns `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 content area of
- *  the window.
- *
- *  This function returns the position of the cursor, in screen coordinates,
- *  relative to the upper-left corner of the content 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 content area, or `NULL`.
- *  @param[out] ypos Where to store the cursor y-coordinate, relative to the to
- *  top edge of the content 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 @ref 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 content area of the
- *  window.
- *
- *  This function sets the position, in screen coordinates, of the cursor
- *  relative to the upper-left corner of the content 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
- *  content area.
- *  @param[in] ypos The desired y-coordinate, relative to the top edge of the
- *  content area.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_PLATFORM_ERROR.
- *
- *  @remark @wayland This function will only work when the cursor mode is
- *  `GLFW_CURSOR_DISABLED`, otherwise it will do nothing.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref cursor_pos
- *  @sa @ref 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 with the red channel first.  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.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref cursor_object
- *  @sa @ref glfwDestroyCursor
- *  @sa @ref 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.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref cursor_object
- *  @sa @ref 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.
- *
- *  If the specified cursor is current for any window, that window will be
- *  reverted to the default cursor.  This does not affect the cursor mode.
- *
- *  @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 @ref 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
- *  content 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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWkeyfun).
- *
- *  @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 callback);
-
-/*! @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 macOS or Alt key
- *  on Windows.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, unsigned int codepoint)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWcharfun).
- *
- *  @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 callback);
-
-/*! @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] callback 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.
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWcharmodsfun).
- *
- *  @deprecated Scheduled for removal in version 4.0.
- *
- *  @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 callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int button, int action, int mods)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWmousebuttonfun).
- *
- *  @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 callback);
-
-/*! @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
- *  content area of the window.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, double xpos, double ypos);
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWcursorposfun).
- *
- *  @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 callback);
-
-/*! @brief Sets the cursor enter/leave callback.
- *
- *  This function sets the cursor boundary crossing callback of the specified
- *  window, which is called when the cursor enters or leaves the content area of
- *  the window.
- *
- *  @param[in] window The window whose callback to set.
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int entered)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWcursorenterfun).
- *
- *  @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 callback);
-
-/*! @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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, double xoffset, double yoffset)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWscrollfun).
- *
- *  @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 callback);
-
-/*! @brief Sets the path drop callback.
- *
- *  This function sets the path drop callback of the specified window, which is
- *  called when one or more dragged paths 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] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(GLFWwindow* window, int path_count, const char* paths[])
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWdropfun).
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
- *
- *  @remark @wayland File drop is currently unimplemented.
- *
- *  @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 callback);
-
-/*! @brief Returns whether the specified joystick is present.
- *
- *  This function returns whether the specified joystick is present.
- *
- *  There is no need to call this function before other functions that accept
- *  a joystick ID, as they all check for presence before performing any other
- *  work.
- *
- *  @param[in] jid 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 jid);
-
-/*! @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.
- *
- *  If the specified joystick is not present this function will return `NULL`
- *  but will not generate an error.  This can be used instead of first calling
- *  @ref glfwJoystickPresent.
- *
- *  @param[in] jid 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 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 jid, 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`.
- *
- *  For backward compatibility with earlier versions that did not have @ref
- *  glfwGetJoystickHats, the button array also includes all hats, each
- *  represented as four buttons.  The hats are in the same order as returned by
- *  __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
- *  _left_.  To disable these extra buttons, set the @ref
- *  GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
- *
- *  If the specified joystick is not present this function will return `NULL`
- *  but will not generate an error.  This can be used instead of first calling
- *  @ref glfwJoystickPresent.
- *
- *  @param[in] jid 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 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 jid, int* count);
-
-/*! @brief Returns the state of all hats of the specified joystick.
- *
- *  This function returns the state of all hats of the specified joystick.
- *  Each element in the array is one of the following values:
- *
- *  Name                  | Value
- *  ----                  | -----
- *  `GLFW_HAT_CENTERED`   | 0
- *  `GLFW_HAT_UP`         | 1
- *  `GLFW_HAT_RIGHT`      | 2
- *  `GLFW_HAT_DOWN`       | 4
- *  `GLFW_HAT_LEFT`       | 8
- *  `GLFW_HAT_RIGHT_UP`   | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
- *  `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
- *  `GLFW_HAT_LEFT_UP`    | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
- *  `GLFW_HAT_LEFT_DOWN`  | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
- *
- *  The diagonal directions are bitwise combinations of the primary (up, right,
- *  down and left) directions and you can test for these individually by ANDing
- *  it with the corresponding direction.
- *
- *  @code
- *  if (hats[2] & GLFW_HAT_RIGHT)
- *  {
- *      // State of hat 2 could be right-up, right or right-down
- *  }
- *  @endcode
- *
- *  If the specified joystick is not present this function will return `NULL`
- *  but will not generate an error.  This can be used instead of first calling
- *  @ref glfwJoystickPresent.
- *
- *  @param[in] jid The [joystick](@ref joysticks) to query.
- *  @param[out] count Where to store the number of hat states in the returned
- *  array.  This is set to zero if the joystick is not present or an error
- *  occurred.
- *  @return An array of hat 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_hat
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, 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.
- *
- *  If the specified joystick is not present this function will return `NULL`
- *  but will not generate an error.  This can be used instead of first calling
- *  @ref glfwJoystickPresent.
- *
- *  @param[in] jid 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 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 jid);
-
-/*! @brief Returns the SDL compatible GUID of the specified joystick.
- *
- *  This function returns the SDL compatible GUID, as a UTF-8 encoded
- *  hexadecimal string, of the specified joystick.  The returned string is
- *  allocated and freed by GLFW.  You should not free it yourself.
- *
- *  The GUID is what connects a joystick to a gamepad mapping.  A connected
- *  joystick will always have a GUID even if there is no gamepad mapping
- *  assigned to it.
- *
- *  If the specified joystick is not present this function will return `NULL`
- *  but will not generate an error.  This can be used instead of first calling
- *  @ref glfwJoystickPresent.
- *
- *  The GUID uses the format introduced in SDL 2.0.5.  This GUID tries to
- *  uniquely identify the make and model of a joystick but does not identify
- *  a specific unit, e.g. all wired Xbox 360 controllers will have the same
- *  GUID on that platform.  The GUID for a unit may vary between platforms
- *  depending on what hardware information the platform specific APIs provide.
- *
- *  @param[in] jid The [joystick](@ref joysticks) to query.
- *  @return The UTF-8 encoded GUID 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 or the library is terminated.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref gamepad
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI const char* glfwGetJoystickGUID(int jid);
-
-/*! @brief Sets the user pointer of the specified joystick.
- *
- *  This function sets the user-defined pointer of the specified joystick.  The
- *  current value is retained until the joystick is disconnected.  The initial
- *  value is `NULL`.
- *
- *  This function may be called from the joystick callback, even for a joystick
- *  that is being disconnected.
- *
- *  @param[in] jid The joystick 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 joystick_userptr
- *  @sa @ref glfwGetJoystickUserPointer
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
-
-/*! @brief Returns the user pointer of the specified joystick.
- *
- *  This function returns the current value of the user-defined pointer of the
- *  specified joystick.  The initial value is `NULL`.
- *
- *  This function may be called from the joystick callback, even for a joystick
- *  that is being disconnected.
- *
- *  @param[in] jid The joystick 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 joystick_userptr
- *  @sa @ref glfwSetJoystickUserPointer
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI void* glfwGetJoystickUserPointer(int jid);
-
-/*! @brief Returns whether the specified joystick has a gamepad mapping.
- *
- *  This function returns whether the specified joystick is both present and has
- *  a gamepad mapping.
- *
- *  If the specified joystick is present but does not have a gamepad mapping
- *  this function will return `GLFW_FALSE` but will not generate an error.  Call
- *  @ref glfwJoystickPresent to check if a joystick is present regardless of
- *  whether it has a mapping.
- *
- *  @param[in] jid The [joystick](@ref joysticks) to query.
- *  @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
- *  or `GLFW_FALSE` otherwise.
- *
- *  @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 gamepad
- *  @sa @ref glfwGetGamepadState
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI int glfwJoystickIsGamepad(int jid);
-
-/*! @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.
- *
- *  For joystick connection and disconnection events to be delivered on all
- *  platforms, you need to call one of the [event processing](@ref events)
- *  functions.  Joystick disconnection may also be detected and the callback
- *  called by joystick functions.  The function will then return whatever it
- *  returns if the joystick is not present.
- *
- *  @param[in] callback 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).
- *
- *  @callback_signature
- *  @code
- *  void function_name(int jid, int event)
- *  @endcode
- *  For more information about the callback parameters, see the
- *  [function pointer type](@ref GLFWjoystickfun).
- *
- *  @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 callback);
-
-/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings.
- *
- *  This function parses the specified ASCII encoded string and updates the
- *  internal list with any gamepad mappings it finds.  This string may
- *  contain either a single gamepad mapping or many mappings separated by
- *  newlines.  The parser supports the full format of the `gamecontrollerdb.txt`
- *  source file including empty lines and comments.
- *
- *  See @ref gamepad_mapping for a description of the format.
- *
- *  If there is already a gamepad mapping for a given GUID in the internal list,
- *  it will be replaced by the one passed to this function.  If the library is
- *  terminated and re-initialized the internal list will revert to the built-in
- *  default.
- *
- *  @param[in] string The string containing the gamepad mappings.
- *  @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
- *  [error](@ref error_handling) occurred.
- *
- *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
- *  GLFW_INVALID_VALUE.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref gamepad
- *  @sa @ref glfwJoystickIsGamepad
- *  @sa @ref glfwGetGamepadName
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI int glfwUpdateGamepadMappings(const char* string);
-
-/*! @brief Returns the human-readable gamepad name for the specified joystick.
- *
- *  This function returns the human-readable name of the gamepad from the
- *  gamepad mapping assigned to the specified joystick.
- *
- *  If the specified joystick is not present or does not have a gamepad mapping
- *  this function will return `NULL` but will not generate an error.  Call
- *  @ref glfwJoystickPresent to check whether it is present regardless of
- *  whether it has a mapping.
- *
- *  @param[in] jid The [joystick](@ref joysticks) to query.
- *  @return The UTF-8 encoded name of the gamepad, or `NULL` if the
- *  joystick is not present, does not have a mapping or an
- *  [error](@ref error_handling) occurred.
- *
- *  @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, the gamepad mappings are updated or the library is terminated.
- *
- *  @thread_safety This function must only be called from the main thread.
- *
- *  @sa @ref gamepad
- *  @sa @ref glfwJoystickIsGamepad
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI const char* glfwGetGamepadName(int jid);
-
-/*! @brief Retrieves the state of the specified joystick remapped as a gamepad.
- *
- *  This function retrieves the state of the specified joystick remapped to
- *  an Xbox-like gamepad.
- *
- *  If the specified joystick is not present or does not have a gamepad mapping
- *  this function will return `GLFW_FALSE` but will not generate an error.  Call
- *  @ref glfwJoystickPresent to check whether it is present regardless of
- *  whether it has a mapping.
- *
- *  The Guide button may not be available for input as it is often hooked by the
- *  system or the Steam client.
- *
- *  Not all devices have all the buttons or axes provided by @ref
- *  GLFWgamepadstate.  Unavailable buttons and axes will always report
- *  `GLFW_RELEASE` and 0.0 respectively.
- *
- *  @param[in] jid The [joystick](@ref joysticks) to query.
- *  @param[out] state The gamepad input state of the joystick.
- *  @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is
- *  connected, it has no gamepad mapping or an [error](@ref error_handling)
- *  occurred.
- *
- *  @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 gamepad
- *  @sa @ref glfwUpdateGamepadMappings
- *  @sa @ref glfwJoystickIsGamepad
- *
- *  @since Added in version 3.3.
- *
- *  @ingroup input
- */
-GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
-
-/*! @brief Sets the clipboard to the specified string.
- *
- *  This function sets the system clipboard to the specified, UTF-8 encoded
- *  string.
- *
- *  @param[in] window Deprecated.  Any valid window or `NULL`.
- *  @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 @ref 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 Deprecated.  Any valid window or `NULL`.
- *  @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 @ref glfwSetClipboardString
- *
- *  @since Added in version 3.0.
- *
- *  @ingroup input
- */
-GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
-
-/*! @brief Returns the GLFW time.
- *
- *  This function returns the current GLFW time, in seconds.  Unless the time
- *  has been set using @ref glfwSetTime it measures time elapsed since GLFW was
- *  initialized.
- *
- *  This function and @ref glfwSetTime are helper functions on top of @ref
- *  glfwGetTimerFrequency and @ref glfwGetTimerValue.
- *
- *  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 time, 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 base time 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 time.
- *
- *  This function sets the current GLFW time, in seconds.  The value must be
- *  a positive finite number less than or equal to 18446744073.0, which is
- *  approximately 584.5 years.
- *
- *  This function and @ref glfwGetTime are helper functions on top of @ref
- *  glfwGetTimerFrequency and @ref glfwGetTimerValue.
- *
- *  @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 GLFW time 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 base time 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&nbsp;/&nbsp;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 @ref 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 @ref 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 must only be made current on
- *  a single thread at a time and each thread can have only a single current
- *  context at a time.
- *
- *  When moving a context between threads, you must make it non-current on the
- *  old thread before making it current on the new one.
- *
- *  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 GLFW_CONTEXT_RELEASE_BEHAVIOR_hint)
- *  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 @ref 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 @ref 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 @ref 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_.
- *
- *  A context that supports either of the `WGL_EXT_swap_control_tear` and
- *  `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap
- *  intervals, which allows the driver to swap immediately even if a frame
- *  arrives a little bit late.  You can check for these extensions with @ref
- *  glfwExtensionSupported.
- *
- *  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 @ref 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 @ref 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 @ref glfwExtensionSupported
- *
- *  @since Added in version 1.0.
- *
- *  @ingroup context
- */
-GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
-
-/*! @brief Returns whether the Vulkan loader and an ICD have been found.
- *
- *  This function returns whether the Vulkan loader and any minimally functional
- *  ICD have been found.
- *
- *  The availability of a Vulkan loader and even an ICD does not by itself
- *  guarantee that surface creation or even instance creation is possible.
- *  For example, on Fermi systems Nvidia will install an ICD that provides no
- *  actual Vulkan support.  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 minimally 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 contain `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 at least minimally 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.
- *
- *  @remark 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.
- *
- *  @remark @macos This function currently only supports the
- *  `VK_MVK_macos_surface` extension from MoltenVK.
- *
- *  @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 @ref 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 at least minimally 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 at least minimally 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.
- *
- *  @remark @macos This function currently always returns `GLFW_TRUE`, as the
- *  `VK_MVK_macos_surface` extension does not provide
- *  a `vkGetPhysicalDevice*PresentationSupport` type function.
- *
- *  @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 or at least one minimally functional ICD were not found,
- *  this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref
- *  GLFW_API_UNAVAILABLE error.  Call @ref glfwVulkanSupported to check whether
- *  Vulkan is at least minimally available.
- *
- *  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 cannot be shared with another API so the window must
- *  have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
- *  set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
- *  and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
- *
- *  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, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
- *
- *  @remark 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.
- *
- *  @remark @macos This function currently only supports the
- *  `VK_MVK_macos_surface` extension from MoltenVK.
- *
- *  @remark @macos This function creates and sets a `CAMetalLayer` instance for
- *  the window content view, which is required for MoltenVK to function.
- *
- *  @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 @ref 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*/
-
-
-/*************************************************************************
- * Global definition cleanup
- *************************************************************************/
-
-/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
-
-#ifdef GLFW_WINGDIAPI_DEFINED
- #undef WINGDIAPI
- #undef GLFW_WINGDIAPI_DEFINED
-#endif
-
-#ifdef GLFW_CALLBACK_DEFINED
- #undef CALLBACK
- #undef GLFW_CALLBACK_DEFINED
-#endif
-
-/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally
- * defined by some gl.h variants (OpenBSD) so define it after if needed.
- */
-#ifndef GLAPIENTRY
- #define GLAPIENTRY APIENTRY
-#endif
-
-/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _glfw3_h_ */
-
+/*************************************************************************
+ * GLFW 3.3 - www.glfw.org
+ * A library for OpenGL, window and input
+ *------------------------------------------------------------------------
+ * Copyright (c) 2002-2006 Marcus Geelnard
+ * Copyright (c) 2006-2019 Camilla Löwy <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
+ *  @brief Functions and types related to OpenGL and OpenGL ES contexts.
+ *
+ *  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
+ *  @brief Functions and types related to Vulkan.
+ *
+ *  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
+ *  @brief Functions and types related to initialization and error handling.
+ *
+ *  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
+ *  @brief Functions and types related to input handling.
+ *
+ *  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
+ *  @brief Functions and types related to monitors.
+ *
+ *  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
+ *  @brief Functions and types related to windows.
+ *
+ *  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 */
+
+/* Include because most Windows GLU headers need wchar_t and
+ * the macOS 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 it unconditionally to avoid surprising side-effects.
+ */
+#include <stdint.h>
+
+#if defined(GLFW_INCLUDE_VULKAN)
+  #include <vulkan/vulkan.h>
+#endif /* Vulkan header */
+
+/* The Vulkan header may have indirectly included windows.h (because of
+ * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it.
+ */
+
+/* It is customary to use APIENTRY for OpenGL function pointer declarations on
+ * all platforms.  Additionally, the Windows OpenGL header needs APIENTRY.
+ */
+#if !defined(APIENTRY)
+ #if defined(_WIN32)
+  #define APIENTRY __stdcall
+ #else
+  #define APIENTRY
+ #endif
+ #define GLFW_APIENTRY_DEFINED
+#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 the chosen OpenGL or OpenGL ES headers.
+ */
+#if 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_ES32)
+
+ #include <GLES3/gl32.h>
+ #if defined(GLFW_INCLUDE_GLEXT)
+  #include <GLES2/gl2ext.h>
+ #endif
+
+#elif defined(GLFW_INCLUDE_GLCOREARB)
+
+ #if defined(__APPLE__)
+
+  #include <OpenGL/gl3.h>
+  #if defined(GLFW_INCLUDE_GLEXT)
+   #include <OpenGL/gl3ext.h>
+  #endif /*GLFW_INCLUDE_GLEXT*/
+
+ #else /*__APPLE__*/
+
+  #include <GL/glcorearb.h>
+
+ #endif /*__APPLE__*/
+
+#elif !defined(GLFW_INCLUDE_NONE)
+
+ #if defined(__APPLE__)
+
+  #if !defined(GLFW_INCLUDE_GLEXT)
+   #define GL_GLEXT_LEGACY
+  #endif
+  #include <OpenGL/gl.h>
+  #if defined(GLFW_INCLUDE_GLU)
+   #include <OpenGL/glu.h>
+  #endif
+
+ #else /*__APPLE__*/
+
+  #include <GL/gl.h>
+  #if defined(GLFW_INCLUDE_GLEXT)
+   #include <GL/glext.h>
+  #endif
+  #if defined(GLFW_INCLUDE_GLU)
+   #include <GL/glu.h>
+  #endif
+
+ #endif /*__APPLE__*/
+
+#endif /* OpenGL and OpenGL ES headers */
+
+#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          3
+/*! @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       2
+/*! @} */
+
+/*! @brief One.
+ *
+ *  This is only semantic sugar for the number 1.  You can instead use `1` or
+ *  `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal
+ *  to one.
+ *
+ *  @ingroup init
+ */
+#define GLFW_TRUE                   1
+/*! @brief Zero.
+ *
+ *  This is only semantic sugar for the number 0.  You can instead use `0` or
+ *  `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is
+ *  equal to zero.
+ *
+ *  @ingroup init
+ */
+#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 hat_state Joystick hat states
+ *  @brief Joystick hat states.
+ *
+ *  See [joystick hat input](@ref joystick_hat) for how these are used.
+ *
+ *  @ingroup input
+ *  @{ */
+#define GLFW_HAT_CENTERED           0
+#define GLFW_HAT_UP                 1
+#define GLFW_HAT_RIGHT              2
+#define GLFW_HAT_DOWN               4
+#define GLFW_HAT_LEFT               8
+#define GLFW_HAT_RIGHT_UP           (GLFW_HAT_RIGHT | GLFW_HAT_UP)
+#define GLFW_HAT_RIGHT_DOWN         (GLFW_HAT_RIGHT | GLFW_HAT_DOWN)
+#define GLFW_HAT_LEFT_UP            (GLFW_HAT_LEFT  | GLFW_HAT_UP)
+#define GLFW_HAT_LEFT_DOWN          (GLFW_HAT_LEFT  | GLFW_HAT_DOWN)
+/*! @} */
+
+/*! @defgroup keys Keyboard keys
+ *  @brief Keyboard key IDs.
+ *
+ *  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
+ *  @brief 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.
+ *
+ *  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.
+ *
+ *  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.
+ *
+ *  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.
+ *
+ *  If this bit is set one or more Super keys were held down.
+ */
+#define GLFW_MOD_SUPER           0x0008
+/*! @brief If this bit is set the Caps Lock key is enabled.
+ *
+ *  If this bit is set the Caps Lock key is enabled and the @ref
+ *  GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_CAPS_LOCK       0x0010
+/*! @brief If this bit is set the Num Lock key is enabled.
+ *
+ *  If this bit is set the Num Lock key is enabled and the @ref
+ *  GLFW_LOCK_KEY_MODS input mode is set.
+ */
+#define GLFW_MOD_NUM_LOCK        0x0020
+
+/*! @} */
+
+/*! @defgroup buttons Mouse buttons
+ *  @brief Mouse button IDs.
+ *
+ *  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
+ *  @brief Joystick IDs.
+ *
+ *  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 gamepad_buttons Gamepad buttons
+ *  @brief Gamepad buttons.
+ *
+ *  See @ref gamepad for how these are used.
+ *
+ *  @ingroup input
+ *  @{ */
+#define GLFW_GAMEPAD_BUTTON_A               0
+#define GLFW_GAMEPAD_BUTTON_B               1
+#define GLFW_GAMEPAD_BUTTON_X               2
+#define GLFW_GAMEPAD_BUTTON_Y               3
+#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER     4
+#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER    5
+#define GLFW_GAMEPAD_BUTTON_BACK            6
+#define GLFW_GAMEPAD_BUTTON_START           7
+#define GLFW_GAMEPAD_BUTTON_GUIDE           8
+#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB      9
+#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB     10
+#define GLFW_GAMEPAD_BUTTON_DPAD_UP         11
+#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT      12
+#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN       13
+#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT       14
+#define GLFW_GAMEPAD_BUTTON_LAST            GLFW_GAMEPAD_BUTTON_DPAD_LEFT
+
+#define GLFW_GAMEPAD_BUTTON_CROSS       GLFW_GAMEPAD_BUTTON_A
+#define GLFW_GAMEPAD_BUTTON_CIRCLE      GLFW_GAMEPAD_BUTTON_B
+#define GLFW_GAMEPAD_BUTTON_SQUARE      GLFW_GAMEPAD_BUTTON_X
+#define GLFW_GAMEPAD_BUTTON_TRIANGLE    GLFW_GAMEPAD_BUTTON_Y
+/*! @} */
+
+/*! @defgroup gamepad_axes Gamepad axes
+ *  @brief Gamepad axes.
+ *
+ *  See @ref gamepad for how these are used.
+ *
+ *  @ingroup input
+ *  @{ */
+#define GLFW_GAMEPAD_AXIS_LEFT_X        0
+#define GLFW_GAMEPAD_AXIS_LEFT_Y        1
+#define GLFW_GAMEPAD_AXIS_RIGHT_X       2
+#define GLFW_GAMEPAD_AXIS_RIGHT_Y       3
+#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER  4
+#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5
+#define GLFW_GAMEPAD_AXIS_LAST          GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER
+/*! @} */
+
+/*! @defgroup errors Error codes
+ *  @brief Error codes.
+ *
+ *  See [error handling](@ref error_handling) for how these are used.
+ *
+ *  @ingroup init
+ *  @{ */
+/*! @brief No error has occurred.
+ *
+ *  No error has occurred.
+ *
+ *  @analysis Yay.
+ */
+#define GLFW_NO_ERROR               0
+/*! @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 @ref GLFW_RED_BITS 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.  macOS 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
+/*! @} */
+
+/*! @addtogroup window
+ *  @{ */
+/*! @brief Input focus window hint and attribute
+ *
+ *  Input focus [window hint](@ref GLFW_FOCUSED_hint) or
+ *  [window attribute](@ref GLFW_FOCUSED_attrib).
+ */
+#define GLFW_FOCUSED                0x00020001
+/*! @brief Window iconification window attribute
+ *
+ *  Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib).
+ */
+#define GLFW_ICONIFIED              0x00020002
+/*! @brief Window resize-ability window hint and attribute
+ *
+ *  Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and
+ *  [window attribute](@ref GLFW_RESIZABLE_attrib).
+ */
+#define GLFW_RESIZABLE              0x00020003
+/*! @brief Window visibility window hint and attribute
+ *
+ *  Window visibility [window hint](@ref GLFW_VISIBLE_hint) and
+ *  [window attribute](@ref GLFW_VISIBLE_attrib).
+ */
+#define GLFW_VISIBLE                0x00020004
+/*! @brief Window decoration window hint and attribute
+ *
+ *  Window decoration [window hint](@ref GLFW_DECORATED_hint) and
+ *  [window attribute](@ref GLFW_DECORATED_attrib).
+ */
+#define GLFW_DECORATED              0x00020005
+/*! @brief Window auto-iconification window hint and attribute
+ *
+ *  Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and
+ *  [window attribute](@ref GLFW_AUTO_ICONIFY_attrib).
+ */
+#define GLFW_AUTO_ICONIFY           0x00020006
+/*! @brief Window decoration window hint and attribute
+ *
+ *  Window decoration [window hint](@ref GLFW_FLOATING_hint) and
+ *  [window attribute](@ref GLFW_FLOATING_attrib).
+ */
+#define GLFW_FLOATING               0x00020007
+/*! @brief Window maximization window hint and attribute
+ *
+ *  Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and
+ *  [window attribute](@ref GLFW_MAXIMIZED_attrib).
+ */
+#define GLFW_MAXIMIZED              0x00020008
+/*! @brief Cursor centering window hint
+ *
+ *  Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint).
+ */
+#define GLFW_CENTER_CURSOR          0x00020009
+/*! @brief Window framebuffer transparency hint and attribute
+ *
+ *  Window framebuffer transparency
+ *  [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and
+ *  [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib).
+ */
+#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A
+/*! @brief Mouse cursor hover window attribute.
+ *
+ *  Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib).
+ */
+#define GLFW_HOVERED                0x0002000B
+/*! @brief Input focus on calling show window hint and attribute
+ *
+ *  Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or
+ *  [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ */
+#define GLFW_FOCUS_ON_SHOW          0x0002000C
+
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_RED_BITS).
+ */
+#define GLFW_RED_BITS               0x00021001
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS).
+ */
+#define GLFW_GREEN_BITS             0x00021002
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS).
+ */
+#define GLFW_BLUE_BITS              0x00021003
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS).
+ */
+#define GLFW_ALPHA_BITS             0x00021004
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS).
+ */
+#define GLFW_DEPTH_BITS             0x00021005
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS).
+ */
+#define GLFW_STENCIL_BITS           0x00021006
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS).
+ */
+#define GLFW_ACCUM_RED_BITS         0x00021007
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS).
+ */
+#define GLFW_ACCUM_GREEN_BITS       0x00021008
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS).
+ */
+#define GLFW_ACCUM_BLUE_BITS        0x00021009
+/*! @brief Framebuffer bit depth hint.
+ *
+ *  Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS).
+ */
+#define GLFW_ACCUM_ALPHA_BITS       0x0002100A
+/*! @brief Framebuffer auxiliary buffer hint.
+ *
+ *  Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS).
+ */
+#define GLFW_AUX_BUFFERS            0x0002100B
+/*! @brief OpenGL stereoscopic rendering hint.
+ *
+ *  OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO).
+ */
+#define GLFW_STEREO                 0x0002100C
+/*! @brief Framebuffer MSAA samples hint.
+ *
+ *  Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES).
+ */
+#define GLFW_SAMPLES                0x0002100D
+/*! @brief Framebuffer sRGB hint.
+ *
+ *  Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE).
+ */
+#define GLFW_SRGB_CAPABLE           0x0002100E
+/*! @brief Monitor refresh rate hint.
+ *
+ *  Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE).
+ */
+#define GLFW_REFRESH_RATE           0x0002100F
+/*! @brief Framebuffer double buffering hint.
+ *
+ *  Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER).
+ */
+#define GLFW_DOUBLEBUFFER           0x00021010
+
+/*! @brief Context client API hint and attribute.
+ *
+ *  Context client API [hint](@ref GLFW_CLIENT_API_hint) and
+ *  [attribute](@ref GLFW_CLIENT_API_attrib).
+ */
+#define GLFW_CLIENT_API             0x00022001
+/*! @brief Context client API major version hint and attribute.
+ *
+ *  Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint)
+ *  and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MAJOR  0x00022002
+/*! @brief Context client API minor version hint and attribute.
+ *
+ *  Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint)
+ *  and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
+ */
+#define GLFW_CONTEXT_VERSION_MINOR  0x00022003
+/*! @brief Context client API revision number hint and attribute.
+ *
+ *  Context client API revision number
+ *  [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
+ */
+#define GLFW_CONTEXT_REVISION       0x00022004
+/*! @brief Context robustness hint and attribute.
+ *
+ *  Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint)
+ *  and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib).
+ */
+#define GLFW_CONTEXT_ROBUSTNESS     0x00022005
+/*! @brief OpenGL forward-compatibility hint and attribute.
+ *
+ *  OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
+ *  and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
+ */
+#define GLFW_OPENGL_FORWARD_COMPAT  0x00022006
+/*! @brief OpenGL debug context hint and attribute.
+ *
+ *  OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and
+ *  [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).
+ */
+#define GLFW_OPENGL_DEBUG_CONTEXT   0x00022007
+/*! @brief OpenGL profile hint and attribute.
+ *
+ *  OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
+ *  [attribute](@ref GLFW_OPENGL_PROFILE_attrib).
+ */
+#define GLFW_OPENGL_PROFILE         0x00022008
+/*! @brief Context flush-on-release hint and attribute.
+ *
+ *  Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and
+ *  [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib).
+ */
+#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
+/*! @brief Context error suppression hint and attribute.
+ *
+ *  Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and
+ *  [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib).
+ */
+#define GLFW_CONTEXT_NO_ERROR       0x0002200A
+/*! @brief Context creation API hint and attribute.
+ *
+ *  Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and
+ *  [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib).
+ */
+#define GLFW_CONTEXT_CREATION_API   0x0002200B
+/*! @brief Window content area scaling window
+ *  [window hint](@ref GLFW_SCALE_TO_MONITOR).
+ */
+#define GLFW_SCALE_TO_MONITOR       0x0002200C
+/*! @brief macOS specific
+ *  [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint).
+ */
+#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001
+/*! @brief macOS specific
+ *  [window hint](@ref GLFW_COCOA_FRAME_NAME_hint).
+ */
+#define GLFW_COCOA_FRAME_NAME         0x00023002
+/*! @brief macOS specific
+ *  [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint).
+ */
+#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003
+/*! @brief X11 specific
+ *  [window hint](@ref GLFW_X11_CLASS_NAME_hint).
+ */
+#define GLFW_X11_CLASS_NAME         0x00024001
+/*! @brief X11 specific
+ *  [window hint](@ref GLFW_X11_CLASS_NAME_hint).
+ */
+#define GLFW_X11_INSTANCE_NAME      0x00024002
+/*! @} */
+
+#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_LOCK_KEY_MODS          0x00033004
+#define GLFW_RAW_MOUSE_MOTION       0x00033005
+
+#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
+#define GLFW_OSMESA_CONTEXT_API     0x00036003
+
+/*! @defgroup shapes Standard cursor shapes
+ *  @brief Standard system 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
+
+/*! @addtogroup init
+ *  @{ */
+/*! @brief Joystick hat buttons init hint.
+ *
+ *  Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS).
+ */
+#define GLFW_JOYSTICK_HAT_BUTTONS   0x00050001
+/*! @brief macOS specific init hint.
+ *
+ *  macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint).
+ */
+#define GLFW_COCOA_CHDIR_RESOURCES  0x00051001
+/*! @brief macOS specific init hint.
+ *
+ *  macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
+ */
+#define GLFW_COCOA_MENUBAR          0x00051002
+/*! @} */
+
+#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 @ref 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 @ref 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 input
+ */
+typedef struct GLFWcursor GLFWcursor;
+
+/*! @brief The function pointer type for error callbacks.
+ *
+ *  This is the function pointer type for error callbacks.  An error callback
+ *  function has the following signature:
+ *  @code
+ *  void callback_name(int error_code, const char* description)
+ *  @endcode
+ *
+ *  @param[in] error_code An [error code](@ref errors).  Future releases may add
+ *  more error codes.
+ *  @param[in] description A UTF-8 encoded string describing the error.
+ *
+ *  @pointer_lifetime The error description string is valid until the callback
+ *  function returns.
+ *
+ *  @sa @ref error_handling
+ *  @sa @ref glfwSetErrorCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup init
+ */
+typedef void (* GLFWerrorfun)(int,const char*);
+
+/*! @brief The function pointer type for window position callbacks.
+ *
+ *  This is the function pointer type for window position callbacks.  A window
+ *  position callback function has the following signature:
+ *  @code
+ *  void callback_name(GLFWwindow* window, int xpos, int ypos)
+ *  @endcode
+ *
+ *  @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 content area of the window.
+ *  @param[in] ypos The new y-coordinate, in screen coordinates, of the
+ *  upper-left corner of the content area of the window.
+ *
+ *  @sa @ref window_pos
+ *  @sa @ref glfwSetWindowPosCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int);
+
+/*! @brief The function pointer type for window size callbacks.
+ *
+ *  This is the function pointer type for window size callbacks.  A window size
+ *  callback function has the following signature:
+ *  @code
+ *  void callback_name(GLFWwindow* window, int width, int height)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetWindowSizeCallback
+ *
+ *  @since Added in version 1.0.
+ *  @glfw3 Added window handle parameter.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function pointer type for window close callbacks.
+ *
+ *  This is the function pointer type for window close callbacks.  A window
+ *  close callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window)
+ *  @endcode
+ *
+ *  @param[in] window The window that the user attempted to close.
+ *
+ *  @sa @ref window_close
+ *  @sa @ref glfwSetWindowCloseCallback
+ *
+ *  @since Added in version 2.5.
+ *  @glfw3 Added window handle parameter.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowclosefun)(GLFWwindow*);
+
+/*! @brief The function pointer type for window content refresh callbacks.
+ *
+ *  This is the function pointer type for window content refresh callbacks.
+ *  A window content refresh callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window);
+ *  @endcode
+ *
+ *  @param[in] window The window whose content needs to be refreshed.
+ *
+ *  @sa @ref window_refresh
+ *  @sa @ref glfwSetWindowRefreshCallback
+ *
+ *  @since Added in version 2.5.
+ *  @glfw3 Added window handle parameter.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowrefreshfun)(GLFWwindow*);
+
+/*! @brief The function pointer type for window focus callbacks.
+ *
+ *  This is the function pointer type for window focus callbacks.  A window
+ *  focus callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int focused)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetWindowFocusCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int);
+
+/*! @brief The function pointer type for window iconify callbacks.
+ *
+ *  This is the function pointer type for window iconify callbacks.  A window
+ *  iconify callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int iconified)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetWindowIconifyCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int);
+
+/*! @brief The function pointer type for window maximize callbacks.
+ *
+ *  This is the function pointer type for window maximize callbacks.  A window
+ *  maximize callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int maximized)
+ *  @endcode
+ *
+ *  @param[in] window The window that was maximized or restored.
+ *  @param[in] iconified `GLFW_TRUE` if the window was maximized, or
+ *  `GLFW_FALSE` if it was restored.
+ *
+ *  @sa @ref window_maximize
+ *  @sa glfwSetWindowMaximizeCallback
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int);
+
+/*! @brief The function pointer type for framebuffer size callbacks.
+ *
+ *  This is the function pointer type for framebuffer size callbacks.
+ *  A framebuffer size callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int width, int height)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetFramebufferSizeCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int);
+
+/*! @brief The function pointer type for window content scale callbacks.
+ *
+ *  This is the function pointer type for window content scale callbacks.
+ *  A window content scale callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, float xscale, float yscale)
+ *  @endcode
+ *
+ *  @param[in] window The window whose content scale changed.
+ *  @param[in] xscale The new x-axis content scale of the window.
+ *  @param[in] yscale The new y-axis content scale of the window.
+ *
+ *  @sa @ref window_scale
+ *  @sa @ref glfwSetWindowContentScaleCallback
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float);
+
+/*! @brief The function pointer type for mouse button callbacks.
+ *
+ *  This is the function pointer type for mouse button callback functions.
+ *  A mouse button callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int button, int action, int mods)
+ *  @endcode
+ *
+ *  @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`.  Future releases
+ *  may add more actions.
+ *  @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ *  held down.
+ *
+ *  @sa @ref input_mouse_button
+ *  @sa @ref 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 pointer type for cursor position callbacks.
+ *
+ *  This is the function pointer type for cursor position callbacks.  A cursor
+ *  position callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, double xpos, double ypos);
+ *  @endcode
+ *
+ *  @param[in] window The window that received the event.
+ *  @param[in] xpos The new cursor x-coordinate, relative to the left edge of
+ *  the content area.
+ *  @param[in] ypos The new cursor y-coordinate, relative to the top edge of the
+ *  content area.
+ *
+ *  @sa @ref cursor_pos
+ *  @sa @ref glfwSetCursorPosCallback
+ *
+ *  @since Added in version 3.0.  Replaces `GLFWmouseposfun`.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double);
+
+/*! @brief The function pointer type for cursor enter/leave callbacks.
+ *
+ *  This is the function pointer type for cursor enter/leave callbacks.
+ *  A cursor enter/leave callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int entered)
+ *  @endcode
+ *
+ *  @param[in] window The window that received the event.
+ *  @param[in] entered `GLFW_TRUE` if the cursor entered the window's content
+ *  area, or `GLFW_FALSE` if it left it.
+ *
+ *  @sa @ref cursor_enter
+ *  @sa @ref glfwSetCursorEnterCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
+
+/*! @brief The function pointer type for scroll callbacks.
+ *
+ *  This is the function pointer type for scroll callbacks.  A scroll callback
+ *  function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, double xoffset, double yoffset)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetScrollCallback
+ *
+ *  @since Added in version 3.0.  Replaces `GLFWmousewheelfun`.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
+
+/*! @brief The function pointer type for keyboard key callbacks.
+ *
+ *  This is the function pointer type for keyboard key callbacks.  A keyboard
+ *  key callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
+ *  @endcode
+ *
+ *  @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`.  Future
+ *  releases may add more actions.
+ *  @param[in] mods Bit field describing which [modifier keys](@ref mods) were
+ *  held down.
+ *
+ *  @sa @ref input_key
+ *  @sa @ref 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 pointer type for Unicode character callbacks.
+ *
+ *  This is the function pointer type for Unicode character callbacks.
+ *  A Unicode character callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, unsigned int codepoint)
+ *  @endcode
+ *
+ *  @param[in] window The window that received the event.
+ *  @param[in] codepoint The Unicode code point of the character.
+ *
+ *  @sa @ref input_char
+ *  @sa @ref glfwSetCharCallback
+ *
+ *  @since Added in version 2.4.
+ *  @glfw3 Added window handle parameter.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int);
+
+/*! @brief The function pointer type for Unicode character with modifiers
+ *  callbacks.
+ *
+ *  This is the function pointer type for Unicode character with modifiers
+ *  callbacks.  It is called for each input character, regardless of what
+ *  modifier keys are held down.  A Unicode character with modifiers callback
+ *  function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
+ *  @endcode
+ *
+ *  @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 @ref glfwSetCharModsCallback
+ *
+ *  @deprecated Scheduled for removal in version 4.0.
+ *
+ *  @since Added in version 3.1.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int);
+
+/*! @brief The function pointer type for path drop callbacks.
+ *
+ *  This is the function pointer type for path drop callbacks.  A path drop
+ *  callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWwindow* window, int path_count, const char* paths[])
+ *  @endcode
+ *
+ *  @param[in] window The window that received the event.
+ *  @param[in] path_count The number of dropped paths.
+ *  @param[in] paths The UTF-8 encoded file and/or directory path names.
+ *
+ *  @pointer_lifetime The path array and its strings are valid until the
+ *  callback function returns.
+ *
+ *  @sa @ref path_drop
+ *  @sa @ref glfwSetDropCallback
+ *
+ *  @since Added in version 3.1.
+ *
+ *  @ingroup input
+ */
+typedef void (* GLFWdropfun)(GLFWwindow*,int,const char*[]);
+
+/*! @brief The function pointer type for monitor configuration callbacks.
+ *
+ *  This is the function pointer type for monitor configuration callbacks.
+ *  A monitor callback function has the following signature:
+ *  @code
+ *  void function_name(GLFWmonitor* monitor, int event)
+ *  @endcode
+ *
+ *  @param[in] monitor The monitor that was connected or disconnected.
+ *  @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.  Future
+ *  releases may add more events.
+ *
+ *  @sa @ref monitor_event
+ *  @sa @ref glfwSetMonitorCallback
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup monitor
+ */
+typedef void (* GLFWmonitorfun)(GLFWmonitor*,int);
+
+/*! @brief The function pointer type for joystick configuration callbacks.
+ *
+ *  This is the function pointer type for joystick configuration callbacks.
+ *  A joystick configuration callback function has the following signature:
+ *  @code
+ *  void function_name(int jid, int event)
+ *  @endcode
+ *
+ *  @param[in] jid The joystick that was connected or disconnected.
+ *  @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.  Future
+ *  releases may add more events.
+ *
+ *  @sa @ref joystick_event
+ *  @sa @ref 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 @ref glfwGetVideoMode
+ *  @sa @ref 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 @ref glfwGetGammaRamp
+ *  @sa @ref 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.
+ *
+ *  This describes a single 2D image.  See the documentation for each related
+ *  function what the expected pixel format is.
+ *
+ *  @sa @ref cursor_custom
+ *  @sa @ref window_icon
+ *
+ *  @since Added in version 2.1.
+ *  @glfw3 Removed format and bytes-per-pixel members.
+ *
+ *  @ingroup window
+ */
+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;
+
+/*! @brief Gamepad input state
+ *
+ *  This describes the input state of a gamepad.
+ *
+ *  @sa @ref gamepad
+ *  @sa @ref glfwGetGamepadState
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+typedef struct GLFWgamepadstate
+{
+    /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS`
+     *  or `GLFW_RELEASE`.
+     */
+    unsigned char buttons[15];
+    /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0
+     *  to 1.0 inclusive.
+     */
+    float axes[6];
+} GLFWgamepadstate;
+
+
+/*************************************************************************
+ * 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 @macos 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 the @ref
+ *  GLFW_COCOA_CHDIR_RESOURCES init hint.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref intro_init
+ *  @sa @ref 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 @ref glfwInit
+ *
+ *  @since Added in version 1.0.
+ *
+ *  @ingroup init
+ */
+GLFWAPI void glfwTerminate(void);
+
+/*! @brief Sets the specified init hint to the desired value.
+ *
+ *  This function sets hints for the next initialization of GLFW.
+ *
+ *  The values you set hints to are never reset by GLFW, but they only take
+ *  effect during initialization.  Once GLFW has been initialized, any values
+ *  you set will be ignored until the library is terminated and initialized
+ *  again.
+ *
+ *  Some hints are platform specific.  These may be set on any platform but they
+ *  will only affect their specific platform.  Other platforms will ignore them.
+ *  Setting these hints requires no platform specific headers or functions.
+ *
+ *  @param[in] hint The [init hint](@ref init_hints) to set.
+ *  @param[in] value The new value of the init hint.
+ *
+ *  @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref
+ *  GLFW_INVALID_VALUE.
+ *
+ *  @remarks This function may be called before @ref glfwInit.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa init_hints
+ *  @sa glfwInit
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup init
+ */
+GLFWAPI void glfwInitHint(int hint, int value);
+
+/*! @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 @ref 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 @ref glfwGetVersion
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup init
+ */
+GLFWAPI const char* glfwGetVersionString(void);
+
+/*! @brief Returns and clears the last error for the calling thread.
+ *
+ *  This function returns and clears the [error code](@ref errors) of the last
+ *  error that occurred on the calling thread, and optionally a UTF-8 encoded
+ *  human-readable description of it.  If no error has occurred since the last
+ *  call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is
+ *  set to `NULL`.
+ *
+ *  @param[in] description Where to store the error description pointer, or `NULL`.
+ *  @return The last error code for the calling thread, or @ref GLFW_NO_ERROR
+ *  (zero).
+ *
+ *  @errors None.
+ *
+ *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You
+ *  should not free it yourself.  It is guaranteed to be valid only until the
+ *  next error occurs or the library is terminated.
+ *
+ *  @remark This function may be called before @ref glfwInit.
+ *
+ *  @thread_safety This function may be called from any thread.
+ *
+ *  @sa @ref error_handling
+ *  @sa @ref glfwSetErrorCallback
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup init
+ */
+GLFWAPI int glfwGetError(const char** description);
+
+/*! @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 code is set before the callback is called.  Calling @ref
+ *  glfwGetError from the error callback will return the same value as the error
+ *  code argument.
+ *
+ *  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] callback The new callback, or `NULL` to remove the currently set
+ *  callback.
+ *  @return The previously set callback, or `NULL` if no callback was set.
+ *
+ *  @callback_signature
+ *  @code
+ *  void callback_name(int error_code, const char* description)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [callback pointer type](@ref GLFWerrorfun).
+ *
+ *  @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
+ *  @sa @ref glfwGetError
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup init
+ */
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback);
+
+/*! @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 @ref 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 @ref 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 Retrieves the work area of the monitor.
+ *
+ *  This function returns the position, in screen coordinates, of the upper-left
+ *  corner of the work area of the specified monitor along with the work area
+ *  size in screen coordinates. The work area is defined as the area of the
+ *  monitor not occluded by the operating system task bar where present. If no
+ *  task bar exists then the work area is the monitor resolution in screen
+ *  coordinates.
+ *
+ *  Any or all of the position and size arguments may be `NULL`.  If an error
+ *  occurs, all non-`NULL` position and size 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`.
+ *  @param[out] width Where to store the monitor width, or `NULL`.
+ *  @param[out] height Where to store the monitor height, 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_workarea
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height);
+
+/*! @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 Retrieves the content scale for the specified monitor.
+ *
+ *  This function retrieves the content scale for the specified monitor.  The
+ *  content scale is the ratio between the current DPI and the platform's
+ *  default DPI.  This is especially important for text and any UI elements.  If
+ *  the pixel dimensions of your UI scaled by this look appropriate on your
+ *  machine then it should appear at a reasonable size on other machines
+ *  regardless of their DPI and scaling settings.  This relies on the system DPI
+ *  and scaling settings being somewhat correct.
+ *
+ *  The content scale may depend on both the monitor resolution and pixel
+ *  density and on user settings.  It may be very different from the raw DPI
+ *  calculated from the physical size and current resolution.
+ *
+ *  @param[in] monitor The monitor to query.
+ *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ *  @param[out] yscale Where to store the y-axis content scale, 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_scale
+ *  @sa @ref glfwGetWindowContentScale
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup monitor
+ */
+GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale);
+
+/*! @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 user pointer of the specified monitor.
+ *
+ *  This function sets the user-defined pointer of the specified monitor.  The
+ *  current value is retained until the monitor is disconnected.  The initial
+ *  value is `NULL`.
+ *
+ *  This function may be called from the monitor callback, even for a monitor
+ *  that is being disconnected.
+ *
+ *  @param[in] monitor The monitor 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 monitor_userptr
+ *  @sa @ref glfwGetMonitorUserPointer
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup monitor
+ */
+GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer);
+
+/*! @brief Returns the user pointer of the specified monitor.
+ *
+ *  This function returns the current value of the user-defined pointer of the
+ *  specified monitor.  The initial value is `NULL`.
+ *
+ *  This function may be called from the monitor callback, even for a monitor
+ *  that is being disconnected.
+ *
+ *  @param[in] monitor The monitor 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 monitor_userptr
+ *  @sa @ref glfwSetMonitorUserPointer
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup monitor
+ */
+GLFWAPI void* glfwGetMonitorUserPointer(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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWmonitor* monitor, int event)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWmonitorfun).
+ *
+ *  @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 callback);
+
+/*! @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 @ref 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 @ref 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 an appropriately sized gamma ramp from the specified
+ *  exponent and then calls @ref glfwSetGammaRamp with it.  The value must be
+ *  a finite number greater than zero.
+ *
+ *  The software controlled gamma ramp is applied _in addition_ to the hardware
+ *  gamma correction, which today is usually an approximation of sRGB gamma.
+ *  This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ *  the default (usually sRGB-like) behavior.
+ *
+ *  For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ *  GLFW_SRGB_CAPABLE hint.
+ *
+ *  @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.
+ *
+ *  @remark @wayland Gamma handling is a privileged protocol, this function
+ *  will thus never be implemented and emits @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.
+ *
+ *  @remark @wayland Gamma handling is a privileged protocol, this function
+ *  will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
+ *  returning `NULL`.
+ *
+ *  @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.
+ *
+ *  The software controlled gamma ramp is applied _in addition_ to the hardware
+ *  gamma correction, which today is usually an approximation of sRGB gamma.
+ *  This means that setting a perfectly linear ramp, or gamma 1.0, will produce
+ *  the default (usually sRGB-like) behavior.
+ *
+ *  For gamma correct rendering with OpenGL or OpenGL ES, see the @ref
+ *  GLFW_SRGB_CAPABLE hint.
+ *
+ *  @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 The size of the specified gamma ramp should match the size of the
+ *  current ramp for that monitor.
+ *
+ *  @remark @win32 The gamma ramp size must be 256.
+ *
+ *  @remark @wayland Gamma handling is a privileged protocol, this function
+ *  will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
+ *
+ *  @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 @ref glfwWindowHint
+ *  @sa @ref glfwWindowHintString
+ *
+ *  @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 this
+ *  function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ *  Only integer value hints can be set with this function.  String value hints
+ *  are set with @ref glfwWindowHintString.
+ *
+ *  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.
+ *
+ *  Some hints are platform specific.  These may be set on any platform but they
+ *  will only affect their specific platform.  Other platforms will ignore them.
+ *  Setting these hints requires no platform specific headers or functions.
+ *
+ *  @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 @ref glfwWindowHintString
+ *  @sa @ref glfwDefaultWindowHints
+ *
+ *  @since Added in version 3.0.  Replaces `glfwOpenWindowHint`.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwWindowHint(int hint, int value);
+
+/*! @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 this
+ *  function or @ref glfwDefaultWindowHints, or until the library is terminated.
+ *
+ *  Only string type hints can be set with this function.  Integer value hints
+ *  are set with @ref glfwWindowHint.
+ *
+ *  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.
+ *
+ *  Some hints are platform specific.  These may be set on any platform but they
+ *  will only affect their specific platform.  Other platforms will ignore them.
+ *  Setting these hints requires no platform specific headers or functions.
+ *
+ *  @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.
+ *
+ *  @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 window_hints
+ *  @sa @ref glfwWindowHint
+ *  @sa @ref glfwDefaultWindowHints
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwWindowHintString(int hint, const char* 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.  This will not affect its
+ *  OpenGL or OpenGL ES context.
+ *
+ *  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 GLFW_VISIBLE_hint) 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_APPLICATION` 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 @macos The OS only supports forward-compatible core profile contexts
+ *  for OpenGL versions 3.2 and later.  Before creating an OpenGL context of
+ *  version 3.2 or later you must set the
+ *  [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and
+ *  [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly.
+ *  OpenGL 3.0 and 3.1 contexts are not supported at all on macOS.
+ *
+ *  @remark @macos 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 @macos The first time a window is created the menu bar is created.
+ *  If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu
+ *  bar.  Otherwise a minimal menu bar is created manually with common commands
+ *  like Hide, Quit and About.  The About entry opens a minimal about dialog
+ *  with information from the application's bundle.  Menu bar creation can be
+ *  disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint.
+ *
+ *  @remark @macos On OS X 10.10 and later the window frame will not be rendered
+ *  at full resolution on Retina displays unless the
+ *  [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint)
+ *  hint is `GLFW_TRUE` and 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 @macos When activating frame autosaving with
+ *  [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
+ *  window size and position may be overridden by previously saved values.
+ *
+ *  @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.
+ *
+ *  @remark @x11 The class part of the `WM_CLASS` window property will by
+ *  default be set to the window title passed to this function.  The instance
+ *  part will use the contents of the `RESOURCE_NAME` environment variable, if
+ *  present and not empty, or fall back to the window title.  Set the
+ *  [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and
+ *  [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to
+ *  override this.
+ *
+ *  @remark @wayland Compositors should implement the xdg-decoration protocol
+ *  for GLFW to decorate the window properly.  If this protocol isn't
+ *  supported, or if the compositor prefers client-side decorations, a very
+ *  simple fallback frame will be drawn using the wp_viewporter protocol.  A
+ *  compositor can still emit close, maximize or fullscreen events, using for
+ *  instance a keybind mechanism.  If neither of these protocols is supported,
+ *  the window won't be decorated.
+ *
+ *  @remark @wayland A full screen window will not attempt to change the mode,
+ *  no matter what the requested size or refresh rate.
+ *
+ *  @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
+ *  to be implemented in the user's compositor.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_creation
+ *  @sa @ref 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 @ref 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 @macos 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 pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+ *  bits per channel with the red channel first.  They are arranged canonically
+ *  as packed sequential rows, starting from the top-left corner.
+ *
+ *  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 @macos 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.
+ *
+ *  @remark @wayland There is no existing protocol to change an icon, the
+ *  window will thus inherit the one defined in the application's desktop file.
+ *  This function always emits @ref GLFW_PLATFORM_ERROR.
+ *
+ *  @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 content area of the specified window.
+ *
+ *  This function retrieves the position, in screen coordinates, of the
+ *  upper-left corner of the content 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 content area, or `NULL`.
+ *  @param[out] ypos Where to store the y-coordinate of the upper-left corner of
+ *  the content area, or `NULL`.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @wayland There is no way for an application to retrieve the global
+ *  position of its windows, this function will always emit @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_pos
+ *  @sa @ref glfwSetWindowPos
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
+
+/*! @brief Sets the position of the content area of the specified window.
+ *
+ *  This function sets the position, in screen coordinates, of the upper-left
+ *  corner of the content 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 content area.
+ *  @param[in] ypos The y-coordinate of the upper-left corner of the content area.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @wayland There is no way for an application to set the global
+ *  position of its windows, this function will always emit @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_pos
+ *  @sa @ref 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 content area of the specified window.
+ *
+ *  This function retrieves the size, in screen coordinates, of the content 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
+ *  content area, or `NULL`.
+ *  @param[out] height Where to store the height, in screen coordinates, of the
+ *  content 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 @ref 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 content 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 content
+ *  area, or `GLFW_DONT_CARE`.
+ *  @param[in] minheight The minimum height, in screen coordinates, of the
+ *  content area, or `GLFW_DONT_CARE`.
+ *  @param[in] maxwidth The maximum width, in screen coordinates, of the content
+ *  area, or `GLFW_DONT_CARE`.
+ *  @param[in] maxheight The maximum height, in screen coordinates, of the
+ *  content 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.
+ *
+ *  @remark @wayland The size limits will not be applied until the window is
+ *  actually resized, either by the user or by the compositor.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_sizelimits
+ *  @sa @ref 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 content 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.
+ *
+ *  @remark @wayland The aspect ratio will not be applied until the window is
+ *  actually resized, either by the user or by the compositor.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_sizelimits
+ *  @sa @ref glfwSetWindowSizeLimits
+ *
+ *  @since Added in version 3.2.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom);
+
+/*! @brief Sets the size of the content area of the specified window.
+ *
+ *  This function sets the size, in screen coordinates, of the content 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
+ *  content area.
+ *  @param[in] height The desired height, in screen coordinates, of the window
+ *  content area.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @wayland A full screen window will not attempt to change the mode,
+ *  no matter what the requested size.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_size
+ *  @sa @ref glfwGetWindowSize
+ *  @sa @ref 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 @ref 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 Retrieves the content scale for the specified window.
+ *
+ *  This function retrieves the content scale for the specified window.  The
+ *  content scale is the ratio between the current DPI and the platform's
+ *  default DPI.  This is especially important for text and any UI elements.  If
+ *  the pixel dimensions of your UI scaled by this look appropriate on your
+ *  machine then it should appear at a reasonable size on other machines
+ *  regardless of their DPI and scaling settings.  This relies on the system DPI
+ *  and scaling settings being somewhat correct.
+ *
+ *  On systems where each monitors can have its own content scale, the window
+ *  content scale will depend on which monitor the system considers the window
+ *  to be on.
+ *
+ *  @param[in] window The window to query.
+ *  @param[out] xscale Where to store the x-axis content scale, or `NULL`.
+ *  @param[out] yscale Where to store the y-axis content scale, 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_scale
+ *  @sa @ref glfwSetWindowContentScaleCallback
+ *  @sa @ref glfwGetMonitorContentScale
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale);
+
+/*! @brief Returns the opacity of the whole window.
+ *
+ *  This function returns the opacity of the window, including any decorations.
+ *
+ *  The opacity (or alpha) value is a positive finite number between zero and
+ *  one, where zero is fully transparent and one is fully opaque.  If the system
+ *  does not support whole window transparency, this function always returns one.
+ *
+ *  The initial opacity value for newly created windows is one.
+ *
+ *  @param[in] window The window to query.
+ *  @return The opacity value of the specified window.
+ *
+ *  @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_transparency
+ *  @sa @ref glfwSetWindowOpacity
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window);
+
+/*! @brief Sets the opacity of the whole window.
+ *
+ *  This function sets the opacity of the window, including any decorations.
+ *
+ *  The opacity (or alpha) value is a positive finite number between zero and
+ *  one, where zero is fully transparent and one is fully opaque.
+ *
+ *  The initial opacity value for newly created windows is one.
+ *
+ *  A window created with framebuffer transparency may not use whole window
+ *  transparency.  The results of doing this are undefined.
+ *
+ *  @param[in] window The window to set the opacity for.
+ *  @param[in] opacity The desired opacity of the specified window.
+ *
+ *  @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_transparency
+ *  @sa @ref glfwGetWindowOpacity
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
+
+/*! @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.
+ *
+ *  @remark @wayland There is no concept of iconification in wl_shell, this
+ *  function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated
+ *  protocol.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_iconify
+ *  @sa @ref glfwRestoreWindow
+ *  @sa @ref 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 @ref glfwIconifyWindow
+ *  @sa @ref 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 @ref glfwIconifyWindow
+ *  @sa @ref 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.
+ *
+ *  By default, windowed mode windows are focused when shown
+ *  Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint
+ *  to change this behavior for all newly created windows, or change the
+ *  behavior for an existing window with @ref glfwSetWindowAttrib.
+ *
+ *  @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 @ref 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 @ref 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 GLFW_FOCUSED_hint) to
+ *  disable this behavior.
+ *
+ *  Also by default, windowed mode windows are focused when shown
+ *  with @ref glfwShowWindow. Set the
+ *  [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) 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.
+ *
+ *  For a less disruptive way of getting the user's attention, see
+ *  [attention requests](@ref window_attention).
+ *
+ *  @param[in] window The window to give input focus.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @wayland It is not possible for an application to bring its windows
+ *  to front, this function will always emit @ref GLFW_PLATFORM_ERROR.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_focus
+ *  @sa @ref window_attention
+ *
+ *  @since Added in version 3.2.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwFocusWindow(GLFWwindow* window);
+
+/*! @brief Requests user attention to the specified window.
+ *
+ *  This function requests user attention to the specified window.  On
+ *  platforms where this is not supported, attention is requested to the
+ *  application as a whole.
+ *
+ *  Once the user has given attention, usually by focusing the window or
+ *  application, the system will end the request automatically.
+ *
+ *  @param[in] window The window to request attention to.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @macos Attention is requested to the application as a whole, not the
+ *  specific window.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_attention
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwRequestWindowAttention(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 @ref 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 content 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
+ *  content area.
+ *  @param[in] ypos The desired y-coordinate of the upper-left corner of the
+ *  content area.
+ *  @param[in] width The desired with, in screen coordinates, of the content
+ *  area or video mode.
+ *  @param[in] height The desired height, in screen coordinates, of the content
+ *  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.
+ *
+ *  @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise
+ *  affected by any resizing or mode switching, although you may need to update
+ *  your viewport if the framebuffer size has changed.
+ *
+ *  @remark @wayland The desired window position is ignored, as there is no way
+ *  for an application to set this property.
+ *
+ *  @remark @wayland Setting the window to full screen will not attempt to
+ *  change the mode, no matter what the requested size or refresh rate.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_monitor
+ *  @sa @ref window_full_screen
+ *  @sa @ref glfwGetWindowMonitor
+ *  @sa @ref 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
+ *  @sa @ref glfwSetWindowAttrib
+ *
+ *  @since Added in version 3.0.  Replaces `glfwGetWindowParam` and
+ *  `glfwGetGLVersion`.
+ *
+ *  @ingroup window
+ */
+GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib);
+
+/*! @brief Sets an attribute of the specified window.
+ *
+ *  This function sets the value of an attribute of the specified window.
+ *
+ *  The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib),
+ *  [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib),
+ *  [GLFW_FLOATING](@ref GLFW_FLOATING_attrib),
+ *  [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and
+ *  [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib).
+ *
+ *  Some of these attributes are ignored for full screen windows.  The new
+ *  value will take effect if the window is later made windowed.
+ *
+ *  Some of these attributes are ignored for windowed mode windows.  The new
+ *  value will take effect if the window is later made full screen.
+ *
+ *  @param[in] window The window to set the attribute for.
+ *  @param[in] attrib A supported window attribute.
+ *  @param[in] value `GLFW_TRUE` or `GLFW_FALSE`.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
+ *
+ *  @remark Calling @ref glfwGetWindowAttrib will always return the latest
+ *  value, even if that value is ignored by the current mode of the window.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_attribs
+ *  @sa @ref glfwGetWindowAttrib
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value);
+
+/*! @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 @ref 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 @ref 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
+ *  position, in screen coordinates, of the upper-left corner of the content
+ *  area of the window.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int xpos, int ypos)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowposfun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @remark @wayland This callback will never be called, as there is no way for
+ *  an application to know its global position.
+ *
+ *  @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 callback);
+
+/*! @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 content area of the window.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int width, int height)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowsizefun).
+ *
+ *  @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 callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowclosefun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @remark @macos 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 callback);
+
+/*! @brief Sets the refresh callback for the specified window.
+ *
+ *  This function sets the refresh callback of the specified window, which is
+ *  called when the content 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, Aqua or Wayland, 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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window);
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowrefreshfun).
+ *
+ *  @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 callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int focused)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowfocusfun).
+ *
+ *  @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 callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int iconified)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowiconifyfun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @remark @wayland The wl_shell protocol has no concept of iconification,
+ *  this callback will never be called when using this deprecated protocol.
+ *
+ *  @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 callback);
+
+/*! @brief Sets the maximize callback for the specified window.
+ *
+ *  This function sets the maximization callback of the specified window, which
+ *  is called when the window is maximized or restored.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int maximized)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowmaximizefun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_maximize
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int width, int height)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWframebuffersizefun).
+ *
+ *  @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 callback);
+
+/*! @brief Sets the window content scale callback for the specified window.
+ *
+ *  This function sets the window content scale callback of the specified window,
+ *  which is called when the content scale of the specified window changes.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, float xscale, float yscale)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWwindowcontentscalefun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref window_scale
+ *  @sa @ref glfwGetWindowContentScale
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup window
+ */
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback);
+
+/*! @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.
+ *
+ *  Do not assume that callbacks you set will _only_ be called in response to
+ *  event processing functions like this one.  While it is necessary to poll for
+ *  events, window systems that require GLFW to register callbacks of its own
+ *  can pass events to GLFW in response to many window system function calls.
+ *  GLFW will pass those events on to the application callbacks before
+ *  returning.
+ *
+ *  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 @ref glfwWaitEvents
+ *  @sa @ref 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.
+ *
+ *  Do not assume that callbacks you set will _only_ be called in response to
+ *  event processing functions like this one.  While it is necessary to poll for
+ *  events, window systems that require GLFW to register callbacks of its own
+ *  can pass events to GLFW in response to many window system function calls.
+ *  GLFW will pass those events on to the application callbacks before
+ *  returning.
+ *
+ *  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 @ref glfwPollEvents
+ *  @sa @ref 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.
+ *
+ *  Do not assume that callbacks you set will _only_ be called in response to
+ *  event processing functions like this one.  While it is necessary to poll for
+ *  events, window systems that require GLFW to register callbacks of its own
+ *  can pass events to GLFW in response to many window system function calls.
+ *  GLFW will pass those events on to the application callbacks before
+ *  returning.
+ *
+ *  Event processing is not required for joystick input to work.
+ *
+ *  @param[in] timeout The maximum amount of time, in seconds, to wait.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_VALUE 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 @ref glfwPollEvents
+ *  @sa @ref 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.
+ *
+ *  @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 @ref glfwWaitEvents
+ *  @sa @ref 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 @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ *  @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
+ *  @ref GLFW_RAW_MOUSE_MOTION.
+ *
+ *  @param[in] window The window to query.
+ *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ *  `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
+ *  `GLFW_RAW_MOUSE_MOTION`.
+ *
+ *  @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 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 @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS,
+ *  @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or
+ *  @ref GLFW_RAW_MOUSE_MOTION.
+ *
+ *  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
+ *    content 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.
+ *
+ *  If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to
+ *  enable lock key modifier bits, or `GLFW_FALSE` to disable them.  If enabled,
+ *  callbacks that receive modifier bits will also have the @ref
+ *  GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on,
+ *  and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on.
+ *
+ *  If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE`
+ *  to enable raw (unscaled and unaccelerated) mouse motion when the cursor is
+ *  disabled, or `GLFW_FALSE` to disable it.  If raw motion is not supported,
+ *  attempting to set this will emit @ref GLFW_PLATFORM_ERROR.  Call @ref
+ *  glfwRawMouseMotionSupported to check for support.
+ *
+ *  @param[in] window The window whose input mode to set.
+ *  @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`,
+ *  `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or
+ *  `GLFW_RAW_MOUSE_MOTION`.
+ *  @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 @ref glfwGetInputMode
+ *
+ *  @since Added in version 3.0.  Replaces `glfwEnable` and `glfwDisable`.
+ *
+ *  @ingroup input
+ */
+GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
+
+/*! @brief Returns whether raw mouse motion is supported.
+ *
+ *  This function returns whether raw mouse motion is supported on the current
+ *  system.  This status does not change after GLFW has been initialized so you
+ *  only need to check this once.  If you attempt to enable raw motion on
+ *  a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted.
+ *
+ *  Raw mouse motion is closer to the actual motion of the mouse across
+ *  a surface.  It is not affected by the scaling and acceleration applied to
+ *  the motion of the desktop cursor.  That processing is suitable for a cursor
+ *  while raw motion is better for controlling for example a 3D camera.  Because
+ *  of this, raw mouse motion is only provided when the cursor is disabled.
+ *
+ *  @return `GLFW_TRUE` if raw mouse motion is supported on the current machine,
+ *  or `GLFW_FALSE` otherwise.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref raw_mouse_motion
+ *  @sa @ref glfwSetInputMode
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI int glfwRawMouseMotionSupported(void);
+
+/*! @brief Returns the layout-specific name of the specified printable key.
+ *
+ *  This function returns the name of the specified printable key, encoded as
+ *  UTF-8.  This is typically the character that key would produce without any
+ *  modifier keys, intended for displaying key bindings to the user.  For dead
+ *  keys, it is typically the diacritic it would add to a character.
+ *
+ *  __Do not use this function__ for [text input](@ref input_char).  You will
+ *  break text input for many languages even if it happens to work for yours.
+ *
+ *  If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key,
+ *  otherwise the scancode is ignored.  If you specify a non-printable key, or
+ *  `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this
+ *  function returns `NULL` but does not emit an error.
+ *
+ *  This behavior allows you to always pass in the arguments in 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`
+ *
+ *  Names for printable keys depend on keyboard layout, while names for
+ *  non-printable keys are the same across layouts but depend on the application
+ *  language and should be localized along with other user interface text.
+ *
+ *  @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`.
+ *  @param[in] scancode The scancode of the key to query.
+ *  @return The UTF-8 encoded, layout-specific name of the key, or `NULL`.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark The contents of the returned string may change when a keyboard
+ *  layout change event is received.
+ *
+ *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You
+ *  should not free it yourself.  It is valid 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 platform-specific scancode of the specified key.
+ *
+ *  This function returns the platform-specific scancode of the specified key.
+ *
+ *  If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this
+ *  method will return `-1`.
+ *
+ *  @param[in] key Any [named key](@ref keys).
+ *  @return The platform-specific scancode for the key, or `-1` if an
+ *  [error](@ref error_handling) occurred.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
+ *  GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR.
+ *
+ *  @thread_safety This function may be called from any thread.
+ *
+ *  @sa @ref input_key
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI int glfwGetKeyScancode(int key);
+
+/*! @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 @ref 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 @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function
+ *  returns `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 content area of
+ *  the window.
+ *
+ *  This function returns the position of the cursor, in screen coordinates,
+ *  relative to the upper-left corner of the content 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 content area, or `NULL`.
+ *  @param[out] ypos Where to store the cursor y-coordinate, relative to the to
+ *  top edge of the content 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 @ref 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 content area of the
+ *  window.
+ *
+ *  This function sets the position, in screen coordinates, of the cursor
+ *  relative to the upper-left corner of the content 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
+ *  content area.
+ *  @param[in] ypos The desired y-coordinate, relative to the top edge of the
+ *  content area.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_PLATFORM_ERROR.
+ *
+ *  @remark @wayland This function will only work when the cursor mode is
+ *  `GLFW_CURSOR_DISABLED`, otherwise it will do nothing.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref cursor_pos
+ *  @sa @ref 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 with the red channel first.  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.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref cursor_object
+ *  @sa @ref glfwDestroyCursor
+ *  @sa @ref 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.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref cursor_object
+ *  @sa @ref 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.
+ *
+ *  If the specified cursor is current for any window, that window will be
+ *  reverted to the default cursor.  This does not affect the cursor mode.
+ *
+ *  @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 @ref 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
+ *  content 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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int key, int scancode, int action, int mods)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWkeyfun).
+ *
+ *  @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 callback);
+
+/*! @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 macOS or Alt key
+ *  on Windows.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, unsigned int codepoint)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWcharfun).
+ *
+ *  @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 callback);
+
+/*! @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] callback 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.
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, unsigned int codepoint, int mods)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWcharmodsfun).
+ *
+ *  @deprecated Scheduled for removal in version 4.0.
+ *
+ *  @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 callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int button, int action, int mods)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWmousebuttonfun).
+ *
+ *  @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 callback);
+
+/*! @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
+ *  content area of the window.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, double xpos, double ypos);
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWcursorposfun).
+ *
+ *  @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 callback);
+
+/*! @brief Sets the cursor enter/leave callback.
+ *
+ *  This function sets the cursor boundary crossing callback of the specified
+ *  window, which is called when the cursor enters or leaves the content area of
+ *  the window.
+ *
+ *  @param[in] window The window whose callback to set.
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int entered)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWcursorenterfun).
+ *
+ *  @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 callback);
+
+/*! @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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, double xoffset, double yoffset)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWscrollfun).
+ *
+ *  @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 callback);
+
+/*! @brief Sets the path drop callback.
+ *
+ *  This function sets the path drop callback of the specified window, which is
+ *  called when one or more dragged paths 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] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(GLFWwindow* window, int path_count, const char* paths[])
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWdropfun).
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
+ *
+ *  @remark @wayland File drop is currently unimplemented.
+ *
+ *  @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 callback);
+
+/*! @brief Returns whether the specified joystick is present.
+ *
+ *  This function returns whether the specified joystick is present.
+ *
+ *  There is no need to call this function before other functions that accept
+ *  a joystick ID, as they all check for presence before performing any other
+ *  work.
+ *
+ *  @param[in] jid 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 jid);
+
+/*! @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.
+ *
+ *  If the specified joystick is not present this function will return `NULL`
+ *  but will not generate an error.  This can be used instead of first calling
+ *  @ref glfwJoystickPresent.
+ *
+ *  @param[in] jid 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 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 jid, 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`.
+ *
+ *  For backward compatibility with earlier versions that did not have @ref
+ *  glfwGetJoystickHats, the button array also includes all hats, each
+ *  represented as four buttons.  The hats are in the same order as returned by
+ *  __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and
+ *  _left_.  To disable these extra buttons, set the @ref
+ *  GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization.
+ *
+ *  If the specified joystick is not present this function will return `NULL`
+ *  but will not generate an error.  This can be used instead of first calling
+ *  @ref glfwJoystickPresent.
+ *
+ *  @param[in] jid 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 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 jid, int* count);
+
+/*! @brief Returns the state of all hats of the specified joystick.
+ *
+ *  This function returns the state of all hats of the specified joystick.
+ *  Each element in the array is one of the following values:
+ *
+ *  Name                  | Value
+ *  ----                  | -----
+ *  `GLFW_HAT_CENTERED`   | 0
+ *  `GLFW_HAT_UP`         | 1
+ *  `GLFW_HAT_RIGHT`      | 2
+ *  `GLFW_HAT_DOWN`       | 4
+ *  `GLFW_HAT_LEFT`       | 8
+ *  `GLFW_HAT_RIGHT_UP`   | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP`
+ *  `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN`
+ *  `GLFW_HAT_LEFT_UP`    | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP`
+ *  `GLFW_HAT_LEFT_DOWN`  | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN`
+ *
+ *  The diagonal directions are bitwise combinations of the primary (up, right,
+ *  down and left) directions and you can test for these individually by ANDing
+ *  it with the corresponding direction.
+ *
+ *  @code
+ *  if (hats[2] & GLFW_HAT_RIGHT)
+ *  {
+ *      // State of hat 2 could be right-up, right or right-down
+ *  }
+ *  @endcode
+ *
+ *  If the specified joystick is not present this function will return `NULL`
+ *  but will not generate an error.  This can be used instead of first calling
+ *  @ref glfwJoystickPresent.
+ *
+ *  @param[in] jid The [joystick](@ref joysticks) to query.
+ *  @param[out] count Where to store the number of hat states in the returned
+ *  array.  This is set to zero if the joystick is not present or an error
+ *  occurred.
+ *  @return An array of hat 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_hat
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, 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.
+ *
+ *  If the specified joystick is not present this function will return `NULL`
+ *  but will not generate an error.  This can be used instead of first calling
+ *  @ref glfwJoystickPresent.
+ *
+ *  @param[in] jid 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 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 jid);
+
+/*! @brief Returns the SDL compatible GUID of the specified joystick.
+ *
+ *  This function returns the SDL compatible GUID, as a UTF-8 encoded
+ *  hexadecimal string, of the specified joystick.  The returned string is
+ *  allocated and freed by GLFW.  You should not free it yourself.
+ *
+ *  The GUID is what connects a joystick to a gamepad mapping.  A connected
+ *  joystick will always have a GUID even if there is no gamepad mapping
+ *  assigned to it.
+ *
+ *  If the specified joystick is not present this function will return `NULL`
+ *  but will not generate an error.  This can be used instead of first calling
+ *  @ref glfwJoystickPresent.
+ *
+ *  The GUID uses the format introduced in SDL 2.0.5.  This GUID tries to
+ *  uniquely identify the make and model of a joystick but does not identify
+ *  a specific unit, e.g. all wired Xbox 360 controllers will have the same
+ *  GUID on that platform.  The GUID for a unit may vary between platforms
+ *  depending on what hardware information the platform specific APIs provide.
+ *
+ *  @param[in] jid The [joystick](@ref joysticks) to query.
+ *  @return The UTF-8 encoded GUID 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 or the library is terminated.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref gamepad
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI const char* glfwGetJoystickGUID(int jid);
+
+/*! @brief Sets the user pointer of the specified joystick.
+ *
+ *  This function sets the user-defined pointer of the specified joystick.  The
+ *  current value is retained until the joystick is disconnected.  The initial
+ *  value is `NULL`.
+ *
+ *  This function may be called from the joystick callback, even for a joystick
+ *  that is being disconnected.
+ *
+ *  @param[in] jid The joystick 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 joystick_userptr
+ *  @sa @ref glfwGetJoystickUserPointer
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer);
+
+/*! @brief Returns the user pointer of the specified joystick.
+ *
+ *  This function returns the current value of the user-defined pointer of the
+ *  specified joystick.  The initial value is `NULL`.
+ *
+ *  This function may be called from the joystick callback, even for a joystick
+ *  that is being disconnected.
+ *
+ *  @param[in] jid The joystick 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 joystick_userptr
+ *  @sa @ref glfwSetJoystickUserPointer
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI void* glfwGetJoystickUserPointer(int jid);
+
+/*! @brief Returns whether the specified joystick has a gamepad mapping.
+ *
+ *  This function returns whether the specified joystick is both present and has
+ *  a gamepad mapping.
+ *
+ *  If the specified joystick is present but does not have a gamepad mapping
+ *  this function will return `GLFW_FALSE` but will not generate an error.  Call
+ *  @ref glfwJoystickPresent to check if a joystick is present regardless of
+ *  whether it has a mapping.
+ *
+ *  @param[in] jid The [joystick](@ref joysticks) to query.
+ *  @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping,
+ *  or `GLFW_FALSE` otherwise.
+ *
+ *  @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 gamepad
+ *  @sa @ref glfwGetGamepadState
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI int glfwJoystickIsGamepad(int jid);
+
+/*! @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.
+ *
+ *  For joystick connection and disconnection events to be delivered on all
+ *  platforms, you need to call one of the [event processing](@ref events)
+ *  functions.  Joystick disconnection may also be detected and the callback
+ *  called by joystick functions.  The function will then return whatever it
+ *  returns if the joystick is not present.
+ *
+ *  @param[in] callback 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).
+ *
+ *  @callback_signature
+ *  @code
+ *  void function_name(int jid, int event)
+ *  @endcode
+ *  For more information about the callback parameters, see the
+ *  [function pointer type](@ref GLFWjoystickfun).
+ *
+ *  @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 callback);
+
+/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings.
+ *
+ *  This function parses the specified ASCII encoded string and updates the
+ *  internal list with any gamepad mappings it finds.  This string may
+ *  contain either a single gamepad mapping or many mappings separated by
+ *  newlines.  The parser supports the full format of the `gamecontrollerdb.txt`
+ *  source file including empty lines and comments.
+ *
+ *  See @ref gamepad_mapping for a description of the format.
+ *
+ *  If there is already a gamepad mapping for a given GUID in the internal list,
+ *  it will be replaced by the one passed to this function.  If the library is
+ *  terminated and re-initialized the internal list will revert to the built-in
+ *  default.
+ *
+ *  @param[in] string The string containing the gamepad mappings.
+ *  @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an
+ *  [error](@ref error_handling) occurred.
+ *
+ *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
+ *  GLFW_INVALID_VALUE.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref gamepad
+ *  @sa @ref glfwJoystickIsGamepad
+ *  @sa @ref glfwGetGamepadName
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI int glfwUpdateGamepadMappings(const char* string);
+
+/*! @brief Returns the human-readable gamepad name for the specified joystick.
+ *
+ *  This function returns the human-readable name of the gamepad from the
+ *  gamepad mapping assigned to the specified joystick.
+ *
+ *  If the specified joystick is not present or does not have a gamepad mapping
+ *  this function will return `NULL` but will not generate an error.  Call
+ *  @ref glfwJoystickPresent to check whether it is present regardless of
+ *  whether it has a mapping.
+ *
+ *  @param[in] jid The [joystick](@ref joysticks) to query.
+ *  @return The UTF-8 encoded name of the gamepad, or `NULL` if the
+ *  joystick is not present, does not have a mapping or an
+ *  [error](@ref error_handling) occurred.
+ *
+ *  @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, the gamepad mappings are updated or the library is terminated.
+ *
+ *  @thread_safety This function must only be called from the main thread.
+ *
+ *  @sa @ref gamepad
+ *  @sa @ref glfwJoystickIsGamepad
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI const char* glfwGetGamepadName(int jid);
+
+/*! @brief Retrieves the state of the specified joystick remapped as a gamepad.
+ *
+ *  This function retrieves the state of the specified joystick remapped to
+ *  an Xbox-like gamepad.
+ *
+ *  If the specified joystick is not present or does not have a gamepad mapping
+ *  this function will return `GLFW_FALSE` but will not generate an error.  Call
+ *  @ref glfwJoystickPresent to check whether it is present regardless of
+ *  whether it has a mapping.
+ *
+ *  The Guide button may not be available for input as it is often hooked by the
+ *  system or the Steam client.
+ *
+ *  Not all devices have all the buttons or axes provided by @ref
+ *  GLFWgamepadstate.  Unavailable buttons and axes will always report
+ *  `GLFW_RELEASE` and 0.0 respectively.
+ *
+ *  @param[in] jid The [joystick](@ref joysticks) to query.
+ *  @param[out] state The gamepad input state of the joystick.
+ *  @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is
+ *  connected, it has no gamepad mapping or an [error](@ref error_handling)
+ *  occurred.
+ *
+ *  @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 gamepad
+ *  @sa @ref glfwUpdateGamepadMappings
+ *  @sa @ref glfwJoystickIsGamepad
+ *
+ *  @since Added in version 3.3.
+ *
+ *  @ingroup input
+ */
+GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state);
+
+/*! @brief Sets the clipboard to the specified string.
+ *
+ *  This function sets the system clipboard to the specified, UTF-8 encoded
+ *  string.
+ *
+ *  @param[in] window Deprecated.  Any valid window or `NULL`.
+ *  @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 @ref 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 Deprecated.  Any valid window or `NULL`.
+ *  @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 @ref glfwSetClipboardString
+ *
+ *  @since Added in version 3.0.
+ *
+ *  @ingroup input
+ */
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window);
+
+/*! @brief Returns the GLFW time.
+ *
+ *  This function returns the current GLFW time, in seconds.  Unless the time
+ *  has been set using @ref glfwSetTime it measures time elapsed since GLFW was
+ *  initialized.
+ *
+ *  This function and @ref glfwSetTime are helper functions on top of @ref
+ *  glfwGetTimerFrequency and @ref glfwGetTimerValue.
+ *
+ *  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 time, 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 base time 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 time.
+ *
+ *  This function sets the current GLFW time, in seconds.  The value must be
+ *  a positive finite number less than or equal to 18446744073.0, which is
+ *  approximately 584.5 years.
+ *
+ *  This function and @ref glfwGetTime are helper functions on top of @ref
+ *  glfwGetTimerFrequency and @ref glfwGetTimerValue.
+ *
+ *  @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 GLFW time 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 base time 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&nbsp;/&nbsp;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 @ref 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 @ref 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 must only be made current on
+ *  a single thread at a time and each thread can have only a single current
+ *  context at a time.
+ *
+ *  When moving a context between threads, you must make it non-current on the
+ *  old thread before making it current on the new one.
+ *
+ *  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 GLFW_CONTEXT_RELEASE_BEHAVIOR_hint)
+ *  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 @ref 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 @ref 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 @ref 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_.
+ *
+ *  A context that supports either of the `WGL_EXT_swap_control_tear` and
+ *  `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap
+ *  intervals, which allows the driver to swap immediately even if a frame
+ *  arrives a little bit late.  You can check for these extensions with @ref
+ *  glfwExtensionSupported.
+ *
+ *  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 @ref 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 @ref 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 @ref glfwExtensionSupported
+ *
+ *  @since Added in version 1.0.
+ *
+ *  @ingroup context
+ */
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname);
+
+/*! @brief Returns whether the Vulkan loader and an ICD have been found.
+ *
+ *  This function returns whether the Vulkan loader and any minimally functional
+ *  ICD have been found.
+ *
+ *  The availability of a Vulkan loader and even an ICD does not by itself
+ *  guarantee that surface creation or even instance creation is possible.
+ *  For example, on Fermi systems Nvidia will install an ICD that provides no
+ *  actual Vulkan support.  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 minimally 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 contain `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 at least minimally 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.
+ *
+ *  @remark 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.
+ *
+ *  @remark @macos This function currently supports either the
+ *  `VK_MVK_macos_surface` extension from MoltenVK or `VK_EXT_metal_surface`
+ *  extension.
+ *
+ *  @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 @ref 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 at least minimally 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 at least minimally 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.
+ *
+ *  @remark @macos This function currently always returns `GLFW_TRUE`, as the
+ *  `VK_MVK_macos_surface` extension does not provide
+ *  a `vkGetPhysicalDevice*PresentationSupport` type function.
+ *
+ *  @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 or at least one minimally functional ICD were not found,
+ *  this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref
+ *  GLFW_API_UNAVAILABLE error.  Call @ref glfwVulkanSupported to check whether
+ *  Vulkan is at least minimally available.
+ *
+ *  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 cannot be shared with another API so the window must
+ *  have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib)
+ *  set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error
+ *  and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`.
+ *
+ *  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, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE
+ *
+ *  @remark 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.
+ *
+ *  @remark @macos This function currently only supports the
+ *  `VK_MVK_macos_surface` extension from MoltenVK.
+ *
+ *  @remark @macos This function creates and sets a `CAMetalLayer` instance for
+ *  the window content view, which is required for MoltenVK to function.
+ *
+ *  @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 @ref 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*/
+
+
+/*************************************************************************
+ * Global definition cleanup
+ *************************************************************************/
+
+/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */
+
+#ifdef GLFW_WINGDIAPI_DEFINED
+ #undef WINGDIAPI
+ #undef GLFW_WINGDIAPI_DEFINED
+#endif
+
+#ifdef GLFW_CALLBACK_DEFINED
+ #undef CALLBACK
+ #undef GLFW_CALLBACK_DEFINED
+#endif
+
+/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally
+ * defined by some gl.h variants (OpenBSD) so define it after if needed.
+ */
+#ifndef GLAPIENTRY
+ #define GLAPIENTRY APIENTRY
+#endif
+
+/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _glfw3_h_ */
+
diff --git a/glfw/src/cocoa_init.m b/glfw/src/cocoa_init.m
--- a/glfw/src/cocoa_init.m
+++ b/glfw/src/cocoa_init.m
@@ -1,595 +1,621 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-#include <sys/param.h> // For MAXPATHLEN
-
-// Needed for _NSGetProgname
-#include <crt_externs.h>
-
-// Change to our application bundle's resources directory, if present
-//
-static void changeToResourcesDirectory(void)
-{
-    char resourcesPath[MAXPATHLEN];
-
-    CFBundleRef bundle = CFBundleGetMainBundle();
-    if (!bundle)
-        return;
-
-    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
-
-    CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
-    if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
-    {
-        CFRelease(last);
-        CFRelease(resourcesURL);
-        return;
-    }
-
-    CFRelease(last);
-
-    if (!CFURLGetFileSystemRepresentation(resourcesURL,
-                                          true,
-                                          (UInt8*) resourcesPath,
-                                          MAXPATHLEN))
-    {
-        CFRelease(resourcesURL);
-        return;
-    }
-
-    CFRelease(resourcesURL);
-
-    chdir(resourcesPath);
-}
-
-// Set up the menu bar (manually)
-// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
-// could go away at any moment, lots of stuff that really should be
-// localize(d|able), etc.  Add a nib to save us this horror.
-//
-static void createMenuBar(void)
-{
-    size_t i;
-    NSString* appName = nil;
-    NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
-    NSString* nameKeys[] =
-    {
-        @"CFBundleDisplayName",
-        @"CFBundleName",
-        @"CFBundleExecutable",
-    };
-
-    // Try to figure out what the calling application is called
-
-    for (i = 0;  i < sizeof(nameKeys) / sizeof(nameKeys[0]);  i++)
-    {
-        id name = bundleInfo[nameKeys[i]];
-        if (name &&
-            [name isKindOfClass:[NSString class]] &&
-            ![name isEqualToString:@""])
-        {
-            appName = name;
-            break;
-        }
-    }
-
-    if (!appName)
-    {
-        char** progname = _NSGetProgname();
-        if (progname && *progname)
-            appName = @(*progname);
-        else
-            appName = @"GLFW Application";
-    }
-
-    NSMenu* bar = [[NSMenu alloc] init];
-    [NSApp setMainMenu:bar];
-
-    NSMenuItem* appMenuItem =
-        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
-    NSMenu* appMenu = [[NSMenu alloc] init];
-    [appMenuItem setSubmenu:appMenu];
-
-    [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
-                       action:@selector(orderFrontStandardAboutPanel:)
-                keyEquivalent:@""];
-    [appMenu addItem:[NSMenuItem separatorItem]];
-    NSMenu* servicesMenu = [[NSMenu alloc] init];
-    [NSApp setServicesMenu:servicesMenu];
-    [[appMenu addItemWithTitle:@"Services"
-                       action:NULL
-                keyEquivalent:@""] setSubmenu:servicesMenu];
-    [servicesMenu release];
-    [appMenu addItem:[NSMenuItem separatorItem]];
-    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
-                       action:@selector(hide:)
-                keyEquivalent:@"h"];
-    [[appMenu addItemWithTitle:@"Hide Others"
-                       action:@selector(hideOtherApplications:)
-                keyEquivalent:@"h"]
-        setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
-    [appMenu addItemWithTitle:@"Show All"
-                       action:@selector(unhideAllApplications:)
-                keyEquivalent:@""];
-    [appMenu addItem:[NSMenuItem separatorItem]];
-    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
-                       action:@selector(terminate:)
-                keyEquivalent:@"q"];
-
-    NSMenuItem* windowMenuItem =
-        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
-    [bar release];
-    NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-    [NSApp setWindowsMenu:windowMenu];
-    [windowMenuItem setSubmenu:windowMenu];
-
-    [windowMenu addItemWithTitle:@"Minimize"
-                          action:@selector(performMiniaturize:)
-                   keyEquivalent:@"m"];
-    [windowMenu addItemWithTitle:@"Zoom"
-                          action:@selector(performZoom:)
-                   keyEquivalent:@""];
-    [windowMenu addItem:[NSMenuItem separatorItem]];
-    [windowMenu addItemWithTitle:@"Bring All to Front"
-                          action:@selector(arrangeInFront:)
-                   keyEquivalent:@""];
-
-    // 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:NSEventModifierFlagControl | NSEventModifierFlagCommand];
-
-    // Prior to Snow Leopard, we need to use this oddly-named semi-private API
-    // to get the application menu working properly.
-    SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
-    [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
-}
-
-// Create key code translation tables
-//
-static void createKeyTables(void)
-{
-    int scancode;
-
-    memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
-    memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
-
-    _glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
-    _glfw.ns.keycodes[0x12] = GLFW_KEY_1;
-    _glfw.ns.keycodes[0x13] = GLFW_KEY_2;
-    _glfw.ns.keycodes[0x14] = GLFW_KEY_3;
-    _glfw.ns.keycodes[0x15] = GLFW_KEY_4;
-    _glfw.ns.keycodes[0x17] = GLFW_KEY_5;
-    _glfw.ns.keycodes[0x16] = GLFW_KEY_6;
-    _glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
-    _glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
-    _glfw.ns.keycodes[0x19] = GLFW_KEY_9;
-    _glfw.ns.keycodes[0x00] = GLFW_KEY_A;
-    _glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
-    _glfw.ns.keycodes[0x08] = GLFW_KEY_C;
-    _glfw.ns.keycodes[0x02] = GLFW_KEY_D;
-    _glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
-    _glfw.ns.keycodes[0x03] = GLFW_KEY_F;
-    _glfw.ns.keycodes[0x05] = GLFW_KEY_G;
-    _glfw.ns.keycodes[0x04] = GLFW_KEY_H;
-    _glfw.ns.keycodes[0x22] = GLFW_KEY_I;
-    _glfw.ns.keycodes[0x26] = GLFW_KEY_J;
-    _glfw.ns.keycodes[0x28] = GLFW_KEY_K;
-    _glfw.ns.keycodes[0x25] = GLFW_KEY_L;
-    _glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
-    _glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
-    _glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
-    _glfw.ns.keycodes[0x23] = GLFW_KEY_P;
-    _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
-    _glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
-    _glfw.ns.keycodes[0x01] = GLFW_KEY_S;
-    _glfw.ns.keycodes[0x11] = GLFW_KEY_T;
-    _glfw.ns.keycodes[0x20] = GLFW_KEY_U;
-    _glfw.ns.keycodes[0x09] = GLFW_KEY_V;
-    _glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
-    _glfw.ns.keycodes[0x07] = GLFW_KEY_X;
-    _glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
-    _glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
-
-    _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
-    _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
-    _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
-    _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
-    _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
-    _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
-    _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
-    _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
-    _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
-    _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
-    _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
-    _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
-
-    _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
-    _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
-    _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
-    _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
-    _glfw.ns.keycodes[0x77] = GLFW_KEY_END;
-    _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
-    _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
-    _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
-    _glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
-    _glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
-    _glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
-    _glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
-    _glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
-    _glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
-    _glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
-    _glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
-    _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
-    _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
-    _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
-    _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
-    _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
-    _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
-    _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
-    _glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
-    _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
-    _glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
-    _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
-    _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
-    _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
-    _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
-    _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
-    _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
-    _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
-    _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
-    _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
-    _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
-    _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
-    _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
-    _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
-    _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
-    _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
-    _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
-    _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
-    _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
-    _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
-    _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
-
-    _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
-    _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
-    _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
-    _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
-    _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
-    _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
-    _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
-    _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
-    _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
-    _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
-    _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
-    _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
-    _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
-    _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
-    _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
-    _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
-    _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
-
-    for (scancode = 0;  scancode < 256;  scancode++)
-    {
-        // Store the reverse translation for faster key name lookup
-        if (_glfw.ns.keycodes[scancode] >= 0)
-            _glfw.ns.scancodes[_glfw.ns.keycodes[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"));
-    _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 ||
-        !TISCopyCurrentKeyboardLayoutInputSource ||
-        !TISGetInputSourceProperty ||
-        !LMGetKbdType)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to load TIS API symbols");
-        return GLFW_FALSE;
-    }
-
-    _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
-        *kPropertyUnicodeKeyLayoutData;
-
-    return updateUnicodeDataNS();
-}
-
-@interface GLFWHelper : NSObject
-@end
-
-@implementation GLFWHelper
-
-- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
-{
-    updateUnicodeDataNS();
-}
-
-- (void)doNothing:(id)object
-{
-}
-
-@end // GLFWHelper
-
-@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
-@end
-
-@implementation GLFWApplicationDelegate
-
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
-{
-    _GLFWwindow* window;
-
-    for (window = _glfw.windowListHead;  window;  window = window->next)
-        _glfwInputWindowCloseRequest(window);
-
-    return NSTerminateCancel;
-}
-
-- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
-{
-    _GLFWwindow* window;
-
-    for (window = _glfw.windowListHead;  window;  window = window->next)
-    {
-        if (window->context.client != GLFW_NO_API)
-            [window->context.nsgl.object update];
-    }
-
-    _glfwPollMonitorsNS();
-}
-
-- (void)applicationWillFinishLaunching:(NSNotification *)notification
-{
-    if (_glfw.hints.init.ns.menubar)
-    {
-        // In case we are unbundled, make us a proper UI application
-        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-
-        // Menu bar setup must go between sharedApplication and finishLaunching
-        // in order to properly emulate the behavior of NSApplicationMain
-
-        if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
-        {
-            [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
-                                          owner:NSApp
-                                topLevelObjects:&_glfw.ns.nibObjects];
-        }
-        else
-            createMenuBar();
-    }
-}
-
-- (void)applicationDidFinishLaunching:(NSNotification *)notification
-{
-    _glfw.ns.finishedLaunching = GLFW_TRUE;
-    _glfwPlatformPostEmptyEvent();
-    [NSApp stop:nil];
-}
-
-- (void)applicationDidHide:(NSNotification *)notification
-{
-    int i;
-
-    for (i = 0;  i < _glfw.monitorCount;  i++)
-        _glfwRestoreVideoModeNS(_glfw.monitors[i]);
-}
-
-@end // GLFWApplicationDelegate
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void)
-{
-    @autoreleasepool {
-
-    _glfw.ns.helper = [[GLFWHelper alloc] init];
-
-    [NSThread detachNewThreadSelector:@selector(doNothing:)
-                             toTarget:_glfw.ns.helper
-                           withObject:nil];
-
-    if (NSApp)
-        _glfw.ns.finishedLaunching = GLFW_TRUE;
-
-    [NSApplication sharedApplication];
-
-    _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
-    if (_glfw.ns.delegate == nil)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to create application delegate");
-        return GLFW_FALSE;
-    }
-
-    [NSApp setDelegate:_glfw.ns.delegate];
-
-    NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
-    {
-        if ([event modifierFlags] & NSEventModifierFlagCommand)
-            [[NSApp keyWindow] sendEvent:event];
-
-        return event;
-    };
-
-    _glfw.ns.keyUpMonitor =
-        [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
-                                              handler:block];
-
-    if (_glfw.hints.init.ns.chdir)
-        changeToResourcesDirectory();
-
-    // Press and Hold prevents some keys from emitting repeated characters
-    NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
-    [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
-
-    [[NSNotificationCenter defaultCenter]
-        addObserver:_glfw.ns.helper
-           selector:@selector(selectedKeyboardInputSourceChanged:)
-               name:NSTextInputContextKeyboardSelectionDidChangeNotification
-             object:nil];
-
-    createKeyTables();
-
-    _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
-    if (!_glfw.ns.eventSource)
-        return GLFW_FALSE;
-
-    CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
-
-    if (!initializeTIS())
-        return GLFW_FALSE;
-
-    _glfwInitTimerNS();
-    _glfwInitJoysticksNS();
-
-    _glfwPollMonitorsNS();
-    return GLFW_TRUE;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformTerminate(void)
-{
-    @autoreleasepool {
-
-    if (_glfw.ns.inputSource)
-    {
-        CFRelease(_glfw.ns.inputSource);
-        _glfw.ns.inputSource = NULL;
-        _glfw.ns.unicodeData = nil;
-    }
-
-    if (_glfw.ns.eventSource)
-    {
-        CFRelease(_glfw.ns.eventSource);
-        _glfw.ns.eventSource = NULL;
-    }
-
-    if (_glfw.ns.delegate)
-    {
-        [NSApp setDelegate:nil];
-        [_glfw.ns.delegate release];
-        _glfw.ns.delegate = nil;
-    }
-
-    if (_glfw.ns.helper)
-    {
-        [[NSNotificationCenter defaultCenter]
-            removeObserver:_glfw.ns.helper
-                      name:NSTextInputContextKeyboardSelectionDidChangeNotification
-                    object:nil];
-        [[NSNotificationCenter defaultCenter]
-            removeObserver:_glfw.ns.helper];
-        [_glfw.ns.helper release];
-        _glfw.ns.helper = nil;
-    }
-
-    if (_glfw.ns.keyUpMonitor)
-        [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
-
-    free(_glfw.ns.clipboardString);
-
-    _glfwTerminateNSGL();
-    _glfwTerminateJoysticksNS();
-
-    } // autoreleasepool
-}
-
-const char* _glfwPlatformGetVersionString(void)
-{
-    return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
-#if defined(_GLFW_BUILD_DLL)
-        " dynamic"
-#endif
-        ;
-}
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+#include <sys/param.h> // For MAXPATHLEN
+
+// Needed for _NSGetProgname
+#include <crt_externs.h>
+
+// Change to our application bundle's resources directory, if present
+//
+static void changeToResourcesDirectory(void)
+{
+    char resourcesPath[MAXPATHLEN];
+
+    CFBundleRef bundle = CFBundleGetMainBundle();
+    if (!bundle)
+        return;
+
+    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(bundle);
+
+    CFStringRef last = CFURLCopyLastPathComponent(resourcesURL);
+    if (CFStringCompare(CFSTR("Resources"), last, 0) != kCFCompareEqualTo)
+    {
+        CFRelease(last);
+        CFRelease(resourcesURL);
+        return;
+    }
+
+    CFRelease(last);
+
+    if (!CFURLGetFileSystemRepresentation(resourcesURL,
+                                          true,
+                                          (UInt8*) resourcesPath,
+                                          MAXPATHLEN))
+    {
+        CFRelease(resourcesURL);
+        return;
+    }
+
+    CFRelease(resourcesURL);
+
+    chdir(resourcesPath);
+}
+
+// Set up the menu bar (manually)
+// This is nasty, nasty stuff -- calls to undocumented semi-private APIs that
+// could go away at any moment, lots of stuff that really should be
+// localize(d|able), etc.  Add a nib to save us this horror.
+//
+static void createMenuBar(void)
+{
+    size_t i;
+    NSString* appName = nil;
+    NSDictionary* bundleInfo = [[NSBundle mainBundle] infoDictionary];
+    NSString* nameKeys[] =
+    {
+        @"CFBundleDisplayName",
+        @"CFBundleName",
+        @"CFBundleExecutable",
+    };
+
+    // Try to figure out what the calling application is called
+
+    for (i = 0;  i < sizeof(nameKeys) / sizeof(nameKeys[0]);  i++)
+    {
+        id name = bundleInfo[nameKeys[i]];
+        if (name &&
+            [name isKindOfClass:[NSString class]] &&
+            ![name isEqualToString:@""])
+        {
+            appName = name;
+            break;
+        }
+    }
+
+    if (!appName)
+    {
+        char** progname = _NSGetProgname();
+        if (progname && *progname)
+            appName = @(*progname);
+        else
+            appName = @"GLFW Application";
+    }
+
+    NSMenu* bar = [[NSMenu alloc] init];
+    [NSApp setMainMenu:bar];
+
+    NSMenuItem* appMenuItem =
+        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+    NSMenu* appMenu = [[NSMenu alloc] init];
+    [appMenuItem setSubmenu:appMenu];
+
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"About %@", appName]
+                       action:@selector(orderFrontStandardAboutPanel:)
+                keyEquivalent:@""];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    NSMenu* servicesMenu = [[NSMenu alloc] init];
+    [NSApp setServicesMenu:servicesMenu];
+    [[appMenu addItemWithTitle:@"Services"
+                       action:NULL
+                keyEquivalent:@""] setSubmenu:servicesMenu];
+    [servicesMenu release];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Hide %@", appName]
+                       action:@selector(hide:)
+                keyEquivalent:@"h"];
+    [[appMenu addItemWithTitle:@"Hide Others"
+                       action:@selector(hideOtherApplications:)
+                keyEquivalent:@"h"]
+        setKeyEquivalentModifierMask:NSEventModifierFlagOption | NSEventModifierFlagCommand];
+    [appMenu addItemWithTitle:@"Show All"
+                       action:@selector(unhideAllApplications:)
+                keyEquivalent:@""];
+    [appMenu addItem:[NSMenuItem separatorItem]];
+    [appMenu addItemWithTitle:[NSString stringWithFormat:@"Quit %@", appName]
+                       action:@selector(terminate:)
+                keyEquivalent:@"q"];
+
+    NSMenuItem* windowMenuItem =
+        [bar addItemWithTitle:@"" action:NULL keyEquivalent:@""];
+    [bar release];
+    NSMenu* windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
+    [NSApp setWindowsMenu:windowMenu];
+    [windowMenuItem setSubmenu:windowMenu];
+
+    [windowMenu addItemWithTitle:@"Minimize"
+                          action:@selector(performMiniaturize:)
+                   keyEquivalent:@"m"];
+    [windowMenu addItemWithTitle:@"Zoom"
+                          action:@selector(performZoom:)
+                   keyEquivalent:@""];
+    [windowMenu addItem:[NSMenuItem separatorItem]];
+    [windowMenu addItemWithTitle:@"Bring All to Front"
+                          action:@selector(arrangeInFront:)
+                   keyEquivalent:@""];
+
+    // 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:NSEventModifierFlagControl | NSEventModifierFlagCommand];
+
+    // Prior to Snow Leopard, we need to use this oddly-named semi-private API
+    // to get the application menu working properly.
+    SEL setAppleMenuSelector = NSSelectorFromString(@"setAppleMenu:");
+    [NSApp performSelector:setAppleMenuSelector withObject:appMenu];
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+    int scancode;
+
+    memset(_glfw.ns.keycodes, -1, sizeof(_glfw.ns.keycodes));
+    memset(_glfw.ns.scancodes, -1, sizeof(_glfw.ns.scancodes));
+
+    _glfw.ns.keycodes[0x1D] = GLFW_KEY_0;
+    _glfw.ns.keycodes[0x12] = GLFW_KEY_1;
+    _glfw.ns.keycodes[0x13] = GLFW_KEY_2;
+    _glfw.ns.keycodes[0x14] = GLFW_KEY_3;
+    _glfw.ns.keycodes[0x15] = GLFW_KEY_4;
+    _glfw.ns.keycodes[0x17] = GLFW_KEY_5;
+    _glfw.ns.keycodes[0x16] = GLFW_KEY_6;
+    _glfw.ns.keycodes[0x1A] = GLFW_KEY_7;
+    _glfw.ns.keycodes[0x1C] = GLFW_KEY_8;
+    _glfw.ns.keycodes[0x19] = GLFW_KEY_9;
+    _glfw.ns.keycodes[0x00] = GLFW_KEY_A;
+    _glfw.ns.keycodes[0x0B] = GLFW_KEY_B;
+    _glfw.ns.keycodes[0x08] = GLFW_KEY_C;
+    _glfw.ns.keycodes[0x02] = GLFW_KEY_D;
+    _glfw.ns.keycodes[0x0E] = GLFW_KEY_E;
+    _glfw.ns.keycodes[0x03] = GLFW_KEY_F;
+    _glfw.ns.keycodes[0x05] = GLFW_KEY_G;
+    _glfw.ns.keycodes[0x04] = GLFW_KEY_H;
+    _glfw.ns.keycodes[0x22] = GLFW_KEY_I;
+    _glfw.ns.keycodes[0x26] = GLFW_KEY_J;
+    _glfw.ns.keycodes[0x28] = GLFW_KEY_K;
+    _glfw.ns.keycodes[0x25] = GLFW_KEY_L;
+    _glfw.ns.keycodes[0x2E] = GLFW_KEY_M;
+    _glfw.ns.keycodes[0x2D] = GLFW_KEY_N;
+    _glfw.ns.keycodes[0x1F] = GLFW_KEY_O;
+    _glfw.ns.keycodes[0x23] = GLFW_KEY_P;
+    _glfw.ns.keycodes[0x0C] = GLFW_KEY_Q;
+    _glfw.ns.keycodes[0x0F] = GLFW_KEY_R;
+    _glfw.ns.keycodes[0x01] = GLFW_KEY_S;
+    _glfw.ns.keycodes[0x11] = GLFW_KEY_T;
+    _glfw.ns.keycodes[0x20] = GLFW_KEY_U;
+    _glfw.ns.keycodes[0x09] = GLFW_KEY_V;
+    _glfw.ns.keycodes[0x0D] = GLFW_KEY_W;
+    _glfw.ns.keycodes[0x07] = GLFW_KEY_X;
+    _glfw.ns.keycodes[0x10] = GLFW_KEY_Y;
+    _glfw.ns.keycodes[0x06] = GLFW_KEY_Z;
+
+    _glfw.ns.keycodes[0x27] = GLFW_KEY_APOSTROPHE;
+    _glfw.ns.keycodes[0x2A] = GLFW_KEY_BACKSLASH;
+    _glfw.ns.keycodes[0x2B] = GLFW_KEY_COMMA;
+    _glfw.ns.keycodes[0x18] = GLFW_KEY_EQUAL;
+    _glfw.ns.keycodes[0x32] = GLFW_KEY_GRAVE_ACCENT;
+    _glfw.ns.keycodes[0x21] = GLFW_KEY_LEFT_BRACKET;
+    _glfw.ns.keycodes[0x1B] = GLFW_KEY_MINUS;
+    _glfw.ns.keycodes[0x2F] = GLFW_KEY_PERIOD;
+    _glfw.ns.keycodes[0x1E] = GLFW_KEY_RIGHT_BRACKET;
+    _glfw.ns.keycodes[0x29] = GLFW_KEY_SEMICOLON;
+    _glfw.ns.keycodes[0x2C] = GLFW_KEY_SLASH;
+    _glfw.ns.keycodes[0x0A] = GLFW_KEY_WORLD_1;
+
+    _glfw.ns.keycodes[0x33] = GLFW_KEY_BACKSPACE;
+    _glfw.ns.keycodes[0x39] = GLFW_KEY_CAPS_LOCK;
+    _glfw.ns.keycodes[0x75] = GLFW_KEY_DELETE;
+    _glfw.ns.keycodes[0x7D] = GLFW_KEY_DOWN;
+    _glfw.ns.keycodes[0x77] = GLFW_KEY_END;
+    _glfw.ns.keycodes[0x24] = GLFW_KEY_ENTER;
+    _glfw.ns.keycodes[0x35] = GLFW_KEY_ESCAPE;
+    _glfw.ns.keycodes[0x7A] = GLFW_KEY_F1;
+    _glfw.ns.keycodes[0x78] = GLFW_KEY_F2;
+    _glfw.ns.keycodes[0x63] = GLFW_KEY_F3;
+    _glfw.ns.keycodes[0x76] = GLFW_KEY_F4;
+    _glfw.ns.keycodes[0x60] = GLFW_KEY_F5;
+    _glfw.ns.keycodes[0x61] = GLFW_KEY_F6;
+    _glfw.ns.keycodes[0x62] = GLFW_KEY_F7;
+    _glfw.ns.keycodes[0x64] = GLFW_KEY_F8;
+    _glfw.ns.keycodes[0x65] = GLFW_KEY_F9;
+    _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10;
+    _glfw.ns.keycodes[0x67] = GLFW_KEY_F11;
+    _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12;
+    _glfw.ns.keycodes[0x69] = GLFW_KEY_F13;
+    _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14;
+    _glfw.ns.keycodes[0x71] = GLFW_KEY_F15;
+    _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16;
+    _glfw.ns.keycodes[0x40] = GLFW_KEY_F17;
+    _glfw.ns.keycodes[0x4F] = GLFW_KEY_F18;
+    _glfw.ns.keycodes[0x50] = GLFW_KEY_F19;
+    _glfw.ns.keycodes[0x5A] = GLFW_KEY_F20;
+    _glfw.ns.keycodes[0x73] = GLFW_KEY_HOME;
+    _glfw.ns.keycodes[0x72] = GLFW_KEY_INSERT;
+    _glfw.ns.keycodes[0x7B] = GLFW_KEY_LEFT;
+    _glfw.ns.keycodes[0x3A] = GLFW_KEY_LEFT_ALT;
+    _glfw.ns.keycodes[0x3B] = GLFW_KEY_LEFT_CONTROL;
+    _glfw.ns.keycodes[0x38] = GLFW_KEY_LEFT_SHIFT;
+    _glfw.ns.keycodes[0x37] = GLFW_KEY_LEFT_SUPER;
+    _glfw.ns.keycodes[0x6E] = GLFW_KEY_MENU;
+    _glfw.ns.keycodes[0x47] = GLFW_KEY_NUM_LOCK;
+    _glfw.ns.keycodes[0x79] = GLFW_KEY_PAGE_DOWN;
+    _glfw.ns.keycodes[0x74] = GLFW_KEY_PAGE_UP;
+    _glfw.ns.keycodes[0x7C] = GLFW_KEY_RIGHT;
+    _glfw.ns.keycodes[0x3D] = GLFW_KEY_RIGHT_ALT;
+    _glfw.ns.keycodes[0x3E] = GLFW_KEY_RIGHT_CONTROL;
+    _glfw.ns.keycodes[0x3C] = GLFW_KEY_RIGHT_SHIFT;
+    _glfw.ns.keycodes[0x36] = GLFW_KEY_RIGHT_SUPER;
+    _glfw.ns.keycodes[0x31] = GLFW_KEY_SPACE;
+    _glfw.ns.keycodes[0x30] = GLFW_KEY_TAB;
+    _glfw.ns.keycodes[0x7E] = GLFW_KEY_UP;
+
+    _glfw.ns.keycodes[0x52] = GLFW_KEY_KP_0;
+    _glfw.ns.keycodes[0x53] = GLFW_KEY_KP_1;
+    _glfw.ns.keycodes[0x54] = GLFW_KEY_KP_2;
+    _glfw.ns.keycodes[0x55] = GLFW_KEY_KP_3;
+    _glfw.ns.keycodes[0x56] = GLFW_KEY_KP_4;
+    _glfw.ns.keycodes[0x57] = GLFW_KEY_KP_5;
+    _glfw.ns.keycodes[0x58] = GLFW_KEY_KP_6;
+    _glfw.ns.keycodes[0x59] = GLFW_KEY_KP_7;
+    _glfw.ns.keycodes[0x5B] = GLFW_KEY_KP_8;
+    _glfw.ns.keycodes[0x5C] = GLFW_KEY_KP_9;
+    _glfw.ns.keycodes[0x45] = GLFW_KEY_KP_ADD;
+    _glfw.ns.keycodes[0x41] = GLFW_KEY_KP_DECIMAL;
+    _glfw.ns.keycodes[0x4B] = GLFW_KEY_KP_DIVIDE;
+    _glfw.ns.keycodes[0x4C] = GLFW_KEY_KP_ENTER;
+    _glfw.ns.keycodes[0x51] = GLFW_KEY_KP_EQUAL;
+    _glfw.ns.keycodes[0x43] = GLFW_KEY_KP_MULTIPLY;
+    _glfw.ns.keycodes[0x4E] = GLFW_KEY_KP_SUBTRACT;
+
+    for (scancode = 0;  scancode < 256;  scancode++)
+    {
+        // Store the reverse translation for faster key name lookup
+        if (_glfw.ns.keycodes[scancode] >= 0)
+            _glfw.ns.scancodes[_glfw.ns.keycodes[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"));
+    _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 ||
+        !TISCopyCurrentKeyboardLayoutInputSource ||
+        !TISGetInputSourceProperty ||
+        !LMGetKbdType)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to load TIS API symbols");
+        return GLFW_FALSE;
+    }
+
+    _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
+        *kPropertyUnicodeKeyLayoutData;
+
+    return updateUnicodeDataNS();
+}
+
+@interface GLFWHelper : NSObject
+@end
+
+@implementation GLFWHelper
+
+- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
+{
+    updateUnicodeDataNS();
+}
+
+- (void)doNothing:(id)object
+{
+}
+
+@end // GLFWHelper
+
+@interface GLFWApplicationDelegate : NSObject <NSApplicationDelegate>
+@end
+
+@implementation GLFWApplicationDelegate
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+    _GLFWwindow* window;
+
+    for (window = _glfw.windowListHead;  window;  window = window->next)
+        _glfwInputWindowCloseRequest(window);
+
+    return NSTerminateCancel;
+}
+
+- (void)applicationDidChangeScreenParameters:(NSNotification *) notification
+{
+    _GLFWwindow* window;
+
+    for (window = _glfw.windowListHead;  window;  window = window->next)
+    {
+        if (window->context.client != GLFW_NO_API)
+            [window->context.nsgl.object update];
+    }
+
+    _glfwPollMonitorsNS();
+}
+
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
+{
+    if (_glfw.hints.init.ns.menubar)
+    {
+        // In case we are unbundled, make us a proper UI application
+        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+        // Menu bar setup must go between sharedApplication and finishLaunching
+        // in order to properly emulate the behavior of NSApplicationMain
+
+        if ([[NSBundle mainBundle] pathForResource:@"MainMenu" ofType:@"nib"])
+        {
+            [[NSBundle mainBundle] loadNibNamed:@"MainMenu"
+                                          owner:NSApp
+                                topLevelObjects:&_glfw.ns.nibObjects];
+        }
+        else
+            createMenuBar();
+    }
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+    _glfw.ns.finishedLaunching = GLFW_TRUE;
+    _glfwPlatformPostEmptyEvent();
+    [NSApp stop:nil];
+}
+
+- (void)applicationDidHide:(NSNotification *)notification
+{
+    int i;
+
+    for (i = 0;  i < _glfw.monitorCount;  i++)
+        _glfwRestoreVideoModeNS(_glfw.monitors[i]);
+}
+
+@end // GLFWApplicationDelegate
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void* _glfwLoadLocalVulkanLoaderNS(void)
+{
+    CFBundleRef bundle = CFBundleGetMainBundle();
+    if (!bundle)
+        return NULL;
+
+    CFURLRef url =
+        CFBundleCopyAuxiliaryExecutableURL(bundle, CFSTR("libvulkan.1.dylib"));
+    if (!url)
+        return NULL;
+
+    char path[PATH_MAX];
+    void* handle = NULL;
+
+    if (CFURLGetFileSystemRepresentation(url, true, (UInt8*) path, sizeof(path) - 1))
+        handle = _glfw_dlopen(path);
+
+    CFRelease(url);
+    return handle;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+    @autoreleasepool {
+
+    _glfw.ns.helper = [[GLFWHelper alloc] init];
+
+    [NSThread detachNewThreadSelector:@selector(doNothing:)
+                             toTarget:_glfw.ns.helper
+                           withObject:nil];
+
+    if (NSApp)
+        _glfw.ns.finishedLaunching = GLFW_TRUE;
+
+    [NSApplication sharedApplication];
+
+    _glfw.ns.delegate = [[GLFWApplicationDelegate alloc] init];
+    if (_glfw.ns.delegate == nil)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to create application delegate");
+        return GLFW_FALSE;
+    }
+
+    [NSApp setDelegate:_glfw.ns.delegate];
+
+    NSEvent* (^block)(NSEvent*) = ^ NSEvent* (NSEvent* event)
+    {
+        if ([event modifierFlags] & NSEventModifierFlagCommand)
+            [[NSApp keyWindow] sendEvent:event];
+
+        return event;
+    };
+
+    _glfw.ns.keyUpMonitor =
+        [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
+                                              handler:block];
+
+    if (_glfw.hints.init.ns.chdir)
+        changeToResourcesDirectory();
+
+    // Press and Hold prevents some keys from emitting repeated characters
+    NSDictionary* defaults = @{@"ApplePressAndHoldEnabled":@NO};
+    [[NSUserDefaults standardUserDefaults] registerDefaults:defaults];
+
+    [[NSNotificationCenter defaultCenter]
+        addObserver:_glfw.ns.helper
+           selector:@selector(selectedKeyboardInputSourceChanged:)
+               name:NSTextInputContextKeyboardSelectionDidChangeNotification
+             object:nil];
+
+    createKeyTables();
+
+    _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+    if (!_glfw.ns.eventSource)
+        return GLFW_FALSE;
+
+    CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
+
+    if (!initializeTIS())
+        return GLFW_FALSE;
+
+    _glfwInitTimerNS();
+    _glfwInitJoysticksNS();
+
+    _glfwPollMonitorsNS();
+    return GLFW_TRUE;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformTerminate(void)
+{
+    @autoreleasepool {
+
+    if (_glfw.ns.inputSource)
+    {
+        CFRelease(_glfw.ns.inputSource);
+        _glfw.ns.inputSource = NULL;
+        _glfw.ns.unicodeData = nil;
+    }
+
+    if (_glfw.ns.eventSource)
+    {
+        CFRelease(_glfw.ns.eventSource);
+        _glfw.ns.eventSource = NULL;
+    }
+
+    if (_glfw.ns.delegate)
+    {
+        [NSApp setDelegate:nil];
+        [_glfw.ns.delegate release];
+        _glfw.ns.delegate = nil;
+    }
+
+    if (_glfw.ns.helper)
+    {
+        [[NSNotificationCenter defaultCenter]
+            removeObserver:_glfw.ns.helper
+                      name:NSTextInputContextKeyboardSelectionDidChangeNotification
+                    object:nil];
+        [[NSNotificationCenter defaultCenter]
+            removeObserver:_glfw.ns.helper];
+        [_glfw.ns.helper release];
+        _glfw.ns.helper = nil;
+    }
+
+    if (_glfw.ns.keyUpMonitor)
+        [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
+
+    free(_glfw.ns.clipboardString);
+
+    _glfwTerminateNSGL();
+    _glfwTerminateJoysticksNS();
+
+    } // autoreleasepool
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+    return _GLFW_VERSION_NUMBER " Cocoa NSGL EGL OSMesa"
+#if defined(_GLFW_BUILD_DLL)
+        " dynamic"
+#endif
+        ;
+}
+
diff --git a/glfw/src/cocoa_joystick.h b/glfw/src/cocoa_joystick.h
--- a/glfw/src/cocoa_joystick.h
+++ b/glfw/src/cocoa_joystick.h
@@ -1,50 +1,50 @@
-//========================================================================
-// GLFW 3.3 Cocoa - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2006-2017 Camilla Löwy <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 <IOKit/IOKitLib.h>
-#include <IOKit/IOCFPlugIn.h>
-#include <IOKit/hid/IOHIDLib.h>
-#include <IOKit/hid/IOHIDKeys.h>
-
-#define _GLFW_PLATFORM_JOYSTICK_STATE         _GLFWjoystickNS ns
-#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyJoystick; }
-
-#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
-
-// Cocoa-specific per-joystick data
-//
-typedef struct _GLFWjoystickNS
-{
-    IOHIDDeviceRef      device;
-    CFMutableArrayRef   axes;
-    CFMutableArrayRef   buttons;
-    CFMutableArrayRef   hats;
-} _GLFWjoystickNS;
-
-
-void _glfwInitJoysticksNS(void);
-void _glfwTerminateJoysticksNS(void);
-
+//========================================================================
+// GLFW 3.3 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2017 Camilla Löwy <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 <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE         _GLFWjoystickNS ns
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyJoystick; }
+
+#define _GLFW_PLATFORM_MAPPING_NAME "Mac OS X"
+
+// Cocoa-specific per-joystick data
+//
+typedef struct _GLFWjoystickNS
+{
+    IOHIDDeviceRef      device;
+    CFMutableArrayRef   axes;
+    CFMutableArrayRef   buttons;
+    CFMutableArrayRef   hats;
+} _GLFWjoystickNS;
+
+
+void _glfwInitJoysticksNS(void);
+void _glfwTerminateJoysticksNS(void);
+
diff --git a/glfw/src/cocoa_joystick.m b/glfw/src/cocoa_joystick.m
--- a/glfw/src/cocoa_joystick.m
+++ b/glfw/src/cocoa_joystick.m
@@ -1,487 +1,487 @@
-//========================================================================
-// GLFW 3.3 Cocoa - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#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 native;
-    uint32_t        usage;
-    int             index;
-    long            minimum;
-    long            maximum;
-
-} _GLFWjoyelementNS;
-
-
-// Returns the value of the specified element of the specified joystick
-//
-static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
-{
-    IOHIDValueRef valueRef;
-    long value = 0;
-
-    if (js->ns.device)
-    {
-        if (IOHIDDeviceGetValue(js->ns.device,
-                                element->native,
-                                &valueRef) == kIOReturnSuccess)
-        {
-            value = IOHIDValueGetIntegerValue(valueRef);
-        }
-    }
-
-    return value;
-}
-
-// Comparison function for matching the SDL element order
-//
-static CFComparisonResult compareElements(const void* fp,
-                                          const void* sp,
-                                          void* user)
-{
-    const _GLFWjoyelementNS* fe = fp;
-    const _GLFWjoyelementNS* se = sp;
-    if (fe->usage < se->usage)
-        return kCFCompareLessThan;
-    if (fe->usage > se->usage)
-        return kCFCompareGreaterThan;
-    if (fe->index < se->index)
-        return kCFCompareLessThan;
-    if (fe->index > se->index)
-        return kCFCompareGreaterThan;
-    return kCFCompareEqualTo;
-}
-
-// Removes the specified joystick
-//
-static void closeJoystick(_GLFWjoystick* js)
-{
-    int i;
-
-    if (!js->present)
-        return;
-
-    for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)
-        free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
-    CFRelease(js->ns.axes);
-
-    for (i = 0;  i < CFArrayGetCount(js->ns.buttons);  i++)
-        free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
-    CFRelease(js->ns.buttons);
-
-    for (i = 0;  i < CFArrayGetCount(js->ns.hats);  i++)
-        free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
-    CFRelease(js->ns.hats);
-
-    _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
-}
-
-// Callback for user-initiated joystick addition
-//
-static void matchCallback(void* context,
-                          IOReturn result,
-                          void* sender,
-                          IOHIDDeviceRef device)
-{
-    int jid;
-    char name[256];
-    char guid[33];
-    CFIndex i;
-    CFTypeRef property;
-    uint32_t vendor = 0, product = 0, version = 0;
-    _GLFWjoystick* js;
-    CFMutableArrayRef axes, buttons, hats;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        if (_glfw.joysticks[jid].ns.device == device)
-            return;
-    }
-
-    axes    = CFArrayCreateMutable(NULL, 0, NULL);
-    buttons = CFArrayCreateMutable(NULL, 0, NULL);
-    hats    = CFArrayCreateMutable(NULL, 0, NULL);
-
-    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
-    if (property)
-    {
-        CFStringGetCString(property,
-                           name,
-                           sizeof(name),
-                           kCFStringEncodingUTF8);
-    }
-    else
-        strncpy(name, "Unknown", sizeof(name));
-
-    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
-    if (property)
-        CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
-
-    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
-    if (property)
-        CFNumberGetValue(property, kCFNumberSInt32Type, &product);
-
-    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
-    if (property)
-        CFNumberGetValue(property, kCFNumberSInt32Type, &version);
-
-    // Generate a joystick GUID that matches the SDL 2.0.5+ one
-    if (vendor && product)
-    {
-        sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
-                (uint8_t) vendor, (uint8_t) (vendor >> 8),
-                (uint8_t) product, (uint8_t) (product >> 8),
-                (uint8_t) version, (uint8_t) (version >> 8));
-    }
-    else
-    {
-        sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
-                name[0], name[1], name[2], name[3],
-                name[4], name[5], name[6], name[7],
-                name[8], name[9], name[10]);
-    }
-
-    CFArrayRef elements =
-        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
-
-    for (i = 0;  i < CFArrayGetCount(elements);  i++)
-    {
-        IOHIDElementRef native = (IOHIDElementRef)
-            CFArrayGetValueAtIndex(elements, i);
-        if (CFGetTypeID(native) != IOHIDElementGetTypeID())
-            continue;
-
-        const IOHIDElementType type = IOHIDElementGetType(native);
-        if ((type != kIOHIDElementTypeInput_Axis) &&
-            (type != kIOHIDElementTypeInput_Button) &&
-            (type != kIOHIDElementTypeInput_Misc))
-        {
-            continue;
-        }
-
-        CFMutableArrayRef target = NULL;
-
-        const uint32_t usage = IOHIDElementGetUsage(native);
-        const uint32_t page = IOHIDElementGetUsagePage(native);
-        if (page == 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:
-                    target = axes;
-                    break;
-                case kHIDUsage_GD_Hatswitch:
-                    target = hats;
-                    break;
-                case kHIDUsage_GD_DPadUp:
-                case kHIDUsage_GD_DPadRight:
-                case kHIDUsage_GD_DPadDown:
-                case kHIDUsage_GD_DPadLeft:
-                case kHIDUsage_GD_SystemMainMenu:
-                case kHIDUsage_GD_Select:
-                case kHIDUsage_GD_Start:
-                    target = buttons;
-                    break;
-            }
-        }
-        else if (page == kHIDPage_Simulation)
-        {
-            switch (usage)
-            {
-                case kHIDUsage_Sim_Accelerator:
-                case kHIDUsage_Sim_Brake:
-                case kHIDUsage_Sim_Throttle:
-                case kHIDUsage_Sim_Rudder:
-                case kHIDUsage_Sim_Steering:
-                    target = axes;
-                    break;
-            }
-        }
-        else if (page == kHIDPage_Button || page == kHIDPage_Consumer)
-            target = buttons;
-
-        if (target)
-        {
-            _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
-            element->native  = native;
-            element->usage   = usage;
-            element->index   = (int) CFArrayGetCount(target);
-            element->minimum = IOHIDElementGetLogicalMin(native);
-            element->maximum = IOHIDElementGetLogicalMax(native);
-            CFArrayAppendValue(target, element);
-        }
-    }
-
-    CFRelease(elements);
-
-    CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
-                      compareElements, NULL);
-    CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
-                      compareElements, NULL);
-    CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
-                      compareElements, NULL);
-
-    js = _glfwAllocJoystick(name, guid,
-                            (int) CFArrayGetCount(axes),
-                            (int) CFArrayGetCount(buttons),
-                            (int) CFArrayGetCount(hats));
-
-    js->ns.device  = device;
-    js->ns.axes    = axes;
-    js->ns.buttons = buttons;
-    js->ns.hats    = hats;
-
-    _glfwInputJoystick(js, GLFW_CONNECTED);
-}
-
-// Callback for user-initiated joystick removal
-//
-static void removeCallback(void* context,
-                           IOReturn result,
-                           void* sender,
-                           IOHIDDeviceRef device)
-{
-    int jid;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        if (_glfw.joysticks[jid].ns.device == device)
-        {
-            closeJoystick(_glfw.joysticks + jid);
-            break;
-        }
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialize joystick interface
-//
-void _glfwInitJoysticksNS(void)
-{
-    CFMutableArrayRef matching;
-    const long usages[] =
-    {
-        kHIDUsage_GD_Joystick,
-        kHIDUsage_GD_GamePad,
-        kHIDUsage_GD_MultiAxisController
-    };
-
-    _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
-                                             kIOHIDOptionsTypeNone);
-
-    matching = CFArrayCreateMutable(kCFAllocatorDefault,
-                                    0,
-                                    &kCFTypeArrayCallBacks);
-    if (!matching)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
-        return;
-    }
-
-    for (size_t i = 0;  i < sizeof(usages) / sizeof(long);  i++)
-    {
-        const long page = kHIDPage_GenericDesktop;
-
-        CFMutableDictionaryRef dict =
-            CFDictionaryCreateMutable(kCFAllocatorDefault,
-                                      0,
-                                      &kCFTypeDictionaryKeyCallBacks,
-                                      &kCFTypeDictionaryValueCallBacks);
-        if (!dict)
-            continue;
-
-        CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
-                                             kCFNumberLongType,
-                                             &page);
-        CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
-                                              kCFNumberLongType,
-                                              &usages[i]);
-        if (pageRef && usageRef)
-        {
-            CFDictionarySetValue(dict,
-                                 CFSTR(kIOHIDDeviceUsagePageKey),
-                                 pageRef);
-            CFDictionarySetValue(dict,
-                                 CFSTR(kIOHIDDeviceUsageKey),
-                                 usageRef);
-            CFArrayAppendValue(matching, dict);
-        }
-
-        if (pageRef)
-            CFRelease(pageRef);
-        if (usageRef)
-            CFRelease(usageRef);
-
-        CFRelease(dict);
-    }
-
-    IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
-    CFRelease(matching);
-
-    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 jid;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-        closeJoystick(_glfw.joysticks + jid);
-
-    CFRelease(_glfw.ns.hidManager);
-    _glfw.ns.hidManager = NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
-{
-    if (mode & _GLFW_POLL_AXES)
-    {
-        CFIndex i;
-
-        for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)
-        {
-            _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
-                CFArrayGetValueAtIndex(js->ns.axes, i);
-
-            const long raw = getElementValue(js, axis);
-            // Perform auto calibration
-            if (raw < axis->minimum)
-                axis->minimum = raw;
-            if (raw > axis->maximum)
-                axis->maximum = raw;
-
-            const long size = axis->maximum - axis->minimum;
-            if (size == 0)
-                _glfwInputJoystickAxis(js, (int) i, 0.f);
-            else
-            {
-                const float value = (2.f * (raw - axis->minimum) / size) - 1.f;
-                _glfwInputJoystickAxis(js, (int) i, value);
-            }
-        }
-    }
-
-    if (mode & _GLFW_POLL_BUTTONS)
-    {
-        CFIndex i;
-
-        for (i = 0;  i < CFArrayGetCount(js->ns.buttons);  i++)
-        {
-            _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
-                CFArrayGetValueAtIndex(js->ns.buttons, i);
-            const char value = getElementValue(js, button) - button->minimum;
-            const int state = (value > 0) ? GLFW_PRESS : GLFW_RELEASE;
-            _glfwInputJoystickButton(js, (int) i, state);
-        }
-
-        for (i = 0;  i < CFArrayGetCount(js->ns.hats);  i++)
-        {
-            const int states[9] =
-            {
-                GLFW_HAT_UP,
-                GLFW_HAT_RIGHT_UP,
-                GLFW_HAT_RIGHT,
-                GLFW_HAT_RIGHT_DOWN,
-                GLFW_HAT_DOWN,
-                GLFW_HAT_LEFT_DOWN,
-                GLFW_HAT_LEFT,
-                GLFW_HAT_LEFT_UP,
-                GLFW_HAT_CENTERED
-            };
-
-            _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
-                CFArrayGetValueAtIndex(js->ns.hats, i);
-            long state = getElementValue(js, hat) - hat->minimum;
-            if (state < 0 || state > 8)
-                state = 8;
-
-            _glfwInputJoystickHat(js, (int) i, states[state]);
-        }
-    }
-
-    return js->present;
-}
-
-void _glfwPlatformUpdateGamepadGUID(char* guid)
-{
-    if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
-        (strncmp(guid + 20, "000000000000", 12) == 0))
-    {
-        char original[33];
-        strncpy(original, guid, sizeof(original) - 1);
-        sprintf(guid, "03000000%.4s0000%.4s000000000000",
-                original, original + 16);
-    }
-}
-
+//========================================================================
+// GLFW 3.3 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#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 native;
+    uint32_t        usage;
+    int             index;
+    long            minimum;
+    long            maximum;
+
+} _GLFWjoyelementNS;
+
+
+// Returns the value of the specified element of the specified joystick
+//
+static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
+{
+    IOHIDValueRef valueRef;
+    long value = 0;
+
+    if (js->ns.device)
+    {
+        if (IOHIDDeviceGetValue(js->ns.device,
+                                element->native,
+                                &valueRef) == kIOReturnSuccess)
+        {
+            value = IOHIDValueGetIntegerValue(valueRef);
+        }
+    }
+
+    return value;
+}
+
+// Comparison function for matching the SDL element order
+//
+static CFComparisonResult compareElements(const void* fp,
+                                          const void* sp,
+                                          void* user)
+{
+    const _GLFWjoyelementNS* fe = fp;
+    const _GLFWjoyelementNS* se = sp;
+    if (fe->usage < se->usage)
+        return kCFCompareLessThan;
+    if (fe->usage > se->usage)
+        return kCFCompareGreaterThan;
+    if (fe->index < se->index)
+        return kCFCompareLessThan;
+    if (fe->index > se->index)
+        return kCFCompareGreaterThan;
+    return kCFCompareEqualTo;
+}
+
+// Removes the specified joystick
+//
+static void closeJoystick(_GLFWjoystick* js)
+{
+    int i;
+
+    if (!js->present)
+        return;
+
+    for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)
+        free((void*) CFArrayGetValueAtIndex(js->ns.axes, i));
+    CFRelease(js->ns.axes);
+
+    for (i = 0;  i < CFArrayGetCount(js->ns.buttons);  i++)
+        free((void*) CFArrayGetValueAtIndex(js->ns.buttons, i));
+    CFRelease(js->ns.buttons);
+
+    for (i = 0;  i < CFArrayGetCount(js->ns.hats);  i++)
+        free((void*) CFArrayGetValueAtIndex(js->ns.hats, i));
+    CFRelease(js->ns.hats);
+
+    _glfwFreeJoystick(js);
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// Callback for user-initiated joystick addition
+//
+static void matchCallback(void* context,
+                          IOReturn result,
+                          void* sender,
+                          IOHIDDeviceRef device)
+{
+    int jid;
+    char name[256];
+    char guid[33];
+    CFIndex i;
+    CFTypeRef property;
+    uint32_t vendor = 0, product = 0, version = 0;
+    _GLFWjoystick* js;
+    CFMutableArrayRef axes, buttons, hats;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        if (_glfw.joysticks[jid].ns.device == device)
+            return;
+    }
+
+    axes    = CFArrayCreateMutable(NULL, 0, NULL);
+    buttons = CFArrayCreateMutable(NULL, 0, NULL);
+    hats    = CFArrayCreateMutable(NULL, 0, NULL);
+
+    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
+    if (property)
+    {
+        CFStringGetCString(property,
+                           name,
+                           sizeof(name),
+                           kCFStringEncodingUTF8);
+    }
+    else
+        strncpy(name, "Unknown", sizeof(name));
+
+    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVendorIDKey));
+    if (property)
+        CFNumberGetValue(property, kCFNumberSInt32Type, &vendor);
+
+    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductIDKey));
+    if (property)
+        CFNumberGetValue(property, kCFNumberSInt32Type, &product);
+
+    property = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDVersionNumberKey));
+    if (property)
+        CFNumberGetValue(property, kCFNumberSInt32Type, &version);
+
+    // Generate a joystick GUID that matches the SDL 2.0.5+ one
+    if (vendor && product)
+    {
+        sprintf(guid, "03000000%02x%02x0000%02x%02x0000%02x%02x0000",
+                (uint8_t) vendor, (uint8_t) (vendor >> 8),
+                (uint8_t) product, (uint8_t) (product >> 8),
+                (uint8_t) version, (uint8_t) (version >> 8));
+    }
+    else
+    {
+        sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+                name[0], name[1], name[2], name[3],
+                name[4], name[5], name[6], name[7],
+                name[8], name[9], name[10]);
+    }
+
+    CFArrayRef elements =
+        IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone);
+
+    for (i = 0;  i < CFArrayGetCount(elements);  i++)
+    {
+        IOHIDElementRef native = (IOHIDElementRef)
+            CFArrayGetValueAtIndex(elements, i);
+        if (CFGetTypeID(native) != IOHIDElementGetTypeID())
+            continue;
+
+        const IOHIDElementType type = IOHIDElementGetType(native);
+        if ((type != kIOHIDElementTypeInput_Axis) &&
+            (type != kIOHIDElementTypeInput_Button) &&
+            (type != kIOHIDElementTypeInput_Misc))
+        {
+            continue;
+        }
+
+        CFMutableArrayRef target = NULL;
+
+        const uint32_t usage = IOHIDElementGetUsage(native);
+        const uint32_t page = IOHIDElementGetUsagePage(native);
+        if (page == 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:
+                    target = axes;
+                    break;
+                case kHIDUsage_GD_Hatswitch:
+                    target = hats;
+                    break;
+                case kHIDUsage_GD_DPadUp:
+                case kHIDUsage_GD_DPadRight:
+                case kHIDUsage_GD_DPadDown:
+                case kHIDUsage_GD_DPadLeft:
+                case kHIDUsage_GD_SystemMainMenu:
+                case kHIDUsage_GD_Select:
+                case kHIDUsage_GD_Start:
+                    target = buttons;
+                    break;
+            }
+        }
+        else if (page == kHIDPage_Simulation)
+        {
+            switch (usage)
+            {
+                case kHIDUsage_Sim_Accelerator:
+                case kHIDUsage_Sim_Brake:
+                case kHIDUsage_Sim_Throttle:
+                case kHIDUsage_Sim_Rudder:
+                case kHIDUsage_Sim_Steering:
+                    target = axes;
+                    break;
+            }
+        }
+        else if (page == kHIDPage_Button || page == kHIDPage_Consumer)
+            target = buttons;
+
+        if (target)
+        {
+            _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
+            element->native  = native;
+            element->usage   = usage;
+            element->index   = (int) CFArrayGetCount(target);
+            element->minimum = IOHIDElementGetLogicalMin(native);
+            element->maximum = IOHIDElementGetLogicalMax(native);
+            CFArrayAppendValue(target, element);
+        }
+    }
+
+    CFRelease(elements);
+
+    CFArraySortValues(axes, CFRangeMake(0, CFArrayGetCount(axes)),
+                      compareElements, NULL);
+    CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)),
+                      compareElements, NULL);
+    CFArraySortValues(hats, CFRangeMake(0, CFArrayGetCount(hats)),
+                      compareElements, NULL);
+
+    js = _glfwAllocJoystick(name, guid,
+                            (int) CFArrayGetCount(axes),
+                            (int) CFArrayGetCount(buttons),
+                            (int) CFArrayGetCount(hats));
+
+    js->ns.device  = device;
+    js->ns.axes    = axes;
+    js->ns.buttons = buttons;
+    js->ns.hats    = hats;
+
+    _glfwInputJoystick(js, GLFW_CONNECTED);
+}
+
+// Callback for user-initiated joystick removal
+//
+static void removeCallback(void* context,
+                           IOReturn result,
+                           void* sender,
+                           IOHIDDeviceRef device)
+{
+    int jid;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        if (_glfw.joysticks[jid].ns.device == device)
+        {
+            closeJoystick(_glfw.joysticks + jid);
+            break;
+        }
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksNS(void)
+{
+    CFMutableArrayRef matching;
+    const long usages[] =
+    {
+        kHIDUsage_GD_Joystick,
+        kHIDUsage_GD_GamePad,
+        kHIDUsage_GD_MultiAxisController
+    };
+
+    _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
+                                             kIOHIDOptionsTypeNone);
+
+    matching = CFArrayCreateMutable(kCFAllocatorDefault,
+                                    0,
+                                    &kCFTypeArrayCallBacks);
+    if (!matching)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array");
+        return;
+    }
+
+    for (size_t i = 0;  i < sizeof(usages) / sizeof(long);  i++)
+    {
+        const long page = kHIDPage_GenericDesktop;
+
+        CFMutableDictionaryRef dict =
+            CFDictionaryCreateMutable(kCFAllocatorDefault,
+                                      0,
+                                      &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks);
+        if (!dict)
+            continue;
+
+        CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
+                                             kCFNumberLongType,
+                                             &page);
+        CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
+                                              kCFNumberLongType,
+                                              &usages[i]);
+        if (pageRef && usageRef)
+        {
+            CFDictionarySetValue(dict,
+                                 CFSTR(kIOHIDDeviceUsagePageKey),
+                                 pageRef);
+            CFDictionarySetValue(dict,
+                                 CFSTR(kIOHIDDeviceUsageKey),
+                                 usageRef);
+            CFArrayAppendValue(matching, dict);
+        }
+
+        if (pageRef)
+            CFRelease(pageRef);
+        if (usageRef)
+            CFRelease(usageRef);
+
+        CFRelease(dict);
+    }
+
+    IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager, matching);
+    CFRelease(matching);
+
+    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 jid;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+        closeJoystick(_glfw.joysticks + jid);
+
+    CFRelease(_glfw.ns.hidManager);
+    _glfw.ns.hidManager = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+    if (mode & _GLFW_POLL_AXES)
+    {
+        CFIndex i;
+
+        for (i = 0;  i < CFArrayGetCount(js->ns.axes);  i++)
+        {
+            _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
+                CFArrayGetValueAtIndex(js->ns.axes, i);
+
+            const long raw = getElementValue(js, axis);
+            // Perform auto calibration
+            if (raw < axis->minimum)
+                axis->minimum = raw;
+            if (raw > axis->maximum)
+                axis->maximum = raw;
+
+            const long size = axis->maximum - axis->minimum;
+            if (size == 0)
+                _glfwInputJoystickAxis(js, (int) i, 0.f);
+            else
+            {
+                const float value = (2.f * (raw - axis->minimum) / size) - 1.f;
+                _glfwInputJoystickAxis(js, (int) i, value);
+            }
+        }
+    }
+
+    if (mode & _GLFW_POLL_BUTTONS)
+    {
+        CFIndex i;
+
+        for (i = 0;  i < CFArrayGetCount(js->ns.buttons);  i++)
+        {
+            _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
+                CFArrayGetValueAtIndex(js->ns.buttons, i);
+            const char value = getElementValue(js, button) - button->minimum;
+            const int state = (value > 0) ? GLFW_PRESS : GLFW_RELEASE;
+            _glfwInputJoystickButton(js, (int) i, state);
+        }
+
+        for (i = 0;  i < CFArrayGetCount(js->ns.hats);  i++)
+        {
+            const int states[9] =
+            {
+                GLFW_HAT_UP,
+                GLFW_HAT_RIGHT_UP,
+                GLFW_HAT_RIGHT,
+                GLFW_HAT_RIGHT_DOWN,
+                GLFW_HAT_DOWN,
+                GLFW_HAT_LEFT_DOWN,
+                GLFW_HAT_LEFT,
+                GLFW_HAT_LEFT_UP,
+                GLFW_HAT_CENTERED
+            };
+
+            _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
+                CFArrayGetValueAtIndex(js->ns.hats, i);
+            long state = getElementValue(js, hat) - hat->minimum;
+            if (state < 0 || state > 8)
+                state = 8;
+
+            _glfwInputJoystickHat(js, (int) i, states[state]);
+        }
+    }
+
+    return js->present;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+    if ((strncmp(guid + 4, "000000000000", 12) == 0) &&
+        (strncmp(guid + 20, "000000000000", 12) == 0))
+    {
+        char original[33];
+        strncpy(original, guid, sizeof(original) - 1);
+        sprintf(guid, "03000000%.4s0000%.4s000000000000",
+                original, original + 16);
+    }
+}
+
diff --git a/glfw/src/cocoa_monitor.m b/glfw/src/cocoa_monitor.m
--- a/glfw/src/cocoa_monitor.m
+++ b/glfw/src/cocoa_monitor.m
@@ -1,612 +1,612 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <limits.h>
-#include <math.h>
-
-#include <IOKit/graphics/IOGraphicsLib.h>
-#include <ApplicationServices/ApplicationServices.h>
-
-
-// Get the name of the specified display, or NULL
-//
-static char* getDisplayName(CGDirectDisplayID displayID)
-{
-    io_iterator_t it;
-    io_service_t service;
-    CFDictionaryRef info;
-
-    if (IOServiceGetMatchingServices(kIOMasterPortDefault,
-                                     IOServiceMatching("IODisplayConnect"),
-                                     &it) != 0)
-    {
-        // This may happen if a desktop Mac is running headless
-        return NULL;
-    }
-
-    while ((service = IOIteratorNext(it)) != 0)
-    {
-        info = IODisplayCreateInfoDictionary(service,
-                                             kIODisplayOnlyPreferredName);
-
-        CFNumberRef vendorIDRef =
-            CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
-        CFNumberRef productIDRef =
-            CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
-        if (!vendorIDRef || !productIDRef)
-        {
-            CFRelease(info);
-            continue;
-        }
-
-        unsigned int vendorID, productID;
-        CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
-        CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
-
-        if (CGDisplayVendorNumber(displayID) == vendorID &&
-            CGDisplayModelNumber(displayID) == productID)
-        {
-            // Info dictionary is used and freed below
-            break;
-        }
-
-        CFRelease(info);
-    }
-
-    IOObjectRelease(it);
-
-    if (!service)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to find service port for display");
-        return NULL;
-    }
-
-    CFDictionaryRef names =
-        CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
-
-    CFStringRef nameRef;
-
-    if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
-                                                 (const void**) &nameRef))
-    {
-        // This may happen if a desktop Mac is running headless
-        CFRelease(info);
-        return NULL;
-    }
-
-    const CFIndex size =
-        CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
-                                          kCFStringEncodingUTF8);
-    char* name = calloc(size + 1, 1);
-    CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
-
-    CFRelease(info);
-    return name;
-}
-
-// Check whether the display mode should be included in enumeration
-//
-static GLFWbool modeIsGood(CGDisplayModeRef mode)
-{
-    uint32_t flags = CGDisplayModeGetIOFlags(mode);
-
-    if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
-        return GLFW_FALSE;
-    if (flags & kDisplayModeInterlacedFlag)
-        return GLFW_FALSE;
-    if (flags & kDisplayModeStretchedFlag)
-        return GLFW_FALSE;
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
-    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
-    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
-        CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
-    {
-        CFRelease(format);
-        return GLFW_FALSE;
-    }
-
-    CFRelease(format);
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
-    return GLFW_TRUE;
-}
-
-// Convert Core Graphics display mode to GLFW video mode
-//
-static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
-                                            double fallbackRefreshRate)
-{
-    GLFWvidmode result;
-    result.width = (int) CGDisplayModeGetWidth(mode);
-    result.height = (int) CGDisplayModeGetHeight(mode);
-    result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
-
-    if (result.refreshRate == 0)
-        result.refreshRate = (int) round(fallbackRefreshRate);
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
-    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
-    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
-    {
-        result.redBits = 5;
-        result.greenBits = 5;
-        result.blueBits = 5;
-    }
-    else
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
-    {
-        result.redBits = 8;
-        result.greenBits = 8;
-        result.blueBits = 8;
-    }
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
-    CFRelease(format);
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
-    return result;
-}
-
-// Starts reservation for display fading
-//
-static CGDisplayFadeReservationToken beginFadeReservation(void)
-{
-    CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
-
-    if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
-    {
-        CGDisplayFade(token, 0.3,
-                      kCGDisplayBlendNormal,
-                      kCGDisplayBlendSolidColor,
-                      0.0, 0.0, 0.0,
-                      TRUE);
-    }
-
-    return token;
-}
-
-// Ends reservation for display fading
-//
-static void endFadeReservation(CGDisplayFadeReservationToken token)
-{
-    if (token != kCGDisplayFadeReservationInvalidToken)
-    {
-        CGDisplayFade(token, 0.5,
-                      kCGDisplayBlendSolidColor,
-                      kCGDisplayBlendNormal,
-                      0.0, 0.0, 0.0,
-                      FALSE);
-        CGReleaseDisplayFadeReservation(token);
-    }
-}
-
-// Finds and caches the NSScreen corresponding to the specified monitor
-//
-static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)
-{
-    if (monitor->ns.screen)
-        return GLFW_TRUE;
-
-    for (NSScreen* screen in [NSScreen screens])
-    {
-        NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"];
-
-        // HACK: Compare unit numbers instead of display IDs to work around
-        //       display replacement on machines with automatic graphics
-        //       switching
-        if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue]))
-        {
-            monitor->ns.screen = screen;
-            return GLFW_TRUE;
-        }
-    }
-
-    _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor");
-    return GLFW_FALSE;
-}
-
-// Returns the display refresh rate queried from the I/O registry
-//
-static double getFallbackRefreshRate(CGDirectDisplayID displayID)
-{
-    double refreshRate = 60.0;
-
-    io_iterator_t it;
-    io_service_t service;
-
-    if (IOServiceGetMatchingServices(kIOMasterPortDefault,
-                                     IOServiceMatching("IOFramebuffer"),
-                                     &it) != 0)
-    {
-        return refreshRate;
-    }
-
-    while ((service = IOIteratorNext(it)) != 0)
-    {
-        const CFNumberRef indexRef =
-            IORegistryEntryCreateCFProperty(service,
-                                            CFSTR("IOFramebufferOpenGLIndex"),
-                                            kCFAllocatorDefault,
-                                            kNilOptions);
-        if (!indexRef)
-            continue;
-
-        uint32_t index = 0;
-        CFNumberGetValue(indexRef, kCFNumberIntType, &index);
-        CFRelease(indexRef);
-
-        if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID)
-            continue;
-
-        const CFNumberRef clockRef =
-            IORegistryEntryCreateCFProperty(service,
-                                            CFSTR("IOFBCurrentPixelClock"),
-                                            kCFAllocatorDefault,
-                                            kNilOptions);
-        const CFNumberRef countRef =
-            IORegistryEntryCreateCFProperty(service,
-                                            CFSTR("IOFBCurrentPixelCount"),
-                                            kCFAllocatorDefault,
-                                            kNilOptions);
-        if (!clockRef || !countRef)
-            break;
-
-        uint32_t clock = 0, count = 0;
-        CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
-        CFNumberGetValue(countRef, kCFNumberIntType, &count);
-        CFRelease(clockRef);
-        CFRelease(countRef);
-
-        if (clock > 0 && count > 0)
-            refreshRate = clock / (double) count;
-
-        break;
-    }
-
-    IOObjectRelease(it);
-    return refreshRate;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Poll for changes in the set of connected monitors
-//
-void _glfwPollMonitorsNS(void)
-{
-    uint32_t displayCount;
-    CGGetOnlineDisplayList(0, NULL, &displayCount);
-    CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
-    CGGetOnlineDisplayList(displayCount, displays, &displayCount);
-
-    for (int i = 0;  i < _glfw.monitorCount;  i++)
-        _glfw.monitors[i]->ns.screen = nil;
-
-    _GLFWmonitor** disconnected = NULL;
-    uint32_t disconnectedCount = _glfw.monitorCount;
-    if (disconnectedCount)
-    {
-        disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
-        memcpy(disconnected,
-               _glfw.monitors,
-               _glfw.monitorCount * sizeof(_GLFWmonitor*));
-    }
-
-    for (uint32_t i = 0;  i < displayCount;  i++)
-    {
-        if (CGDisplayIsAsleep(displays[i]))
-            continue;
-
-        // HACK: Compare unit numbers instead of display IDs to work around
-        //       display replacement on machines with automatic graphics
-        //       switching
-        const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
-        for (uint32_t j = 0;  j < disconnectedCount;  j++)
-        {
-            if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
-            {
-                disconnected[j] = NULL;
-                break;
-            }
-        }
-
-        const CGSize size = CGDisplayScreenSize(displays[i]);
-        char* name = getDisplayName(displays[i]);
-        if (!name)
-            name = _glfw_strdup("Unknown");
-
-        _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
-        monitor->ns.displayID  = displays[i];
-        monitor->ns.unitNumber = unitNumber;
-
-        free(name);
-
-        CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
-        if (CGDisplayModeGetRefreshRate(mode) == 0.0)
-            monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]);
-        CGDisplayModeRelease(mode);
-
-        _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
-    }
-
-    for (uint32_t i = 0;  i < disconnectedCount;  i++)
-    {
-        if (disconnected[i])
-            _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
-    }
-
-    free(disconnected);
-    free(displays);
-}
-
-// Change the current video mode
-//
-void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
-{
-    GLFWvidmode current;
-    _glfwPlatformGetVideoMode(monitor, &current);
-
-    const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
-    if (_glfwCompareVideoModes(&current, best) == 0)
-        return;
-
-    CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
-    const CFIndex count = CFArrayGetCount(modes);
-    CGDisplayModeRef native = NULL;
-
-    for (CFIndex i = 0;  i < count;  i++)
-    {
-        CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
-        if (!modeIsGood(dm))
-            continue;
-
-        const GLFWvidmode mode =
-            vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
-        if (_glfwCompareVideoModes(best, &mode) == 0)
-        {
-            native = dm;
-            break;
-        }
-    }
-
-    if (native)
-    {
-        if (monitor->ns.previousMode == NULL)
-            monitor->ns.previousMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
-
-        CGDisplayFadeReservationToken token = beginFadeReservation();
-        CGDisplaySetDisplayMode(monitor->ns.displayID, native, NULL);
-        endFadeReservation(token);
-    }
-
-    CFRelease(modes);
-}
-
-// Restore the previously saved (original) video mode
-//
-void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
-{
-    if (monitor->ns.previousMode)
-    {
-        CGDisplayFadeReservationToken token = beginFadeReservation();
-        CGDisplaySetDisplayMode(monitor->ns.displayID,
-                                monitor->ns.previousMode, NULL);
-        endFadeReservation(token);
-
-        CGDisplayModeRelease(monitor->ns.previousMode);
-        monitor->ns.previousMode = NULL;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
-{
-}
-
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
-{
-    @autoreleasepool {
-
-    const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
-
-    if (xpos)
-        *xpos = (int) bounds.origin.x;
-    if (ypos)
-        *ypos = (int) bounds.origin.y;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale)
-{
-    @autoreleasepool {
-
-    if (!refreshMonitorScreen(monitor))
-        return;
-
-    const NSRect points = [monitor->ns.screen frame];
-    const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
-
-    if (xscale)
-        *xscale = (float) (pixels.size.width / points.size.width);
-    if (yscale)
-        *yscale = (float) (pixels.size.height / points.size.height);
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
-                                     int* xpos, int* ypos,
-                                     int* width, int* height)
-{
-    @autoreleasepool {
-
-    if (!refreshMonitorScreen(monitor))
-        return;
-
-    const NSRect frameRect = [monitor->ns.screen visibleFrame];
-
-    if (xpos)
-        *xpos = frameRect.origin.x;
-    if (ypos)
-        *ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
-    if (width)
-        *width = frameRect.size.width;
-    if (height)
-        *height = frameRect.size.height;
-
-    } // autoreleasepool
-}
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
-{
-    @autoreleasepool {
-
-    *count = 0;
-
-    CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
-    const CFIndex found = CFArrayGetCount(modes);
-    GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
-
-    for (CFIndex i = 0;  i < found;  i++)
-    {
-        CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
-        if (!modeIsGood(dm))
-            continue;
-
-        const GLFWvidmode mode =
-            vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
-        CFIndex j;
-
-        for (j = 0;  j < *count;  j++)
-        {
-            if (_glfwCompareVideoModes(result + j, &mode) == 0)
-                break;
-        }
-
-        // Skip duplicate modes
-        if (i < *count)
-            continue;
-
-        (*count)++;
-        result[*count - 1] = mode;
-    }
-
-    CFRelease(modes);
-    return result;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
-{
-    @autoreleasepool {
-
-    CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
-    *mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
-    CGDisplayModeRelease(native);
-
-    } // autoreleasepool
-}
-
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
-{
-    @autoreleasepool {
-
-    uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
-    CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
-
-    CGGetDisplayTransferByTable(monitor->ns.displayID,
-                                size,
-                                values,
-                                values + size,
-                                values + size * 2,
-                                &size);
-
-    _glfwAllocGammaArrays(ramp, size);
-
-    for (uint32_t i = 0; i < size; i++)
-    {
-        ramp->red[i]   = (unsigned short) (values[i] * 65535);
-        ramp->green[i] = (unsigned short) (values[i + size] * 65535);
-        ramp->blue[i]  = (unsigned short) (values[i + size * 2] * 65535);
-    }
-
-    free(values);
-    return GLFW_TRUE;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
-{
-    @autoreleasepool {
-
-    CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
-
-    for (unsigned int i = 0;  i < ramp->size;  i++)
-    {
-        values[i]                  = ramp->red[i] / 65535.f;
-        values[i + ramp->size]     = ramp->green[i] / 65535.f;
-        values[i + ramp->size * 2] = ramp->blue[i] / 65535.f;
-    }
-
-    CGSetDisplayTransferByTable(monitor->ns.displayID,
-                                ramp->size,
-                                values,
-                                values + ramp->size,
-                                values + ramp->size * 2);
-
-    free(values);
-
-    } // autoreleasepool
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
-    return monitor->ns.displayID;
-}
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <math.h>
+
+#include <IOKit/graphics/IOGraphicsLib.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+
+// Get the name of the specified display, or NULL
+//
+static char* getDisplayName(CGDirectDisplayID displayID)
+{
+    io_iterator_t it;
+    io_service_t service;
+    CFDictionaryRef info;
+
+    if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+                                     IOServiceMatching("IODisplayConnect"),
+                                     &it) != 0)
+    {
+        // This may happen if a desktop Mac is running headless
+        return NULL;
+    }
+
+    while ((service = IOIteratorNext(it)) != 0)
+    {
+        info = IODisplayCreateInfoDictionary(service,
+                                             kIODisplayOnlyPreferredName);
+
+        CFNumberRef vendorIDRef =
+            CFDictionaryGetValue(info, CFSTR(kDisplayVendorID));
+        CFNumberRef productIDRef =
+            CFDictionaryGetValue(info, CFSTR(kDisplayProductID));
+        if (!vendorIDRef || !productIDRef)
+        {
+            CFRelease(info);
+            continue;
+        }
+
+        unsigned int vendorID, productID;
+        CFNumberGetValue(vendorIDRef, kCFNumberIntType, &vendorID);
+        CFNumberGetValue(productIDRef, kCFNumberIntType, &productID);
+
+        if (CGDisplayVendorNumber(displayID) == vendorID &&
+            CGDisplayModelNumber(displayID) == productID)
+        {
+            // Info dictionary is used and freed below
+            break;
+        }
+
+        CFRelease(info);
+    }
+
+    IOObjectRelease(it);
+
+    if (!service)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to find service port for display");
+        return NULL;
+    }
+
+    CFDictionaryRef names =
+        CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
+
+    CFStringRef nameRef;
+
+    if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
+                                                 (const void**) &nameRef))
+    {
+        // This may happen if a desktop Mac is running headless
+        CFRelease(info);
+        return NULL;
+    }
+
+    const CFIndex size =
+        CFStringGetMaximumSizeForEncoding(CFStringGetLength(nameRef),
+                                          kCFStringEncodingUTF8);
+    char* name = calloc(size + 1, 1);
+    CFStringGetCString(nameRef, name, size, kCFStringEncodingUTF8);
+
+    CFRelease(info);
+    return name;
+}
+
+// Check whether the display mode should be included in enumeration
+//
+static GLFWbool modeIsGood(CGDisplayModeRef mode)
+{
+    uint32_t flags = CGDisplayModeGetIOFlags(mode);
+
+    if (!(flags & kDisplayModeValidFlag) || !(flags & kDisplayModeSafeFlag))
+        return GLFW_FALSE;
+    if (flags & kDisplayModeInterlacedFlag)
+        return GLFW_FALSE;
+    if (flags & kDisplayModeStretchedFlag)
+        return GLFW_FALSE;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
+        CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
+    {
+        CFRelease(format);
+        return GLFW_FALSE;
+    }
+
+    CFRelease(format);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+    return GLFW_TRUE;
+}
+
+// Convert Core Graphics display mode to GLFW video mode
+//
+static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
+                                            double fallbackRefreshRate)
+{
+    GLFWvidmode result;
+    result.width = (int) CGDisplayModeGetWidth(mode);
+    result.height = (int) CGDisplayModeGetHeight(mode);
+    result.refreshRate = (int) round(CGDisplayModeGetRefreshRate(mode));
+
+    if (result.refreshRate == 0)
+        result.refreshRate = (int) round(fallbackRefreshRate);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+    CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+    if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
+    {
+        result.redBits = 5;
+        result.greenBits = 5;
+        result.blueBits = 5;
+    }
+    else
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+    {
+        result.redBits = 8;
+        result.greenBits = 8;
+        result.blueBits = 8;
+    }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= 101100
+    CFRelease(format);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED */
+    return result;
+}
+
+// Starts reservation for display fading
+//
+static CGDisplayFadeReservationToken beginFadeReservation(void)
+{
+    CGDisplayFadeReservationToken token = kCGDisplayFadeReservationInvalidToken;
+
+    if (CGAcquireDisplayFadeReservation(5, &token) == kCGErrorSuccess)
+    {
+        CGDisplayFade(token, 0.3,
+                      kCGDisplayBlendNormal,
+                      kCGDisplayBlendSolidColor,
+                      0.0, 0.0, 0.0,
+                      TRUE);
+    }
+
+    return token;
+}
+
+// Ends reservation for display fading
+//
+static void endFadeReservation(CGDisplayFadeReservationToken token)
+{
+    if (token != kCGDisplayFadeReservationInvalidToken)
+    {
+        CGDisplayFade(token, 0.5,
+                      kCGDisplayBlendSolidColor,
+                      kCGDisplayBlendNormal,
+                      0.0, 0.0, 0.0,
+                      FALSE);
+        CGReleaseDisplayFadeReservation(token);
+    }
+}
+
+// Finds and caches the NSScreen corresponding to the specified monitor
+//
+static GLFWbool refreshMonitorScreen(_GLFWmonitor* monitor)
+{
+    if (monitor->ns.screen)
+        return GLFW_TRUE;
+
+    for (NSScreen* screen in [NSScreen screens])
+    {
+        NSNumber* displayID = [screen deviceDescription][@"NSScreenNumber"];
+
+        // HACK: Compare unit numbers instead of display IDs to work around
+        //       display replacement on machines with automatic graphics
+        //       switching
+        if (monitor->ns.unitNumber == CGDisplayUnitNumber([displayID unsignedIntValue]))
+        {
+            monitor->ns.screen = screen;
+            return GLFW_TRUE;
+        }
+    }
+
+    _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to find a screen for monitor");
+    return GLFW_FALSE;
+}
+
+// Returns the display refresh rate queried from the I/O registry
+//
+static double getFallbackRefreshRate(CGDirectDisplayID displayID)
+{
+    double refreshRate = 60.0;
+
+    io_iterator_t it;
+    io_service_t service;
+
+    if (IOServiceGetMatchingServices(kIOMasterPortDefault,
+                                     IOServiceMatching("IOFramebuffer"),
+                                     &it) != 0)
+    {
+        return refreshRate;
+    }
+
+    while ((service = IOIteratorNext(it)) != 0)
+    {
+        const CFNumberRef indexRef =
+            IORegistryEntryCreateCFProperty(service,
+                                            CFSTR("IOFramebufferOpenGLIndex"),
+                                            kCFAllocatorDefault,
+                                            kNilOptions);
+        if (!indexRef)
+            continue;
+
+        uint32_t index = 0;
+        CFNumberGetValue(indexRef, kCFNumberIntType, &index);
+        CFRelease(indexRef);
+
+        if (CGOpenGLDisplayMaskToDisplayID(1 << index) != displayID)
+            continue;
+
+        const CFNumberRef clockRef =
+            IORegistryEntryCreateCFProperty(service,
+                                            CFSTR("IOFBCurrentPixelClock"),
+                                            kCFAllocatorDefault,
+                                            kNilOptions);
+        const CFNumberRef countRef =
+            IORegistryEntryCreateCFProperty(service,
+                                            CFSTR("IOFBCurrentPixelCount"),
+                                            kCFAllocatorDefault,
+                                            kNilOptions);
+        if (!clockRef || !countRef)
+            break;
+
+        uint32_t clock = 0, count = 0;
+        CFNumberGetValue(clockRef, kCFNumberIntType, &clock);
+        CFNumberGetValue(countRef, kCFNumberIntType, &count);
+        CFRelease(clockRef);
+        CFRelease(countRef);
+
+        if (clock > 0 && count > 0)
+            refreshRate = clock / (double) count;
+
+        break;
+    }
+
+    IOObjectRelease(it);
+    return refreshRate;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsNS(void)
+{
+    uint32_t displayCount;
+    CGGetOnlineDisplayList(0, NULL, &displayCount);
+    CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
+    CGGetOnlineDisplayList(displayCount, displays, &displayCount);
+
+    for (int i = 0;  i < _glfw.monitorCount;  i++)
+        _glfw.monitors[i]->ns.screen = nil;
+
+    _GLFWmonitor** disconnected = NULL;
+    uint32_t disconnectedCount = _glfw.monitorCount;
+    if (disconnectedCount)
+    {
+        disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+        memcpy(disconnected,
+               _glfw.monitors,
+               _glfw.monitorCount * sizeof(_GLFWmonitor*));
+    }
+
+    for (uint32_t i = 0;  i < displayCount;  i++)
+    {
+        if (CGDisplayIsAsleep(displays[i]))
+            continue;
+
+        // HACK: Compare unit numbers instead of display IDs to work around
+        //       display replacement on machines with automatic graphics
+        //       switching
+        const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
+        for (uint32_t j = 0;  j < disconnectedCount;  j++)
+        {
+            if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
+            {
+                disconnected[j] = NULL;
+                break;
+            }
+        }
+
+        const CGSize size = CGDisplayScreenSize(displays[i]);
+        char* name = getDisplayName(displays[i]);
+        if (!name)
+            name = _glfw_strdup("Unknown");
+
+        _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
+        monitor->ns.displayID  = displays[i];
+        monitor->ns.unitNumber = unitNumber;
+
+        free(name);
+
+        CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displays[i]);
+        if (CGDisplayModeGetRefreshRate(mode) == 0.0)
+            monitor->ns.fallbackRefreshRate = getFallbackRefreshRate(displays[i]);
+        CGDisplayModeRelease(mode);
+
+        _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
+    }
+
+    for (uint32_t i = 0;  i < disconnectedCount;  i++)
+    {
+        if (disconnected[i])
+            _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+    }
+
+    free(disconnected);
+    free(displays);
+}
+
+// Change the current video mode
+//
+void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+    GLFWvidmode current;
+    _glfwPlatformGetVideoMode(monitor, &current);
+
+    const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
+    if (_glfwCompareVideoModes(&current, best) == 0)
+        return;
+
+    CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+    const CFIndex count = CFArrayGetCount(modes);
+    CGDisplayModeRef native = NULL;
+
+    for (CFIndex i = 0;  i < count;  i++)
+    {
+        CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+        if (!modeIsGood(dm))
+            continue;
+
+        const GLFWvidmode mode =
+            vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
+        if (_glfwCompareVideoModes(best, &mode) == 0)
+        {
+            native = dm;
+            break;
+        }
+    }
+
+    if (native)
+    {
+        if (monitor->ns.previousMode == NULL)
+            monitor->ns.previousMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
+
+        CGDisplayFadeReservationToken token = beginFadeReservation();
+        CGDisplaySetDisplayMode(monitor->ns.displayID, native, NULL);
+        endFadeReservation(token);
+    }
+
+    CFRelease(modes);
+}
+
+// Restore the previously saved (original) video mode
+//
+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
+{
+    if (monitor->ns.previousMode)
+    {
+        CGDisplayFadeReservationToken token = beginFadeReservation();
+        CGDisplaySetDisplayMode(monitor->ns.displayID,
+                                monitor->ns.previousMode, NULL);
+        endFadeReservation(token);
+
+        CGDisplayModeRelease(monitor->ns.previousMode);
+        monitor->ns.previousMode = NULL;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+    @autoreleasepool {
+
+    const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
+
+    if (xpos)
+        *xpos = (int) bounds.origin.x;
+    if (ypos)
+        *ypos = (int) bounds.origin.y;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale)
+{
+    @autoreleasepool {
+
+    if (!refreshMonitorScreen(monitor))
+        return;
+
+    const NSRect points = [monitor->ns.screen frame];
+    const NSRect pixels = [monitor->ns.screen convertRectToBacking:points];
+
+    if (xscale)
+        *xscale = (float) (pixels.size.width / points.size.width);
+    if (yscale)
+        *yscale = (float) (pixels.size.height / points.size.height);
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
+                                     int* xpos, int* ypos,
+                                     int* width, int* height)
+{
+    @autoreleasepool {
+
+    if (!refreshMonitorScreen(monitor))
+        return;
+
+    const NSRect frameRect = [monitor->ns.screen visibleFrame];
+
+    if (xpos)
+        *xpos = frameRect.origin.x;
+    if (ypos)
+        *ypos = _glfwTransformYNS(frameRect.origin.y + frameRect.size.height - 1);
+    if (width)
+        *width = frameRect.size.width;
+    if (height)
+        *height = frameRect.size.height;
+
+    } // autoreleasepool
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+    @autoreleasepool {
+
+    *count = 0;
+
+    CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+    const CFIndex found = CFArrayGetCount(modes);
+    GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
+
+    for (CFIndex i = 0;  i < found;  i++)
+    {
+        CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+        if (!modeIsGood(dm))
+            continue;
+
+        const GLFWvidmode mode =
+            vidmodeFromCGDisplayMode(dm, monitor->ns.fallbackRefreshRate);
+        CFIndex j;
+
+        for (j = 0;  j < *count;  j++)
+        {
+            if (_glfwCompareVideoModes(result + j, &mode) == 0)
+                break;
+        }
+
+        // Skip duplicate modes
+        if (i < *count)
+            continue;
+
+        (*count)++;
+        result[*count - 1] = mode;
+    }
+
+    CFRelease(modes);
+    return result;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
+{
+    @autoreleasepool {
+
+    CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
+    *mode = vidmodeFromCGDisplayMode(native, monitor->ns.fallbackRefreshRate);
+    CGDisplayModeRelease(native);
+
+    } // autoreleasepool
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+    @autoreleasepool {
+
+    uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
+    CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
+
+    CGGetDisplayTransferByTable(monitor->ns.displayID,
+                                size,
+                                values,
+                                values + size,
+                                values + size * 2,
+                                &size);
+
+    _glfwAllocGammaArrays(ramp, size);
+
+    for (uint32_t i = 0; i < size; i++)
+    {
+        ramp->red[i]   = (unsigned short) (values[i] * 65535);
+        ramp->green[i] = (unsigned short) (values[i + size] * 65535);
+        ramp->blue[i]  = (unsigned short) (values[i + size * 2] * 65535);
+    }
+
+    free(values);
+    return GLFW_TRUE;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+    @autoreleasepool {
+
+    CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
+
+    for (unsigned int i = 0;  i < ramp->size;  i++)
+    {
+        values[i]                  = ramp->red[i] / 65535.f;
+        values[i + ramp->size]     = ramp->green[i] / 65535.f;
+        values[i + ramp->size * 2] = ramp->blue[i] / 65535.f;
+    }
+
+    CGSetDisplayTransferByTable(monitor->ns.displayID,
+                                ramp->size,
+                                values,
+                                values + ramp->size,
+                                values + ramp->size * 2);
+
+    free(values);
+
+    } // autoreleasepool
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(kCGNullDirectDisplay);
+    return monitor->ns.displayID;
+}
+
diff --git a/glfw/src/cocoa_platform.h b/glfw/src/cocoa_platform.h
--- a/glfw/src/cocoa_platform.h
+++ b/glfw/src/cocoa_platform.h
@@ -1,199 +1,211 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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 <stdint.h>
-#include <dlfcn.h>
-
-#include <Carbon/Carbon.h>
-
-// NOTE: All of NSGL was deprecated in the 10.14 SDK
-//       This disables the pointless warnings for every symbol we use
-#define GL_SILENCE_DEPRECATION
-
-#if defined(__OBJC__)
-#import <Cocoa/Cocoa.h>
-#else
-typedef void* id;
-#endif
-
-// NOTE: Many Cocoa enum values have been renamed and we need to build across
-//       SDK versions where one is unavailable or the other deprecated
-//       We use the newer names in code and these macros to handle compatibility
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
- #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
- #define NSEventMaskAny NSAnyEventMask
- #define NSEventMaskKeyUp NSKeyUpMask
- #define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
- #define NSEventModifierFlagCommand NSCommandKeyMask
- #define NSEventModifierFlagControl NSControlKeyMask
- #define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
- #define NSEventModifierFlagOption NSAlternateKeyMask
- #define NSEventModifierFlagShift NSShiftKeyMask
- #define NSEventTypeApplicationDefined NSApplicationDefined
- #define NSWindowStyleMaskBorderless NSBorderlessWindowMask
- #define NSWindowStyleMaskClosable NSClosableWindowMask
- #define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
- #define NSWindowStyleMaskResizable NSResizableWindowMask
- #define NSWindowStyleMaskTitled NSTitledWindowMask
-#endif
-
-typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
-
-typedef struct VkMacOSSurfaceCreateInfoMVK
-{
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkMacOSSurfaceCreateFlagsMVK    flags;
-    const void*                     pView;
-} VkMacOSSurfaceCreateInfoMVK;
-
-typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
-
-#include "posix_thread.h"
-#include "cocoa_joystick.h"
-#include "nsgl_context.h"
-#include "egl_context.h"
-#include "osmesa_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->ns.view)
-#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
-
-#define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowNS  ns
-#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
-#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE  _GLFWtimerNS   ns
-#define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorNS ns
-#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorNS  ns
-
-// HIToolbox.framework pointer typedefs
-#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
-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              view;
-    id              layer;
-
-    GLFWbool        maximized;
-    GLFWbool        retina;
-
-    // Cached window properties to filter out duplicate events
-    int             width, height;
-    int             fbWidth, fbHeight;
-    float           xscale, yscale;
-
-    // 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          cursorWarpDeltaX, cursorWarpDeltaY;
-
-} _GLFWwindowNS;
-
-// Cocoa-specific global data
-//
-typedef struct _GLFWlibraryNS
-{
-    CGEventSourceRef    eventSource;
-    id                  delegate;
-    GLFWbool            finishedLaunching;
-    GLFWbool            cursorHidden;
-    TISInputSourceRef   inputSource;
-    IOHIDManagerRef     hidManager;
-    id                  unicodeData;
-    id                  helper;
-    id                  keyUpMonitor;
-    id                  nibObjects;
-
-    char                keynames[GLFW_KEY_LAST + 1][17];
-    short int           keycodes[256];
-    short int           scancodes[GLFW_KEY_LAST + 1];
-    char*               clipboardString;
-    CGPoint             cascadePoint;
-    // Where to place the cursor when re-enabled
-    double              restoreCursorPosX, restoreCursorPosY;
-    // The window whose disabled cursor mode is active
-    _GLFWwindow*        disabledCursorWindow;
-
-    struct {
-        CFBundleRef     bundle;
-        PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
-        PFN_TISGetInputSourceProperty GetInputSourceProperty;
-        PFN_LMGetKbdType GetKbdType;
-        CFStringRef     kPropertyUnicodeKeyLayoutData;
-    } tis;
-
-} _GLFWlibraryNS;
-
-// Cocoa-specific per-monitor data
-//
-typedef struct _GLFWmonitorNS
-{
-    CGDirectDisplayID   displayID;
-    CGDisplayModeRef    previousMode;
-    uint32_t            unitNumber;
-    id                  screen;
-    double              fallbackRefreshRate;
-
-} _GLFWmonitorNS;
-
-// Cocoa-specific per-cursor data
-//
-typedef struct _GLFWcursorNS
-{
-    id              object;
-
-} _GLFWcursorNS;
-
-// Cocoa-specific global timer data
-//
-typedef struct _GLFWtimerNS
-{
-    uint64_t        frequency;
-
-} _GLFWtimerNS;
-
-
-void _glfwInitTimerNS(void);
-
-void _glfwPollMonitorsNS(void);
-void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
-void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
-
-float _glfwTransformYNS(float y);
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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 <stdint.h>
+#include <dlfcn.h>
+
+#include <Carbon/Carbon.h>
+
+// NOTE: All of NSGL was deprecated in the 10.14 SDK
+//       This disables the pointless warnings for every symbol we use
+#define GL_SILENCE_DEPRECATION
+
+#if defined(__OBJC__)
+#import <Cocoa/Cocoa.h>
+#else
+typedef void* id;
+#endif
+
+// NOTE: Many Cocoa enum values have been renamed and we need to build across
+//       SDK versions where one is unavailable or the other deprecated
+//       We use the newer names in code and these macros to handle compatibility
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101200
+ #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat
+ #define NSEventMaskAny NSAnyEventMask
+ #define NSEventMaskKeyUp NSKeyUpMask
+ #define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
+ #define NSEventModifierFlagCommand NSCommandKeyMask
+ #define NSEventModifierFlagControl NSControlKeyMask
+ #define NSEventModifierFlagDeviceIndependentFlagsMask NSDeviceIndependentModifierFlagsMask
+ #define NSEventModifierFlagOption NSAlternateKeyMask
+ #define NSEventModifierFlagShift NSShiftKeyMask
+ #define NSEventTypeApplicationDefined NSApplicationDefined
+ #define NSWindowStyleMaskBorderless NSBorderlessWindowMask
+ #define NSWindowStyleMaskClosable NSClosableWindowMask
+ #define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
+ #define NSWindowStyleMaskResizable NSResizableWindowMask
+ #define NSWindowStyleMaskTitled NSTitledWindowMask
+#endif
+
+typedef VkFlags VkMacOSSurfaceCreateFlagsMVK;
+typedef VkFlags VkMetalSurfaceCreateFlagsEXT;
+
+typedef struct VkMacOSSurfaceCreateInfoMVK
+{
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkMacOSSurfaceCreateFlagsMVK    flags;
+    const void*                     pView;
+} VkMacOSSurfaceCreateInfoMVK;
+
+typedef struct VkMetalSurfaceCreateInfoEXT
+{
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkMetalSurfaceCreateFlagsEXT    flags;
+    const void*                     pLayer;
+} VkMetalSurfaceCreateInfoEXT;
+
+typedef VkResult (APIENTRY *PFN_vkCreateMacOSSurfaceMVK)(VkInstance,const VkMacOSSurfaceCreateInfoMVK*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkResult (APIENTRY *PFN_vkCreateMetalSurfaceEXT)(VkInstance,const VkMetalSurfaceCreateInfoEXT*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+
+#include "posix_thread.h"
+#include "cocoa_joystick.h"
+#include "nsgl_context.h"
+#include "egl_context.h"
+#include "osmesa_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->ns.view)
+#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
+
+#define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowNS  ns
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
+#define _GLFW_PLATFORM_LIBRARY_TIMER_STATE  _GLFWtimerNS   ns
+#define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorNS ns
+#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorNS  ns
+
+// HIToolbox.framework pointer typedefs
+#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
+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              view;
+    id              layer;
+
+    GLFWbool        maximized;
+    GLFWbool        retina;
+
+    // Cached window properties to filter out duplicate events
+    int             width, height;
+    int             fbWidth, fbHeight;
+    float           xscale, yscale;
+
+    // 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          cursorWarpDeltaX, cursorWarpDeltaY;
+
+} _GLFWwindowNS;
+
+// Cocoa-specific global data
+//
+typedef struct _GLFWlibraryNS
+{
+    CGEventSourceRef    eventSource;
+    id                  delegate;
+    GLFWbool            finishedLaunching;
+    GLFWbool            cursorHidden;
+    TISInputSourceRef   inputSource;
+    IOHIDManagerRef     hidManager;
+    id                  unicodeData;
+    id                  helper;
+    id                  keyUpMonitor;
+    id                  nibObjects;
+
+    char                keynames[GLFW_KEY_LAST + 1][17];
+    short int           keycodes[256];
+    short int           scancodes[GLFW_KEY_LAST + 1];
+    char*               clipboardString;
+    CGPoint             cascadePoint;
+    // Where to place the cursor when re-enabled
+    double              restoreCursorPosX, restoreCursorPosY;
+    // The window whose disabled cursor mode is active
+    _GLFWwindow*        disabledCursorWindow;
+
+    struct {
+        CFBundleRef     bundle;
+        PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
+        PFN_TISGetInputSourceProperty GetInputSourceProperty;
+        PFN_LMGetKbdType GetKbdType;
+        CFStringRef     kPropertyUnicodeKeyLayoutData;
+    } tis;
+
+} _GLFWlibraryNS;
+
+// Cocoa-specific per-monitor data
+//
+typedef struct _GLFWmonitorNS
+{
+    CGDirectDisplayID   displayID;
+    CGDisplayModeRef    previousMode;
+    uint32_t            unitNumber;
+    id                  screen;
+    double              fallbackRefreshRate;
+
+} _GLFWmonitorNS;
+
+// Cocoa-specific per-cursor data
+//
+typedef struct _GLFWcursorNS
+{
+    id              object;
+
+} _GLFWcursorNS;
+
+// Cocoa-specific global timer data
+//
+typedef struct _GLFWtimerNS
+{
+    uint64_t        frequency;
+
+} _GLFWtimerNS;
+
+
+void _glfwInitTimerNS(void);
+
+void _glfwPollMonitorsNS(void);
+void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
+
+float _glfwTransformYNS(float y);
+
+void* _glfwLoadLocalVulkanLoaderNS(void);
+
diff --git a/glfw/src/cocoa_time.c b/glfw/src/cocoa_time.c
--- a/glfw/src/cocoa_time.c
+++ b/glfw/src/cocoa_time.c
@@ -1,62 +1,62 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2016 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#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.timer.ns.frequency = (info.denom * 1e9) / info.numer;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-uint64_t _glfwPlatformGetTimerValue(void)
-{
-    return mach_absolute_time();
-}
-
-uint64_t _glfwPlatformGetTimerFrequency(void)
-{
-    return _glfw.timer.ns.frequency;
-}
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#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.timer.ns.frequency = (info.denom * 1e9) / info.numer;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+    return mach_absolute_time();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+    return _glfw.timer.ns.frequency;
+}
+
diff --git a/glfw/src/cocoa_window.m b/glfw/src/cocoa_window.m
--- a/glfw/src/cocoa_window.m
+++ b/glfw/src/cocoa_window.m
@@ -1,1783 +1,1820 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <float.h>
-#include <string.h>
-
-// Returns the style mask corresponding to the window settings
-//
-static NSUInteger getStyleMask(_GLFWwindow* window)
-{
-    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
-
-    if (window->monitor || !window->decorated)
-        styleMask |= NSWindowStyleMaskBorderless;
-    else
-    {
-        styleMask |= NSWindowStyleMaskTitled |
-                     NSWindowStyleMaskClosable;
-
-        if (window->resizable)
-            styleMask |= NSWindowStyleMaskResizable;
-    }
-
-    return styleMask;
-}
-
-// Returns whether the cursor is in the content area of the specified window
-//
-static GLFWbool cursorInContentArea(_GLFWwindow* window)
-{
-    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
-    return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
-}
-
-// Hides the cursor if not already hidden
-//
-static void hideCursor(_GLFWwindow* window)
-{
-    if (!_glfw.ns.cursorHidden)
-    {
-        [NSCursor hide];
-        _glfw.ns.cursorHidden = GLFW_TRUE;
-    }
-}
-
-// Shows the cursor if not already shown
-//
-static void showCursor(_GLFWwindow* window)
-{
-    if (_glfw.ns.cursorHidden)
-    {
-        [NSCursor unhide];
-        _glfw.ns.cursorHidden = GLFW_FALSE;
-    }
-}
-
-// Updates the cursor image according to its cursor mode
-//
-static void updateCursorImage(_GLFWwindow* window)
-{
-    if (window->cursorMode == GLFW_CURSOR_NORMAL)
-    {
-        showCursor(window);
-
-        if (window->cursor)
-            [(NSCursor*) window->cursor->ns.object set];
-        else
-            [[NSCursor arrowCursor] set];
-    }
-    else
-        hideCursor(window);
-}
-
-// Apply chosen cursor mode to a focused window
-//
-static void updateCursorMode(_GLFWwindow* window)
-{
-    if (window->cursorMode == GLFW_CURSOR_DISABLED)
-    {
-        _glfw.ns.disabledCursorWindow = window;
-        _glfwPlatformGetCursorPos(window,
-                                  &_glfw.ns.restoreCursorPosX,
-                                  &_glfw.ns.restoreCursorPosY);
-        _glfwCenterCursorInContentArea(window);
-        CGAssociateMouseAndMouseCursorPosition(false);
-    }
-    else if (_glfw.ns.disabledCursorWindow == window)
-    {
-        _glfw.ns.disabledCursorWindow = NULL;
-        CGAssociateMouseAndMouseCursorPosition(true);
-        _glfwPlatformSetCursorPos(window,
-                                  _glfw.ns.restoreCursorPosX,
-                                  _glfw.ns.restoreCursorPosY);
-    }
-
-    if (cursorInContentArea(window))
-        updateCursorImage(window);
-}
-
-// Make the specified window and its video mode active on its monitor
-//
-static void acquireMonitor(_GLFWwindow* window)
-{
-    _glfwSetVideoModeNS(window->monitor, &window->videoMode);
-    const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
-    const NSRect frame = NSMakeRect(bounds.origin.x,
-                                    _glfwTransformYNS(bounds.origin.y + bounds.size.height - 1),
-                                    bounds.size.width,
-                                    bounds.size.height);
-
-    [window->ns.object setFrame:frame display:YES];
-
-    _glfwInputMonitorWindow(window->monitor, window);
-}
-
-// Remove the window and restore the original video mode
-//
-static void releaseMonitor(_GLFWwindow* window)
-{
-    if (window->monitor->window != window)
-        return;
-
-    _glfwInputMonitorWindow(window->monitor, NULL);
-    _glfwRestoreVideoModeNS(window->monitor);
-}
-
-// Translates macOS key modifiers into GLFW ones
-//
-static int translateFlags(NSUInteger flags)
-{
-    int mods = 0;
-
-    if (flags & NSEventModifierFlagShift)
-        mods |= GLFW_MOD_SHIFT;
-    if (flags & NSEventModifierFlagControl)
-        mods |= GLFW_MOD_CONTROL;
-    if (flags & NSEventModifierFlagOption)
-        mods |= GLFW_MOD_ALT;
-    if (flags & NSEventModifierFlagCommand)
-        mods |= GLFW_MOD_SUPER;
-    if (flags & NSEventModifierFlagCapsLock)
-        mods |= GLFW_MOD_CAPS_LOCK;
-
-    return mods;
-}
-
-// Translates a macOS keycode to a GLFW keycode
-//
-static int translateKey(unsigned int key)
-{
-    if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
-        return GLFW_KEY_UNKNOWN;
-
-    return _glfw.ns.keycodes[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 NSEventModifierFlagShift;
-        case GLFW_KEY_LEFT_CONTROL:
-        case GLFW_KEY_RIGHT_CONTROL:
-            return NSEventModifierFlagControl;
-        case GLFW_KEY_LEFT_ALT:
-        case GLFW_KEY_RIGHT_ALT:
-            return NSEventModifierFlagOption;
-        case GLFW_KEY_LEFT_SUPER:
-        case GLFW_KEY_RIGHT_SUPER:
-            return NSEventModifierFlagCommand;
-        case GLFW_KEY_CAPS_LOCK:
-            return NSEventModifierFlagCapsLock;
-    }
-
-    return 0;
-}
-
-// Defines a constant for empty ranges in NSTextInputClient
-//
-static const NSRange kEmptyRange = { NSNotFound, 0 };
-
-
-//------------------------------------------------------------------------
-// Delegate for window related notifications
-//------------------------------------------------------------------------
-
-@interface GLFWWindowDelegate : NSObject
-{
-    _GLFWwindow* window;
-}
-
-- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
-
-@end
-
-@implementation GLFWWindowDelegate
-
-- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
-{
-    self = [super init];
-    if (self != nil)
-        window = initWindow;
-
-    return self;
-}
-
-- (BOOL)windowShouldClose:(id)sender
-{
-    _glfwInputWindowCloseRequest(window);
-    return NO;
-}
-
-- (void)windowDidResize:(NSNotification *)notification
-{
-    if (window->context.client != GLFW_NO_API)
-        [window->context.nsgl.object update];
-
-    if (_glfw.ns.disabledCursorWindow == window)
-        _glfwCenterCursorInContentArea(window);
-
-    const int maximized = [window->ns.object isZoomed];
-    if (window->ns.maximized != maximized)
-    {
-        window->ns.maximized = maximized;
-        _glfwInputWindowMaximize(window, maximized);
-    }
-
-    const NSRect contentRect = [window->ns.view frame];
-    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
-
-    if (fbRect.size.width != window->ns.fbWidth ||
-        fbRect.size.height != window->ns.fbHeight)
-    {
-        window->ns.fbWidth  = fbRect.size.width;
-        window->ns.fbHeight = fbRect.size.height;
-        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
-    }
-
-    if (contentRect.size.width != window->ns.width ||
-        contentRect.size.height != window->ns.height)
-    {
-        window->ns.width  = contentRect.size.width;
-        window->ns.height = contentRect.size.height;
-        _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
-    }
-}
-
-- (void)windowDidMove:(NSNotification *)notification
-{
-    if (window->context.client != GLFW_NO_API)
-        [window->context.nsgl.object update];
-
-    if (_glfw.ns.disabledCursorWindow == window)
-        _glfwCenterCursorInContentArea(window);
-
-    int x, y;
-    _glfwPlatformGetWindowPos(window, &x, &y);
-    _glfwInputWindowPos(window, x, y);
-}
-
-- (void)windowDidMiniaturize:(NSNotification *)notification
-{
-    if (window->monitor)
-        releaseMonitor(window);
-
-    _glfwInputWindowIconify(window, GLFW_TRUE);
-}
-
-- (void)windowDidDeminiaturize:(NSNotification *)notification
-{
-    if (window->monitor)
-        acquireMonitor(window);
-
-    _glfwInputWindowIconify(window, GLFW_FALSE);
-}
-
-- (void)windowDidBecomeKey:(NSNotification *)notification
-{
-    if (_glfw.ns.disabledCursorWindow == window)
-        _glfwCenterCursorInContentArea(window);
-
-    _glfwInputWindowFocus(window, GLFW_TRUE);
-    updateCursorMode(window);
-}
-
-- (void)windowDidResignKey:(NSNotification *)notification
-{
-    if (window->monitor && window->autoIconify)
-        _glfwPlatformIconifyWindow(window);
-
-    _glfwInputWindowFocus(window, GLFW_FALSE);
-}
-
-@end
-
-
-//------------------------------------------------------------------------
-// Content view class for the GLFW window
-//------------------------------------------------------------------------
-
-@interface GLFWContentView : NSView <NSTextInputClient>
-{
-    _GLFWwindow* window;
-    NSTrackingArea* trackingArea;
-    NSMutableAttributedString* markedText;
-}
-
-- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
-
-@end
-
-@implementation GLFWContentView
-
-- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
-{
-    self = [super init];
-    if (self != nil)
-    {
-        window = initWindow;
-        trackingArea = nil;
-        markedText = [[NSMutableAttributedString alloc] init];
-
-        [self updateTrackingAreas];
-        // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
-        //       on 10.7 without having been deprecated yet
-        [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
-    }
-
-    return self;
-}
-
-- (void)dealloc
-{
-    [trackingArea release];
-    [markedText release];
-    [super dealloc];
-}
-
-- (BOOL)isOpaque
-{
-    return [window->ns.object isOpaque];
-}
-
-- (BOOL)canBecomeKeyView
-{
-    return YES;
-}
-
-- (BOOL)acceptsFirstResponder
-{
-    return YES;
-}
-
-- (BOOL)wantsUpdateLayer
-{
-    return YES;
-}
-
-- (void)updateLayer
-{
-    if (window->context.client != GLFW_NO_API)
-        [window->context.nsgl.object update];
-
-    _glfwInputWindowDamage(window);
-}
-
-- (void)cursorUpdate:(NSEvent *)event
-{
-    updateCursorImage(window);
-}
-
-- (BOOL)acceptsFirstMouse:(NSEvent *)event
-{
-    return YES;
-}
-
-- (void)mouseDown:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         GLFW_MOUSE_BUTTON_LEFT,
-                         GLFW_PRESS,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)mouseDragged:(NSEvent *)event
-{
-    [self mouseMoved:event];
-}
-
-- (void)mouseUp:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         GLFW_MOUSE_BUTTON_LEFT,
-                         GLFW_RELEASE,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)mouseMoved:(NSEvent *)event
-{
-    if (window->cursorMode == GLFW_CURSOR_DISABLED)
-    {
-        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];
-        // NOTE: The returned location uses base 0,1 not 0,0
-        const NSPoint pos = [event locationInWindow];
-
-        _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
-    }
-
-    window->ns.cursorWarpDeltaX = 0;
-    window->ns.cursorWarpDeltaY = 0;
-}
-
-- (void)rightMouseDown:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         GLFW_MOUSE_BUTTON_RIGHT,
-                         GLFW_PRESS,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)rightMouseDragged:(NSEvent *)event
-{
-    [self mouseMoved:event];
-}
-
-- (void)rightMouseUp:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         GLFW_MOUSE_BUTTON_RIGHT,
-                         GLFW_RELEASE,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)otherMouseDown:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         (int) [event buttonNumber],
-                         GLFW_PRESS,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)otherMouseDragged:(NSEvent *)event
-{
-    [self mouseMoved:event];
-}
-
-- (void)otherMouseUp:(NSEvent *)event
-{
-    _glfwInputMouseClick(window,
-                         (int) [event buttonNumber],
-                         GLFW_RELEASE,
-                         translateFlags([event modifierFlags]));
-}
-
-- (void)mouseExited:(NSEvent *)event
-{
-    if (window->cursorMode == GLFW_CURSOR_HIDDEN)
-        showCursor(window);
-
-    _glfwInputCursorEnter(window, GLFW_FALSE);
-}
-
-- (void)mouseEntered:(NSEvent *)event
-{
-    if (window->cursorMode == GLFW_CURSOR_HIDDEN)
-        hideCursor(window);
-
-    _glfwInputCursorEnter(window, GLFW_TRUE);
-}
-
-- (void)viewDidChangeBackingProperties
-{
-    const NSRect contentRect = [window->ns.view frame];
-    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
-
-    if (fbRect.size.width != window->ns.fbWidth ||
-        fbRect.size.height != window->ns.fbHeight)
-    {
-        window->ns.fbWidth  = fbRect.size.width;
-        window->ns.fbHeight = fbRect.size.height;
-        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
-    }
-
-    const float xscale = fbRect.size.width / contentRect.size.width;
-    const float yscale = fbRect.size.height / contentRect.size.height;
-
-    if (xscale != window->ns.xscale || yscale != window->ns.yscale)
-    {
-        window->ns.xscale = xscale;
-        window->ns.yscale = yscale;
-        _glfwInputWindowContentScale(window, xscale, yscale);
-
-        if (window->ns.retina && window->ns.layer)
-            [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
-    }
-}
-
-- (void)drawRect:(NSRect)rect
-{
-    _glfwInputWindowDamage(window);
-}
-
-- (void)updateTrackingAreas
-{
-    if (trackingArea != nil)
-    {
-        [self removeTrackingArea:trackingArea];
-        [trackingArea release];
-    }
-
-    const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
-                                          NSTrackingActiveInKeyWindow |
-                                          NSTrackingEnabledDuringMouseDrag |
-                                          NSTrackingCursorUpdate |
-                                          NSTrackingInVisibleRect |
-                                          NSTrackingAssumeInside;
-
-    trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
-                                                options:options
-                                                  owner:self
-                                               userInfo:nil];
-
-    [self addTrackingArea:trackingArea];
-    [super updateTrackingAreas];
-}
-
-- (void)keyDown:(NSEvent *)event
-{
-    const int key = translateKey([event keyCode]);
-    const int mods = translateFlags([event modifierFlags]);
-
-    _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
-
-    [self interpretKeyEvents:@[event]];
-}
-
-- (void)flagsChanged:(NSEvent *)event
-{
-    int action;
-    const unsigned int modifierFlags =
-        [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
-    const int key = translateKey([event keyCode]);
-    const int mods = translateFlags(modifierFlags);
-    const NSUInteger keyFlag = translateKeyToModifierFlag(key);
-
-    if (keyFlag & modifierFlags)
-    {
-        if (window->keys[key] == GLFW_PRESS)
-            action = GLFW_RELEASE;
-        else
-            action = GLFW_PRESS;
-    }
-    else
-        action = GLFW_RELEASE;
-
-    _glfwInputKey(window, key, [event keyCode], action, mods);
-}
-
-- (void)keyUp:(NSEvent *)event
-{
-    const int key = translateKey([event keyCode]);
-    const int mods = translateFlags([event modifierFlags]);
-    _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
-}
-
-- (void)scrollWheel:(NSEvent *)event
-{
-    double deltaX = [event scrollingDeltaX];
-    double deltaY = [event scrollingDeltaY];
-
-    if ([event hasPreciseScrollingDeltas])
-    {
-        deltaX *= 0.1;
-        deltaY *= 0.1;
-    }
-
-    if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0)
-        _glfwInputScroll(window, deltaX, deltaY);
-}
-
-- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
-{
-    // HACK: We don't know what to say here because we don't know what the
-    //       application wants to do with the paths
-    return NSDragOperationGeneric;
-}
-
-- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
-{
-    const NSRect contentRect = [window->ns.view frame];
-    // NOTE: The returned location uses base 0,1 not 0,0
-    const NSPoint pos = [sender draggingLocation];
-    _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
-
-    NSPasteboard* pasteboard = [sender draggingPasteboard];
-    NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
-    NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
-                                              options:options];
-    const NSUInteger count = [urls count];
-    if (count)
-    {
-        char** paths = calloc(count, sizeof(char*));
-
-        for (NSUInteger i = 0;  i < count;  i++)
-            paths[i] = _glfw_strdup([urls[i] fileSystemRepresentation]);
-
-        _glfwInputDrop(window, (int) count, (const char**) paths);
-
-        for (NSUInteger i = 0;  i < count;  i++)
-            free(paths[i]);
-        free(paths);
-    }
-
-    return 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
-{
-    [markedText release];
-    if ([string isKindOfClass:[NSAttributedString class]])
-        markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
-    else
-        markedText = [[NSMutableAttributedString alloc] 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
-{
-    const NSRect frame = [window->ns.view frame];
-    return NSMakeRect(frame.origin.x, frame.origin.y, 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;
-
-    const NSUInteger length = [characters length];
-    for (NSUInteger 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
-
-
-//------------------------------------------------------------------------
-// GLFW window class
-//------------------------------------------------------------------------
-
-@interface GLFWWindow : NSWindow {}
-@end
-
-@implementation GLFWWindow
-
-- (BOOL)canBecomeKeyWindow
-{
-    // Required for NSWindowStyleMaskBorderless windows
-    return YES;
-}
-
-- (BOOL)canBecomeMainWindow
-{
-    return YES;
-}
-
-@end
-
-
-// Create the Cocoa window
-//
-static GLFWbool createNativeWindow(_GLFWwindow* window,
-                                   const _GLFWwndconfig* wndconfig,
-                                   const _GLFWfbconfig* fbconfig)
-{
-    window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
-    if (window->ns.delegate == nil)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to create window delegate");
-        return GLFW_FALSE;
-    }
-
-    NSRect contentRect;
-
-    if (window->monitor)
-    {
-        GLFWvidmode mode;
-        int xpos, ypos;
-
-        _glfwPlatformGetVideoMode(window->monitor, &mode);
-        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
-
-        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:getStyleMask(window)
-                    backing:NSBackingStoreBuffered
-                      defer:NO];
-
-    if (window->ns.object == nil)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window");
-        return GLFW_FALSE;
-    }
-
-    if (window->monitor)
-        [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
-    else
-    {
-        [(NSWindow*) window->ns.object center];
-        _glfw.ns.cascadePoint =
-            NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
-                              NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
-
-        if (wndconfig->resizable)
-        {
-            const NSWindowCollectionBehavior behavior =
-                NSWindowCollectionBehaviorFullScreenPrimary |
-                NSWindowCollectionBehaviorManaged;
-            [window->ns.object setCollectionBehavior:behavior];
-        }
-
-        if (wndconfig->floating)
-            [window->ns.object setLevel:NSFloatingWindowLevel];
-
-        if (wndconfig->maximized)
-            [window->ns.object zoom:nil];
-    }
-
-    if (strlen(wndconfig->ns.frameName))
-        [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)];
-
-    window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
-    window->ns.retina = wndconfig->ns.retina;
-
-    if (fbconfig->transparent)
-    {
-        [window->ns.object setOpaque:NO];
-        [window->ns.object setHasShadow:NO];
-        [window->ns.object setBackgroundColor:[NSColor clearColor]];
-    }
-
-    [window->ns.object setContentView:window->ns.view];
-    [window->ns.object makeFirstResponder:window->ns.view];
-    [window->ns.object setTitle:@(wndconfig->title)];
-    [window->ns.object setDelegate:window->ns.delegate];
-    [window->ns.object setAcceptsMouseMovedEvents:YES];
-    [window->ns.object setRestorable:NO];
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
-    if ([window->ns.object respondsToSelector:@selector(setTabbingMode:)])
-        [window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed];
-#endif
-
-    _glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
-    _glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
-
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Transforms a y-coordinate between the CG display and NS screen spaces
-//
-float _glfwTransformYNS(float y)
-{
-    return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformCreateWindow(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig)
-{
-    @autoreleasepool {
-
-    if (!_glfw.ns.finishedLaunching)
-        [NSApp run];
-
-    if (!createNativeWindow(window, wndconfig, fbconfig))
-        return GLFW_FALSE;
-
-    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 if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
-        {
-            if (!_glfwInitEGL())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwInitOSMesa())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-    }
-
-    if (window->monitor)
-    {
-        _glfwPlatformShowWindow(window);
-        _glfwPlatformFocusWindow(window);
-        acquireMonitor(window);
-    }
-
-    return GLFW_TRUE;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformDestroyWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-
-    if (_glfw.ns.disabledCursorWindow == window)
-        _glfw.ns.disabledCursorWindow = NULL;
-
-    [window->ns.object orderOut:nil];
-
-    if (window->monitor)
-        releaseMonitor(window);
-
-    if (window->context.destroy)
-        window->context.destroy(window);
-
-    [window->ns.object setDelegate:nil];
-    [window->ns.delegate release];
-    window->ns.delegate = nil;
-
-    [window->ns.view release];
-    window->ns.view = nil;
-
-    [window->ns.object close];
-    window->ns.object = nil;
-
-    // HACK: Allow Cocoa to catch up before returning
-    _glfwPlatformPollEvents();
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
-{
-    @autoreleasepool {
-    NSString* string = @(title);
-    [window->ns.object setTitle:string];
-    // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
-    //       if the window lacks NSWindowStyleMaskTitled
-    [window->ns.object setMiniwindowTitle:string];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
-                                int count, const GLFWimage* images)
-{
-    // Regular windows do not have icons
-}
-
-void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect =
-        [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
-
-    if (xpos)
-        *xpos = contentRect.origin.x;
-    if (ypos)
-        *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height - 1);
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect = [window->ns.view frame];
-    const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height - 1), 0, 0);
-    const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
-    [window->ns.object setFrameOrigin:frameRect.origin];
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect = [window->ns.view frame];
-
-    if (width)
-        *width = contentRect.size.width;
-    if (height)
-        *height = contentRect.size.height;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
-{
-    @autoreleasepool {
-
-    if (window->monitor)
-    {
-        if (window->monitor->window == window)
-            acquireMonitor(window);
-    }
-    else
-    {
-        NSRect contentRect =
-            [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
-        contentRect.origin.y += contentRect.size.height - height;
-        contentRect.size = NSMakeSize(width, height);
-        [window->ns.object setFrame:[window->ns.object frameRectForContentRect:contentRect]
-                            display:YES];
-    }
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
-                                      int minwidth, int minheight,
-                                      int maxwidth, int maxheight)
-{
-    @autoreleasepool {
-
-    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)];
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
-{
-    @autoreleasepool {
-    if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
-        [window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
-    else
-        [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect = [window->ns.view frame];
-    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
-
-    if (width)
-        *width = (int) fbRect.size.width;
-    if (height)
-        *height = (int) fbRect.size.height;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
-                                     int* left, int* top,
-                                     int* right, int* bottom)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect = [window->ns.view frame];
-    const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect];
-
-    if (left)
-        *left = contentRect.origin.x - frameRect.origin.x;
-    if (top)
-        *top = frameRect.origin.y + frameRect.size.height -
-               contentRect.origin.y - contentRect.size.height;
-    if (right)
-        *right = frameRect.origin.x + frameRect.size.width -
-                 contentRect.origin.x - contentRect.size.width;
-    if (bottom)
-        *bottom = contentRect.origin.y - frameRect.origin.y;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale)
-{
-    @autoreleasepool {
-
-    const NSRect points = [window->ns.view frame];
-    const NSRect pixels = [window->ns.view convertRectToBacking:points];
-
-    if (xscale)
-        *xscale = (float) (pixels.size.width / points.size.width);
-    if (yscale)
-        *yscale = (float) (pixels.size.height / points.size.height);
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformIconifyWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    [window->ns.object miniaturize:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformRestoreWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    if ([window->ns.object isMiniaturized])
-        [window->ns.object deminiaturize:nil];
-    else if ([window->ns.object isZoomed])
-        [window->ns.object zoom:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    if (![window->ns.object isZoomed])
-        [window->ns.object zoom:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformShowWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    [window->ns.object orderFront:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformHideWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    [window->ns.object orderOut:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    [NSApp requestUserAttention:NSInformationalRequest];
-    } // autoreleasepool
-}
-
-void _glfwPlatformFocusWindow(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    // Make us the active application
-    // HACK: This is here to prevent applications using only hidden windows from
-    //       being activated, but should probably not be done every time any
-    //       window is shown
-    [NSApp activateIgnoringOtherApps:YES];
-    [window->ns.object makeKeyAndOrderFront:nil];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
-                                   _GLFWmonitor* monitor,
-                                   int xpos, int ypos,
-                                   int width, int height,
-                                   int refreshRate)
-{
-    @autoreleasepool {
-
-    if (window->monitor == monitor)
-    {
-        if (monitor)
-        {
-            if (monitor->window == window)
-                acquireMonitor(window);
-        }
-        else
-        {
-            const NSRect contentRect =
-                NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height);
-            const NSRect frameRect =
-                [window->ns.object frameRectForContentRect:contentRect
-                                                 styleMask:getStyleMask(window)];
-
-            [window->ns.object setFrame:frameRect display:YES];
-        }
-
-        return;
-    }
-
-    if (window->monitor)
-        releaseMonitor(window);
-
-    _glfwInputWindowMonitor(window, monitor);
-
-    // HACK: Allow the state cached in Cocoa to catch up to reality
-    // TODO: Solve this in a less terrible way
-    _glfwPlatformPollEvents();
-
-    const NSUInteger styleMask = getStyleMask(window);
-    [window->ns.object setStyleMask:styleMask];
-    // HACK: Changing the style mask can cause the first responder to be cleared
-    [window->ns.object makeFirstResponder:window->ns.view];
-
-    if (window->monitor)
-    {
-        [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
-        [window->ns.object setHasShadow:NO];
-
-        acquireMonitor(window);
-    }
-    else
-    {
-        NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1),
-                                        width, height);
-        NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
-                                                            styleMask:styleMask];
-        [window->ns.object setFrame:frameRect display:YES];
-
-        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];
-        // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
-        //       title property but the miniwindow title property is unaffected
-        [window->ns.object setTitle:[window->ns.object miniwindowTitle]];
-    }
-
-    } // autoreleasepool
-}
-
-int _glfwPlatformWindowFocused(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return [window->ns.object isKeyWindow];
-    } // autoreleasepool
-}
-
-int _glfwPlatformWindowIconified(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return [window->ns.object isMiniaturized];
-    } // autoreleasepool
-}
-
-int _glfwPlatformWindowVisible(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return [window->ns.object isVisible];
-    } // autoreleasepool
-}
-
-int _glfwPlatformWindowMaximized(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return [window->ns.object isZoomed];
-    } // autoreleasepool
-}
-
-int _glfwPlatformWindowHovered(_GLFWwindow* window)
-{
-    @autoreleasepool {
-
-    const NSPoint point = [NSEvent mouseLocation];
-
-    if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
-        [window->ns.object windowNumber])
-    {
-        return GLFW_FALSE;
-    }
-
-    return NSMouseInRect(point,
-        [window->ns.object convertRectToScreen:[window->ns.view frame]], NO);
-
-    } // autoreleasepool
-}
-
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
-{
-    @autoreleasepool {
-    [window->ns.object setStyleMask:getStyleMask(window)];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
-{
-    @autoreleasepool {
-    [window->ns.object setStyleMask:getStyleMask(window)];
-    [window->ns.object makeFirstResponder:window->ns.view];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
-{
-    @autoreleasepool {
-    if (enabled)
-        [window->ns.object setLevel:NSFloatingWindowLevel];
-    else
-        [window->ns.object setLevel:NSNormalWindowLevel];
-    } // autoreleasepool
-}
-
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
-{
-    @autoreleasepool {
-    return (float) [window->ns.object alphaValue];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
-{
-    @autoreleasepool {
-    [window->ns.object setAlphaValue:opacity];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
-{
-}
-
-GLFWbool _glfwPlatformRawMouseMotionSupported(void)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformPollEvents(void)
-{
-    @autoreleasepool {
-
-    if (!_glfw.ns.finishedLaunching)
-        [NSApp run];
-
-    for (;;)
-    {
-        NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
-                                            untilDate:[NSDate distantPast]
-                                               inMode:NSDefaultRunLoopMode
-                                              dequeue:YES];
-        if (event == nil)
-            break;
-
-        [NSApp sendEvent:event];
-    }
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformWaitEvents(void)
-{
-    @autoreleasepool {
-
-    if (!_glfw.ns.finishedLaunching)
-        [NSApp run];
-
-    // I wanted to pass NO to dequeue:, and rely on PollEvents to
-    // dequeue and send.  For reasons not at all clear to me, passing
-    // NO to dequeue: causes this method never to return.
-    NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
-                                        untilDate:[NSDate distantFuture]
-                                           inMode:NSDefaultRunLoopMode
-                                          dequeue:YES];
-    [NSApp sendEvent:event];
-
-    _glfwPlatformPollEvents();
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformWaitEventsTimeout(double timeout)
-{
-    @autoreleasepool {
-
-    if (!_glfw.ns.finishedLaunching)
-        [NSApp run];
-
-    NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
-    NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
-                                        untilDate:date
-                                           inMode:NSDefaultRunLoopMode
-                                          dequeue:YES];
-    if (event)
-        [NSApp sendEvent:event];
-
-    _glfwPlatformPollEvents();
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformPostEmptyEvent(void)
-{
-    @autoreleasepool {
-
-    if (!_glfw.ns.finishedLaunching)
-        [NSApp run];
-
-    NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
-                                        location:NSMakePoint(0, 0)
-                                   modifierFlags:0
-                                       timestamp:0
-                                    windowNumber:0
-                                         context:nil
-                                         subtype:0
-                                           data1:0
-                                           data2:0];
-    [NSApp postEvent:event atStart:YES];
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
-{
-    @autoreleasepool {
-
-    const NSRect contentRect = [window->ns.view frame];
-    // NOTE: The returned location uses base 0,1 not 0,0
-    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
-
-    if (xpos)
-        *xpos = pos.x;
-    if (ypos)
-        *ypos = contentRect.size.height - pos.y;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
-{
-    @autoreleasepool {
-
-    updateCursorImage(window);
-
-    const NSRect contentRect = [window->ns.view frame];
-    // NOTE: The returned location uses base 0,1 not 0,0
-    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
-
-    window->ns.cursorWarpDeltaX += x - pos.x;
-    window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y;
-
-    if (window->monitor)
-    {
-        CGDisplayMoveCursorToPoint(window->monitor->ns.displayID,
-                                   CGPointMake(x, y));
-    }
-    else
-    {
-        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,
-                                              _glfwTransformYNS(globalPoint.y)));
-    }
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
-{
-    @autoreleasepool {
-    if (_glfwPlatformWindowFocused(window))
-        updateCursorMode(window);
-    } // autoreleasepool
-}
-
-const char* _glfwPlatformGetScancodeName(int scancode)
-{
-    @autoreleasepool {
-
-    const int key = _glfw.ns.keycodes[scancode];
-
-    UInt32 deadKeyState = 0;
-    UniChar characters[4];
-    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.keynames[key],
-                       sizeof(_glfw.ns.keynames[key]),
-                       kCFStringEncodingUTF8);
-    CFRelease(string);
-
-    return _glfw.ns.keynames[key];
-
-    } // autoreleasepool
-}
-
-int _glfwPlatformGetKeyScancode(int key)
-{
-    return _glfw.ns.scancodes[key];
-}
-
-int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
-                              const GLFWimage* image,
-                              int xhot, int yhot)
-{
-    @autoreleasepool {
-
-    NSImage* native;
-    NSBitmapImageRep* rep;
-
-    rep = [[NSBitmapImageRep alloc]
-        initWithBitmapDataPlanes:NULL
-                      pixelsWide:image->width
-                      pixelsHigh:image->height
-                   bitsPerSample:8
-                 samplesPerPixel:4
-                        hasAlpha:YES
-                        isPlanar:NO
-                  colorSpaceName:NSCalibratedRGBColorSpace
-                    bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
-                     bytesPerRow:image->width * 4
-                    bitsPerPixel:32];
-
-    if (rep == nil)
-        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];
-
-    cursor->ns.object = [[NSCursor alloc] initWithImage:native
-                                                hotSpot:NSMakePoint(xhot, yhot)];
-
-    [native release];
-    [rep release];
-
-    if (cursor->ns.object == nil)
-        return GLFW_FALSE;
-
-    return GLFW_TRUE;
-
-    } // autoreleasepool
-}
-
-int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
-{
-    @autoreleasepool {
-
-    if (shape == GLFW_ARROW_CURSOR)
-        cursor->ns.object = [NSCursor arrowCursor];
-    else if (shape == GLFW_IBEAM_CURSOR)
-        cursor->ns.object = [NSCursor IBeamCursor];
-    else if (shape == GLFW_CROSSHAIR_CURSOR)
-        cursor->ns.object = [NSCursor crosshairCursor];
-    else if (shape == GLFW_HAND_CURSOR)
-        cursor->ns.object = [NSCursor pointingHandCursor];
-    else if (shape == GLFW_HRESIZE_CURSOR)
-        cursor->ns.object = [NSCursor resizeLeftRightCursor];
-    else if (shape == GLFW_VRESIZE_CURSOR)
-        cursor->ns.object = [NSCursor resizeUpDownCursor];
-
-    if (!cursor->ns.object)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to retrieve standard cursor");
-        return GLFW_FALSE;
-    }
-
-    [cursor->ns.object retain];
-    return GLFW_TRUE;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
-{
-    @autoreleasepool {
-    if (cursor->ns.object)
-        [(NSCursor*) cursor->ns.object release];
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
-{
-    @autoreleasepool {
-    if (cursorInContentArea(window))
-        updateCursorImage(window);
-    } // autoreleasepool
-}
-
-void _glfwPlatformSetClipboardString(const char* string)
-{
-    @autoreleasepool {
-    NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
-    [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
-    [pasteboard setString:@(string) forType:NSPasteboardTypeString];
-    } // autoreleasepool
-}
-
-const char* _glfwPlatformGetClipboardString(void)
-{
-    @autoreleasepool {
-
-    NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
-
-    if (![[pasteboard types] containsObject:NSPasteboardTypeString])
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "Cocoa: Failed to retrieve string from pasteboard");
-        return NULL;
-    }
-
-    NSString* object = [pasteboard stringForType:NSPasteboardTypeString];
-    if (!object)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to retrieve object from pasteboard");
-        return NULL;
-    }
-
-    free(_glfw.ns.clipboardString);
-    _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
-
-    return _glfw.ns.clipboardString;
-
-    } // autoreleasepool
-}
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
-{
-    if (!_glfw.vk.KHR_surface || !_glfw.vk.MVK_macos_surface)
-        return;
-
-    extensions[0] = "VK_KHR_surface";
-    extensions[1] = "VK_MVK_macos_surface";
-}
-
-int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
-                                                      VkPhysicalDevice device,
-                                                      uint32_t queuefamily)
-{
-    return GLFW_TRUE;
-}
-
-VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
-                                          _GLFWwindow* window,
-                                          const VkAllocationCallbacks* allocator,
-                                          VkSurfaceKHR* surface)
-{
-    @autoreleasepool {
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
-    VkResult err;
-    VkMacOSSurfaceCreateInfoMVK sci;
-    PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
-
-    vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
-        vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
-    if (!vkCreateMacOSSurfaceMVK)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
-    }
-
-    // HACK: Dynamically load Core Animation to avoid adding an extra
-    //       dependency for the majority who don't use MoltenVK
-    NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
-    if (!bundle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to find QuartzCore.framework");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
-    }
-
-    // NOTE: Create the layer here as makeBackingLayer should not return nil
-    window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
-    if (!window->ns.layer)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to create layer for view");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
-    }
-
-    if (window->ns.retina)
-        [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
-
-    [window->ns.view setLayer:window->ns.layer];
-    [window->ns.view setWantsLayer:YES];
-
-    memset(&sci, 0, sizeof(sci));
-    sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
-    sci.pView = window->ns.view;
-
-    err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
-    if (err)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Cocoa: Failed to create Vulkan surface: %s",
-                        _glfwGetVulkanResultString(err));
-    }
-
-    return err;
-#else
-    return VK_ERROR_EXTENSION_NOT_PRESENT;
-#endif
-
-    } // autoreleasepool
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(nil);
-    return window->ns.object;
-}
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <float.h>
+#include <string.h>
+
+// Returns the style mask corresponding to the window settings
+//
+static NSUInteger getStyleMask(_GLFWwindow* window)
+{
+    NSUInteger styleMask = NSWindowStyleMaskMiniaturizable;
+
+    if (window->monitor || !window->decorated)
+        styleMask |= NSWindowStyleMaskBorderless;
+    else
+    {
+        styleMask |= NSWindowStyleMaskTitled |
+                     NSWindowStyleMaskClosable;
+
+        if (window->resizable)
+            styleMask |= NSWindowStyleMaskResizable;
+    }
+
+    return styleMask;
+}
+
+// Returns whether the cursor is in the content area of the specified window
+//
+static GLFWbool cursorInContentArea(_GLFWwindow* window)
+{
+    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+    return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
+}
+
+// Hides the cursor if not already hidden
+//
+static void hideCursor(_GLFWwindow* window)
+{
+    if (!_glfw.ns.cursorHidden)
+    {
+        [NSCursor hide];
+        _glfw.ns.cursorHidden = GLFW_TRUE;
+    }
+}
+
+// Shows the cursor if not already shown
+//
+static void showCursor(_GLFWwindow* window)
+{
+    if (_glfw.ns.cursorHidden)
+    {
+        [NSCursor unhide];
+        _glfw.ns.cursorHidden = GLFW_FALSE;
+    }
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+    if (window->cursorMode == GLFW_CURSOR_NORMAL)
+    {
+        showCursor(window);
+
+        if (window->cursor)
+            [(NSCursor*) window->cursor->ns.object set];
+        else
+            [[NSCursor arrowCursor] set];
+    }
+    else
+        hideCursor(window);
+}
+
+// Apply chosen cursor mode to a focused window
+//
+static void updateCursorMode(_GLFWwindow* window)
+{
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        _glfw.ns.disabledCursorWindow = window;
+        _glfwPlatformGetCursorPos(window,
+                                  &_glfw.ns.restoreCursorPosX,
+                                  &_glfw.ns.restoreCursorPosY);
+        _glfwCenterCursorInContentArea(window);
+        CGAssociateMouseAndMouseCursorPosition(false);
+    }
+    else if (_glfw.ns.disabledCursorWindow == window)
+    {
+        _glfw.ns.disabledCursorWindow = NULL;
+        CGAssociateMouseAndMouseCursorPosition(true);
+        _glfwPlatformSetCursorPos(window,
+                                  _glfw.ns.restoreCursorPosX,
+                                  _glfw.ns.restoreCursorPosY);
+    }
+
+    if (cursorInContentArea(window))
+        updateCursorImage(window);
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
+{
+    _glfwSetVideoModeNS(window->monitor, &window->videoMode);
+    const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
+    const NSRect frame = NSMakeRect(bounds.origin.x,
+                                    _glfwTransformYNS(bounds.origin.y + bounds.size.height - 1),
+                                    bounds.size.width,
+                                    bounds.size.height);
+
+    [window->ns.object setFrame:frame display:YES];
+
+    _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+    if (window->monitor->window != window)
+        return;
+
+    _glfwInputMonitorWindow(window->monitor, NULL);
+    _glfwRestoreVideoModeNS(window->monitor);
+}
+
+// Translates macOS key modifiers into GLFW ones
+//
+static int translateFlags(NSUInteger flags)
+{
+    int mods = 0;
+
+    if (flags & NSEventModifierFlagShift)
+        mods |= GLFW_MOD_SHIFT;
+    if (flags & NSEventModifierFlagControl)
+        mods |= GLFW_MOD_CONTROL;
+    if (flags & NSEventModifierFlagOption)
+        mods |= GLFW_MOD_ALT;
+    if (flags & NSEventModifierFlagCommand)
+        mods |= GLFW_MOD_SUPER;
+    if (flags & NSEventModifierFlagCapsLock)
+        mods |= GLFW_MOD_CAPS_LOCK;
+
+    return mods;
+}
+
+// Translates a macOS keycode to a GLFW keycode
+//
+static int translateKey(unsigned int key)
+{
+    if (key >= sizeof(_glfw.ns.keycodes) / sizeof(_glfw.ns.keycodes[0]))
+        return GLFW_KEY_UNKNOWN;
+
+    return _glfw.ns.keycodes[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 NSEventModifierFlagShift;
+        case GLFW_KEY_LEFT_CONTROL:
+        case GLFW_KEY_RIGHT_CONTROL:
+            return NSEventModifierFlagControl;
+        case GLFW_KEY_LEFT_ALT:
+        case GLFW_KEY_RIGHT_ALT:
+            return NSEventModifierFlagOption;
+        case GLFW_KEY_LEFT_SUPER:
+        case GLFW_KEY_RIGHT_SUPER:
+            return NSEventModifierFlagCommand;
+        case GLFW_KEY_CAPS_LOCK:
+            return NSEventModifierFlagCapsLock;
+    }
+
+    return 0;
+}
+
+// Defines a constant for empty ranges in NSTextInputClient
+//
+static const NSRange kEmptyRange = { NSNotFound, 0 };
+
+
+//------------------------------------------------------------------------
+// Delegate for window related notifications
+//------------------------------------------------------------------------
+
+@interface GLFWWindowDelegate : NSObject
+{
+    _GLFWwindow* window;
+}
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWWindowDelegate
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
+{
+    self = [super init];
+    if (self != nil)
+        window = initWindow;
+
+    return self;
+}
+
+- (BOOL)windowShouldClose:(id)sender
+{
+    _glfwInputWindowCloseRequest(window);
+    return NO;
+}
+
+- (void)windowDidResize:(NSNotification *)notification
+{
+    if (window->context.client != GLFW_NO_API)
+        [window->context.nsgl.object update];
+
+    if (_glfw.ns.disabledCursorWindow == window)
+        _glfwCenterCursorInContentArea(window);
+
+    const int maximized = [window->ns.object isZoomed];
+    if (window->ns.maximized != maximized)
+    {
+        window->ns.maximized = maximized;
+        _glfwInputWindowMaximize(window, maximized);
+    }
+
+    const NSRect contentRect = [window->ns.view frame];
+    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+    if (fbRect.size.width != window->ns.fbWidth ||
+        fbRect.size.height != window->ns.fbHeight)
+    {
+        window->ns.fbWidth  = fbRect.size.width;
+        window->ns.fbHeight = fbRect.size.height;
+        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
+    }
+
+    if (contentRect.size.width != window->ns.width ||
+        contentRect.size.height != window->ns.height)
+    {
+        window->ns.width  = contentRect.size.width;
+        window->ns.height = contentRect.size.height;
+        _glfwInputWindowSize(window, contentRect.size.width, contentRect.size.height);
+    }
+}
+
+- (void)windowDidMove:(NSNotification *)notification
+{
+    if (window->context.client != GLFW_NO_API)
+        [window->context.nsgl.object update];
+
+    if (_glfw.ns.disabledCursorWindow == window)
+        _glfwCenterCursorInContentArea(window);
+
+    int x, y;
+    _glfwPlatformGetWindowPos(window, &x, &y);
+    _glfwInputWindowPos(window, x, y);
+}
+
+- (void)windowDidMiniaturize:(NSNotification *)notification
+{
+    if (window->monitor)
+        releaseMonitor(window);
+
+    _glfwInputWindowIconify(window, GLFW_TRUE);
+}
+
+- (void)windowDidDeminiaturize:(NSNotification *)notification
+{
+    if (window->monitor)
+        acquireMonitor(window);
+
+    _glfwInputWindowIconify(window, GLFW_FALSE);
+}
+
+- (void)windowDidBecomeKey:(NSNotification *)notification
+{
+    if (_glfw.ns.disabledCursorWindow == window)
+        _glfwCenterCursorInContentArea(window);
+
+    _glfwInputWindowFocus(window, GLFW_TRUE);
+    updateCursorMode(window);
+}
+
+- (void)windowDidResignKey:(NSNotification *)notification
+{
+    if (window->monitor && window->autoIconify)
+        _glfwPlatformIconifyWindow(window);
+
+    _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// Content view class for the GLFW window
+//------------------------------------------------------------------------
+
+@interface GLFWContentView : NSView <NSTextInputClient>
+{
+    _GLFWwindow* window;
+    NSTrackingArea* trackingArea;
+    NSMutableAttributedString* markedText;
+}
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWContentView
+
+- (instancetype)initWithGlfwWindow:(_GLFWwindow *)initWindow
+{
+    self = [super init];
+    if (self != nil)
+    {
+        window = initWindow;
+        trackingArea = nil;
+        markedText = [[NSMutableAttributedString alloc] init];
+
+        [self updateTrackingAreas];
+        // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available
+        //       on 10.7 without having been deprecated yet
+        [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]];
+    }
+
+    return self;
+}
+
+- (void)dealloc
+{
+    [trackingArea release];
+    [markedText release];
+    [super dealloc];
+}
+
+- (BOOL)isOpaque
+{
+    return [window->ns.object isOpaque];
+}
+
+- (BOOL)canBecomeKeyView
+{
+    return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+    return YES;
+}
+
+- (BOOL)wantsUpdateLayer
+{
+    return YES;
+}
+
+- (void)updateLayer
+{
+    if (window->context.client != GLFW_NO_API)
+        [window->context.nsgl.object update];
+
+    _glfwInputWindowDamage(window);
+}
+
+- (void)cursorUpdate:(NSEvent *)event
+{
+    updateCursorImage(window);
+}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)event
+{
+    return YES;
+}
+
+- (void)mouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         GLFW_MOUSE_BUTTON_LEFT,
+                         GLFW_PRESS,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)mouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)mouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         GLFW_MOUSE_BUTTON_LEFT,
+                         GLFW_RELEASE,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)mouseMoved:(NSEvent *)event
+{
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        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];
+        // NOTE: The returned location uses base 0,1 not 0,0
+        const NSPoint pos = [event locationInWindow];
+
+        _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
+    }
+
+    window->ns.cursorWarpDeltaX = 0;
+    window->ns.cursorWarpDeltaY = 0;
+}
+
+- (void)rightMouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         GLFW_MOUSE_BUTTON_RIGHT,
+                         GLFW_PRESS,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)rightMouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)rightMouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         GLFW_MOUSE_BUTTON_RIGHT,
+                         GLFW_RELEASE,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)otherMouseDown:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         (int) [event buttonNumber],
+                         GLFW_PRESS,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)otherMouseDragged:(NSEvent *)event
+{
+    [self mouseMoved:event];
+}
+
+- (void)otherMouseUp:(NSEvent *)event
+{
+    _glfwInputMouseClick(window,
+                         (int) [event buttonNumber],
+                         GLFW_RELEASE,
+                         translateFlags([event modifierFlags]));
+}
+
+- (void)mouseExited:(NSEvent *)event
+{
+    if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+        showCursor(window);
+
+    _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+- (void)mouseEntered:(NSEvent *)event
+{
+    if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+        hideCursor(window);
+
+    _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+- (void)viewDidChangeBackingProperties
+{
+    const NSRect contentRect = [window->ns.view frame];
+    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+    if (fbRect.size.width != window->ns.fbWidth ||
+        fbRect.size.height != window->ns.fbHeight)
+    {
+        window->ns.fbWidth  = fbRect.size.width;
+        window->ns.fbHeight = fbRect.size.height;
+        _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
+    }
+
+    const float xscale = fbRect.size.width / contentRect.size.width;
+    const float yscale = fbRect.size.height / contentRect.size.height;
+
+    if (xscale != window->ns.xscale || yscale != window->ns.yscale)
+    {
+        window->ns.xscale = xscale;
+        window->ns.yscale = yscale;
+        _glfwInputWindowContentScale(window, xscale, yscale);
+
+        if (window->ns.retina && window->ns.layer)
+            [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
+    }
+}
+
+- (void)drawRect:(NSRect)rect
+{
+    _glfwInputWindowDamage(window);
+}
+
+- (void)updateTrackingAreas
+{
+    if (trackingArea != nil)
+    {
+        [self removeTrackingArea:trackingArea];
+        [trackingArea release];
+    }
+
+    const NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited |
+                                          NSTrackingActiveInKeyWindow |
+                                          NSTrackingEnabledDuringMouseDrag |
+                                          NSTrackingCursorUpdate |
+                                          NSTrackingInVisibleRect |
+                                          NSTrackingAssumeInside;
+
+    trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
+                                                options:options
+                                                  owner:self
+                                               userInfo:nil];
+
+    [self addTrackingArea:trackingArea];
+    [super updateTrackingAreas];
+}
+
+- (void)keyDown:(NSEvent *)event
+{
+    const int key = translateKey([event keyCode]);
+    const int mods = translateFlags([event modifierFlags]);
+
+    _glfwInputKey(window, key, [event keyCode], GLFW_PRESS, mods);
+
+    [self interpretKeyEvents:@[event]];
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+    int action;
+    const unsigned int modifierFlags =
+        [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
+    const int key = translateKey([event keyCode]);
+    const int mods = translateFlags(modifierFlags);
+    const NSUInteger keyFlag = translateKeyToModifierFlag(key);
+
+    if (keyFlag & modifierFlags)
+    {
+        if (window->keys[key] == GLFW_PRESS)
+            action = GLFW_RELEASE;
+        else
+            action = GLFW_PRESS;
+    }
+    else
+        action = GLFW_RELEASE;
+
+    _glfwInputKey(window, key, [event keyCode], action, mods);
+}
+
+- (void)keyUp:(NSEvent *)event
+{
+    const int key = translateKey([event keyCode]);
+    const int mods = translateFlags([event modifierFlags]);
+    _glfwInputKey(window, key, [event keyCode], GLFW_RELEASE, mods);
+}
+
+- (void)scrollWheel:(NSEvent *)event
+{
+    double deltaX = [event scrollingDeltaX];
+    double deltaY = [event scrollingDeltaY];
+
+    if ([event hasPreciseScrollingDeltas])
+    {
+        deltaX *= 0.1;
+        deltaY *= 0.1;
+    }
+
+    if (fabs(deltaX) > 0.0 || fabs(deltaY) > 0.0)
+        _glfwInputScroll(window, deltaX, deltaY);
+}
+
+- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
+{
+    // HACK: We don't know what to say here because we don't know what the
+    //       application wants to do with the paths
+    return NSDragOperationGeneric;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+    const NSRect contentRect = [window->ns.view frame];
+    // NOTE: The returned location uses base 0,1 not 0,0
+    const NSPoint pos = [sender draggingLocation];
+    _glfwInputCursorPos(window, pos.x, contentRect.size.height - pos.y);
+
+    NSPasteboard* pasteboard = [sender draggingPasteboard];
+    NSDictionary* options = @{NSPasteboardURLReadingFileURLsOnlyKey:@YES};
+    NSArray* urls = [pasteboard readObjectsForClasses:@[[NSURL class]]
+                                              options:options];
+    const NSUInteger count = [urls count];
+    if (count)
+    {
+        char** paths = calloc(count, sizeof(char*));
+
+        for (NSUInteger i = 0;  i < count;  i++)
+            paths[i] = _glfw_strdup([urls[i] fileSystemRepresentation]);
+
+        _glfwInputDrop(window, (int) count, (const char**) paths);
+
+        for (NSUInteger i = 0;  i < count;  i++)
+            free(paths[i]);
+        free(paths);
+    }
+
+    return 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
+{
+    [markedText release];
+    if ([string isKindOfClass:[NSAttributedString class]])
+        markedText = [[NSMutableAttributedString alloc] initWithAttributedString:string];
+    else
+        markedText = [[NSMutableAttributedString alloc] 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
+{
+    const NSRect frame = [window->ns.view frame];
+    return NSMakeRect(frame.origin.x, frame.origin.y, 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;
+
+    const NSUInteger length = [characters length];
+    for (NSUInteger 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
+
+
+//------------------------------------------------------------------------
+// GLFW window class
+//------------------------------------------------------------------------
+
+@interface GLFWWindow : NSWindow {}
+@end
+
+@implementation GLFWWindow
+
+- (BOOL)canBecomeKeyWindow
+{
+    // Required for NSWindowStyleMaskBorderless windows
+    return YES;
+}
+
+- (BOOL)canBecomeMainWindow
+{
+    return YES;
+}
+
+@end
+
+
+// Create the Cocoa window
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+                                   const _GLFWwndconfig* wndconfig,
+                                   const _GLFWfbconfig* fbconfig)
+{
+    window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
+    if (window->ns.delegate == nil)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to create window delegate");
+        return GLFW_FALSE;
+    }
+
+    NSRect contentRect;
+
+    if (window->monitor)
+    {
+        GLFWvidmode mode;
+        int xpos, ypos;
+
+        _glfwPlatformGetVideoMode(window->monitor, &mode);
+        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+
+        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:getStyleMask(window)
+                    backing:NSBackingStoreBuffered
+                      defer:NO];
+
+    if (window->ns.object == nil)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window");
+        return GLFW_FALSE;
+    }
+
+    if (window->monitor)
+        [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+    else
+    {
+        [(NSWindow*) window->ns.object center];
+        _glfw.ns.cascadePoint =
+            NSPointToCGPoint([window->ns.object cascadeTopLeftFromPoint:
+                              NSPointFromCGPoint(_glfw.ns.cascadePoint)]);
+
+        if (wndconfig->resizable)
+        {
+            const NSWindowCollectionBehavior behavior =
+                NSWindowCollectionBehaviorFullScreenPrimary |
+                NSWindowCollectionBehaviorManaged;
+            [window->ns.object setCollectionBehavior:behavior];
+        }
+
+        if (wndconfig->floating)
+            [window->ns.object setLevel:NSFloatingWindowLevel];
+
+        if (wndconfig->maximized)
+            [window->ns.object zoom:nil];
+    }
+
+    if (strlen(wndconfig->ns.frameName))
+        [window->ns.object setFrameAutosaveName:@(wndconfig->ns.frameName)];
+
+    window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
+    window->ns.retina = wndconfig->ns.retina;
+
+    if (fbconfig->transparent)
+    {
+        [window->ns.object setOpaque:NO];
+        [window->ns.object setHasShadow:NO];
+        [window->ns.object setBackgroundColor:[NSColor clearColor]];
+    }
+
+    [window->ns.object setContentView:window->ns.view];
+    [window->ns.object makeFirstResponder:window->ns.view];
+    [window->ns.object setTitle:@(wndconfig->title)];
+    [window->ns.object setDelegate:window->ns.delegate];
+    [window->ns.object setAcceptsMouseMovedEvents:YES];
+    [window->ns.object setRestorable:NO];
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
+    if ([window->ns.object respondsToSelector:@selector(setTabbingMode:)])
+        [window->ns.object setTabbingMode:NSWindowTabbingModeDisallowed];
+#endif
+
+    _glfwPlatformGetWindowSize(window, &window->ns.width, &window->ns.height);
+    _glfwPlatformGetFramebufferSize(window, &window->ns.fbWidth, &window->ns.fbHeight);
+
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Transforms a y-coordinate between the CG display and NS screen spaces
+//
+float _glfwTransformYNS(float y)
+{
+    return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+                              const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig)
+{
+    @autoreleasepool {
+
+    if (!_glfw.ns.finishedLaunching)
+        [NSApp run];
+
+    if (!createNativeWindow(window, wndconfig, fbconfig))
+        return GLFW_FALSE;
+
+    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 if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+        {
+            if (!_glfwInitEGL())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwInitOSMesa())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+    }
+
+    if (window->monitor)
+    {
+        _glfwPlatformShowWindow(window);
+        _glfwPlatformFocusWindow(window);
+        acquireMonitor(window);
+    }
+
+    return GLFW_TRUE;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+
+    if (_glfw.ns.disabledCursorWindow == window)
+        _glfw.ns.disabledCursorWindow = NULL;
+
+    [window->ns.object orderOut:nil];
+
+    if (window->monitor)
+        releaseMonitor(window);
+
+    if (window->context.destroy)
+        window->context.destroy(window);
+
+    [window->ns.object setDelegate:nil];
+    [window->ns.delegate release];
+    window->ns.delegate = nil;
+
+    [window->ns.view release];
+    window->ns.view = nil;
+
+    [window->ns.object close];
+    window->ns.object = nil;
+
+    // HACK: Allow Cocoa to catch up before returning
+    _glfwPlatformPollEvents();
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+    @autoreleasepool {
+    NSString* string = @(title);
+    [window->ns.object setTitle:string];
+    // HACK: Set the miniwindow title explicitly as setTitle: doesn't update it
+    //       if the window lacks NSWindowStyleMaskTitled
+    [window->ns.object setMiniwindowTitle:string];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+                                int count, const GLFWimage* images)
+{
+    // Regular windows do not have icons
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect =
+        [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
+
+    if (xpos)
+        *xpos = contentRect.origin.x;
+    if (ypos)
+        *ypos = _glfwTransformYNS(contentRect.origin.y + contentRect.size.height - 1);
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect = [window->ns.view frame];
+    const NSRect dummyRect = NSMakeRect(x, _glfwTransformYNS(y + contentRect.size.height - 1), 0, 0);
+    const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
+    [window->ns.object setFrameOrigin:frameRect.origin];
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect = [window->ns.view frame];
+
+    if (width)
+        *width = contentRect.size.width;
+    if (height)
+        *height = contentRect.size.height;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+    @autoreleasepool {
+
+    if (window->monitor)
+    {
+        if (window->monitor->window == window)
+            acquireMonitor(window);
+    }
+    else
+    {
+        NSRect contentRect =
+            [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
+        contentRect.origin.y += contentRect.size.height - height;
+        contentRect.size = NSMakeSize(width, height);
+        [window->ns.object setFrame:[window->ns.object frameRectForContentRect:contentRect]
+                            display:YES];
+    }
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+                                      int minwidth, int minheight,
+                                      int maxwidth, int maxheight)
+{
+    @autoreleasepool {
+
+    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)];
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+    @autoreleasepool {
+    if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
+        [window->ns.object setResizeIncrements:NSMakeSize(1.0, 1.0)];
+    else
+        [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect = [window->ns.view frame];
+    const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+    if (width)
+        *width = (int) fbRect.size.width;
+    if (height)
+        *height = (int) fbRect.size.height;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+                                     int* left, int* top,
+                                     int* right, int* bottom)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect = [window->ns.view frame];
+    const NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect];
+
+    if (left)
+        *left = contentRect.origin.x - frameRect.origin.x;
+    if (top)
+        *top = frameRect.origin.y + frameRect.size.height -
+               contentRect.origin.y - contentRect.size.height;
+    if (right)
+        *right = frameRect.origin.x + frameRect.size.width -
+                 contentRect.origin.x - contentRect.size.width;
+    if (bottom)
+        *bottom = contentRect.origin.y - frameRect.origin.y;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale)
+{
+    @autoreleasepool {
+
+    const NSRect points = [window->ns.view frame];
+    const NSRect pixels = [window->ns.view convertRectToBacking:points];
+
+    if (xscale)
+        *xscale = (float) (pixels.size.width / points.size.width);
+    if (yscale)
+        *yscale = (float) (pixels.size.height / points.size.height);
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    [window->ns.object miniaturize:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    if ([window->ns.object isMiniaturized])
+        [window->ns.object deminiaturize:nil];
+    else if ([window->ns.object isZoomed])
+        [window->ns.object zoom:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    if (![window->ns.object isZoomed])
+        [window->ns.object zoom:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    [window->ns.object orderFront:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    [window->ns.object orderOut:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    [NSApp requestUserAttention:NSInformationalRequest];
+    } // autoreleasepool
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    // Make us the active application
+    // HACK: This is here to prevent applications using only hidden windows from
+    //       being activated, but should probably not be done every time any
+    //       window is shown
+    [NSApp activateIgnoringOtherApps:YES];
+    [window->ns.object makeKeyAndOrderFront:nil];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+                                   _GLFWmonitor* monitor,
+                                   int xpos, int ypos,
+                                   int width, int height,
+                                   int refreshRate)
+{
+    @autoreleasepool {
+
+    if (window->monitor == monitor)
+    {
+        if (monitor)
+        {
+            if (monitor->window == window)
+                acquireMonitor(window);
+        }
+        else
+        {
+            const NSRect contentRect =
+                NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1), width, height);
+            const NSRect frameRect =
+                [window->ns.object frameRectForContentRect:contentRect
+                                                 styleMask:getStyleMask(window)];
+
+            [window->ns.object setFrame:frameRect display:YES];
+        }
+
+        return;
+    }
+
+    if (window->monitor)
+        releaseMonitor(window);
+
+    _glfwInputWindowMonitor(window, monitor);
+
+    // HACK: Allow the state cached in Cocoa to catch up to reality
+    // TODO: Solve this in a less terrible way
+    _glfwPlatformPollEvents();
+
+    const NSUInteger styleMask = getStyleMask(window);
+    [window->ns.object setStyleMask:styleMask];
+    // HACK: Changing the style mask can cause the first responder to be cleared
+    [window->ns.object makeFirstResponder:window->ns.view];
+
+    if (window->monitor)
+    {
+        [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+        [window->ns.object setHasShadow:NO];
+
+        acquireMonitor(window);
+    }
+    else
+    {
+        NSRect contentRect = NSMakeRect(xpos, _glfwTransformYNS(ypos + height - 1),
+                                        width, height);
+        NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
+                                                            styleMask:styleMask];
+        [window->ns.object setFrame:frameRect display:YES];
+
+        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];
+        // HACK: Clearing NSWindowStyleMaskTitled resets and disables the window
+        //       title property but the miniwindow title property is unaffected
+        [window->ns.object setTitle:[window->ns.object miniwindowTitle]];
+    }
+
+    } // autoreleasepool
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return [window->ns.object isKeyWindow];
+    } // autoreleasepool
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return [window->ns.object isMiniaturized];
+    } // autoreleasepool
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return [window->ns.object isVisible];
+    } // autoreleasepool
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return [window->ns.object isZoomed];
+    } // autoreleasepool
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    @autoreleasepool {
+
+    const NSPoint point = [NSEvent mouseLocation];
+
+    if ([NSWindow windowNumberAtPoint:point belowWindowWithWindowNumber:0] !=
+        [window->ns.object windowNumber])
+    {
+        return GLFW_FALSE;
+    }
+
+    return NSMouseInRect(point,
+        [window->ns.object convertRectToScreen:[window->ns.view frame]], NO);
+
+    } // autoreleasepool
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return ![window->ns.object isOpaque] && ![window->ns.view isOpaque];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+    @autoreleasepool {
+    [window->ns.object setStyleMask:getStyleMask(window)];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+    @autoreleasepool {
+    [window->ns.object setStyleMask:getStyleMask(window)];
+    [window->ns.object makeFirstResponder:window->ns.view];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+    @autoreleasepool {
+    if (enabled)
+        [window->ns.object setLevel:NSFloatingWindowLevel];
+    else
+        [window->ns.object setLevel:NSNormalWindowLevel];
+    } // autoreleasepool
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+    @autoreleasepool {
+    return (float) [window->ns.object alphaValue];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+    @autoreleasepool {
+    [window->ns.object setAlphaValue:opacity];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+{
+}
+
+GLFWbool _glfwPlatformRawMouseMotionSupported(void)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+    @autoreleasepool {
+
+    if (!_glfw.ns.finishedLaunching)
+        [NSApp run];
+
+    for (;;)
+    {
+        NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
+                                            untilDate:[NSDate distantPast]
+                                               inMode:NSDefaultRunLoopMode
+                                              dequeue:YES];
+        if (event == nil)
+            break;
+
+        [NSApp sendEvent:event];
+    }
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+    @autoreleasepool {
+
+    if (!_glfw.ns.finishedLaunching)
+        [NSApp run];
+
+    // I wanted to pass NO to dequeue:, and rely on PollEvents to
+    // dequeue and send.  For reasons not at all clear to me, passing
+    // NO to dequeue: causes this method never to return.
+    NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
+                                        untilDate:[NSDate distantFuture]
+                                           inMode:NSDefaultRunLoopMode
+                                          dequeue:YES];
+    [NSApp sendEvent:event];
+
+    _glfwPlatformPollEvents();
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+    @autoreleasepool {
+
+    if (!_glfw.ns.finishedLaunching)
+        [NSApp run];
+
+    NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
+    NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny
+                                        untilDate:date
+                                           inMode:NSDefaultRunLoopMode
+                                          dequeue:YES];
+    if (event)
+        [NSApp sendEvent:event];
+
+    _glfwPlatformPollEvents();
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+    @autoreleasepool {
+
+    if (!_glfw.ns.finishedLaunching)
+        [NSApp run];
+
+    NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
+                                        location:NSMakePoint(0, 0)
+                                   modifierFlags:0
+                                       timestamp:0
+                                    windowNumber:0
+                                         context:nil
+                                         subtype:0
+                                           data1:0
+                                           data2:0];
+    [NSApp postEvent:event atStart:YES];
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+    @autoreleasepool {
+
+    const NSRect contentRect = [window->ns.view frame];
+    // NOTE: The returned location uses base 0,1 not 0,0
+    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+
+    if (xpos)
+        *xpos = pos.x;
+    if (ypos)
+        *ypos = contentRect.size.height - pos.y;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+    @autoreleasepool {
+
+    updateCursorImage(window);
+
+    const NSRect contentRect = [window->ns.view frame];
+    // NOTE: The returned location uses base 0,1 not 0,0
+    const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+
+    window->ns.cursorWarpDeltaX += x - pos.x;
+    window->ns.cursorWarpDeltaY += y - contentRect.size.height + pos.y;
+
+    if (window->monitor)
+    {
+        CGDisplayMoveCursorToPoint(window->monitor->ns.displayID,
+                                   CGPointMake(x, y));
+    }
+    else
+    {
+        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,
+                                              _glfwTransformYNS(globalPoint.y)));
+    }
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+    @autoreleasepool {
+    if (_glfwPlatformWindowFocused(window))
+        updateCursorMode(window);
+    } // autoreleasepool
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+    @autoreleasepool {
+
+    if (scancode < 0 || scancode > 0xff ||
+        _glfw.ns.keycodes[scancode] == GLFW_KEY_UNKNOWN)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
+        return NULL;
+    }
+
+    const int key = _glfw.ns.keycodes[scancode];
+
+    UInt32 deadKeyState = 0;
+    UniChar characters[4];
+    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.keynames[key],
+                       sizeof(_glfw.ns.keynames[key]),
+                       kCFStringEncodingUTF8);
+    CFRelease(string);
+
+    return _glfw.ns.keynames[key];
+
+    } // autoreleasepool
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+    return _glfw.ns.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+                              const GLFWimage* image,
+                              int xhot, int yhot)
+{
+    @autoreleasepool {
+
+    NSImage* native;
+    NSBitmapImageRep* rep;
+
+    rep = [[NSBitmapImageRep alloc]
+        initWithBitmapDataPlanes:NULL
+                      pixelsWide:image->width
+                      pixelsHigh:image->height
+                   bitsPerSample:8
+                 samplesPerPixel:4
+                        hasAlpha:YES
+                        isPlanar:NO
+                  colorSpaceName:NSCalibratedRGBColorSpace
+                    bitmapFormat:NSBitmapFormatAlphaNonpremultiplied
+                     bytesPerRow:image->width * 4
+                    bitsPerPixel:32];
+
+    if (rep == nil)
+        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];
+
+    cursor->ns.object = [[NSCursor alloc] initWithImage:native
+                                                hotSpot:NSMakePoint(xhot, yhot)];
+
+    [native release];
+    [rep release];
+
+    if (cursor->ns.object == nil)
+        return GLFW_FALSE;
+
+    return GLFW_TRUE;
+
+    } // autoreleasepool
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+    @autoreleasepool {
+
+    if (shape == GLFW_ARROW_CURSOR)
+        cursor->ns.object = [NSCursor arrowCursor];
+    else if (shape == GLFW_IBEAM_CURSOR)
+        cursor->ns.object = [NSCursor IBeamCursor];
+    else if (shape == GLFW_CROSSHAIR_CURSOR)
+        cursor->ns.object = [NSCursor crosshairCursor];
+    else if (shape == GLFW_HAND_CURSOR)
+        cursor->ns.object = [NSCursor pointingHandCursor];
+    else if (shape == GLFW_HRESIZE_CURSOR)
+        cursor->ns.object = [NSCursor resizeLeftRightCursor];
+    else if (shape == GLFW_VRESIZE_CURSOR)
+        cursor->ns.object = [NSCursor resizeUpDownCursor];
+
+    if (!cursor->ns.object)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to retrieve standard cursor");
+        return GLFW_FALSE;
+    }
+
+    [cursor->ns.object retain];
+    return GLFW_TRUE;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+    @autoreleasepool {
+    if (cursor->ns.object)
+        [(NSCursor*) cursor->ns.object release];
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+    @autoreleasepool {
+    if (cursorInContentArea(window))
+        updateCursorImage(window);
+    } // autoreleasepool
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+    @autoreleasepool {
+    NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+    [pasteboard declareTypes:@[NSPasteboardTypeString] owner:nil];
+    [pasteboard setString:@(string) forType:NSPasteboardTypeString];
+    } // autoreleasepool
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+    @autoreleasepool {
+
+    NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+
+    if (![[pasteboard types] containsObject:NSPasteboardTypeString])
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "Cocoa: Failed to retrieve string from pasteboard");
+        return NULL;
+    }
+
+    NSString* object = [pasteboard stringForType:NSPasteboardTypeString];
+    if (!object)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to retrieve object from pasteboard");
+        return NULL;
+    }
+
+    free(_glfw.ns.clipboardString);
+    _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]);
+
+    return _glfw.ns.clipboardString;
+
+    } // autoreleasepool
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+    if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface)
+    {
+        extensions[0] = "VK_KHR_surface";
+        extensions[1] = "VK_EXT_metal_surface";
+    }
+    else if (_glfw.vk.KHR_surface && _glfw.vk.MVK_macos_surface)
+    {
+        extensions[0] = "VK_KHR_surface";
+        extensions[1] = "VK_MVK_macos_surface";
+    }
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+                                                      VkPhysicalDevice device,
+                                                      uint32_t queuefamily)
+{
+    return GLFW_TRUE;
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+                                          _GLFWwindow* window,
+                                          const VkAllocationCallbacks* allocator,
+                                          VkSurfaceKHR* surface)
+{
+    @autoreleasepool {
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
+    // HACK: Dynamically load Core Animation to avoid adding an extra
+    //       dependency for the majority who don't use MoltenVK
+    NSBundle* bundle = [NSBundle bundleWithPath:@"/System/Library/Frameworks/QuartzCore.framework"];
+    if (!bundle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to find QuartzCore.framework");
+        return VK_ERROR_EXTENSION_NOT_PRESENT;
+    }
+
+    // NOTE: Create the layer here as makeBackingLayer should not return nil
+    window->ns.layer = [[bundle classNamed:@"CAMetalLayer"] layer];
+    if (!window->ns.layer)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to create layer for view");
+        return VK_ERROR_EXTENSION_NOT_PRESENT;
+    }
+
+    if (window->ns.retina)
+        [window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
+
+    [window->ns.view setLayer:window->ns.layer];
+    [window->ns.view setWantsLayer:YES];
+
+    VkResult err;
+
+    if (_glfw.vk.EXT_metal_surface)
+    {
+        VkMetalSurfaceCreateInfoEXT sci;
+
+        PFN_vkCreateMetalSurfaceEXT vkCreateMetalSurfaceEXT;
+        vkCreateMetalSurfaceEXT = (PFN_vkCreateMetalSurfaceEXT)
+            vkGetInstanceProcAddr(instance, "vkCreateMetalSurfaceEXT");
+        if (!vkCreateMetalSurfaceEXT)
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "Cocoa: Vulkan instance missing VK_EXT_metal_surface extension");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
+        memset(&sci, 0, sizeof(sci));
+        sci.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
+        sci.pLayer = window->ns.layer;
+
+        err = vkCreateMetalSurfaceEXT(instance, &sci, allocator, surface);
+    }
+    else
+    {
+        VkMacOSSurfaceCreateInfoMVK sci;
+
+        PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK;
+        vkCreateMacOSSurfaceMVK = (PFN_vkCreateMacOSSurfaceMVK)
+            vkGetInstanceProcAddr(instance, "vkCreateMacOSSurfaceMVK");
+        if (!vkCreateMacOSSurfaceMVK)
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "Cocoa: Vulkan instance missing VK_MVK_macos_surface extension");
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+
+        memset(&sci, 0, sizeof(sci));
+        sci.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+        sci.pView = window->ns.view;
+
+        err = vkCreateMacOSSurfaceMVK(instance, &sci, allocator, surface);
+    }
+
+    if (err)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Cocoa: Failed to create Vulkan surface: %s",
+                        _glfwGetVulkanResultString(err));
+    }
+
+    return err;
+#else
+    return VK_ERROR_EXTENSION_NOT_PRESENT;
+#endif
+
+    } // autoreleasepool
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(nil);
+    return window->ns.object;
+}
+
diff --git a/glfw/src/context.c b/glfw/src/context.c
--- a/glfw/src/context.c
+++ b/glfw/src/context.c
@@ -1,760 +1,760 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2016 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-#include <limits.h>
-#include <stdio.h>
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Checks whether the desired context attributes are valid
-//
-// This function checks things like whether the specified client API version
-// exists and whether all relevant options have supported and non-conflicting
-// values
-//
-GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
-{
-    if (ctxconfig->share)
-    {
-        if (ctxconfig->client == GLFW_NO_API ||
-            ctxconfig->share->context.client == GLFW_NO_API)
-        {
-            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-            return GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
-        ctxconfig->source != GLFW_EGL_CONTEXT_API &&
-        ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM,
-                        "Invalid context creation API 0x%08X",
-                        ctxconfig->source);
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->client != GLFW_NO_API &&
-        ctxconfig->client != GLFW_OPENGL_API &&
-        ctxconfig->client != GLFW_OPENGL_ES_API)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM,
-                        "Invalid client API 0x%08X",
-                        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) ||
-            (ctxconfig->major == 3 && ctxconfig->minor > 3))
-        {
-            // OpenGL 1.0 is the smallest valid version
-            // 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",
-                            ctxconfig->major, ctxconfig->minor);
-            return GLFW_FALSE;
-        }
-
-        if (ctxconfig->profile)
-        {
-            if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
-                ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
-            {
-                _glfwInputError(GLFW_INVALID_ENUM,
-                                "Invalid OpenGL profile 0x%08X",
-                                ctxconfig->profile);
-                return GLFW_FALSE;
-            }
-
-            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 are only defined for OpenGL version 3.2 and above");
-                return GLFW_FALSE;
-            }
-        }
-
-        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 is only defined for OpenGL version 3.0 and above");
-            return GLFW_FALSE;
-        }
-    }
-    else if (ctxconfig->client == GLFW_OPENGL_ES_API)
-    {
-        if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
-            (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
-            (ctxconfig->major == 2 && ctxconfig->minor > 0))
-        {
-            // 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
-            // For now, let everything else through
-
-            _glfwInputError(GLFW_INVALID_VALUE,
-                            "Invalid OpenGL ES version %i.%i",
-                            ctxconfig->major, ctxconfig->minor);
-            return GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->robustness)
-    {
-        if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
-            ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
-        {
-            _glfwInputError(GLFW_INVALID_ENUM,
-                            "Invalid context robustness mode 0x%08X",
-                            ctxconfig->robustness);
-            return GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->release)
-    {
-        if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
-            ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
-        {
-            _glfwInputError(GLFW_INVALID_ENUM,
-                            "Invalid context release behavior 0x%08X",
-                            ctxconfig->release);
-            return GLFW_FALSE;
-        }
-    }
-
-    return GLFW_TRUE;
-}
-
-// Chooses the framebuffer config that best matches the desired one
-//
-const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
-                                         const _GLFWfbconfig* alternatives,
-                                         unsigned int count)
-{
-    unsigned int i;
-    unsigned int missing, leastMissing = UINT_MAX;
-    unsigned int colorDiff, leastColorDiff = UINT_MAX;
-    unsigned int extraDiff, leastExtraDiff = UINT_MAX;
-    const _GLFWfbconfig* current;
-    const _GLFWfbconfig* closest = NULL;
-
-    for (i = 0;  i < count;  i++)
-    {
-        current = alternatives + i;
-
-        if (desired->stereo > 0 && current->stereo == 0)
-        {
-            // Stereo is a hard constraint
-            continue;
-        }
-
-        if (desired->doublebuffer != current->doublebuffer)
-        {
-            // Double buffering is a hard constraint
-            continue;
-        }
-
-        // Count number of missing buffers
-        {
-            missing = 0;
-
-            if (desired->alphaBits > 0 && current->alphaBits == 0)
-                missing++;
-
-            if (desired->depthBits > 0 && current->depthBits == 0)
-                missing++;
-
-            if (desired->stencilBits > 0 && current->stencilBits == 0)
-                missing++;
-
-            if (desired->auxBuffers > 0 &&
-                current->auxBuffers < desired->auxBuffers)
-            {
-                missing += desired->auxBuffers - current->auxBuffers;
-            }
-
-            if (desired->samples > 0 && current->samples == 0)
-            {
-                // Technically, several multisampling buffers could be
-                // involved, but that's a lower level implementation detail and
-                // not important to us here, so we count them as one
-                missing++;
-            }
-
-            if (desired->transparent != current->transparent)
-                missing++;
-        }
-
-        // These polynomials make many small channel size differences matter
-        // less than one large channel size difference
-
-        // Calculate color channel size difference value
-        {
-            colorDiff = 0;
-
-            if (desired->redBits != GLFW_DONT_CARE)
-            {
-                colorDiff += (desired->redBits - current->redBits) *
-                             (desired->redBits - current->redBits);
-            }
-
-            if (desired->greenBits != GLFW_DONT_CARE)
-            {
-                colorDiff += (desired->greenBits - current->greenBits) *
-                             (desired->greenBits - current->greenBits);
-            }
-
-            if (desired->blueBits != GLFW_DONT_CARE)
-            {
-                colorDiff += (desired->blueBits - current->blueBits) *
-                             (desired->blueBits - current->blueBits);
-            }
-        }
-
-        // Calculate non-color channel size difference value
-        {
-            extraDiff = 0;
-
-            if (desired->alphaBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->alphaBits - current->alphaBits) *
-                             (desired->alphaBits - current->alphaBits);
-            }
-
-            if (desired->depthBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->depthBits - current->depthBits) *
-                             (desired->depthBits - current->depthBits);
-            }
-
-            if (desired->stencilBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->stencilBits - current->stencilBits) *
-                             (desired->stencilBits - current->stencilBits);
-            }
-
-            if (desired->accumRedBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->accumRedBits - current->accumRedBits) *
-                             (desired->accumRedBits - current->accumRedBits);
-            }
-
-            if (desired->accumGreenBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
-                             (desired->accumGreenBits - current->accumGreenBits);
-            }
-
-            if (desired->accumBlueBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
-                             (desired->accumBlueBits - current->accumBlueBits);
-            }
-
-            if (desired->accumAlphaBits != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
-                             (desired->accumAlphaBits - current->accumAlphaBits);
-            }
-
-            if (desired->samples != GLFW_DONT_CARE)
-            {
-                extraDiff += (desired->samples - current->samples) *
-                             (desired->samples - current->samples);
-            }
-
-            if (desired->sRGB && !current->sRGB)
-                extraDiff++;
-        }
-
-        // Figure out if the current one is better than the best one found so far
-        // Least number of missing buffers is the most important heuristic,
-        // then color buffer size match and lastly size match for other buffers
-
-        if (missing < leastMissing)
-            closest = current;
-        else if (missing == leastMissing)
-        {
-            if ((colorDiff < leastColorDiff) ||
-                (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
-            {
-                closest = current;
-            }
-        }
-
-        if (current == closest)
-        {
-            leastMissing = missing;
-            leastColorDiff = colorDiff;
-            leastExtraDiff = extraDiff;
-        }
-    }
-
-    return closest;
-}
-
-// Retrieves the attributes of the current context
-//
-GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
-                                    const _GLFWctxconfig* ctxconfig)
-{
-    int i;
-    _GLFWwindow* previous;
-    const char* version;
-    const char* prefixes[] =
-    {
-        "OpenGL ES-CM ",
-        "OpenGL ES-CL ",
-        "OpenGL ES ",
-        NULL
-    };
-
-    window->context.source = ctxconfig->source;
-    window->context.client = GLFW_OPENGL_API;
-
-    previous = _glfwPlatformGetTls(&_glfw.contextSlot);
-    glfwMakeContextCurrent((GLFWwindow*) window);
-
-    window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
-        window->context.getProcAddress("glGetIntegerv");
-    window->context.GetString = (PFNGLGETSTRINGPROC)
-        window->context.getProcAddress("glGetString");
-    if (!window->context.GetIntegerv || !window->context.GetString)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
-        glfwMakeContextCurrent((GLFWwindow*) previous);
-        return GLFW_FALSE;
-    }
-
-    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");
-        }
-
-        glfwMakeContextCurrent((GLFWwindow*) previous);
-        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");
-        }
-
-        glfwMakeContextCurrent((GLFWwindow*) previous);
-        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);
-        }
-
-        glfwMakeContextCurrent((GLFWwindow*) previous);
-        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->context.GetStringi = (PFNGLGETSTRINGIPROC)
-            window->context.getProcAddress("glGetStringi");
-        if (!window->context.GetStringi)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Entry point retrieval is broken");
-            glfwMakeContextCurrent((GLFWwindow*) previous);
-            return GLFW_FALSE;
-        }
-    }
-
-    if (window->context.client == GLFW_OPENGL_API)
-    {
-        // Read back context flags (OpenGL 3.0 and above)
-        if (window->context.major >= 3)
-        {
-            GLint flags;
-            window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
-
-            if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
-                window->context.forward = GLFW_TRUE;
-
-            if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
-                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 = 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 >= 4 ||
-            (window->context.major == 3 && window->context.minor >= 2))
-        {
-            GLint mask;
-            window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
-
-            if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
-                window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
-            else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
-                window->context.profile = GLFW_OPENGL_CORE_PROFILE;
-            else if (glfwExtensionSupported("GL_ARB_compatibility"))
-            {
-                // HACK: This is a workaround for the compatibility profile bit
-                //       not being set in the context flags if an OpenGL 3.2+
-                //       context was created without having requested a specific
-                //       version
-                window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
-            }
-        }
-
-        // Read back robustness strategy
-        if (glfwExtensionSupported("GL_ARB_robustness"))
-        {
-            // NOTE: We avoid using the context flags for detection, as they are
-            //       only present from 3.0 while the extension applies from 1.1
-
-            GLint 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;
-            else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
-                window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
-        }
-    }
-    else
-    {
-        // Read back robustness strategy
-        if (glfwExtensionSupported("GL_EXT_robustness"))
-        {
-            // NOTE: The values of these constants match those of the OpenGL ARB
-            //       one, so we can reuse them here
-
-            GLint 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;
-            else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
-                window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
-        }
-    }
-
-    if (glfwExtensionSupported("GL_KHR_context_flush_control"))
-    {
-        GLint 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;
-    }
-
-    // Clearing the front buffer to black to avoid garbage pixels left over from
-    // previous uses of our bit of VRAM
-    {
-        PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
-            window->context.getProcAddress("glClear");
-        glClear(GL_COLOR_BUFFER_BIT);
-        window->context.swapBuffers(window);
-    }
-
-    glfwMakeContextCurrent((GLFWwindow*) previous);
-    return GLFW_TRUE;
-}
-
-// Searches an extension string for the specified extension
-//
-GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
-{
-    const char* start = extensions;
-
-    for (;;)
-    {
-        const char* where;
-        const char* terminator;
-
-        where = strstr(start, string);
-        if (!where)
-            return GLFW_FALSE;
-
-        terminator = where + strlen(string);
-        if (where == start || *(where - 1) == ' ')
-        {
-            if (*terminator == ' ' || *terminator == '\0')
-                break;
-        }
-
-        start = terminator;
-    }
-
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window && window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
-                        "Cannot make current with a window that has no OpenGL or OpenGL ES context");
-        return;
-    }
-
-    if (previous)
-    {
-        if (!window || window->context.source != previous->context.source)
-            previous->context.makeCurrent(NULL);
-    }
-
-    if (window)
-        window->context.makeCurrent(window);
-}
-
-GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return _glfwPlatformGetTls(&_glfw.contextSlot);
-}
-
-GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
-                        "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
-        return;
-    }
-
-    window->context.swapBuffers(window);
-}
-
-GLFWAPI void glfwSwapInterval(int interval)
-{
-    _GLFWwindow* window;
-
-    _GLFW_REQUIRE_INIT();
-
-    window = _glfwPlatformGetTls(&_glfw.contextSlot);
-    if (!window)
-    {
-        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
-                        "Cannot set swap interval without a current OpenGL or OpenGL ES context");
-        return;
-    }
-
-    window->context.swapInterval(interval);
-}
-
-GLFWAPI int glfwExtensionSupported(const char* extension)
-{
-    _GLFWwindow* window;
-    assert(extension != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    window = _glfwPlatformGetTls(&_glfw.contextSlot);
-    if (!window)
-    {
-        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
-                        "Cannot query extension without a current OpenGL or OpenGL ES context");
-        return GLFW_FALSE;
-    }
-
-    if (*extension == '\0')
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
-        return GLFW_FALSE;
-    }
-
-    if (window->context.major >= 3)
-    {
-        int i;
-        GLint count;
-
-        // Check if extension is in the modern OpenGL extensions string list
-
-        window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
-
-        for (i = 0;  i < count;  i++)
-        {
-            const char* en = (const char*)
-                window->context.GetStringi(GL_EXTENSIONS, i);
-            if (!en)
-            {
-                _glfwInputError(GLFW_PLATFORM_ERROR,
-                                "Extension string retrieval is broken");
-                return GLFW_FALSE;
-            }
-
-            if (strcmp(en, extension) == 0)
-                return GLFW_TRUE;
-        }
-    }
-    else
-    {
-        // Check if extension is in the old style OpenGL extensions string
-
-        const char* extensions = (const char*)
-            window->context.GetString(GL_EXTENSIONS);
-        if (!extensions)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Extension string retrieval is broken");
-            return GLFW_FALSE;
-        }
-
-        if (_glfwStringInExtensionString(extension, extensions))
-            return GLFW_TRUE;
-    }
-
-    // Check if extension is in the platform-specific string
-    return window->context.extensionSupported(extension);
-}
-
-GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
-{
-    _GLFWwindow* window;
-    assert(procname != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    window = _glfwPlatformGetTls(&_glfw.contextSlot);
-    if (!window)
-    {
-        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
-                        "Cannot query entry point without a current OpenGL or OpenGL ES context");
-        return NULL;
-    }
-
-    return window->context.getProcAddress(procname);
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Checks whether the desired context attributes are valid
+//
+// This function checks things like whether the specified client API version
+// exists and whether all relevant options have supported and non-conflicting
+// values
+//
+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
+{
+    if (ctxconfig->share)
+    {
+        if (ctxconfig->client == GLFW_NO_API ||
+            ctxconfig->share->context.client == GLFW_NO_API)
+        {
+            _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+            return GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
+        ctxconfig->source != GLFW_EGL_CONTEXT_API &&
+        ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM,
+                        "Invalid context creation API 0x%08X",
+                        ctxconfig->source);
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->client != GLFW_NO_API &&
+        ctxconfig->client != GLFW_OPENGL_API &&
+        ctxconfig->client != GLFW_OPENGL_ES_API)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM,
+                        "Invalid client API 0x%08X",
+                        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) ||
+            (ctxconfig->major == 3 && ctxconfig->minor > 3))
+        {
+            // OpenGL 1.0 is the smallest valid version
+            // 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",
+                            ctxconfig->major, ctxconfig->minor);
+            return GLFW_FALSE;
+        }
+
+        if (ctxconfig->profile)
+        {
+            if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
+                ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
+            {
+                _glfwInputError(GLFW_INVALID_ENUM,
+                                "Invalid OpenGL profile 0x%08X",
+                                ctxconfig->profile);
+                return GLFW_FALSE;
+            }
+
+            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 are only defined for OpenGL version 3.2 and above");
+                return GLFW_FALSE;
+            }
+        }
+
+        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 is only defined for OpenGL version 3.0 and above");
+            return GLFW_FALSE;
+        }
+    }
+    else if (ctxconfig->client == GLFW_OPENGL_ES_API)
+    {
+        if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
+            (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
+            (ctxconfig->major == 2 && ctxconfig->minor > 0))
+        {
+            // 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
+            // For now, let everything else through
+
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid OpenGL ES version %i.%i",
+                            ctxconfig->major, ctxconfig->minor);
+            return GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->robustness)
+    {
+        if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
+            ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
+        {
+            _glfwInputError(GLFW_INVALID_ENUM,
+                            "Invalid context robustness mode 0x%08X",
+                            ctxconfig->robustness);
+            return GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->release)
+    {
+        if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
+            ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
+        {
+            _glfwInputError(GLFW_INVALID_ENUM,
+                            "Invalid context release behavior 0x%08X",
+                            ctxconfig->release);
+            return GLFW_FALSE;
+        }
+    }
+
+    return GLFW_TRUE;
+}
+
+// Chooses the framebuffer config that best matches the desired one
+//
+const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
+                                         const _GLFWfbconfig* alternatives,
+                                         unsigned int count)
+{
+    unsigned int i;
+    unsigned int missing, leastMissing = UINT_MAX;
+    unsigned int colorDiff, leastColorDiff = UINT_MAX;
+    unsigned int extraDiff, leastExtraDiff = UINT_MAX;
+    const _GLFWfbconfig* current;
+    const _GLFWfbconfig* closest = NULL;
+
+    for (i = 0;  i < count;  i++)
+    {
+        current = alternatives + i;
+
+        if (desired->stereo > 0 && current->stereo == 0)
+        {
+            // Stereo is a hard constraint
+            continue;
+        }
+
+        if (desired->doublebuffer != current->doublebuffer)
+        {
+            // Double buffering is a hard constraint
+            continue;
+        }
+
+        // Count number of missing buffers
+        {
+            missing = 0;
+
+            if (desired->alphaBits > 0 && current->alphaBits == 0)
+                missing++;
+
+            if (desired->depthBits > 0 && current->depthBits == 0)
+                missing++;
+
+            if (desired->stencilBits > 0 && current->stencilBits == 0)
+                missing++;
+
+            if (desired->auxBuffers > 0 &&
+                current->auxBuffers < desired->auxBuffers)
+            {
+                missing += desired->auxBuffers - current->auxBuffers;
+            }
+
+            if (desired->samples > 0 && current->samples == 0)
+            {
+                // Technically, several multisampling buffers could be
+                // involved, but that's a lower level implementation detail and
+                // not important to us here, so we count them as one
+                missing++;
+            }
+
+            if (desired->transparent != current->transparent)
+                missing++;
+        }
+
+        // These polynomials make many small channel size differences matter
+        // less than one large channel size difference
+
+        // Calculate color channel size difference value
+        {
+            colorDiff = 0;
+
+            if (desired->redBits != GLFW_DONT_CARE)
+            {
+                colorDiff += (desired->redBits - current->redBits) *
+                             (desired->redBits - current->redBits);
+            }
+
+            if (desired->greenBits != GLFW_DONT_CARE)
+            {
+                colorDiff += (desired->greenBits - current->greenBits) *
+                             (desired->greenBits - current->greenBits);
+            }
+
+            if (desired->blueBits != GLFW_DONT_CARE)
+            {
+                colorDiff += (desired->blueBits - current->blueBits) *
+                             (desired->blueBits - current->blueBits);
+            }
+        }
+
+        // Calculate non-color channel size difference value
+        {
+            extraDiff = 0;
+
+            if (desired->alphaBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->alphaBits - current->alphaBits) *
+                             (desired->alphaBits - current->alphaBits);
+            }
+
+            if (desired->depthBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->depthBits - current->depthBits) *
+                             (desired->depthBits - current->depthBits);
+            }
+
+            if (desired->stencilBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->stencilBits - current->stencilBits) *
+                             (desired->stencilBits - current->stencilBits);
+            }
+
+            if (desired->accumRedBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->accumRedBits - current->accumRedBits) *
+                             (desired->accumRedBits - current->accumRedBits);
+            }
+
+            if (desired->accumGreenBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
+                             (desired->accumGreenBits - current->accumGreenBits);
+            }
+
+            if (desired->accumBlueBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
+                             (desired->accumBlueBits - current->accumBlueBits);
+            }
+
+            if (desired->accumAlphaBits != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
+                             (desired->accumAlphaBits - current->accumAlphaBits);
+            }
+
+            if (desired->samples != GLFW_DONT_CARE)
+            {
+                extraDiff += (desired->samples - current->samples) *
+                             (desired->samples - current->samples);
+            }
+
+            if (desired->sRGB && !current->sRGB)
+                extraDiff++;
+        }
+
+        // Figure out if the current one is better than the best one found so far
+        // Least number of missing buffers is the most important heuristic,
+        // then color buffer size match and lastly size match for other buffers
+
+        if (missing < leastMissing)
+            closest = current;
+        else if (missing == leastMissing)
+        {
+            if ((colorDiff < leastColorDiff) ||
+                (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
+            {
+                closest = current;
+            }
+        }
+
+        if (current == closest)
+        {
+            leastMissing = missing;
+            leastColorDiff = colorDiff;
+            leastExtraDiff = extraDiff;
+        }
+    }
+
+    return closest;
+}
+
+// Retrieves the attributes of the current context
+//
+GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
+                                    const _GLFWctxconfig* ctxconfig)
+{
+    int i;
+    _GLFWwindow* previous;
+    const char* version;
+    const char* prefixes[] =
+    {
+        "OpenGL ES-CM ",
+        "OpenGL ES-CL ",
+        "OpenGL ES ",
+        NULL
+    };
+
+    window->context.source = ctxconfig->source;
+    window->context.client = GLFW_OPENGL_API;
+
+    previous = _glfwPlatformGetTls(&_glfw.contextSlot);
+    glfwMakeContextCurrent((GLFWwindow*) window);
+
+    window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
+        window->context.getProcAddress("glGetIntegerv");
+    window->context.GetString = (PFNGLGETSTRINGPROC)
+        window->context.getProcAddress("glGetString");
+    if (!window->context.GetIntegerv || !window->context.GetString)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
+        glfwMakeContextCurrent((GLFWwindow*) previous);
+        return GLFW_FALSE;
+    }
+
+    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");
+        }
+
+        glfwMakeContextCurrent((GLFWwindow*) previous);
+        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");
+        }
+
+        glfwMakeContextCurrent((GLFWwindow*) previous);
+        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);
+        }
+
+        glfwMakeContextCurrent((GLFWwindow*) previous);
+        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->context.GetStringi = (PFNGLGETSTRINGIPROC)
+            window->context.getProcAddress("glGetStringi");
+        if (!window->context.GetStringi)
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Entry point retrieval is broken");
+            glfwMakeContextCurrent((GLFWwindow*) previous);
+            return GLFW_FALSE;
+        }
+    }
+
+    if (window->context.client == GLFW_OPENGL_API)
+    {
+        // Read back context flags (OpenGL 3.0 and above)
+        if (window->context.major >= 3)
+        {
+            GLint flags;
+            window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
+
+            if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
+                window->context.forward = GLFW_TRUE;
+
+            if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
+                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 = 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 >= 4 ||
+            (window->context.major == 3 && window->context.minor >= 2))
+        {
+            GLint mask;
+            window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
+
+            if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
+                window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
+            else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
+                window->context.profile = GLFW_OPENGL_CORE_PROFILE;
+            else if (glfwExtensionSupported("GL_ARB_compatibility"))
+            {
+                // HACK: This is a workaround for the compatibility profile bit
+                //       not being set in the context flags if an OpenGL 3.2+
+                //       context was created without having requested a specific
+                //       version
+                window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
+            }
+        }
+
+        // Read back robustness strategy
+        if (glfwExtensionSupported("GL_ARB_robustness"))
+        {
+            // NOTE: We avoid using the context flags for detection, as they are
+            //       only present from 3.0 while the extension applies from 1.1
+
+            GLint 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;
+            else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
+                window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
+        }
+    }
+    else
+    {
+        // Read back robustness strategy
+        if (glfwExtensionSupported("GL_EXT_robustness"))
+        {
+            // NOTE: The values of these constants match those of the OpenGL ARB
+            //       one, so we can reuse them here
+
+            GLint 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;
+            else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
+                window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
+        }
+    }
+
+    if (glfwExtensionSupported("GL_KHR_context_flush_control"))
+    {
+        GLint 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;
+    }
+
+    // Clearing the front buffer to black to avoid garbage pixels left over from
+    // previous uses of our bit of VRAM
+    {
+        PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
+            window->context.getProcAddress("glClear");
+        glClear(GL_COLOR_BUFFER_BIT);
+        window->context.swapBuffers(window);
+    }
+
+    glfwMakeContextCurrent((GLFWwindow*) previous);
+    return GLFW_TRUE;
+}
+
+// Searches an extension string for the specified extension
+//
+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
+{
+    const char* start = extensions;
+
+    for (;;)
+    {
+        const char* where;
+        const char* terminator;
+
+        where = strstr(start, string);
+        if (!where)
+            return GLFW_FALSE;
+
+        terminator = where + strlen(string);
+        if (where == start || *(where - 1) == ' ')
+        {
+            if (*terminator == ' ' || *terminator == '\0')
+                break;
+        }
+
+        start = terminator;
+    }
+
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window && window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
+                        "Cannot make current with a window that has no OpenGL or OpenGL ES context");
+        return;
+    }
+
+    if (previous)
+    {
+        if (!window || window->context.source != previous->context.source)
+            previous->context.makeCurrent(NULL);
+    }
+
+    if (window)
+        window->context.makeCurrent(window);
+}
+
+GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return _glfwPlatformGetTls(&_glfw.contextSlot);
+}
+
+GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
+                        "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
+        return;
+    }
+
+    window->context.swapBuffers(window);
+}
+
+GLFWAPI void glfwSwapInterval(int interval)
+{
+    _GLFWwindow* window;
+
+    _GLFW_REQUIRE_INIT();
+
+    window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    if (!window)
+    {
+        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+                        "Cannot set swap interval without a current OpenGL or OpenGL ES context");
+        return;
+    }
+
+    window->context.swapInterval(interval);
+}
+
+GLFWAPI int glfwExtensionSupported(const char* extension)
+{
+    _GLFWwindow* window;
+    assert(extension != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    if (!window)
+    {
+        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+                        "Cannot query extension without a current OpenGL or OpenGL ES context");
+        return GLFW_FALSE;
+    }
+
+    if (*extension == '\0')
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
+        return GLFW_FALSE;
+    }
+
+    if (window->context.major >= 3)
+    {
+        int i;
+        GLint count;
+
+        // Check if extension is in the modern OpenGL extensions string list
+
+        window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
+
+        for (i = 0;  i < count;  i++)
+        {
+            const char* en = (const char*)
+                window->context.GetStringi(GL_EXTENSIONS, i);
+            if (!en)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Extension string retrieval is broken");
+                return GLFW_FALSE;
+            }
+
+            if (strcmp(en, extension) == 0)
+                return GLFW_TRUE;
+        }
+    }
+    else
+    {
+        // Check if extension is in the old style OpenGL extensions string
+
+        const char* extensions = (const char*)
+            window->context.GetString(GL_EXTENSIONS);
+        if (!extensions)
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Extension string retrieval is broken");
+            return GLFW_FALSE;
+        }
+
+        if (_glfwStringInExtensionString(extension, extensions))
+            return GLFW_TRUE;
+    }
+
+    // Check if extension is in the platform-specific string
+    return window->context.extensionSupported(extension);
+}
+
+GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
+{
+    _GLFWwindow* window;
+    assert(procname != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    if (!window)
+    {
+        _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
+                        "Cannot query entry point without a current OpenGL or OpenGL ES context");
+        return NULL;
+    }
+
+    return window->context.getProcAddress(procname);
+}
+
diff --git a/glfw/src/egl_context.c b/glfw/src/egl_context.c
--- a/glfw/src/egl_context.c
+++ b/glfw/src/egl_context.c
@@ -1,789 +1,789 @@
-//========================================================================
-// GLFW 3.3 EGL - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#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* getEGLErrorString(EGLint error)
-{
-    switch (error)
-    {
-        case EGL_SUCCESS:
-            return "Success";
-        case EGL_NOT_INITIALIZED:
-            return "EGL is not or could not be initialized";
-        case EGL_BAD_ACCESS:
-            return "EGL cannot access a requested resource";
-        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";
-        case EGL_BAD_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";
-        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";
-        case EGL_BAD_DISPLAY:
-            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";
-        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";
-        case EGL_BAD_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";
-    }
-}
-
-// Returns the specified attribute of the specified EGLConfig
-//
-static int getEGLConfigAttrib(EGLConfig config, int attrib)
-{
-    int value;
-    eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
-    return value;
-}
-
-// Return the EGLConfig most closely matching the specified hints
-//
-static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
-                                const _GLFWfbconfig* desired,
-                                EGLConfig* result)
-{
-    EGLConfig* nativeConfigs;
-    _GLFWfbconfig* usableConfigs;
-    const _GLFWfbconfig* closest;
-    int i, nativeCount, usableCount;
-
-    eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
-    if (!nativeCount)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
-        return GLFW_FALSE;
-    }
-
-    nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
-    eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
-
-    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
-    usableCount = 0;
-
-    for (i = 0;  i < nativeCount;  i++)
-    {
-        const EGLConfig n = nativeConfigs[i];
-        _GLFWfbconfig* u = usableConfigs + usableCount;
-
-        // Only consider RGB(A) EGLConfigs
-        if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
-            continue;
-
-        // Only consider window EGLConfigs
-        if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
-            continue;
-
-#if defined(_GLFW_X11)
-        {
-            XVisualInfo vi = {0};
-
-            // Only consider EGLConfigs with associated Visuals
-            vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
-            if (!vi.visualid)
-                continue;
-
-            if (desired->transparent)
-            {
-                int count;
-                XVisualInfo* vis =
-                    XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
-                if (vis)
-                {
-                    u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
-                    XFree(vis);
-                }
-            }
-        }
-#endif // _GLFW_X11
-
-        if (ctxconfig->client == GLFW_OPENGL_ES_API)
-        {
-            if (ctxconfig->major == 1)
-            {
-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
-                    continue;
-            }
-            else
-            {
-                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
-                    continue;
-            }
-        }
-        else if (ctxconfig->client == GLFW_OPENGL_API)
-        {
-            if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
-                continue;
-        }
-
-        u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
-        u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
-        u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
-
-        u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
-        u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
-        u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
-
-        u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
-        u->doublebuffer = GLFW_TRUE;
-
-        u->handle = (uintptr_t) n;
-        usableCount++;
-    }
-
-    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
-    if (closest)
-        *result = (EGLConfig) closest->handle;
-
-    free(nativeConfigs);
-    free(usableConfigs);
-
-    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;
-        }
-    }
-
-    _glfwPlatformSetTls(&_glfw.contextSlot, window);
-}
-
-static void swapBuffersEGL(_GLFWwindow* window)
-{
-    if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
-    {
-        _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 = _glfwPlatformGetTls(&_glfw.contextSlot);
-
-    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
-//
-GLFWbool _glfwInitEGL(void)
-{
-    int i;
-    const char* sonames[] =
-    {
-#if defined(_GLFW_EGL_LIBRARY)
-        _GLFW_EGL_LIBRARY,
-#elif defined(_GLFW_WIN32)
-        "libEGL.dll",
-        "EGL.dll",
-#elif defined(_GLFW_COCOA)
-        "libEGL.dylib",
-#elif defined(__CYGWIN__)
-        "libEGL-1.so",
-#else
-        "libEGL.so.1",
-#endif
-        NULL
-    };
-
-    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 = (PFN_eglGetConfigAttrib)
-        _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
-    _glfw.egl.GetConfigs = (PFN_eglGetConfigs)
-        _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
-    _glfw.egl.GetDisplay = (PFN_eglGetDisplay)
-        _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
-    _glfw.egl.GetError = (PFN_eglGetError)
-        _glfw_dlsym(_glfw.egl.handle, "eglGetError");
-    _glfw.egl.Initialize = (PFN_eglInitialize)
-        _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
-    _glfw.egl.Terminate = (PFN_eglTerminate)
-        _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
-    _glfw.egl.BindAPI = (PFN_eglBindAPI)
-        _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
-    _glfw.egl.CreateContext = (PFN_eglCreateContext)
-        _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
-    _glfw.egl.DestroySurface = (PFN_eglDestroySurface)
-        _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
-    _glfw.egl.DestroyContext = (PFN_eglDestroyContext)
-        _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
-    _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
-        _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
-    _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
-        _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
-    _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
-        _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
-    _glfw.egl.SwapInterval = (PFN_eglSwapInterval)
-        _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
-    _glfw.egl.QueryString = (PFN_eglQueryString)
-        _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
-    _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
-        _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",
-                        getEGLErrorString(eglGetError()));
-
-        _glfwTerminateEGL();
-        return GLFW_FALSE;
-    }
-
-    if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "EGL: Failed to initialize EGL: %s",
-                        getEGLErrorString(eglGetError()));
-
-        _glfwTerminateEGL();
-        return GLFW_FALSE;
-    }
-
-    _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");
-    _glfw.egl.KHR_get_all_proc_addresses =
-        extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
-    _glfw.egl.KHR_context_flush_control =
-        extensionSupportedEGL("EGL_KHR_context_flush_control");
-
-    return GLFW_TRUE;
-}
-
-// Terminate EGL
-//
-void _glfwTerminateEGL(void)
-{
-    if (_glfw.egl.display)
-    {
-        eglTerminate(_glfw.egl.display);
-        _glfw.egl.display = EGL_NO_DISPLAY;
-    }
-
-    if (_glfw.egl.handle)
-    {
-        _glfw_dlclose(_glfw.egl.handle);
-        _glfw.egl.handle = NULL;
-    }
-}
-
-#define setAttrib(a, v) \
-{ \
-    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[index++] = a; \
-    attribs[index++] = v; \
-}
-
-// Create the OpenGL or OpenGL ES context
-//
-GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig)
-{
-    EGLint attribs[40];
-    EGLConfig config;
-    EGLContext share = NULL;
-    int index = 0;
-
-    if (!_glfw.egl.display)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->share)
-        share = ctxconfig->share->context.egl.handle;
-
-    if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "EGL: Failed to find a suitable EGLConfig");
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->client == GLFW_OPENGL_ES_API)
-    {
-        if (!eglBindAPI(EGL_OPENGL_ES_API))
-        {
-            _glfwInputError(GLFW_API_UNAVAILABLE,
-                            "EGL: Failed to bind OpenGL ES: %s",
-                            getEGLErrorString(eglGetError()));
-            return GLFW_FALSE;
-        }
-    }
-    else
-    {
-        if (!eglBindAPI(EGL_OPENGL_API))
-        {
-            _glfwInputError(GLFW_API_UNAVAILABLE,
-                            "EGL: Failed to bind OpenGL: %s",
-                            getEGLErrorString(eglGetError()));
-            return GLFW_FALSE;
-        }
-    }
-
-    if (_glfw.egl.KHR_create_context)
-    {
-        int mask = 0, flags = 0;
-
-        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->debug)
-            flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
-
-        if (ctxconfig->robustness)
-        {
-            if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
-            {
-                setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
-                          EGL_NO_RESET_NOTIFICATION_KHR);
-            }
-            else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
-            {
-                setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
-                          EGL_LOSE_CONTEXT_ON_RESET_KHR);
-            }
-
-            flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
-        }
-
-        if (ctxconfig->noerror)
-        {
-            if (_glfw.egl.KHR_create_context_no_error)
-                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
-        }
-
-        if (ctxconfig->major != 1 || ctxconfig->minor != 0)
-        {
-            setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
-            setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
-        }
-
-        if (mask)
-            setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
-
-        if (flags)
-            setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
-    }
-    else
-    {
-        if (ctxconfig->client == GLFW_OPENGL_ES_API)
-            setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
-    }
-
-    if (_glfw.egl.KHR_context_flush_control)
-    {
-        if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
-        {
-            setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
-                      EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
-        }
-        else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
-        {
-            setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
-                      EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
-        }
-    }
-
-    setAttrib(EGL_NONE, EGL_NONE);
-
-    window->context.egl.handle = eglCreateContext(_glfw.egl.display,
-                                                  config, share, attribs);
-
-    if (window->context.egl.handle == EGL_NO_CONTEXT)
-    {
-        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                        "EGL: Failed to create context: %s",
-                        getEGLErrorString(eglGetError()));
-        return GLFW_FALSE;
-    }
-
-    // Set up attributes for surface creation
-    {
-        int index = 0;
-
-        if (fbconfig->sRGB)
-        {
-            if (_glfw.egl.KHR_gl_colorspace)
-                setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
-        }
-
-        setAttrib(EGL_NONE, EGL_NONE);
-    }
-
-    window->context.egl.surface =
-        eglCreateWindowSurface(_glfw.egl.display,
-                               config,
-                               _GLFW_EGL_NATIVE_WINDOW,
-                               attribs);
-    if (window->context.egl.surface == EGL_NO_SURFACE)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "EGL: Failed to create window surface: %s",
-                        getEGLErrorString(eglGetError()));
-        return GLFW_FALSE;
-    }
-
-    window->context.egl.config = config;
-
-    // Load the appropriate client library
-    if (!_glfw.egl.KHR_get_all_proc_addresses)
-    {
-        int i;
-        const char** sonames;
-        const char* es1sonames[] =
-        {
-#if defined(_GLFW_GLESV1_LIBRARY)
-            _GLFW_GLESV1_LIBRARY,
-#elif defined(_GLFW_WIN32)
-            "GLESv1_CM.dll",
-            "libGLES_CM.dll",
-#elif defined(_GLFW_COCOA)
-            "libGLESv1_CM.dylib",
-#else
-            "libGLESv1_CM.so.1",
-            "libGLES_CM.so.1",
-#endif
-            NULL
-        };
-        const char* es2sonames[] =
-        {
-#if defined(_GLFW_GLESV2_LIBRARY)
-            _GLFW_GLESV2_LIBRARY,
-#elif defined(_GLFW_WIN32)
-            "GLESv2.dll",
-            "libGLESv2.dll",
-#elif defined(_GLFW_COCOA)
-            "libGLESv2.dylib",
-#elif defined(__CYGWIN__)
-            "libGLESv2-2.so",
-#else
-            "libGLESv2.so.2",
-#endif
-            NULL
-        };
-        const char* glsonames[] =
-        {
-#if defined(_GLFW_OPENGL_LIBRARY)
-            _GLFW_OPENGL_LIBRARY,
-#elif defined(_GLFW_WIN32)
-#elif defined(_GLFW_COCOA)
-#else
-            "libGL.so.1",
-#endif
-            NULL
-        };
-
-        if (ctxconfig->client == GLFW_OPENGL_ES_API)
-        {
-            if (ctxconfig->major == 1)
-                sonames = es1sonames;
-            else
-                sonames = es2sonames;
-        }
-        else
-            sonames = glsonames;
-
-        for (i = 0;  sonames[i];  i++)
-        {
-            // 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;
-        }
-
-        if (!window->context.egl.client)
-        {
-            _glfwInputError(GLFW_API_UNAVAILABLE,
-                            "EGL: Failed to load client library");
-            return GLFW_FALSE;
-        }
-    }
-
-    window->context.makeCurrent = makeContextCurrentEGL;
-    window->context.swapBuffers = swapBuffersEGL;
-    window->context.swapInterval = swapIntervalEGL;
-    window->context.extensionSupported = extensionSupportedEGL;
-    window->context.getProcAddress = getProcAddressEGL;
-    window->context.destroy = destroyContextEGL;
-
-    return GLFW_TRUE;
-}
-
-#undef setAttrib
-
-// Returns the Visual and depth of the chosen EGLConfig
-//
-#if defined(_GLFW_X11)
-GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig,
-                              Visual** visual, int* depth)
-{
-    XVisualInfo* result;
-    XVisualInfo desired;
-    EGLConfig native;
-    EGLint visualID = 0, count = 0;
-    const long vimask = VisualScreenMask | VisualIDMask;
-
-    if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "EGL: Failed to find a suitable EGLConfig");
-        return GLFW_FALSE;
-    }
-
-    eglGetConfigAttrib(_glfw.egl.display, native,
-                       EGL_NATIVE_VISUAL_ID, &visualID);
-
-    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
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
-    return _glfw.egl.display;
-}
-
-GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_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);
-
-    if (window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-        return EGL_NO_SURFACE;
-    }
-
-    return window->context.egl.surface;
-}
-
+//========================================================================
+// GLFW 3.3 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#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* getEGLErrorString(EGLint error)
+{
+    switch (error)
+    {
+        case EGL_SUCCESS:
+            return "Success";
+        case EGL_NOT_INITIALIZED:
+            return "EGL is not or could not be initialized";
+        case EGL_BAD_ACCESS:
+            return "EGL cannot access a requested resource";
+        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";
+        case EGL_BAD_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";
+        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";
+        case EGL_BAD_DISPLAY:
+            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";
+        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";
+        case EGL_BAD_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";
+    }
+}
+
+// Returns the specified attribute of the specified EGLConfig
+//
+static int getEGLConfigAttrib(EGLConfig config, int attrib)
+{
+    int value;
+    eglGetConfigAttrib(_glfw.egl.display, config, attrib, &value);
+    return value;
+}
+
+// Return the EGLConfig most closely matching the specified hints
+//
+static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig,
+                                const _GLFWfbconfig* desired,
+                                EGLConfig* result)
+{
+    EGLConfig* nativeConfigs;
+    _GLFWfbconfig* usableConfigs;
+    const _GLFWfbconfig* closest;
+    int i, nativeCount, usableCount;
+
+    eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount);
+    if (!nativeCount)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned");
+        return GLFW_FALSE;
+    }
+
+    nativeConfigs = calloc(nativeCount, sizeof(EGLConfig));
+    eglGetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount);
+
+    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+    usableCount = 0;
+
+    for (i = 0;  i < nativeCount;  i++)
+    {
+        const EGLConfig n = nativeConfigs[i];
+        _GLFWfbconfig* u = usableConfigs + usableCount;
+
+        // Only consider RGB(A) EGLConfigs
+        if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER)
+            continue;
+
+        // Only consider window EGLConfigs
+        if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT))
+            continue;
+
+#if defined(_GLFW_X11)
+        {
+            XVisualInfo vi = {0};
+
+            // Only consider EGLConfigs with associated Visuals
+            vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID);
+            if (!vi.visualid)
+                continue;
+
+            if (desired->transparent)
+            {
+                int count;
+                XVisualInfo* vis =
+                    XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count);
+                if (vis)
+                {
+                    u->transparent = _glfwIsVisualTransparentX11(vis[0].visual);
+                    XFree(vis);
+                }
+            }
+        }
+#endif // _GLFW_X11
+
+        if (ctxconfig->client == GLFW_OPENGL_ES_API)
+        {
+            if (ctxconfig->major == 1)
+            {
+                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT))
+                    continue;
+            }
+            else
+            {
+                if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT))
+                    continue;
+            }
+        }
+        else if (ctxconfig->client == GLFW_OPENGL_API)
+        {
+            if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT))
+                continue;
+        }
+
+        u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE);
+        u->greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE);
+        u->blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE);
+
+        u->alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE);
+        u->depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE);
+        u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE);
+
+        u->samples = getEGLConfigAttrib(n, EGL_SAMPLES);
+        u->doublebuffer = GLFW_TRUE;
+
+        u->handle = (uintptr_t) n;
+        usableCount++;
+    }
+
+    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
+    if (closest)
+        *result = (EGLConfig) closest->handle;
+
+    free(nativeConfigs);
+    free(usableConfigs);
+
+    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;
+        }
+    }
+
+    _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static void swapBuffersEGL(_GLFWwindow* window)
+{
+    if (window != _glfwPlatformGetTls(&_glfw.contextSlot))
+    {
+        _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 = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+    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
+//
+GLFWbool _glfwInitEGL(void)
+{
+    int i;
+    const char* sonames[] =
+    {
+#if defined(_GLFW_EGL_LIBRARY)
+        _GLFW_EGL_LIBRARY,
+#elif defined(_GLFW_WIN32)
+        "libEGL.dll",
+        "EGL.dll",
+#elif defined(_GLFW_COCOA)
+        "libEGL.dylib",
+#elif defined(__CYGWIN__)
+        "libEGL-1.so",
+#else
+        "libEGL.so.1",
+#endif
+        NULL
+    };
+
+    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 = (PFN_eglGetConfigAttrib)
+        _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
+    _glfw.egl.GetConfigs = (PFN_eglGetConfigs)
+        _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
+    _glfw.egl.GetDisplay = (PFN_eglGetDisplay)
+        _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
+    _glfw.egl.GetError = (PFN_eglGetError)
+        _glfw_dlsym(_glfw.egl.handle, "eglGetError");
+    _glfw.egl.Initialize = (PFN_eglInitialize)
+        _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
+    _glfw.egl.Terminate = (PFN_eglTerminate)
+        _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
+    _glfw.egl.BindAPI = (PFN_eglBindAPI)
+        _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
+    _glfw.egl.CreateContext = (PFN_eglCreateContext)
+        _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
+    _glfw.egl.DestroySurface = (PFN_eglDestroySurface)
+        _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
+    _glfw.egl.DestroyContext = (PFN_eglDestroyContext)
+        _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
+    _glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
+        _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
+    _glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
+        _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
+    _glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
+        _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
+    _glfw.egl.SwapInterval = (PFN_eglSwapInterval)
+        _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
+    _glfw.egl.QueryString = (PFN_eglQueryString)
+        _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
+    _glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
+        _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",
+                        getEGLErrorString(eglGetError()));
+
+        _glfwTerminateEGL();
+        return GLFW_FALSE;
+    }
+
+    if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor))
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "EGL: Failed to initialize EGL: %s",
+                        getEGLErrorString(eglGetError()));
+
+        _glfwTerminateEGL();
+        return GLFW_FALSE;
+    }
+
+    _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");
+    _glfw.egl.KHR_get_all_proc_addresses =
+        extensionSupportedEGL("EGL_KHR_get_all_proc_addresses");
+    _glfw.egl.KHR_context_flush_control =
+        extensionSupportedEGL("EGL_KHR_context_flush_control");
+
+    return GLFW_TRUE;
+}
+
+// Terminate EGL
+//
+void _glfwTerminateEGL(void)
+{
+    if (_glfw.egl.display)
+    {
+        eglTerminate(_glfw.egl.display);
+        _glfw.egl.display = EGL_NO_DISPLAY;
+    }
+
+    if (_glfw.egl.handle)
+    {
+        _glfw_dlclose(_glfw.egl.handle);
+        _glfw.egl.handle = NULL;
+    }
+}
+
+#define setAttrib(a, v) \
+{ \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+    attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig)
+{
+    EGLint attribs[40];
+    EGLConfig config;
+    EGLContext share = NULL;
+    int index = 0;
+
+    if (!_glfw.egl.display)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available");
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->share)
+        share = ctxconfig->share->context.egl.handle;
+
+    if (!chooseEGLConfig(ctxconfig, fbconfig, &config))
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "EGL: Failed to find a suitable EGLConfig");
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->client == GLFW_OPENGL_ES_API)
+    {
+        if (!eglBindAPI(EGL_OPENGL_ES_API))
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "EGL: Failed to bind OpenGL ES: %s",
+                            getEGLErrorString(eglGetError()));
+            return GLFW_FALSE;
+        }
+    }
+    else
+    {
+        if (!eglBindAPI(EGL_OPENGL_API))
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "EGL: Failed to bind OpenGL: %s",
+                            getEGLErrorString(eglGetError()));
+            return GLFW_FALSE;
+        }
+    }
+
+    if (_glfw.egl.KHR_create_context)
+    {
+        int mask = 0, flags = 0;
+
+        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->debug)
+            flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+
+        if (ctxconfig->robustness)
+        {
+            if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+            {
+                setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+                          EGL_NO_RESET_NOTIFICATION_KHR);
+            }
+            else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+            {
+                setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+                          EGL_LOSE_CONTEXT_ON_RESET_KHR);
+            }
+
+            flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+        }
+
+        if (ctxconfig->noerror)
+        {
+            if (_glfw.egl.KHR_create_context_no_error)
+                setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE);
+        }
+
+        if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+        {
+            setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
+            setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
+        }
+
+        if (mask)
+            setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
+
+        if (flags)
+            setAttrib(EGL_CONTEXT_FLAGS_KHR, flags);
+    }
+    else
+    {
+        if (ctxconfig->client == GLFW_OPENGL_ES_API)
+            setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
+    }
+
+    if (_glfw.egl.KHR_context_flush_control)
+    {
+        if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+        {
+            setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
+                      EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR);
+        }
+        else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+        {
+            setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR,
+                      EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR);
+        }
+    }
+
+    setAttrib(EGL_NONE, EGL_NONE);
+
+    window->context.egl.handle = eglCreateContext(_glfw.egl.display,
+                                                  config, share, attribs);
+
+    if (window->context.egl.handle == EGL_NO_CONTEXT)
+    {
+        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                        "EGL: Failed to create context: %s",
+                        getEGLErrorString(eglGetError()));
+        return GLFW_FALSE;
+    }
+
+    // Set up attributes for surface creation
+    {
+        int index = 0;
+
+        if (fbconfig->sRGB)
+        {
+            if (_glfw.egl.KHR_gl_colorspace)
+                setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
+        }
+
+        setAttrib(EGL_NONE, EGL_NONE);
+    }
+
+    window->context.egl.surface =
+        eglCreateWindowSurface(_glfw.egl.display,
+                               config,
+                               _GLFW_EGL_NATIVE_WINDOW,
+                               attribs);
+    if (window->context.egl.surface == EGL_NO_SURFACE)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "EGL: Failed to create window surface: %s",
+                        getEGLErrorString(eglGetError()));
+        return GLFW_FALSE;
+    }
+
+    window->context.egl.config = config;
+
+    // Load the appropriate client library
+    if (!_glfw.egl.KHR_get_all_proc_addresses)
+    {
+        int i;
+        const char** sonames;
+        const char* es1sonames[] =
+        {
+#if defined(_GLFW_GLESV1_LIBRARY)
+            _GLFW_GLESV1_LIBRARY,
+#elif defined(_GLFW_WIN32)
+            "GLESv1_CM.dll",
+            "libGLES_CM.dll",
+#elif defined(_GLFW_COCOA)
+            "libGLESv1_CM.dylib",
+#else
+            "libGLESv1_CM.so.1",
+            "libGLES_CM.so.1",
+#endif
+            NULL
+        };
+        const char* es2sonames[] =
+        {
+#if defined(_GLFW_GLESV2_LIBRARY)
+            _GLFW_GLESV2_LIBRARY,
+#elif defined(_GLFW_WIN32)
+            "GLESv2.dll",
+            "libGLESv2.dll",
+#elif defined(_GLFW_COCOA)
+            "libGLESv2.dylib",
+#elif defined(__CYGWIN__)
+            "libGLESv2-2.so",
+#else
+            "libGLESv2.so.2",
+#endif
+            NULL
+        };
+        const char* glsonames[] =
+        {
+#if defined(_GLFW_OPENGL_LIBRARY)
+            _GLFW_OPENGL_LIBRARY,
+#elif defined(_GLFW_WIN32)
+#elif defined(_GLFW_COCOA)
+#else
+            "libGL.so.1",
+#endif
+            NULL
+        };
+
+        if (ctxconfig->client == GLFW_OPENGL_ES_API)
+        {
+            if (ctxconfig->major == 1)
+                sonames = es1sonames;
+            else
+                sonames = es2sonames;
+        }
+        else
+            sonames = glsonames;
+
+        for (i = 0;  sonames[i];  i++)
+        {
+            // 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;
+        }
+
+        if (!window->context.egl.client)
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "EGL: Failed to load client library");
+            return GLFW_FALSE;
+        }
+    }
+
+    window->context.makeCurrent = makeContextCurrentEGL;
+    window->context.swapBuffers = swapBuffersEGL;
+    window->context.swapInterval = swapIntervalEGL;
+    window->context.extensionSupported = extensionSupportedEGL;
+    window->context.getProcAddress = getProcAddressEGL;
+    window->context.destroy = destroyContextEGL;
+
+    return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+// Returns the Visual and depth of the chosen EGLConfig
+//
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig,
+                              Visual** visual, int* depth)
+{
+    XVisualInfo* result;
+    XVisualInfo desired;
+    EGLConfig native;
+    EGLint visualID = 0, count = 0;
+    const long vimask = VisualScreenMask | VisualIDMask;
+
+    if (!chooseEGLConfig(ctxconfig, fbconfig, &native))
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "EGL: Failed to find a suitable EGLConfig");
+        return GLFW_FALSE;
+    }
+
+    eglGetConfigAttrib(_glfw.egl.display, native,
+                       EGL_NATIVE_VISUAL_ID, &visualID);
+
+    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
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI EGLDisplay glfwGetEGLDisplay(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_DISPLAY);
+    return _glfw.egl.display;
+}
+
+GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(EGL_NO_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);
+
+    if (window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+        return EGL_NO_SURFACE;
+    }
+
+    return window->context.egl.surface;
+}
+
diff --git a/glfw/src/egl_context.h b/glfw/src/egl_context.h
--- a/glfw/src/egl_context.h
+++ b/glfw/src/egl_context.h
@@ -1,215 +1,215 @@
-//========================================================================
-// GLFW 3.3 EGL - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-
-#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_COCOA)
- #define EGLAPIENTRY
-typedef void* EGLNativeDisplayType;
-typedef id 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;
-#else
- #error "No supported EGL platform selected"
-#endif
-
-#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)
-
-#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 EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
-#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
-#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
-
-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 * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
-typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
-typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
-typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
-typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
-typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
-typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
-typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(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       handle;
-   EGLSurface       surface;
-
-   void*            client;
-
-} _GLFWcontextEGL;
-
-// EGL-specific global data
-//
-typedef struct _GLFWlibraryEGL
-{
-    EGLDisplay      display;
-    EGLint          major, minor;
-    GLFWbool        prefix;
-
-    GLFWbool        KHR_create_context;
-    GLFWbool        KHR_create_context_no_error;
-    GLFWbool        KHR_gl_colorspace;
-    GLFWbool        KHR_get_all_proc_addresses;
-    GLFWbool        KHR_context_flush_control;
-
-    void*           handle;
-
-    PFN_eglGetConfigAttrib      GetConfigAttrib;
-    PFN_eglGetConfigs           GetConfigs;
-    PFN_eglGetDisplay           GetDisplay;
-    PFN_eglGetError             GetError;
-    PFN_eglInitialize           Initialize;
-    PFN_eglTerminate            Terminate;
-    PFN_eglBindAPI              BindAPI;
-    PFN_eglCreateContext        CreateContext;
-    PFN_eglDestroySurface       DestroySurface;
-    PFN_eglDestroyContext       DestroyContext;
-    PFN_eglCreateWindowSurface  CreateWindowSurface;
-    PFN_eglMakeCurrent          MakeCurrent;
-    PFN_eglSwapBuffers          SwapBuffers;
-    PFN_eglSwapInterval         SwapInterval;
-    PFN_eglQueryString          QueryString;
-    PFN_eglGetProcAddress       GetProcAddress;
-
-} _GLFWlibraryEGL;
-
-
-GLFWbool _glfwInitEGL(void);
-void _glfwTerminateEGL(void);
-GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig);
-#if defined(_GLFW_X11)
-GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig,
-                              Visual** visual, int* depth);
-#endif /*_GLFW_X11*/
-
+//========================================================================
+// GLFW 3.3 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+
+#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_COCOA)
+ #define EGLAPIENTRY
+typedef void* EGLNativeDisplayType;
+typedef id 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;
+#else
+ #error "No supported EGL platform selected"
+#endif
+
+#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)
+
+#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 EGL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x2097
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR 0
+#define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098
+
+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 * PFN_eglGetConfigAttrib)(EGLDisplay,EGLConfig,EGLint,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglGetConfigs)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
+typedef EGLDisplay (EGLAPIENTRY * PFN_eglGetDisplay)(EGLNativeDisplayType);
+typedef EGLint (EGLAPIENTRY * PFN_eglGetError)(void);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglInitialize)(EGLDisplay,EGLint*,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglTerminate)(EGLDisplay);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglBindAPI)(EGLenum);
+typedef EGLContext (EGLAPIENTRY * PFN_eglCreateContext)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroySurface)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglDestroyContext)(EGLDisplay,EGLContext);
+typedef EGLSurface (EGLAPIENTRY * PFN_eglCreateWindowSurface)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglMakeCurrent)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapBuffers)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFN_eglSwapInterval)(EGLDisplay,EGLint);
+typedef const char* (EGLAPIENTRY * PFN_eglQueryString)(EGLDisplay,EGLint);
+typedef GLFWglproc (EGLAPIENTRY * PFN_eglGetProcAddress)(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       handle;
+   EGLSurface       surface;
+
+   void*            client;
+
+} _GLFWcontextEGL;
+
+// EGL-specific global data
+//
+typedef struct _GLFWlibraryEGL
+{
+    EGLDisplay      display;
+    EGLint          major, minor;
+    GLFWbool        prefix;
+
+    GLFWbool        KHR_create_context;
+    GLFWbool        KHR_create_context_no_error;
+    GLFWbool        KHR_gl_colorspace;
+    GLFWbool        KHR_get_all_proc_addresses;
+    GLFWbool        KHR_context_flush_control;
+
+    void*           handle;
+
+    PFN_eglGetConfigAttrib      GetConfigAttrib;
+    PFN_eglGetConfigs           GetConfigs;
+    PFN_eglGetDisplay           GetDisplay;
+    PFN_eglGetError             GetError;
+    PFN_eglInitialize           Initialize;
+    PFN_eglTerminate            Terminate;
+    PFN_eglBindAPI              BindAPI;
+    PFN_eglCreateContext        CreateContext;
+    PFN_eglDestroySurface       DestroySurface;
+    PFN_eglDestroyContext       DestroyContext;
+    PFN_eglCreateWindowSurface  CreateWindowSurface;
+    PFN_eglMakeCurrent          MakeCurrent;
+    PFN_eglSwapBuffers          SwapBuffers;
+    PFN_eglSwapInterval         SwapInterval;
+    PFN_eglQueryString          QueryString;
+    PFN_eglGetProcAddress       GetProcAddress;
+
+} _GLFWlibraryEGL;
+
+
+GLFWbool _glfwInitEGL(void);
+void _glfwTerminateEGL(void);
+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig);
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig,
+                              Visual** visual, int* depth);
+#endif /*_GLFW_X11*/
+
diff --git a/glfw/src/glx_context.c b/glfw/src/glx_context.c
--- a/glfw/src/glx_context.c
+++ b/glfw/src/glx_context.c
@@ -1,698 +1,698 @@
-//========================================================================
-// GLFW 3.3 GLX - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#ifndef GLXBadProfileARB
- #define GLXBadProfileARB 13
-#endif
-
-
-// Returns the specified attribute of the specified GLXFBConfig
-//
-static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
-{
-    int value;
-    glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
-    return value;
-}
-
-// Return the GLXFBConfig most closely matching the specified hints
-//
-static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
-                                  GLXFBConfig* result)
-{
-    GLXFBConfig* nativeConfigs;
-    _GLFWfbconfig* usableConfigs;
-    const _GLFWfbconfig* closest;
-    int i, nativeCount, usableCount;
-    const char* vendor;
-    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 (vendor && strcmp(vendor, "Chromium") == 0)
-        trustWindowBit = GLFW_FALSE;
-
-    nativeConfigs =
-        glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
-    if (!nativeConfigs || !nativeCount)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
-        return GLFW_FALSE;
-    }
-
-    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
-    usableCount = 0;
-
-    for (i = 0;  i < nativeCount;  i++)
-    {
-        const GLXFBConfig n = nativeConfigs[i];
-        _GLFWfbconfig* u = usableConfigs + usableCount;
-
-        // Only consider RGBA GLXFBConfigs
-        if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
-            continue;
-
-        // Only consider window GLXFBConfigs
-        if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
-        {
-            if (trustWindowBit)
-                continue;
-        }
-
-        if (desired->transparent)
-        {
-            XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
-            if (vi)
-            {
-                u->transparent = _glfwIsVisualTransparentX11(vi->visual);
-                XFree(vi);
-            }
-        }
-
-        u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
-        u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
-        u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
-
-        u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
-        u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
-        u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_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 = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
-
-        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 = getGLXFBConfigAttrib(n, GLX_SAMPLES);
-
-        if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
-            u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
-
-        u->handle = (uintptr_t) n;
-        usableCount++;
-    }
-
-    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
-    if (closest)
-        *result = (GLXFBConfig) closest->handle;
-
-    XFree(nativeConfigs);
-    free(usableConfigs);
-
-    return closest != NULL;
-}
-
-// Create the OpenGL context using legacy API
-//
-static GLXContext createLegacyContextGLX(_GLFWwindow* window,
-                                         GLXFBConfig fbconfig,
-                                         GLXContext share)
-{
-    return glXCreateNewContext(_glfw.x11.display,
-                               fbconfig,
-                               GLX_RGBA_TYPE,
-                               share,
-                               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;
-        }
-    }
-
-    _glfwPlatformSetTls(&_glfw.contextSlot, window);
-}
-
-static void swapBuffersGLX(_GLFWwindow* window)
-{
-    glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
-}
-
-static void swapIntervalGLX(int interval)
-{
-    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
-
-    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 _glfw_dlsym(_glfw.glx.handle, procname);
-}
-
-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
-//
-GLFWbool _glfwInitGLX(void)
-{
-    int i;
-    const char* sonames[] =
-    {
-#if defined(_GLFW_GLX_LIBRARY)
-        _GLFW_GLX_LIBRARY,
-#elif defined(__CYGWIN__)
-        "libGL-1.so",
-#else
-        "libGL.so.1",
-        "libGL.so",
-#endif
-        NULL
-    };
-
-    if (_glfw.glx.handle)
-        return GLFW_TRUE;
-
-    for (i = 0;  sonames[i];  i++)
-    {
-        _glfw.glx.handle = _glfw_dlopen(sonames[i]);
-        if (_glfw.glx.handle)
-            break;
-    }
-
-    if (!_glfw.glx.handle)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
-        return GLFW_FALSE;
-    }
-
-    _glfw.glx.GetFBConfigs =
-        _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
-    _glfw.glx.GetFBConfigAttrib =
-        _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
-    _glfw.glx.GetClientString =
-        _glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
-    _glfw.glx.QueryExtension =
-        _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
-    _glfw.glx.QueryVersion =
-        _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
-    _glfw.glx.DestroyContext =
-        _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
-    _glfw.glx.MakeCurrent =
-        _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
-    _glfw.glx.SwapBuffers =
-        _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
-    _glfw.glx.QueryExtensionsString =
-        _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
-    _glfw.glx.CreateNewContext =
-        _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
-    _glfw.glx.CreateWindow =
-        _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
-    _glfw.glx.DestroyWindow =
-        _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
-    _glfw.glx.GetProcAddress =
-        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
-    _glfw.glx.GetProcAddressARB =
-        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
-    _glfw.glx.GetVisualFromFBConfig =
-        _glfw_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 GLFW_FALSE;
-    }
-
-    if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "GLX: Failed to query GLX version");
-        return GLFW_FALSE;
-    }
-
-    if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "GLX: GLX version 1.3 is required");
-        return GLFW_FALSE;
-    }
-
-    if (extensionSupportedGLX("GLX_EXT_swap_control"))
-    {
-        _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
-            getProcAddressGLX("glXSwapIntervalEXT");
-
-        if (_glfw.glx.SwapIntervalEXT)
-            _glfw.glx.EXT_swap_control = GLFW_TRUE;
-    }
-
-    if (extensionSupportedGLX("GLX_SGI_swap_control"))
-    {
-        _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
-            getProcAddressGLX("glXSwapIntervalSGI");
-
-        if (_glfw.glx.SwapIntervalSGI)
-            _glfw.glx.SGI_swap_control = GLFW_TRUE;
-    }
-
-    if (extensionSupportedGLX("GLX_MESA_swap_control"))
-    {
-        _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
-            getProcAddressGLX("glXSwapIntervalMESA");
-
-        if (_glfw.glx.SwapIntervalMESA)
-            _glfw.glx.MESA_swap_control = GLFW_TRUE;
-    }
-
-    if (extensionSupportedGLX("GLX_ARB_multisample"))
-        _glfw.glx.ARB_multisample = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
-        _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
-        _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_ARB_create_context"))
-    {
-        _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
-            getProcAddressGLX("glXCreateContextAttribsARB");
-
-        if (_glfw.glx.CreateContextAttribsARB)
-            _glfw.glx.ARB_create_context = GLFW_TRUE;
-    }
-
-    if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
-        _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
-        _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
-        _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
-        _glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
-
-    if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
-        _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
-
-    return GLFW_TRUE;
-}
-
-// Terminate GLX
-//
-void _glfwTerminateGLX(void)
-{
-    // NOTE: This function must not call any X11 functions, as it is called
-    //       after XCloseDisplay (see _glfwPlatformTerminate for details)
-
-    if (_glfw.glx.handle)
-    {
-        _glfw_dlclose(_glfw.glx.handle);
-        _glfw.glx.handle = NULL;
-    }
-}
-
-#define setAttrib(a, v) \
-{ \
-    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[index++] = a; \
-    attribs[index++] = v; \
-}
-
-// Create the OpenGL or OpenGL ES context
-//
-GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig)
-{
-    int attribs[40];
-    GLXFBConfig native = NULL;
-    GLXContext share = NULL;
-
-    if (ctxconfig->share)
-        share = ctxconfig->share->context.glx.handle;
-
-    if (!chooseGLXFBConfig(fbconfig, &native))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "GLX: Failed to find a suitable GLXFBConfig");
-        return GLFW_FALSE;
-    }
-
-    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 GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->forward)
-    {
-        if (!_glfw.glx.ARB_create_context)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
-            return GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->profile)
-    {
-        if (!_glfw.glx.ARB_create_context ||
-            !_glfw.glx.ARB_create_context_profile)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
-            return GLFW_FALSE;
-        }
-    }
-
-    _glfwGrabErrorHandlerX11();
-
-    if (_glfw.glx.ARB_create_context)
-    {
-        int index = 0, mask = 0, flags = 0;
-
-        if (ctxconfig->client == GLFW_OPENGL_API)
-        {
-            if (ctxconfig->forward)
-                flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_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->robustness)
-        {
-            if (_glfw.glx.ARB_create_context_robustness)
-            {
-                if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
-                {
-                    setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
-                              GLX_NO_RESET_NOTIFICATION_ARB);
-                }
-                else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
-                {
-                    setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
-                              GLX_LOSE_CONTEXT_ON_RESET_ARB);
-                }
-
-                flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
-            }
-        }
-
-        if (ctxconfig->release)
-        {
-            if (_glfw.glx.ARB_context_flush_control)
-            {
-                if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
-                {
-                    setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
-                              GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
-                }
-                else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
-                {
-                    setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
-                              GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
-                }
-            }
-        }
-
-        if (ctxconfig->noerror)
-        {
-            if (_glfw.glx.ARB_create_context_no_error)
-                setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
-        }
-
-        // 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)
-        {
-            setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
-            setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
-        }
-
-        if (mask)
-            setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
-
-        if (flags)
-            setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
-
-        setAttrib(None, None);
-
-        window->context.glx.handle =
-            _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
-                                              native,
-                                              share,
-                                              True,
-                                              attribs);
-
-        // 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)
-        {
-            if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
-                ctxconfig->client == GLFW_OPENGL_API &&
-                ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
-                ctxconfig->forward == GLFW_FALSE)
-            {
-                window->context.glx.handle =
-                    createLegacyContextGLX(window, native, share);
-            }
-        }
-    }
-    else
-    {
-        window->context.glx.handle =
-            createLegacyContextGLX(window, native, share);
-    }
-
-    _glfwReleaseErrorHandlerX11();
-
-    if (!window->context.glx.handle)
-    {
-        _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
-        return GLFW_FALSE;
-    }
-
-    window->context.glx.window =
-        glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
-    if (!window->context.glx.window)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
-        return GLFW_FALSE;
-    }
-
-    window->context.makeCurrent = makeContextCurrentGLX;
-    window->context.swapBuffers = swapBuffersGLX;
-    window->context.swapInterval = swapIntervalGLX;
-    window->context.extensionSupported = extensionSupportedGLX;
-    window->context.getProcAddress = getProcAddressGLX;
-    window->context.destroy = destroyContextGLX;
-
-    return GLFW_TRUE;
-}
-
-#undef setAttrib
-
-// Returns the Visual and depth of the chosen GLXFBConfig
-//
-GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig,
-                              Visual** visual, int* depth)
-{
-    GLXFBConfig native;
-    XVisualInfo* result;
-
-    if (!chooseGLXFBConfig(fbconfig, &native))
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "GLX: Failed to find a suitable GLXFBConfig");
-        return GLFW_FALSE;
-    }
-
-    result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
-    if (!result)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "GLX: Failed to retrieve Visual for GLXFBConfig");
-        return GLFW_FALSE;
-    }
-
-    *visual = result->visual;
-    *depth  = result->depth;
-
-    XFree(result);
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    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 3.3 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#ifndef GLXBadProfileARB
+ #define GLXBadProfileARB 13
+#endif
+
+
+// Returns the specified attribute of the specified GLXFBConfig
+//
+static int getGLXFBConfigAttrib(GLXFBConfig fbconfig, int attrib)
+{
+    int value;
+    glXGetFBConfigAttrib(_glfw.x11.display, fbconfig, attrib, &value);
+    return value;
+}
+
+// Return the GLXFBConfig most closely matching the specified hints
+//
+static GLFWbool chooseGLXFBConfig(const _GLFWfbconfig* desired,
+                                  GLXFBConfig* result)
+{
+    GLXFBConfig* nativeConfigs;
+    _GLFWfbconfig* usableConfigs;
+    const _GLFWfbconfig* closest;
+    int i, nativeCount, usableCount;
+    const char* vendor;
+    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 (vendor && strcmp(vendor, "Chromium") == 0)
+        trustWindowBit = GLFW_FALSE;
+
+    nativeConfigs =
+        glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
+    if (!nativeConfigs || !nativeCount)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: No GLXFBConfigs returned");
+        return GLFW_FALSE;
+    }
+
+    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+    usableCount = 0;
+
+    for (i = 0;  i < nativeCount;  i++)
+    {
+        const GLXFBConfig n = nativeConfigs[i];
+        _GLFWfbconfig* u = usableConfigs + usableCount;
+
+        // Only consider RGBA GLXFBConfigs
+        if (!(getGLXFBConfigAttrib(n, GLX_RENDER_TYPE) & GLX_RGBA_BIT))
+            continue;
+
+        // Only consider window GLXFBConfigs
+        if (!(getGLXFBConfigAttrib(n, GLX_DRAWABLE_TYPE) & GLX_WINDOW_BIT))
+        {
+            if (trustWindowBit)
+                continue;
+        }
+
+        if (desired->transparent)
+        {
+            XVisualInfo* vi = glXGetVisualFromFBConfig(_glfw.x11.display, n);
+            if (vi)
+            {
+                u->transparent = _glfwIsVisualTransparentX11(vi->visual);
+                XFree(vi);
+            }
+        }
+
+        u->redBits = getGLXFBConfigAttrib(n, GLX_RED_SIZE);
+        u->greenBits = getGLXFBConfigAttrib(n, GLX_GREEN_SIZE);
+        u->blueBits = getGLXFBConfigAttrib(n, GLX_BLUE_SIZE);
+
+        u->alphaBits = getGLXFBConfigAttrib(n, GLX_ALPHA_SIZE);
+        u->depthBits = getGLXFBConfigAttrib(n, GLX_DEPTH_SIZE);
+        u->stencilBits = getGLXFBConfigAttrib(n, GLX_STENCIL_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 = getGLXFBConfigAttrib(n, GLX_AUX_BUFFERS);
+
+        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 = getGLXFBConfigAttrib(n, GLX_SAMPLES);
+
+        if (_glfw.glx.ARB_framebuffer_sRGB || _glfw.glx.EXT_framebuffer_sRGB)
+            u->sRGB = getGLXFBConfigAttrib(n, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+
+        u->handle = (uintptr_t) n;
+        usableCount++;
+    }
+
+    closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount);
+    if (closest)
+        *result = (GLXFBConfig) closest->handle;
+
+    XFree(nativeConfigs);
+    free(usableConfigs);
+
+    return closest != NULL;
+}
+
+// Create the OpenGL context using legacy API
+//
+static GLXContext createLegacyContextGLX(_GLFWwindow* window,
+                                         GLXFBConfig fbconfig,
+                                         GLXContext share)
+{
+    return glXCreateNewContext(_glfw.x11.display,
+                               fbconfig,
+                               GLX_RGBA_TYPE,
+                               share,
+                               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;
+        }
+    }
+
+    _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static void swapBuffersGLX(_GLFWwindow* window)
+{
+    glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
+}
+
+static void swapIntervalGLX(int interval)
+{
+    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+    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 _glfw_dlsym(_glfw.glx.handle, procname);
+}
+
+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
+//
+GLFWbool _glfwInitGLX(void)
+{
+    int i;
+    const char* sonames[] =
+    {
+#if defined(_GLFW_GLX_LIBRARY)
+        _GLFW_GLX_LIBRARY,
+#elif defined(__CYGWIN__)
+        "libGL-1.so",
+#else
+        "libGL.so.1",
+        "libGL.so",
+#endif
+        NULL
+    };
+
+    if (_glfw.glx.handle)
+        return GLFW_TRUE;
+
+    for (i = 0;  sonames[i];  i++)
+    {
+        _glfw.glx.handle = _glfw_dlopen(sonames[i]);
+        if (_glfw.glx.handle)
+            break;
+    }
+
+    if (!_glfw.glx.handle)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
+        return GLFW_FALSE;
+    }
+
+    _glfw.glx.GetFBConfigs =
+        _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs");
+    _glfw.glx.GetFBConfigAttrib =
+        _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
+    _glfw.glx.GetClientString =
+        _glfw_dlsym(_glfw.glx.handle, "glXGetClientString");
+    _glfw.glx.QueryExtension =
+        _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension");
+    _glfw.glx.QueryVersion =
+        _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion");
+    _glfw.glx.DestroyContext =
+        _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext");
+    _glfw.glx.MakeCurrent =
+        _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent");
+    _glfw.glx.SwapBuffers =
+        _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
+    _glfw.glx.QueryExtensionsString =
+        _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
+    _glfw.glx.CreateNewContext =
+        _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
+    _glfw.glx.CreateWindow =
+        _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
+    _glfw.glx.DestroyWindow =
+        _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
+    _glfw.glx.GetProcAddress =
+        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
+    _glfw.glx.GetProcAddressARB =
+        _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
+    _glfw.glx.GetVisualFromFBConfig =
+        _glfw_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 GLFW_FALSE;
+    }
+
+    if (!glXQueryVersion(_glfw.x11.display, &_glfw.glx.major, &_glfw.glx.minor))
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "GLX: Failed to query GLX version");
+        return GLFW_FALSE;
+    }
+
+    if (_glfw.glx.major == 1 && _glfw.glx.minor < 3)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "GLX: GLX version 1.3 is required");
+        return GLFW_FALSE;
+    }
+
+    if (extensionSupportedGLX("GLX_EXT_swap_control"))
+    {
+        _glfw.glx.SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)
+            getProcAddressGLX("glXSwapIntervalEXT");
+
+        if (_glfw.glx.SwapIntervalEXT)
+            _glfw.glx.EXT_swap_control = GLFW_TRUE;
+    }
+
+    if (extensionSupportedGLX("GLX_SGI_swap_control"))
+    {
+        _glfw.glx.SwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)
+            getProcAddressGLX("glXSwapIntervalSGI");
+
+        if (_glfw.glx.SwapIntervalSGI)
+            _glfw.glx.SGI_swap_control = GLFW_TRUE;
+    }
+
+    if (extensionSupportedGLX("GLX_MESA_swap_control"))
+    {
+        _glfw.glx.SwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)
+            getProcAddressGLX("glXSwapIntervalMESA");
+
+        if (_glfw.glx.SwapIntervalMESA)
+            _glfw.glx.MESA_swap_control = GLFW_TRUE;
+    }
+
+    if (extensionSupportedGLX("GLX_ARB_multisample"))
+        _glfw.glx.ARB_multisample = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_ARB_framebuffer_sRGB"))
+        _glfw.glx.ARB_framebuffer_sRGB = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_EXT_framebuffer_sRGB"))
+        _glfw.glx.EXT_framebuffer_sRGB = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_ARB_create_context"))
+    {
+        _glfw.glx.CreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)
+            getProcAddressGLX("glXCreateContextAttribsARB");
+
+        if (_glfw.glx.CreateContextAttribsARB)
+            _glfw.glx.ARB_create_context = GLFW_TRUE;
+    }
+
+    if (extensionSupportedGLX("GLX_ARB_create_context_robustness"))
+        _glfw.glx.ARB_create_context_robustness = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_ARB_create_context_profile"))
+        _glfw.glx.ARB_create_context_profile = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_EXT_create_context_es2_profile"))
+        _glfw.glx.EXT_create_context_es2_profile = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_ARB_create_context_no_error"))
+        _glfw.glx.ARB_create_context_no_error = GLFW_TRUE;
+
+    if (extensionSupportedGLX("GLX_ARB_context_flush_control"))
+        _glfw.glx.ARB_context_flush_control = GLFW_TRUE;
+
+    return GLFW_TRUE;
+}
+
+// Terminate GLX
+//
+void _glfwTerminateGLX(void)
+{
+    // NOTE: This function must not call any X11 functions, as it is called
+    //       after XCloseDisplay (see _glfwPlatformTerminate for details)
+
+    if (_glfw.glx.handle)
+    {
+        _glfw_dlclose(_glfw.glx.handle);
+        _glfw.glx.handle = NULL;
+    }
+}
+
+#define setAttrib(a, v) \
+{ \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+    attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig)
+{
+    int attribs[40];
+    GLXFBConfig native = NULL;
+    GLXContext share = NULL;
+
+    if (ctxconfig->share)
+        share = ctxconfig->share->context.glx.handle;
+
+    if (!chooseGLXFBConfig(fbconfig, &native))
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "GLX: Failed to find a suitable GLXFBConfig");
+        return GLFW_FALSE;
+    }
+
+    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 GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->forward)
+    {
+        if (!_glfw.glx.ARB_create_context)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "GLX: Forward compatibility requested but GLX_ARB_create_context_profile is unavailable");
+            return GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->profile)
+    {
+        if (!_glfw.glx.ARB_create_context ||
+            !_glfw.glx.ARB_create_context_profile)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "GLX: An OpenGL profile requested but GLX_ARB_create_context_profile is unavailable");
+            return GLFW_FALSE;
+        }
+    }
+
+    _glfwGrabErrorHandlerX11();
+
+    if (_glfw.glx.ARB_create_context)
+    {
+        int index = 0, mask = 0, flags = 0;
+
+        if (ctxconfig->client == GLFW_OPENGL_API)
+        {
+            if (ctxconfig->forward)
+                flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_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->robustness)
+        {
+            if (_glfw.glx.ARB_create_context_robustness)
+            {
+                if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+                {
+                    setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+                              GLX_NO_RESET_NOTIFICATION_ARB);
+                }
+                else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+                {
+                    setAttrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+                              GLX_LOSE_CONTEXT_ON_RESET_ARB);
+                }
+
+                flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+            }
+        }
+
+        if (ctxconfig->release)
+        {
+            if (_glfw.glx.ARB_context_flush_control)
+            {
+                if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+                {
+                    setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+                              GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+                }
+                else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+                {
+                    setAttrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+                              GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+                }
+            }
+        }
+
+        if (ctxconfig->noerror)
+        {
+            if (_glfw.glx.ARB_create_context_no_error)
+                setAttrib(GLX_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
+        }
+
+        // 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)
+        {
+            setAttrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+            setAttrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+        }
+
+        if (mask)
+            setAttrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
+
+        if (flags)
+            setAttrib(GLX_CONTEXT_FLAGS_ARB, flags);
+
+        setAttrib(None, None);
+
+        window->context.glx.handle =
+            _glfw.glx.CreateContextAttribsARB(_glfw.x11.display,
+                                              native,
+                                              share,
+                                              True,
+                                              attribs);
+
+        // 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)
+        {
+            if (_glfw.x11.errorCode == _glfw.glx.errorBase + GLXBadProfileARB &&
+                ctxconfig->client == GLFW_OPENGL_API &&
+                ctxconfig->profile == GLFW_OPENGL_ANY_PROFILE &&
+                ctxconfig->forward == GLFW_FALSE)
+            {
+                window->context.glx.handle =
+                    createLegacyContextGLX(window, native, share);
+            }
+        }
+    }
+    else
+    {
+        window->context.glx.handle =
+            createLegacyContextGLX(window, native, share);
+    }
+
+    _glfwReleaseErrorHandlerX11();
+
+    if (!window->context.glx.handle)
+    {
+        _glfwInputErrorX11(GLFW_VERSION_UNAVAILABLE, "GLX: Failed to create context");
+        return GLFW_FALSE;
+    }
+
+    window->context.glx.window =
+        glXCreateWindow(_glfw.x11.display, native, window->x11.handle, NULL);
+    if (!window->context.glx.window)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "GLX: Failed to create window");
+        return GLFW_FALSE;
+    }
+
+    window->context.makeCurrent = makeContextCurrentGLX;
+    window->context.swapBuffers = swapBuffersGLX;
+    window->context.swapInterval = swapIntervalGLX;
+    window->context.extensionSupported = extensionSupportedGLX;
+    window->context.getProcAddress = getProcAddressGLX;
+    window->context.destroy = destroyContextGLX;
+
+    return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+// Returns the Visual and depth of the chosen GLXFBConfig
+//
+GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig,
+                              Visual** visual, int* depth)
+{
+    GLXFBConfig native;
+    XVisualInfo* result;
+
+    if (!chooseGLXFBConfig(fbconfig, &native))
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "GLX: Failed to find a suitable GLXFBConfig");
+        return GLFW_FALSE;
+    }
+
+    result = glXGetVisualFromFBConfig(_glfw.x11.display, native);
+    if (!result)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "GLX: Failed to retrieve Visual for GLXFBConfig");
+        return GLFW_FALSE;
+    }
+
+    *visual = result->visual;
+    *depth  = result->depth;
+
+    XFree(result);
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    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;
+}
+
diff --git a/glfw/src/glx_context.h b/glfw/src/glx_context.h
--- a/glfw/src/glx_context.h
+++ b/glfw/src/glx_context.h
@@ -1,181 +1,181 @@
-//========================================================================
-// GLFW 3.3 GLX - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-
-#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
-
-#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
-#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
-
-typedef XID GLXWindow;
-typedef XID GLXDrawable;
-typedef struct __GLXFBConfig* GLXFBConfig;
-typedef struct __GLXcontext* GLXContext;
-typedef void (*__GLXextproc)(void);
-
-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 void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
-typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
-typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
-typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
-
-typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
-typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
-typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
-
-// 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
-
-
-// GLX-specific per-context data
-//
-typedef struct _GLFWcontextGLX
-{
-    GLXContext      handle;
-    GLXWindow       window;
-
-} _GLFWcontextGLX;
-
-// GLX-specific global data
-//
-typedef struct _GLFWlibraryGLX
-{
-    int             major, minor;
-    int             eventBase;
-    int             errorBase;
-
-    // dlopen handle for libGL.so.1
-    void*           handle;
-
-    // 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_create_context_no_error;
-    GLFWbool        ARB_context_flush_control;
-
-} _GLFWlibraryGLX;
-
-GLFWbool _glfwInitGLX(void);
-void _glfwTerminateGLX(void);
-GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig);
-void _glfwDestroyContextGLX(_GLFWwindow* window);
-GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig,
-                              Visual** visual, int* depth);
-
+//========================================================================
+// GLFW 3.3 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+
+#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
+
+#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
+#define GLX_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
+
+typedef XID GLXWindow;
+typedef XID GLXDrawable;
+typedef struct __GLXFBConfig* GLXFBConfig;
+typedef struct __GLXcontext* GLXContext;
+typedef void (*__GLXextproc)(void);
+
+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 void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
+typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
+typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
+typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
+
+typedef int (*PFNGLXSWAPINTERVALMESAPROC)(int);
+typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
+
+// 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
+
+
+// GLX-specific per-context data
+//
+typedef struct _GLFWcontextGLX
+{
+    GLXContext      handle;
+    GLXWindow       window;
+
+} _GLFWcontextGLX;
+
+// GLX-specific global data
+//
+typedef struct _GLFWlibraryGLX
+{
+    int             major, minor;
+    int             eventBase;
+    int             errorBase;
+
+    // dlopen handle for libGL.so.1
+    void*           handle;
+
+    // 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_create_context_no_error;
+    GLFWbool        ARB_context_flush_control;
+
+} _GLFWlibraryGLX;
+
+GLFWbool _glfwInitGLX(void);
+void _glfwTerminateGLX(void);
+GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig);
+void _glfwDestroyContextGLX(_GLFWwindow* window);
+GLFWbool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig,
+                              Visual** visual, int* depth);
+
diff --git a/glfw/src/init.c b/glfw/src/init.c
--- a/glfw/src/init.c
+++ b/glfw/src/init.c
@@ -1,340 +1,340 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2018 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-#include "mappings.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <assert.h>
-
-
-// The global variables below comprise all mutable global data in GLFW
-//
-// Any other global variable is a bug
-
-// Global state shared between compilation units of GLFW
-//
-_GLFWlibrary _glfw = { GLFW_FALSE };
-
-// These are outside of _glfw so they can be used before initialization and
-// after termination
-//
-static _GLFWerror _glfwMainThreadError;
-static GLFWerrorfun _glfwErrorCallback;
-static _GLFWinitconfig _glfwInitHints =
-{
-    GLFW_TRUE,      // hat buttons
-    {
-        GLFW_TRUE,  // macOS menu bar
-        GLFW_TRUE   // macOS bundle chdir
-    }
-};
-
-// Terminate the library
-//
-static void terminate(void)
-{
-    int i;
-
-    memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
-
-    while (_glfw.windowListHead)
-        glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
-
-    while (_glfw.cursorListHead)
-        glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
-
-    for (i = 0;  i < _glfw.monitorCount;  i++)
-    {
-        _GLFWmonitor* monitor = _glfw.monitors[i];
-        if (monitor->originalRamp.size)
-            _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
-        _glfwFreeMonitor(monitor);
-    }
-
-    free(_glfw.monitors);
-    _glfw.monitors = NULL;
-    _glfw.monitorCount = 0;
-
-    free(_glfw.mappings);
-    _glfw.mappings = NULL;
-    _glfw.mappingCount = 0;
-
-    _glfwTerminateVulkan();
-    _glfwPlatformTerminate();
-
-    _glfw.initialized = GLFW_FALSE;
-
-    while (_glfw.errorListHead)
-    {
-        _GLFWerror* error = _glfw.errorListHead;
-        _glfw.errorListHead = error->next;
-        free(error);
-    }
-
-    _glfwPlatformDestroyTls(&_glfw.contextSlot);
-    _glfwPlatformDestroyTls(&_glfw.errorSlot);
-    _glfwPlatformDestroyMutex(&_glfw.errorLock);
-
-    memset(&_glfw, 0, sizeof(_glfw));
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-char* _glfw_strdup(const char* source)
-{
-    const size_t length = strlen(source);
-    char* result = calloc(length + 1, 1);
-    strcpy(result, source);
-    return result;
-}
-
-float _glfw_fminf(float a, float b)
-{
-    if (a != a)
-        return b;
-    else if (b != b)
-        return a;
-    else if (a < b)
-        return a;
-    else
-        return b;
-}
-
-float _glfw_fmaxf(float a, float b)
-{
-    if (a != a)
-        return b;
-    else if (b != b)
-        return a;
-    else if (a > b)
-        return a;
-    else
-        return b;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                         GLFW event API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-// Notifies shared code of an error
-//
-void _glfwInputError(int code, const char* format, ...)
-{
-    _GLFWerror* error;
-    char description[_GLFW_MESSAGE_SIZE];
-
-    if (format)
-    {
-        va_list vl;
-
-        va_start(vl, format);
-        vsnprintf(description, sizeof(description), format, vl);
-        va_end(vl);
-
-        description[sizeof(description) - 1] = '\0';
-    }
-    else
-    {
-        if (code == GLFW_NOT_INITIALIZED)
-            strcpy(description, "The GLFW library is not initialized");
-        else if (code == GLFW_NO_CURRENT_CONTEXT)
-            strcpy(description, "There is no current context");
-        else if (code == GLFW_INVALID_ENUM)
-            strcpy(description, "Invalid argument for enum parameter");
-        else if (code == GLFW_INVALID_VALUE)
-            strcpy(description, "Invalid value for parameter");
-        else if (code == GLFW_OUT_OF_MEMORY)
-            strcpy(description, "Out of memory");
-        else if (code == GLFW_API_UNAVAILABLE)
-            strcpy(description, "The requested API is unavailable");
-        else if (code == GLFW_VERSION_UNAVAILABLE)
-            strcpy(description, "The requested API version is unavailable");
-        else if (code == GLFW_PLATFORM_ERROR)
-            strcpy(description, "A platform-specific error occurred");
-        else if (code == GLFW_FORMAT_UNAVAILABLE)
-            strcpy(description, "The requested format is unavailable");
-        else if (code == GLFW_NO_WINDOW_CONTEXT)
-            strcpy(description, "The specified window has no context");
-        else
-            strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
-    }
-
-    if (_glfw.initialized)
-    {
-        error = _glfwPlatformGetTls(&_glfw.errorSlot);
-        if (!error)
-        {
-            error = calloc(1, sizeof(_GLFWerror));
-            _glfwPlatformSetTls(&_glfw.errorSlot, error);
-            _glfwPlatformLockMutex(&_glfw.errorLock);
-            error->next = _glfw.errorListHead;
-            _glfw.errorListHead = error;
-            _glfwPlatformUnlockMutex(&_glfw.errorLock);
-        }
-    }
-    else
-        error = &_glfwMainThreadError;
-
-    error->code = code;
-    strcpy(error->description, description);
-
-    if (_glfwErrorCallback)
-        _glfwErrorCallback(code, description);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI int glfwInit(void)
-{
-    if (_glfw.initialized)
-        return GLFW_TRUE;
-
-    memset(&_glfw, 0, sizeof(_glfw));
-    _glfw.hints.init = _glfwInitHints;
-
-    if (!_glfwPlatformInit())
-    {
-        terminate();
-        return GLFW_FALSE;
-    }
-
-    if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
-        !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
-        !_glfwPlatformCreateTls(&_glfw.contextSlot))
-    {
-        terminate();
-        return GLFW_FALSE;
-    }
-
-    _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
-
-    _glfw.initialized = GLFW_TRUE;
-    _glfw.timer.offset = _glfwPlatformGetTimerValue();
-
-    glfwDefaultWindowHints();
-
-    {
-        int i;
-
-        for (i = 0;  _glfwDefaultMappings[i];  i++)
-        {
-            if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
-            {
-                terminate();
-                return GLFW_FALSE;
-            }
-        }
-    }
-
-    return GLFW_TRUE;
-}
-
-GLFWAPI void glfwTerminate(void)
-{
-    if (!_glfw.initialized)
-        return;
-
-    terminate();
-}
-
-GLFWAPI void glfwInitHint(int hint, int value)
-{
-    switch (hint)
-    {
-        case GLFW_JOYSTICK_HAT_BUTTONS:
-            _glfwInitHints.hatButtons = value;
-            return;
-        case GLFW_COCOA_CHDIR_RESOURCES:
-            _glfwInitHints.ns.chdir = value;
-            return;
-        case GLFW_COCOA_MENUBAR:
-            _glfwInitHints.ns.menubar = value;
-            return;
-    }
-
-    _glfwInputError(GLFW_INVALID_ENUM,
-                    "Invalid init hint 0x%08X", hint);
-}
-
-GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
-{
-    if (major != NULL)
-        *major = GLFW_VERSION_MAJOR;
-    if (minor != NULL)
-        *minor = GLFW_VERSION_MINOR;
-    if (rev != NULL)
-        *rev = GLFW_VERSION_REVISION;
-}
-
-GLFWAPI const char* glfwGetVersionString(void)
-{
-    return _glfwPlatformGetVersionString();
-}
-
-GLFWAPI int glfwGetError(const char** description)
-{
-    _GLFWerror* error;
-    int code = GLFW_NO_ERROR;
-
-    if (description)
-        *description = NULL;
-
-    if (_glfw.initialized)
-        error = _glfwPlatformGetTls(&_glfw.errorSlot);
-    else
-        error = &_glfwMainThreadError;
-
-    if (error)
-    {
-        code = error->code;
-        error->code = GLFW_NO_ERROR;
-        if (description && code)
-            *description = error->description;
-    }
-
-    return code;
-}
-
-GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
-{
-    _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
-    return cbfun;
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2018 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+#include "mappings.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+
+// The global variables below comprise all mutable global data in GLFW
+//
+// Any other global variable is a bug
+
+// Global state shared between compilation units of GLFW
+//
+_GLFWlibrary _glfw = { GLFW_FALSE };
+
+// These are outside of _glfw so they can be used before initialization and
+// after termination
+//
+static _GLFWerror _glfwMainThreadError;
+static GLFWerrorfun _glfwErrorCallback;
+static _GLFWinitconfig _glfwInitHints =
+{
+    GLFW_TRUE,      // hat buttons
+    {
+        GLFW_TRUE,  // macOS menu bar
+        GLFW_TRUE   // macOS bundle chdir
+    }
+};
+
+// Terminate the library
+//
+static void terminate(void)
+{
+    int i;
+
+    memset(&_glfw.callbacks, 0, sizeof(_glfw.callbacks));
+
+    while (_glfw.windowListHead)
+        glfwDestroyWindow((GLFWwindow*) _glfw.windowListHead);
+
+    while (_glfw.cursorListHead)
+        glfwDestroyCursor((GLFWcursor*) _glfw.cursorListHead);
+
+    for (i = 0;  i < _glfw.monitorCount;  i++)
+    {
+        _GLFWmonitor* monitor = _glfw.monitors[i];
+        if (monitor->originalRamp.size)
+            _glfwPlatformSetGammaRamp(monitor, &monitor->originalRamp);
+        _glfwFreeMonitor(monitor);
+    }
+
+    free(_glfw.monitors);
+    _glfw.monitors = NULL;
+    _glfw.monitorCount = 0;
+
+    free(_glfw.mappings);
+    _glfw.mappings = NULL;
+    _glfw.mappingCount = 0;
+
+    _glfwTerminateVulkan();
+    _glfwPlatformTerminate();
+
+    _glfw.initialized = GLFW_FALSE;
+
+    while (_glfw.errorListHead)
+    {
+        _GLFWerror* error = _glfw.errorListHead;
+        _glfw.errorListHead = error->next;
+        free(error);
+    }
+
+    _glfwPlatformDestroyTls(&_glfw.contextSlot);
+    _glfwPlatformDestroyTls(&_glfw.errorSlot);
+    _glfwPlatformDestroyMutex(&_glfw.errorLock);
+
+    memset(&_glfw, 0, sizeof(_glfw));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+char* _glfw_strdup(const char* source)
+{
+    const size_t length = strlen(source);
+    char* result = calloc(length + 1, 1);
+    strcpy(result, source);
+    return result;
+}
+
+float _glfw_fminf(float a, float b)
+{
+    if (a != a)
+        return b;
+    else if (b != b)
+        return a;
+    else if (a < b)
+        return a;
+    else
+        return b;
+}
+
+float _glfw_fmaxf(float a, float b)
+{
+    if (a != a)
+        return b;
+    else if (b != b)
+        return a;
+    else if (a > b)
+        return a;
+    else
+        return b;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of an error
+//
+void _glfwInputError(int code, const char* format, ...)
+{
+    _GLFWerror* error;
+    char description[_GLFW_MESSAGE_SIZE];
+
+    if (format)
+    {
+        va_list vl;
+
+        va_start(vl, format);
+        vsnprintf(description, sizeof(description), format, vl);
+        va_end(vl);
+
+        description[sizeof(description) - 1] = '\0';
+    }
+    else
+    {
+        if (code == GLFW_NOT_INITIALIZED)
+            strcpy(description, "The GLFW library is not initialized");
+        else if (code == GLFW_NO_CURRENT_CONTEXT)
+            strcpy(description, "There is no current context");
+        else if (code == GLFW_INVALID_ENUM)
+            strcpy(description, "Invalid argument for enum parameter");
+        else if (code == GLFW_INVALID_VALUE)
+            strcpy(description, "Invalid value for parameter");
+        else if (code == GLFW_OUT_OF_MEMORY)
+            strcpy(description, "Out of memory");
+        else if (code == GLFW_API_UNAVAILABLE)
+            strcpy(description, "The requested API is unavailable");
+        else if (code == GLFW_VERSION_UNAVAILABLE)
+            strcpy(description, "The requested API version is unavailable");
+        else if (code == GLFW_PLATFORM_ERROR)
+            strcpy(description, "A platform-specific error occurred");
+        else if (code == GLFW_FORMAT_UNAVAILABLE)
+            strcpy(description, "The requested format is unavailable");
+        else if (code == GLFW_NO_WINDOW_CONTEXT)
+            strcpy(description, "The specified window has no context");
+        else
+            strcpy(description, "ERROR: UNKNOWN GLFW ERROR");
+    }
+
+    if (_glfw.initialized)
+    {
+        error = _glfwPlatformGetTls(&_glfw.errorSlot);
+        if (!error)
+        {
+            error = calloc(1, sizeof(_GLFWerror));
+            _glfwPlatformSetTls(&_glfw.errorSlot, error);
+            _glfwPlatformLockMutex(&_glfw.errorLock);
+            error->next = _glfw.errorListHead;
+            _glfw.errorListHead = error;
+            _glfwPlatformUnlockMutex(&_glfw.errorLock);
+        }
+    }
+    else
+        error = &_glfwMainThreadError;
+
+    error->code = code;
+    strcpy(error->description, description);
+
+    if (_glfwErrorCallback)
+        _glfwErrorCallback(code, description);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwInit(void)
+{
+    if (_glfw.initialized)
+        return GLFW_TRUE;
+
+    memset(&_glfw, 0, sizeof(_glfw));
+    _glfw.hints.init = _glfwInitHints;
+
+    if (!_glfwPlatformInit())
+    {
+        terminate();
+        return GLFW_FALSE;
+    }
+
+    if (!_glfwPlatformCreateMutex(&_glfw.errorLock) ||
+        !_glfwPlatformCreateTls(&_glfw.errorSlot) ||
+        !_glfwPlatformCreateTls(&_glfw.contextSlot))
+    {
+        terminate();
+        return GLFW_FALSE;
+    }
+
+    _glfwPlatformSetTls(&_glfw.errorSlot, &_glfwMainThreadError);
+
+    _glfw.initialized = GLFW_TRUE;
+    _glfw.timer.offset = _glfwPlatformGetTimerValue();
+
+    glfwDefaultWindowHints();
+
+    {
+        int i;
+
+        for (i = 0;  _glfwDefaultMappings[i];  i++)
+        {
+            if (!glfwUpdateGamepadMappings(_glfwDefaultMappings[i]))
+            {
+                terminate();
+                return GLFW_FALSE;
+            }
+        }
+    }
+
+    return GLFW_TRUE;
+}
+
+GLFWAPI void glfwTerminate(void)
+{
+    if (!_glfw.initialized)
+        return;
+
+    terminate();
+}
+
+GLFWAPI void glfwInitHint(int hint, int value)
+{
+    switch (hint)
+    {
+        case GLFW_JOYSTICK_HAT_BUTTONS:
+            _glfwInitHints.hatButtons = value;
+            return;
+        case GLFW_COCOA_CHDIR_RESOURCES:
+            _glfwInitHints.ns.chdir = value;
+            return;
+        case GLFW_COCOA_MENUBAR:
+            _glfwInitHints.ns.menubar = value;
+            return;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM,
+                    "Invalid init hint 0x%08X", hint);
+}
+
+GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev)
+{
+    if (major != NULL)
+        *major = GLFW_VERSION_MAJOR;
+    if (minor != NULL)
+        *minor = GLFW_VERSION_MINOR;
+    if (rev != NULL)
+        *rev = GLFW_VERSION_REVISION;
+}
+
+GLFWAPI const char* glfwGetVersionString(void)
+{
+    return _glfwPlatformGetVersionString();
+}
+
+GLFWAPI int glfwGetError(const char** description)
+{
+    _GLFWerror* error;
+    int code = GLFW_NO_ERROR;
+
+    if (description)
+        *description = NULL;
+
+    if (_glfw.initialized)
+        error = _glfwPlatformGetTls(&_glfw.errorSlot);
+    else
+        error = &_glfwMainThreadError;
+
+    if (error)
+    {
+        code = error->code;
+        error->code = GLFW_NO_ERROR;
+        if (description && code)
+            *description = error->description;
+    }
+
+    return code;
+}
+
+GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
+{
+    _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
+    return cbfun;
+}
+
diff --git a/glfw/src/input.c b/glfw/src/input.c
--- a/glfw/src/input.c
+++ b/glfw/src/input.c
@@ -1,1356 +1,1356 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <float.h>
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-
-// Internal key state used for sticky keys
-#define _GLFW_STICK 3
-
-// Internal constants for gamepad mapping source types
-#define _GLFW_JOYSTICK_AXIS     1
-#define _GLFW_JOYSTICK_BUTTON   2
-#define _GLFW_JOYSTICK_HATBIT   3
-
-// Finds a mapping based on joystick GUID
-//
-static _GLFWmapping* findMapping(const char* guid)
-{
-    int i;
-
-    for (i = 0;  i < _glfw.mappingCount;  i++)
-    {
-        if (strcmp(_glfw.mappings[i].guid, guid) == 0)
-            return _glfw.mappings + i;
-    }
-
-    return NULL;
-}
-
-// Checks whether a gamepad mapping element is present in the hardware
-//
-static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
-                                          const _GLFWjoystick* js)
-{
-    if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
-        return GLFW_FALSE;
-    else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
-        return GLFW_FALSE;
-    else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
-        return GLFW_FALSE;
-
-    return GLFW_TRUE;
-}
-
-// Finds a mapping based on joystick GUID and verifies element indices
-//
-static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
-{
-    _GLFWmapping* mapping = findMapping(js->guid);
-    if (mapping)
-    {
-        int i;
-
-        for (i = 0;  i <= GLFW_GAMEPAD_BUTTON_LAST;  i++)
-        {
-            if (!isValidElementForJoystick(mapping->buttons + i, js))
-            {
-                _glfwInputError(GLFW_INVALID_VALUE,
-                                "Invalid button in gamepad mapping %s (%s)",
-                                mapping->guid,
-                                mapping->name);
-                return NULL;
-            }
-        }
-
-        for (i = 0;  i <= GLFW_GAMEPAD_AXIS_LAST;  i++)
-        {
-            if (!isValidElementForJoystick(mapping->axes + i, js))
-            {
-                _glfwInputError(GLFW_INVALID_VALUE,
-                                "Invalid axis in gamepad mapping %s (%s)",
-                                mapping->guid,
-                                mapping->name);
-                return NULL;
-            }
-        }
-    }
-
-    return mapping;
-}
-
-// Parses an SDL_GameControllerDB line and adds it to the mapping list
-//
-static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
-{
-    const char* c = string;
-    size_t i, length;
-    struct
-    {
-        const char* name;
-        _GLFWmapelement* element;
-    } fields[] =
-    {
-        { "platform",      NULL },
-        { "a",             mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
-        { "b",             mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
-        { "x",             mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
-        { "y",             mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
-        { "back",          mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
-        { "start",         mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
-        { "guide",         mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
-        { "leftshoulder",  mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
-        { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
-        { "leftstick",     mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
-        { "rightstick",    mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
-        { "dpup",          mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
-        { "dpright",       mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
-        { "dpdown",        mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
-        { "dpleft",        mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
-        { "lefttrigger",   mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
-        { "righttrigger",  mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
-        { "leftx",         mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
-        { "lefty",         mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
-        { "rightx",        mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
-        { "righty",        mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
-    };
-
-    length = strcspn(c, ",");
-    if (length != 32 || c[length] != ',')
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, NULL);
-        return GLFW_FALSE;
-    }
-
-    memcpy(mapping->guid, c, length);
-    c += length + 1;
-
-    length = strcspn(c, ",");
-    if (length >= sizeof(mapping->name) || c[length] != ',')
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, NULL);
-        return GLFW_FALSE;
-    }
-
-    memcpy(mapping->name, c, length);
-    c += length + 1;
-
-    while (*c)
-    {
-        // TODO: Implement output modifiers
-        if (*c == '+' || *c == '-')
-            return GLFW_FALSE;
-
-        for (i = 0;  i < sizeof(fields) / sizeof(fields[0]);  i++)
-        {
-            length = strlen(fields[i].name);
-            if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
-                continue;
-
-            c += length + 1;
-
-            if (fields[i].element)
-            {
-                _GLFWmapelement* e = fields[i].element;
-                int8_t minimum = -1;
-                int8_t maximum = 1;
-
-                if (*c == '+')
-                {
-                    minimum = 0;
-                    c += 1;
-                }
-                else if (*c == '-')
-                {
-                    maximum = 0;
-                    c += 1;
-                }
-
-                if (*c == 'a')
-                    e->type = _GLFW_JOYSTICK_AXIS;
-                else if (*c == 'b')
-                    e->type = _GLFW_JOYSTICK_BUTTON;
-                else if (*c == 'h')
-                    e->type = _GLFW_JOYSTICK_HATBIT;
-                else
-                    break;
-
-                if (e->type == _GLFW_JOYSTICK_HATBIT)
-                {
-                    const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
-                    const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
-                    e->index = (uint8_t) ((hat << 4) | bit);
-                }
-                else
-                    e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
-
-                if (e->type == _GLFW_JOYSTICK_AXIS)
-                {
-                    e->axisScale = 2 / (maximum - minimum);
-                    e->axisOffset = -(maximum + minimum);
-
-                    if (*c == '~')
-                    {
-                        e->axisScale = -e->axisScale;
-                        e->axisOffset = -e->axisOffset;
-                    }
-                }
-            }
-            else
-            {
-                length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
-                if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
-                    return GLFW_FALSE;
-            }
-
-            break;
-        }
-
-        c += strcspn(c, ",");
-        c += strspn(c, ",");
-    }
-
-    for (i = 0;  i < 32;  i++)
-    {
-        if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
-            mapping->guid[i] += 'a' - 'A';
-    }
-
-    _glfwPlatformUpdateGamepadGUID(mapping->guid);
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                         GLFW event API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-// Notifies shared code of a physical key event
-//
-void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
-{
-    if (key >= 0 && key <= GLFW_KEY_LAST)
-    {
-        GLFWbool repeated = GLFW_FALSE;
-
-        if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
-            return;
-
-        if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
-            repeated = GLFW_TRUE;
-
-        if (action == GLFW_RELEASE && window->stickyKeys)
-            window->keys[key] = _GLFW_STICK;
-        else
-            window->keys[key] = (char) action;
-
-        if (repeated)
-            action = GLFW_REPEAT;
-    }
-
-    if (!window->lockKeyMods)
-        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
-
-    if (window->callbacks.key)
-        window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
-}
-
-// Notifies shared code of a Unicode codepoint input event
-// The 'plain' parameter determines whether to emit a regular character event
-//
-void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
-{
-    if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
-        return;
-
-    if (!window->lockKeyMods)
-        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
-
-    if (window->callbacks.charmods)
-        window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
-
-    if (plain)
-    {
-        if (window->callbacks.character)
-            window->callbacks.character((GLFWwindow*) window, codepoint);
-    }
-}
-
-// Notifies shared code of a scroll event
-//
-void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
-{
-    if (window->callbacks.scroll)
-        window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
-}
-
-// Notifies shared code of a mouse button click event
-//
-void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
-{
-    if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
-        return;
-
-    if (!window->lockKeyMods)
-        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
-
-    if (action == GLFW_RELEASE && window->stickyMouseButtons)
-        window->mouseButtons[button] = _GLFW_STICK;
-    else
-        window->mouseButtons[button] = (char) action;
-
-    if (window->callbacks.mouseButton)
-        window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
-}
-
-// Notifies shared code of a cursor motion event
-// The position is specified in content area relative screen coordinates
-//
-void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
-{
-    if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
-        return;
-
-    window->virtualCursorPosX = xpos;
-    window->virtualCursorPosY = ypos;
-
-    if (window->callbacks.cursorPos)
-        window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
-}
-
-// Notifies shared code of a cursor enter/leave event
-//
-void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
-{
-    if (window->callbacks.cursorEnter)
-        window->callbacks.cursorEnter((GLFWwindow*) window, entered);
-}
-
-// Notifies shared code of files or directories dropped on a window
-//
-void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
-{
-    if (window->callbacks.drop)
-        window->callbacks.drop((GLFWwindow*) window, count, paths);
-}
-
-// Notifies shared code of a joystick connection or disconnection
-//
-void _glfwInputJoystick(_GLFWjoystick* js, int event)
-{
-    const int jid = (int) (js - _glfw.joysticks);
-
-    if (_glfw.callbacks.joystick)
-        _glfw.callbacks.joystick(jid, event);
-}
-
-// Notifies shared code of the new value of a joystick axis
-//
-void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
-{
-    js->axes[axis] = value;
-}
-
-// Notifies shared code of the new value of a joystick button
-//
-void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
-{
-    js->buttons[button] = value;
-}
-
-// Notifies shared code of the new value of a joystick hat
-//
-void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
-{
-    const int base = js->buttonCount + hat * 4;
-
-    js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
-    js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
-    js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
-    js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
-
-    js->hats[hat] = value;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Returns an available joystick object with arrays and name allocated
-//
-_GLFWjoystick* _glfwAllocJoystick(const char* name,
-                                  const char* guid,
-                                  int axisCount,
-                                  int buttonCount,
-                                  int hatCount)
-{
-    int jid;
-    _GLFWjoystick* js;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        if (!_glfw.joysticks[jid].present)
-            break;
-    }
-
-    if (jid > GLFW_JOYSTICK_LAST)
-        return NULL;
-
-    js = _glfw.joysticks + jid;
-    js->present     = GLFW_TRUE;
-    js->name        = _glfw_strdup(name);
-    js->axes        = calloc(axisCount, sizeof(float));
-    js->buttons     = calloc(buttonCount + (size_t) hatCount * 4, 1);
-    js->hats        = calloc(hatCount, 1);
-    js->axisCount   = axisCount;
-    js->buttonCount = buttonCount;
-    js->hatCount    = hatCount;
-
-    strncpy(js->guid, guid, sizeof(js->guid) - 1);
-    js->mapping = findValidMapping(js);
-
-    return js;
-}
-
-// Frees arrays and name and flags the joystick object as unused
-//
-void _glfwFreeJoystick(_GLFWjoystick* js)
-{
-    free(js->name);
-    free(js->axes);
-    free(js->buttons);
-    free(js->hats);
-    memset(js, 0, sizeof(_GLFWjoystick));
-}
-
-// Center the cursor in the content area of the specified window
-//
-void _glfwCenterCursorInContentArea(_GLFWwindow* window)
-{
-    int width, height;
-
-    _glfwPlatformGetWindowSize(window, &width, &height);
-    _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(0);
-
-    switch (mode)
-    {
-        case GLFW_CURSOR:
-            return window->cursorMode;
-        case GLFW_STICKY_KEYS:
-            return window->stickyKeys;
-        case GLFW_STICKY_MOUSE_BUTTONS:
-            return window->stickyMouseButtons;
-        case GLFW_LOCK_KEY_MODS:
-            return window->lockKeyMods;
-        case GLFW_RAW_MOUSE_MOTION:
-            return window->rawMouseMotion;
-    }
-
-    _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
-    return 0;
-}
-
-GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (mode == GLFW_CURSOR)
-    {
-        if (value != GLFW_CURSOR_NORMAL &&
-            value != GLFW_CURSOR_HIDDEN &&
-            value != GLFW_CURSOR_DISABLED)
-        {
-            _glfwInputError(GLFW_INVALID_ENUM,
-                            "Invalid cursor mode 0x%08X",
-                            value);
-            return;
-        }
-
-        if (window->cursorMode == value)
-            return;
-
-        window->cursorMode = value;
-
-        _glfwPlatformGetCursorPos(window,
-                                  &window->virtualCursorPosX,
-                                  &window->virtualCursorPosY);
-        _glfwPlatformSetCursorMode(window, value);
-    }
-    else if (mode == GLFW_STICKY_KEYS)
-    {
-        value = value ? GLFW_TRUE : GLFW_FALSE;
-        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;
-    }
-    else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
-    {
-        value = value ? GLFW_TRUE : GLFW_FALSE;
-        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;
-    }
-    else if (mode == GLFW_LOCK_KEY_MODS)
-    {
-        window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
-    }
-    else if (mode == GLFW_RAW_MOUSE_MOTION)
-    {
-        if (!_glfwPlatformRawMouseMotionSupported())
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Raw mouse motion is not supported on this system");
-            return;
-        }
-
-        value = value ? GLFW_TRUE : GLFW_FALSE;
-        if (window->rawMouseMotion == value)
-            return;
-
-        window->rawMouseMotion = value;
-        _glfwPlatformSetRawMouseMotion(window, value);
-    }
-    else
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
-}
-
-GLFWAPI int glfwRawMouseMotionSupported(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-    return _glfwPlatformRawMouseMotionSupported();
-}
-
-GLFWAPI const char* glfwGetKeyName(int key, int scancode)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (key != GLFW_KEY_UNKNOWN)
-    {
-        if (key != GLFW_KEY_KP_EQUAL &&
-            (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
-            (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
-        {
-            return NULL;
-        }
-
-        scancode = _glfwPlatformGetKeyScancode(key);
-    }
-
-    return _glfwPlatformGetScancodeName(scancode);
-}
-
-GLFWAPI int glfwGetKeyScancode(int key)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(-1);
-
-    if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
-        return GLFW_RELEASE;
-    }
-
-    return _glfwPlatformGetKeyScancode(key);
-}
-
-GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
-
-    if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
-        return GLFW_RELEASE;
-    }
-
-    if (window->keys[key] == _GLFW_STICK)
-    {
-        // Sticky mode: release key now
-        window->keys[key] = GLFW_RELEASE;
-        return GLFW_PRESS;
-    }
-
-    return (int) window->keys[key];
-}
-
-GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
-
-    if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
-        return GLFW_RELEASE;
-    }
-
-    if (window->mouseButtons[button] == _GLFW_STICK)
-    {
-        // Sticky mode: release mouse button now
-        window->mouseButtons[button] = GLFW_RELEASE;
-        return GLFW_PRESS;
-    }
-
-    return (int) window->mouseButtons[button];
-}
-
-GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    if (xpos)
-        *xpos = 0;
-    if (ypos)
-        *ypos = 0;
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window->cursorMode == GLFW_CURSOR_DISABLED)
-    {
-        if (xpos)
-            *xpos = window->virtualCursorPosX;
-        if (ypos)
-            *ypos = window->virtualCursorPosY;
-    }
-    else
-        _glfwPlatformGetCursorPos(window, xpos, ypos);
-}
-
-GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    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->virtualCursorPosX = xpos;
-        window->virtualCursorPosY = ypos;
-    }
-    else
-    {
-        // Update system cursor position
-        _glfwPlatformSetCursorPos(window, xpos, ypos);
-    }
-}
-
-GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
-{
-    _GLFWcursor* cursor;
-
-    assert(image != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    cursor = calloc(1, sizeof(_GLFWcursor));
-    cursor->next = _glfw.cursorListHead;
-    _glfw.cursorListHead = cursor;
-
-    if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
-    {
-        glfwDestroyCursor((GLFWcursor*) cursor);
-        return NULL;
-    }
-
-    return (GLFWcursor*) cursor;
-}
-
-GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
-{
-    _GLFWcursor* cursor;
-
-    _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 0x%08X", shape);
-        return NULL;
-    }
-
-    cursor = calloc(1, sizeof(_GLFWcursor));
-    cursor->next = _glfw.cursorListHead;
-    _glfw.cursorListHead = cursor;
-
-    if (!_glfwPlatformCreateStandardCursor(cursor, shape))
-    {
-        glfwDestroyCursor((GLFWcursor*) cursor);
-        return NULL;
-    }
-
-    return (GLFWcursor*) cursor;
-}
-
-GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
-{
-    _GLFWcursor* cursor = (_GLFWcursor*) handle;
-
-    _GLFW_REQUIRE_INIT();
-
-    if (cursor == NULL)
-        return;
-
-    // Make sure the cursor is not being used by any window
-    {
-        _GLFWwindow* window;
-
-        for (window = _glfw.windowListHead;  window;  window = window->next)
-        {
-            if (window->cursor == cursor)
-                glfwSetCursor((GLFWwindow*) window, NULL);
-        }
-    }
-
-    _glfwPlatformDestroyCursor(cursor);
-
-    // Unlink cursor from global linked list
-    {
-        _GLFWcursor** prev = &_glfw.cursorListHead;
-
-        while (*prev != cursor)
-            prev = &((*prev)->next);
-
-        *prev = cursor->next;
-    }
-
-    free(cursor);
-}
-
-GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) windowHandle;
-    _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    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;
-}
-
-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;
-}
-
-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;
-}
-
-GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
-                                                      GLFWmousebuttonfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
-                                                  GLFWcursorposfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
-                                                      GLFWcursorenterfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
-                                            GLFWscrollfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
-    return cbfun;
-}
-
-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;
-}
-
-GLFWAPI int glfwJoystickPresent(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return GLFW_FALSE;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return GLFW_FALSE;
-
-    return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
-}
-
-GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
-        return NULL;
-
-    *count = js->axisCount;
-    return js->axes;
-}
-
-GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
-        return NULL;
-
-    if (_glfw.hints.init.hatButtons)
-        *count = js->buttonCount + js->hatCount * 4;
-    else
-        *count = js->buttonCount;
-
-    return js->buttons;
-}
-
-GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
-        return NULL;
-
-    *count = js->hatCount;
-    return js->hats;
-}
-
-GLFWAPI const char* glfwGetJoystickName(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
-        return NULL;
-
-    return js->name;
-}
-
-GLFWAPI const char* glfwGetJoystickGUID(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
-        return NULL;
-
-    return js->guid;
-}
-
-GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT();
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return;
-
-    js->userPointer = pointer;
-}
-
-GLFWAPI void* glfwGetJoystickUserPointer(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    return js->userPointer;
-}
-
-GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
-    return cbfun;
-}
-
-GLFWAPI int glfwUpdateGamepadMappings(const char* string)
-{
-    int jid;
-    const char* c = string;
-
-    assert(string != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    while (*c)
-    {
-        if ((*c >= '0' && *c <= '9') ||
-            (*c >= 'a' && *c <= 'f') ||
-            (*c >= 'A' && *c <= 'F'))
-        {
-            char line[1024];
-
-            const size_t length = strcspn(c, "\r\n");
-            if (length < sizeof(line))
-            {
-                _GLFWmapping mapping = {{0}};
-
-                memcpy(line, c, length);
-                line[length] = '\0';
-
-                if (parseMapping(&mapping, line))
-                {
-                    _GLFWmapping* previous = findMapping(mapping.guid);
-                    if (previous)
-                        *previous = mapping;
-                    else
-                    {
-                        _glfw.mappingCount++;
-                        _glfw.mappings =
-                            realloc(_glfw.mappings,
-                                    sizeof(_GLFWmapping) * _glfw.mappingCount);
-                        _glfw.mappings[_glfw.mappingCount - 1] = mapping;
-                    }
-                }
-            }
-
-            c += length;
-        }
-        else
-        {
-            c += strcspn(c, "\r\n");
-            c += strspn(c, "\r\n");
-        }
-    }
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
-            js->mapping = findValidMapping(js);
-    }
-
-    return GLFW_TRUE;
-}
-
-GLFWAPI int glfwJoystickIsGamepad(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return GLFW_FALSE;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return GLFW_FALSE;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
-        return GLFW_FALSE;
-
-    return js->mapping != NULL;
-}
-
-GLFWAPI const char* glfwGetGamepadName(int jid)
-{
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return NULL;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return NULL;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
-        return NULL;
-
-    if (!js->mapping)
-        return NULL;
-
-    return js->mapping->name;
-}
-
-GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
-{
-    int i;
-    _GLFWjoystick* js;
-
-    assert(jid >= GLFW_JOYSTICK_1);
-    assert(jid <= GLFW_JOYSTICK_LAST);
-    assert(state != NULL);
-
-    memset(state, 0, sizeof(GLFWgamepadstate));
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
-    {
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
-        return GLFW_FALSE;
-    }
-
-    js = _glfw.joysticks + jid;
-    if (!js->present)
-        return GLFW_FALSE;
-
-    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
-        return GLFW_FALSE;
-
-    if (!js->mapping)
-        return GLFW_FALSE;
-
-    for (i = 0;  i <= GLFW_GAMEPAD_BUTTON_LAST;  i++)
-    {
-        const _GLFWmapelement* e = js->mapping->buttons + i;
-        if (e->type == _GLFW_JOYSTICK_AXIS)
-        {
-            const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
-            // HACK: This should be baked into the value transform
-            // TODO: Bake into transform when implementing output modifiers
-            if (e->axisOffset < 0 || (e->axisOffset == 0 && e->axisScale > 0))
-            {
-                if (value >= 0.f)
-                    state->buttons[i] = GLFW_PRESS;
-            }
-            else
-            {
-                if (value <= 0.f)
-                    state->buttons[i] = GLFW_PRESS;
-            }
-        }
-        else if (e->type == _GLFW_JOYSTICK_HATBIT)
-        {
-            const unsigned int hat = e->index >> 4;
-            const unsigned int bit = e->index & 0xf;
-            if (js->hats[hat] & bit)
-                state->buttons[i] = GLFW_PRESS;
-        }
-        else if (e->type == _GLFW_JOYSTICK_BUTTON)
-            state->buttons[i] = js->buttons[e->index];
-    }
-
-    for (i = 0;  i <= GLFW_GAMEPAD_AXIS_LAST;  i++)
-    {
-        const _GLFWmapelement* e = js->mapping->axes + i;
-        if (e->type == _GLFW_JOYSTICK_AXIS)
-        {
-            const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
-            state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f);
-        }
-        else if (e->type == _GLFW_JOYSTICK_HATBIT)
-        {
-            const unsigned int hat = e->index >> 4;
-            const unsigned int bit = e->index & 0xf;
-            if (js->hats[hat] & bit)
-                state->axes[i] = 1.f;
-            else
-                state->axes[i] = -1.f;
-        }
-        else if (e->type == _GLFW_JOYSTICK_BUTTON)
-            state->axes[i] = js->buttons[e->index] * 2.f - 1.f;
-    }
-
-    return GLFW_TRUE;
-}
-
-GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
-{
-    assert(string != NULL);
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformSetClipboardString(string);
-}
-
-GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return _glfwPlatformGetClipboardString();
-}
-
-GLFWAPI double glfwGetTime(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
-    return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
-        _glfwPlatformGetTimerFrequency();
-}
-
-GLFWAPI void glfwSetTime(double time)
-{
-    _GLFW_REQUIRE_INIT();
-
-    if (time != time || time < 0.0 || time > 18446744073.0)
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
-        return;
-    }
-
-    _glfw.timer.offset = _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 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Internal key state used for sticky keys
+#define _GLFW_STICK 3
+
+// Internal constants for gamepad mapping source types
+#define _GLFW_JOYSTICK_AXIS     1
+#define _GLFW_JOYSTICK_BUTTON   2
+#define _GLFW_JOYSTICK_HATBIT   3
+
+// Finds a mapping based on joystick GUID
+//
+static _GLFWmapping* findMapping(const char* guid)
+{
+    int i;
+
+    for (i = 0;  i < _glfw.mappingCount;  i++)
+    {
+        if (strcmp(_glfw.mappings[i].guid, guid) == 0)
+            return _glfw.mappings + i;
+    }
+
+    return NULL;
+}
+
+// Checks whether a gamepad mapping element is present in the hardware
+//
+static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
+                                          const _GLFWjoystick* js)
+{
+    if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
+        return GLFW_FALSE;
+    else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
+        return GLFW_FALSE;
+    else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
+        return GLFW_FALSE;
+
+    return GLFW_TRUE;
+}
+
+// Finds a mapping based on joystick GUID and verifies element indices
+//
+static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
+{
+    _GLFWmapping* mapping = findMapping(js->guid);
+    if (mapping)
+    {
+        int i;
+
+        for (i = 0;  i <= GLFW_GAMEPAD_BUTTON_LAST;  i++)
+        {
+            if (!isValidElementForJoystick(mapping->buttons + i, js))
+            {
+                _glfwInputError(GLFW_INVALID_VALUE,
+                                "Invalid button in gamepad mapping %s (%s)",
+                                mapping->guid,
+                                mapping->name);
+                return NULL;
+            }
+        }
+
+        for (i = 0;  i <= GLFW_GAMEPAD_AXIS_LAST;  i++)
+        {
+            if (!isValidElementForJoystick(mapping->axes + i, js))
+            {
+                _glfwInputError(GLFW_INVALID_VALUE,
+                                "Invalid axis in gamepad mapping %s (%s)",
+                                mapping->guid,
+                                mapping->name);
+                return NULL;
+            }
+        }
+    }
+
+    return mapping;
+}
+
+// Parses an SDL_GameControllerDB line and adds it to the mapping list
+//
+static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
+{
+    const char* c = string;
+    size_t i, length;
+    struct
+    {
+        const char* name;
+        _GLFWmapelement* element;
+    } fields[] =
+    {
+        { "platform",      NULL },
+        { "a",             mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
+        { "b",             mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
+        { "x",             mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
+        { "y",             mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
+        { "back",          mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
+        { "start",         mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
+        { "guide",         mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
+        { "leftshoulder",  mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
+        { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
+        { "leftstick",     mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
+        { "rightstick",    mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
+        { "dpup",          mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
+        { "dpright",       mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
+        { "dpdown",        mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
+        { "dpleft",        mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
+        { "lefttrigger",   mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
+        { "righttrigger",  mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
+        { "leftx",         mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
+        { "lefty",         mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
+        { "rightx",        mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
+        { "righty",        mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
+    };
+
+    length = strcspn(c, ",");
+    if (length != 32 || c[length] != ',')
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, NULL);
+        return GLFW_FALSE;
+    }
+
+    memcpy(mapping->guid, c, length);
+    c += length + 1;
+
+    length = strcspn(c, ",");
+    if (length >= sizeof(mapping->name) || c[length] != ',')
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, NULL);
+        return GLFW_FALSE;
+    }
+
+    memcpy(mapping->name, c, length);
+    c += length + 1;
+
+    while (*c)
+    {
+        // TODO: Implement output modifiers
+        if (*c == '+' || *c == '-')
+            return GLFW_FALSE;
+
+        for (i = 0;  i < sizeof(fields) / sizeof(fields[0]);  i++)
+        {
+            length = strlen(fields[i].name);
+            if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
+                continue;
+
+            c += length + 1;
+
+            if (fields[i].element)
+            {
+                _GLFWmapelement* e = fields[i].element;
+                int8_t minimum = -1;
+                int8_t maximum = 1;
+
+                if (*c == '+')
+                {
+                    minimum = 0;
+                    c += 1;
+                }
+                else if (*c == '-')
+                {
+                    maximum = 0;
+                    c += 1;
+                }
+
+                if (*c == 'a')
+                    e->type = _GLFW_JOYSTICK_AXIS;
+                else if (*c == 'b')
+                    e->type = _GLFW_JOYSTICK_BUTTON;
+                else if (*c == 'h')
+                    e->type = _GLFW_JOYSTICK_HATBIT;
+                else
+                    break;
+
+                if (e->type == _GLFW_JOYSTICK_HATBIT)
+                {
+                    const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
+                    const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
+                    e->index = (uint8_t) ((hat << 4) | bit);
+                }
+                else
+                    e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
+
+                if (e->type == _GLFW_JOYSTICK_AXIS)
+                {
+                    e->axisScale = 2 / (maximum - minimum);
+                    e->axisOffset = -(maximum + minimum);
+
+                    if (*c == '~')
+                    {
+                        e->axisScale = -e->axisScale;
+                        e->axisOffset = -e->axisOffset;
+                    }
+                }
+            }
+            else
+            {
+                length = strlen(_GLFW_PLATFORM_MAPPING_NAME);
+                if (strncmp(c, _GLFW_PLATFORM_MAPPING_NAME, length) != 0)
+                    return GLFW_FALSE;
+            }
+
+            break;
+        }
+
+        c += strcspn(c, ",");
+        c += strspn(c, ",");
+    }
+
+    for (i = 0;  i < 32;  i++)
+    {
+        if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
+            mapping->guid[i] += 'a' - 'A';
+    }
+
+    _glfwPlatformUpdateGamepadGUID(mapping->guid);
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of a physical key event
+//
+void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
+{
+    if (key >= 0 && key <= GLFW_KEY_LAST)
+    {
+        GLFWbool repeated = GLFW_FALSE;
+
+        if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
+            return;
+
+        if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
+            repeated = GLFW_TRUE;
+
+        if (action == GLFW_RELEASE && window->stickyKeys)
+            window->keys[key] = _GLFW_STICK;
+        else
+            window->keys[key] = (char) action;
+
+        if (repeated)
+            action = GLFW_REPEAT;
+    }
+
+    if (!window->lockKeyMods)
+        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+    if (window->callbacks.key)
+        window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
+}
+
+// Notifies shared code of a Unicode codepoint input event
+// The 'plain' parameter determines whether to emit a regular character event
+//
+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
+{
+    if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
+        return;
+
+    if (!window->lockKeyMods)
+        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+    if (window->callbacks.charmods)
+        window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
+
+    if (plain)
+    {
+        if (window->callbacks.character)
+            window->callbacks.character((GLFWwindow*) window, codepoint);
+    }
+}
+
+// Notifies shared code of a scroll event
+//
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
+{
+    if (window->callbacks.scroll)
+        window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
+}
+
+// Notifies shared code of a mouse button click event
+//
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
+{
+    if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
+        return;
+
+    if (!window->lockKeyMods)
+        mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
+
+    if (action == GLFW_RELEASE && window->stickyMouseButtons)
+        window->mouseButtons[button] = _GLFW_STICK;
+    else
+        window->mouseButtons[button] = (char) action;
+
+    if (window->callbacks.mouseButton)
+        window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
+}
+
+// Notifies shared code of a cursor motion event
+// The position is specified in content area relative screen coordinates
+//
+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+    if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
+        return;
+
+    window->virtualCursorPosX = xpos;
+    window->virtualCursorPosY = ypos;
+
+    if (window->callbacks.cursorPos)
+        window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
+}
+
+// Notifies shared code of a cursor enter/leave event
+//
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
+{
+    if (window->callbacks.cursorEnter)
+        window->callbacks.cursorEnter((GLFWwindow*) window, entered);
+}
+
+// Notifies shared code of files or directories dropped on a window
+//
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
+{
+    if (window->callbacks.drop)
+        window->callbacks.drop((GLFWwindow*) window, count, paths);
+}
+
+// Notifies shared code of a joystick connection or disconnection
+//
+void _glfwInputJoystick(_GLFWjoystick* js, int event)
+{
+    const int jid = (int) (js - _glfw.joysticks);
+
+    if (_glfw.callbacks.joystick)
+        _glfw.callbacks.joystick(jid, event);
+}
+
+// Notifies shared code of the new value of a joystick axis
+//
+void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
+{
+    js->axes[axis] = value;
+}
+
+// Notifies shared code of the new value of a joystick button
+//
+void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
+{
+    js->buttons[button] = value;
+}
+
+// Notifies shared code of the new value of a joystick hat
+//
+void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
+{
+    const int base = js->buttonCount + hat * 4;
+
+    js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
+    js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
+    js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
+    js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
+
+    js->hats[hat] = value;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns an available joystick object with arrays and name allocated
+//
+_GLFWjoystick* _glfwAllocJoystick(const char* name,
+                                  const char* guid,
+                                  int axisCount,
+                                  int buttonCount,
+                                  int hatCount)
+{
+    int jid;
+    _GLFWjoystick* js;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        if (!_glfw.joysticks[jid].present)
+            break;
+    }
+
+    if (jid > GLFW_JOYSTICK_LAST)
+        return NULL;
+
+    js = _glfw.joysticks + jid;
+    js->present     = GLFW_TRUE;
+    js->name        = _glfw_strdup(name);
+    js->axes        = calloc(axisCount, sizeof(float));
+    js->buttons     = calloc(buttonCount + (size_t) hatCount * 4, 1);
+    js->hats        = calloc(hatCount, 1);
+    js->axisCount   = axisCount;
+    js->buttonCount = buttonCount;
+    js->hatCount    = hatCount;
+
+    strncpy(js->guid, guid, sizeof(js->guid) - 1);
+    js->mapping = findValidMapping(js);
+
+    return js;
+}
+
+// Frees arrays and name and flags the joystick object as unused
+//
+void _glfwFreeJoystick(_GLFWjoystick* js)
+{
+    free(js->name);
+    free(js->axes);
+    free(js->buttons);
+    free(js->hats);
+    memset(js, 0, sizeof(_GLFWjoystick));
+}
+
+// Center the cursor in the content area of the specified window
+//
+void _glfwCenterCursorInContentArea(_GLFWwindow* window)
+{
+    int width, height;
+
+    _glfwPlatformGetWindowSize(window, &width, &height);
+    _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+    switch (mode)
+    {
+        case GLFW_CURSOR:
+            return window->cursorMode;
+        case GLFW_STICKY_KEYS:
+            return window->stickyKeys;
+        case GLFW_STICKY_MOUSE_BUTTONS:
+            return window->stickyMouseButtons;
+        case GLFW_LOCK_KEY_MODS:
+            return window->lockKeyMods;
+        case GLFW_RAW_MOUSE_MOTION:
+            return window->rawMouseMotion;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
+    return 0;
+}
+
+GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (mode == GLFW_CURSOR)
+    {
+        if (value != GLFW_CURSOR_NORMAL &&
+            value != GLFW_CURSOR_HIDDEN &&
+            value != GLFW_CURSOR_DISABLED)
+        {
+            _glfwInputError(GLFW_INVALID_ENUM,
+                            "Invalid cursor mode 0x%08X",
+                            value);
+            return;
+        }
+
+        if (window->cursorMode == value)
+            return;
+
+        window->cursorMode = value;
+
+        _glfwPlatformGetCursorPos(window,
+                                  &window->virtualCursorPosX,
+                                  &window->virtualCursorPosY);
+        _glfwPlatformSetCursorMode(window, value);
+    }
+    else if (mode == GLFW_STICKY_KEYS)
+    {
+        value = value ? GLFW_TRUE : GLFW_FALSE;
+        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;
+    }
+    else if (mode == GLFW_STICKY_MOUSE_BUTTONS)
+    {
+        value = value ? GLFW_TRUE : GLFW_FALSE;
+        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;
+    }
+    else if (mode == GLFW_LOCK_KEY_MODS)
+    {
+        window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
+    }
+    else if (mode == GLFW_RAW_MOUSE_MOTION)
+    {
+        if (!_glfwPlatformRawMouseMotionSupported())
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Raw mouse motion is not supported on this system");
+            return;
+        }
+
+        value = value ? GLFW_TRUE : GLFW_FALSE;
+        if (window->rawMouseMotion == value)
+            return;
+
+        window->rawMouseMotion = value;
+        _glfwPlatformSetRawMouseMotion(window, value);
+    }
+    else
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
+}
+
+GLFWAPI int glfwRawMouseMotionSupported(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+    return _glfwPlatformRawMouseMotionSupported();
+}
+
+GLFWAPI const char* glfwGetKeyName(int key, int scancode)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (key != GLFW_KEY_UNKNOWN)
+    {
+        if (key != GLFW_KEY_KP_EQUAL &&
+            (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
+            (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
+        {
+            return NULL;
+        }
+
+        scancode = _glfwPlatformGetKeyScancode(key);
+    }
+
+    return _glfwPlatformGetScancodeName(scancode);
+}
+
+GLFWAPI int glfwGetKeyScancode(int key)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(-1);
+
+    if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
+        return GLFW_RELEASE;
+    }
+
+    return _glfwPlatformGetKeyScancode(key);
+}
+
+GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
+
+    if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
+        return GLFW_RELEASE;
+    }
+
+    if (window->keys[key] == _GLFW_STICK)
+    {
+        // Sticky mode: release key now
+        window->keys[key] = GLFW_RELEASE;
+        return GLFW_PRESS;
+    }
+
+    return (int) window->keys[key];
+}
+
+GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
+
+    if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
+        return GLFW_RELEASE;
+    }
+
+    if (window->mouseButtons[button] == _GLFW_STICK)
+    {
+        // Sticky mode: release mouse button now
+        window->mouseButtons[button] = GLFW_RELEASE;
+        return GLFW_PRESS;
+    }
+
+    return (int) window->mouseButtons[button];
+}
+
+GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (xpos)
+        *xpos = 0;
+    if (ypos)
+        *ypos = 0;
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        if (xpos)
+            *xpos = window->virtualCursorPosX;
+        if (ypos)
+            *ypos = window->virtualCursorPosY;
+    }
+    else
+        _glfwPlatformGetCursorPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    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->virtualCursorPosX = xpos;
+        window->virtualCursorPosY = ypos;
+    }
+    else
+    {
+        // Update system cursor position
+        _glfwPlatformSetCursorPos(window, xpos, ypos);
+    }
+}
+
+GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
+{
+    _GLFWcursor* cursor;
+
+    assert(image != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    cursor = calloc(1, sizeof(_GLFWcursor));
+    cursor->next = _glfw.cursorListHead;
+    _glfw.cursorListHead = cursor;
+
+    if (!_glfwPlatformCreateCursor(cursor, image, xhot, yhot))
+    {
+        glfwDestroyCursor((GLFWcursor*) cursor);
+        return NULL;
+    }
+
+    return (GLFWcursor*) cursor;
+}
+
+GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
+{
+    _GLFWcursor* cursor;
+
+    _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 0x%08X", shape);
+        return NULL;
+    }
+
+    cursor = calloc(1, sizeof(_GLFWcursor));
+    cursor->next = _glfw.cursorListHead;
+    _glfw.cursorListHead = cursor;
+
+    if (!_glfwPlatformCreateStandardCursor(cursor, shape))
+    {
+        glfwDestroyCursor((GLFWcursor*) cursor);
+        return NULL;
+    }
+
+    return (GLFWcursor*) cursor;
+}
+
+GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
+{
+    _GLFWcursor* cursor = (_GLFWcursor*) handle;
+
+    _GLFW_REQUIRE_INIT();
+
+    if (cursor == NULL)
+        return;
+
+    // Make sure the cursor is not being used by any window
+    {
+        _GLFWwindow* window;
+
+        for (window = _glfw.windowListHead;  window;  window = window->next)
+        {
+            if (window->cursor == cursor)
+                glfwSetCursor((GLFWwindow*) window, NULL);
+        }
+    }
+
+    _glfwPlatformDestroyCursor(cursor);
+
+    // Unlink cursor from global linked list
+    {
+        _GLFWcursor** prev = &_glfw.cursorListHead;
+
+        while (*prev != cursor)
+            prev = &((*prev)->next);
+
+        *prev = cursor->next;
+    }
+
+    free(cursor);
+}
+
+GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) windowHandle;
+    _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    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;
+}
+
+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;
+}
+
+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;
+}
+
+GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
+                                                      GLFWmousebuttonfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.mouseButton, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
+                                                  GLFWcursorposfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.cursorPos, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
+                                                      GLFWcursorenterfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.cursorEnter, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
+                                            GLFWscrollfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.scroll, cbfun);
+    return cbfun;
+}
+
+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;
+}
+
+GLFWAPI int glfwJoystickPresent(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return GLFW_FALSE;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return GLFW_FALSE;
+
+    return _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
+}
+
+GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_AXES))
+        return NULL;
+
+    *count = js->axisCount;
+    return js->axes;
+}
+
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
+        return NULL;
+
+    if (_glfw.hints.init.hatButtons)
+        *count = js->buttonCount + js->hatCount * 4;
+    else
+        *count = js->buttonCount;
+
+    return js->buttons;
+}
+
+GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_BUTTONS))
+        return NULL;
+
+    *count = js->hatCount;
+    return js->hats;
+}
+
+GLFWAPI const char* glfwGetJoystickName(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+        return NULL;
+
+    return js->name;
+}
+
+GLFWAPI const char* glfwGetJoystickGUID(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+        return NULL;
+
+    return js->guid;
+}
+
+GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT();
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return;
+
+    js->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetJoystickUserPointer(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    return js->userPointer;
+}
+
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
+    return cbfun;
+}
+
+GLFWAPI int glfwUpdateGamepadMappings(const char* string)
+{
+    int jid;
+    const char* c = string;
+
+    assert(string != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    while (*c)
+    {
+        if ((*c >= '0' && *c <= '9') ||
+            (*c >= 'a' && *c <= 'f') ||
+            (*c >= 'A' && *c <= 'F'))
+        {
+            char line[1024];
+
+            const size_t length = strcspn(c, "\r\n");
+            if (length < sizeof(line))
+            {
+                _GLFWmapping mapping = {{0}};
+
+                memcpy(line, c, length);
+                line[length] = '\0';
+
+                if (parseMapping(&mapping, line))
+                {
+                    _GLFWmapping* previous = findMapping(mapping.guid);
+                    if (previous)
+                        *previous = mapping;
+                    else
+                    {
+                        _glfw.mappingCount++;
+                        _glfw.mappings =
+                            realloc(_glfw.mappings,
+                                    sizeof(_GLFWmapping) * _glfw.mappingCount);
+                        _glfw.mappings[_glfw.mappingCount - 1] = mapping;
+                    }
+                }
+            }
+
+            c += length;
+        }
+        else
+        {
+            c += strcspn(c, "\r\n");
+            c += strspn(c, "\r\n");
+        }
+    }
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        _GLFWjoystick* js = _glfw.joysticks + jid;
+        if (js->present)
+            js->mapping = findValidMapping(js);
+    }
+
+    return GLFW_TRUE;
+}
+
+GLFWAPI int glfwJoystickIsGamepad(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return GLFW_FALSE;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return GLFW_FALSE;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+        return GLFW_FALSE;
+
+    return js->mapping != NULL;
+}
+
+GLFWAPI const char* glfwGetGamepadName(int jid)
+{
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return NULL;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return NULL;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE))
+        return NULL;
+
+    if (!js->mapping)
+        return NULL;
+
+    return js->mapping->name;
+}
+
+GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
+{
+    int i;
+    _GLFWjoystick* js;
+
+    assert(jid >= GLFW_JOYSTICK_1);
+    assert(jid <= GLFW_JOYSTICK_LAST);
+    assert(state != NULL);
+
+    memset(state, 0, sizeof(GLFWgamepadstate));
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
+    {
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
+        return GLFW_FALSE;
+    }
+
+    js = _glfw.joysticks + jid;
+    if (!js->present)
+        return GLFW_FALSE;
+
+    if (!_glfwPlatformPollJoystick(js, _GLFW_POLL_ALL))
+        return GLFW_FALSE;
+
+    if (!js->mapping)
+        return GLFW_FALSE;
+
+    for (i = 0;  i <= GLFW_GAMEPAD_BUTTON_LAST;  i++)
+    {
+        const _GLFWmapelement* e = js->mapping->buttons + i;
+        if (e->type == _GLFW_JOYSTICK_AXIS)
+        {
+            const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
+            // HACK: This should be baked into the value transform
+            // TODO: Bake into transform when implementing output modifiers
+            if (e->axisOffset < 0 || (e->axisOffset == 0 && e->axisScale > 0))
+            {
+                if (value >= 0.f)
+                    state->buttons[i] = GLFW_PRESS;
+            }
+            else
+            {
+                if (value <= 0.f)
+                    state->buttons[i] = GLFW_PRESS;
+            }
+        }
+        else if (e->type == _GLFW_JOYSTICK_HATBIT)
+        {
+            const unsigned int hat = e->index >> 4;
+            const unsigned int bit = e->index & 0xf;
+            if (js->hats[hat] & bit)
+                state->buttons[i] = GLFW_PRESS;
+        }
+        else if (e->type == _GLFW_JOYSTICK_BUTTON)
+            state->buttons[i] = js->buttons[e->index];
+    }
+
+    for (i = 0;  i <= GLFW_GAMEPAD_AXIS_LAST;  i++)
+    {
+        const _GLFWmapelement* e = js->mapping->axes + i;
+        if (e->type == _GLFW_JOYSTICK_AXIS)
+        {
+            const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
+            state->axes[i] = _glfw_fminf(_glfw_fmaxf(value, -1.f), 1.f);
+        }
+        else if (e->type == _GLFW_JOYSTICK_HATBIT)
+        {
+            const unsigned int hat = e->index >> 4;
+            const unsigned int bit = e->index & 0xf;
+            if (js->hats[hat] & bit)
+                state->axes[i] = 1.f;
+            else
+                state->axes[i] = -1.f;
+        }
+        else if (e->type == _GLFW_JOYSTICK_BUTTON)
+            state->axes[i] = js->buttons[e->index] * 2.f - 1.f;
+    }
+
+    return GLFW_TRUE;
+}
+
+GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
+{
+    assert(string != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformSetClipboardString(string);
+}
+
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return _glfwPlatformGetClipboardString();
+}
+
+GLFWAPI double glfwGetTime(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
+    return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
+        _glfwPlatformGetTimerFrequency();
+}
+
+GLFWAPI void glfwSetTime(double time)
+{
+    _GLFW_REQUIRE_INIT();
+
+    if (time != time || time < 0.0 || time > 18446744073.0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
+        return;
+    }
+
+    _glfw.timer.offset = _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();
+}
diff --git a/glfw/src/internal.h b/glfw/src/internal.h
--- a/glfw/src/internal.h
+++ b/glfw/src/internal.h
@@ -1,776 +1,778 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-
-#pragma once
-
-#if defined(_GLFW_USE_CONFIG_H)
- #include "glfw_config.h"
-#endif
-
-#if defined(GLFW_INCLUDE_GLCOREARB) || \
-    defined(GLFW_INCLUDE_ES1)       || \
-    defined(GLFW_INCLUDE_ES2)       || \
-    defined(GLFW_INCLUDE_ES3)       || \
-    defined(GLFW_INCLUDE_ES31)      || \
-    defined(GLFW_INCLUDE_ES32)      || \
-    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
-
-#define GLFW_INCLUDE_NONE
-#include "../include/GLFW/glfw3.h"
-
-#define _GLFW_INSERT_FIRST      0
-#define _GLFW_INSERT_LAST       1
-
-#define _GLFW_POLL_PRESENCE     0
-#define _GLFW_POLL_AXES         1
-#define _GLFW_POLL_BUTTONS      2
-#define _GLFW_POLL_ALL          (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
-
-#define _GLFW_MESSAGE_SIZE      1024
-
-typedef int GLFWbool;
-
-typedef struct _GLFWerror       _GLFWerror;
-typedef struct _GLFWinitconfig  _GLFWinitconfig;
-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 struct _GLFWmapelement  _GLFWmapelement;
-typedef struct _GLFWmapping     _GLFWmapping;
-typedef struct _GLFWjoystick    _GLFWjoystick;
-typedef struct _GLFWtls         _GLFWtls;
-typedef struct _GLFWmutex       _GLFWmutex;
-
-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_UNSIGNED_BYTE 0x1401
-#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_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
-    VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
-    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)
- #include "win32_platform.h"
-#elif defined(_GLFW_X11)
- #include "x11_platform.h"
-#elif defined(_GLFW_WAYLAND)
- #include "wl_platform.h"
-#elif defined(_GLFW_OSMESA)
- #include "null_platform.h"
-#else
- #error "No supported window creation API selected"
-#endif
-
-// 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 (!_glfw.initialized)                          \
-    {                                                \
-        _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
-        return;                                      \
-    }
-#define _GLFW_REQUIRE_INIT_OR_RETURN(x)              \
-    if (!_glfw.initialized)                          \
-    {                                                \
-        _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
-        return x;                                    \
-    }
-
-// Swaps the provided pointers
-#define _GLFW_SWAP_POINTERS(x, y) \
-    {                             \
-        void* t;                  \
-        t = x;                    \
-        x = y;                    \
-        y = t;                    \
-    }
-
-// Per-thread error structure
-//
-struct _GLFWerror
-{
-    _GLFWerror*     next;
-    int             code;
-    char            description[_GLFW_MESSAGE_SIZE];
-};
-
-// Initialization configuration
-//
-// Parameters relating to the initialization of the library
-//
-struct _GLFWinitconfig
-{
-    GLFWbool      hatButtons;
-    struct {
-        GLFWbool  menubar;
-        GLFWbool  chdir;
-    } ns;
-};
-
-// Window configuration
-//
-// Parameters relating to the creation of the window but not directly related
-// to the framebuffer.  This is used to pass window creation parameters from
-// shared code to the platform API.
-//
-struct _GLFWwndconfig
-{
-    int           width;
-    int           height;
-    const char*   title;
-    GLFWbool      resizable;
-    GLFWbool      visible;
-    GLFWbool      decorated;
-    GLFWbool      focused;
-    GLFWbool      autoIconify;
-    GLFWbool      floating;
-    GLFWbool      maximized;
-    GLFWbool      centerCursor;
-    GLFWbool      focusOnShow;
-    GLFWbool      scaleToMonitor;
-    struct {
-        GLFWbool  retina;
-        char      frameName[256];
-    } ns;
-    struct {
-        char      className[256];
-        char      instanceName[256];
-    } x11;
-};
-
-// Context configuration
-//
-// Parameters relating to the creation of the context but not directly related
-// to the framebuffer.  This is used to pass context creation parameters from
-// shared code to the platform API.
-//
-struct _GLFWctxconfig
-{
-    int           client;
-    int           source;
-    int           major;
-    int           minor;
-    GLFWbool      forward;
-    GLFWbool      debug;
-    GLFWbool      noerror;
-    int           profile;
-    int           robustness;
-    int           release;
-    _GLFWwindow*  share;
-    struct {
-        GLFWbool  offline;
-    } nsgl;
-};
-
-// Framebuffer configuration
-//
-// This describes buffers and their sizes.  It also contains
-// a platform-specific ID used to map back to the backend API object.
-//
-// It is used to pass framebuffer parameters from shared code to the platform
-// API and also to enumerate and select available framebuffer configs.
-//
-struct _GLFWfbconfig
-{
-    int         redBits;
-    int         greenBits;
-    int         blueBits;
-    int         alphaBits;
-    int         depthBits;
-    int         stencilBits;
-    int         accumRedBits;
-    int         accumGreenBits;
-    int         accumBlueBits;
-    int         accumAlphaBits;
-    int         auxBuffers;
-    GLFWbool    stereo;
-    int         samples;
-    GLFWbool    sRGB;
-    GLFWbool    doublebuffer;
-    GLFWbool    transparent;
-    uintptr_t   handle;
-};
-
-// 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_CONTEXT_STATE;
-    // This is defined in egl_context.h
-    _GLFW_EGL_CONTEXT_STATE;
-    // This is defined in osmesa_context.h
-    _GLFW_OSMESA_CONTEXT_STATE;
-};
-
-// Window and context structure
-//
-struct _GLFWwindow
-{
-    struct _GLFWwindow* next;
-
-    // Window settings and state
-    GLFWbool            resizable;
-    GLFWbool            decorated;
-    GLFWbool            autoIconify;
-    GLFWbool            floating;
-    GLFWbool            focusOnShow;
-    GLFWbool            shouldClose;
-    void*               userPointer;
-    GLFWvidmode         videoMode;
-    _GLFWmonitor*       monitor;
-    _GLFWcursor*        cursor;
-
-    int                 minwidth, minheight;
-    int                 maxwidth, maxheight;
-    int                 numer, denom;
-
-    GLFWbool            stickyKeys;
-    GLFWbool            stickyMouseButtons;
-    GLFWbool            lockKeyMods;
-    int                 cursorMode;
-    char                mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
-    char                keys[GLFW_KEY_LAST + 1];
-    // Virtual cursor position when cursor is disabled
-    double              virtualCursorPosX, virtualCursorPosY;
-    GLFWbool            rawMouseMotion;
-
-    _GLFWcontext        context;
-
-    struct {
-        GLFWwindowposfun        pos;
-        GLFWwindowsizefun       size;
-        GLFWwindowclosefun      close;
-        GLFWwindowrefreshfun    refresh;
-        GLFWwindowfocusfun      focus;
-        GLFWwindowiconifyfun    iconify;
-        GLFWwindowmaximizefun   maximize;
-        GLFWframebuffersizefun  fbsize;
-        GLFWwindowcontentscalefun scale;
-        GLFWmousebuttonfun      mouseButton;
-        GLFWcursorposfun        cursorPos;
-        GLFWcursorenterfun      cursorEnter;
-        GLFWscrollfun           scroll;
-        GLFWkeyfun              key;
-        GLFWcharfun             character;
-        GLFWcharmodsfun         charmods;
-        GLFWdropfun             drop;
-    } callbacks;
-
-    // This is defined in the window API's platform.h
-    _GLFW_PLATFORM_WINDOW_STATE;
-};
-
-// Monitor structure
-//
-struct _GLFWmonitor
-{
-    char*           name;
-    void*           userPointer;
-
-    // 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;
-
-    GLFWgammaramp   originalRamp;
-    GLFWgammaramp   currentRamp;
-
-    // This is defined in the window API's platform.h
-    _GLFW_PLATFORM_MONITOR_STATE;
-};
-
-// Cursor structure
-//
-struct _GLFWcursor
-{
-    _GLFWcursor*    next;
-
-    // This is defined in the window API's platform.h
-    _GLFW_PLATFORM_CURSOR_STATE;
-};
-
-// Gamepad mapping element structure
-//
-struct _GLFWmapelement
-{
-    uint8_t         type;
-    uint8_t         index;
-    int8_t          axisScale;
-    int8_t          axisOffset;
-};
-
-// Gamepad mapping structure
-//
-struct _GLFWmapping
-{
-    char            name[128];
-    char            guid[33];
-    _GLFWmapelement buttons[15];
-    _GLFWmapelement axes[6];
-};
-
-// Joystick structure
-//
-struct _GLFWjoystick
-{
-    GLFWbool        present;
-    float*          axes;
-    int             axisCount;
-    unsigned char*  buttons;
-    int             buttonCount;
-    unsigned char*  hats;
-    int             hatCount;
-    char*           name;
-    void*           userPointer;
-    char            guid[33];
-    _GLFWmapping*   mapping;
-
-    // This is defined in the joystick API's joystick.h
-    _GLFW_PLATFORM_JOYSTICK_STATE;
-};
-
-// Thread local storage structure
-//
-struct _GLFWtls
-{
-    // This is defined in the platform's thread.h
-    _GLFW_PLATFORM_TLS_STATE;
-};
-
-// Mutex structure
-//
-struct _GLFWmutex
-{
-    // This is defined in the platform's thread.h
-    _GLFW_PLATFORM_MUTEX_STATE;
-};
-
-// Library global data
-//
-struct _GLFWlibrary
-{
-    GLFWbool            initialized;
-
-    struct {
-        _GLFWinitconfig init;
-        _GLFWfbconfig   framebuffer;
-        _GLFWwndconfig  window;
-        _GLFWctxconfig  context;
-        int             refreshRate;
-    } hints;
-
-    _GLFWerror*         errorListHead;
-    _GLFWcursor*        cursorListHead;
-    _GLFWwindow*        windowListHead;
-
-    _GLFWmonitor**      monitors;
-    int                 monitorCount;
-
-    _GLFWjoystick       joysticks[GLFW_JOYSTICK_LAST + 1];
-    _GLFWmapping*       mappings;
-    int                 mappingCount;
-
-    _GLFWtls            errorSlot;
-    _GLFWtls            contextSlot;
-    _GLFWmutex          errorLock;
-
-    struct {
-        uint64_t        offset;
-        // This is defined in the platform's time.h
-        _GLFW_PLATFORM_LIBRARY_TIMER_STATE;
-    } timer;
-
-    struct {
-        GLFWbool        available;
-        void*           handle;
-        char*           extensions[2];
-#if !defined(_GLFW_VULKAN_STATIC)
-        PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
-        PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
-#endif
-        GLFWbool        KHR_surface;
-#if defined(_GLFW_WIN32)
-        GLFWbool        KHR_win32_surface;
-#elif defined(_GLFW_COCOA)
-        GLFWbool        MVK_macos_surface;
-#elif defined(_GLFW_X11)
-        GLFWbool        KHR_xlib_surface;
-        GLFWbool        KHR_xcb_surface;
-#elif defined(_GLFW_WAYLAND)
-        GLFWbool        KHR_wayland_surface;
-#endif
-    } vk;
-
-    struct {
-        GLFWmonitorfun  monitor;
-        GLFWjoystickfun joystick;
-    } callbacks;
-
-    // This is defined in the window API's platform.h
-    _GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
-    // This is defined in the context API's context.h
-    _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
-    // This is defined in the platform's joystick.h
-    _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
-    // This is defined in egl_context.h
-    _GLFW_EGL_LIBRARY_CONTEXT_STATE;
-    // This is defined in osmesa_context.h
-    _GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
-};
-
-// Global state shared between compilation units of GLFW
-//
-extern _GLFWlibrary _glfw;
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void);
-void _glfwPlatformTerminate(void);
-const char* _glfwPlatformGetVersionString(void);
-
-void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
-void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
-void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled);
-GLFWbool _glfwPlatformRawMouseMotionSupported(void);
-int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
-                              const GLFWimage* image, int xhot, int yhot);
-int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
-void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
-void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
-
-const char* _glfwPlatformGetScancodeName(int scancode);
-int _glfwPlatformGetKeyScancode(int key);
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale);
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
-
-void _glfwPlatformSetClipboardString(const char* string);
-const char* _glfwPlatformGetClipboardString(void);
-
-int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
-void _glfwPlatformUpdateGamepadGUID(char* guid);
-
-uint64_t _glfwPlatformGetTimerValue(void);
-uint64_t _glfwPlatformGetTimerFrequency(void);
-
-int _glfwPlatformCreateWindow(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig);
-void _glfwPlatformDestroyWindow(_GLFWwindow* window);
-void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
-void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
-                                int count, const GLFWimage* images);
-void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
-void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
-void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
-void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
-void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
-                                      int minwidth, int minheight,
-                                      int maxwidth, int maxheight);
-void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
-void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
-void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
-                                     int* left, int* top,
-                                     int* right, int* bottom);
-void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale);
-void _glfwPlatformIconifyWindow(_GLFWwindow* window);
-void _glfwPlatformRestoreWindow(_GLFWwindow* window);
-void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
-void _glfwPlatformShowWindow(_GLFWwindow* window);
-void _glfwPlatformHideWindow(_GLFWwindow* window);
-void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
-void _glfwPlatformFocusWindow(_GLFWwindow* window);
-void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
-                                   int xpos, int ypos, int width, int height,
-                                   int refreshRate);
-int _glfwPlatformWindowFocused(_GLFWwindow* window);
-int _glfwPlatformWindowIconified(_GLFWwindow* window);
-int _glfwPlatformWindowVisible(_GLFWwindow* window);
-int _glfwPlatformWindowMaximized(_GLFWwindow* window);
-int _glfwPlatformWindowHovered(_GLFWwindow* window);
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
-
-void _glfwPlatformPollEvents(void);
-void _glfwPlatformWaitEvents(void);
-void _glfwPlatformWaitEventsTimeout(double timeout);
-void _glfwPlatformPostEmptyEvent(void);
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
-int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
-                                                      VkPhysicalDevice device,
-                                                      uint32_t queuefamily);
-VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
-                                          _GLFWwindow* window,
-                                          const VkAllocationCallbacks* allocator,
-                                          VkSurfaceKHR* surface);
-
-GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
-void _glfwPlatformDestroyTls(_GLFWtls* tls);
-void* _glfwPlatformGetTls(_GLFWtls* tls);
-void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
-
-GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
-void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
-void _glfwPlatformLockMutex(_GLFWmutex* mutex);
-void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                         GLFW event API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
-void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
-void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
-void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
-void _glfwInputWindowContentScale(_GLFWwindow* window,
-                                  float xscale, float yscale);
-void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
-void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
-void _glfwInputWindowDamage(_GLFWwindow* window);
-void _glfwInputWindowCloseRequest(_GLFWwindow* window);
-void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
-
-void _glfwInputKey(_GLFWwindow* window,
-                   int key, int scancode, int action, int mods);
-void _glfwInputChar(_GLFWwindow* window,
-                    unsigned int codepoint, int mods, GLFWbool plain);
-void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
-void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
-void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
-void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
-void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
-void _glfwInputJoystick(_GLFWjoystick* js, int event);
-void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
-void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
-void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
-
-void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
-void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
-
-#if defined(__GNUC__)
-void _glfwInputError(int code, const char* format, ...)
-    __attribute__((format(printf, 2, 3)));
-#else
-void _glfwInputError(int code, const char* format, ...);
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
-const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
-                                         const _GLFWfbconfig* alternatives,
-                                         unsigned int count);
-GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
-                                    const _GLFWctxconfig* ctxconfig);
-GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
-
-const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
-                                        const GLFWvidmode* desired);
-int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
-_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
-void _glfwFreeMonitor(_GLFWmonitor* monitor);
-void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
-void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
-void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
-
-_GLFWjoystick* _glfwAllocJoystick(const char* name,
-                                  const char* guid,
-                                  int axisCount,
-                                  int buttonCount,
-                                  int hatCount);
-void _glfwFreeJoystick(_GLFWjoystick* js);
-void _glfwCenterCursorInContentArea(_GLFWwindow* window);
-
-GLFWbool _glfwInitVulkan(int mode);
-void _glfwTerminateVulkan(void);
-const char* _glfwGetVulkanResultString(VkResult result);
-
-char* _glfw_strdup(const char* source);
-float _glfw_fminf(float a, float b);
-float _glfw_fmaxf(float a, float b);
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+
+#pragma once
+
+#if defined(_GLFW_USE_CONFIG_H)
+ #include "glfw_config.h"
+#endif
+
+#if defined(GLFW_INCLUDE_GLCOREARB) || \
+    defined(GLFW_INCLUDE_ES1)       || \
+    defined(GLFW_INCLUDE_ES2)       || \
+    defined(GLFW_INCLUDE_ES3)       || \
+    defined(GLFW_INCLUDE_ES31)      || \
+    defined(GLFW_INCLUDE_ES32)      || \
+    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
+
+#define GLFW_INCLUDE_NONE
+#include "../include/GLFW/glfw3.h"
+
+#define _GLFW_INSERT_FIRST      0
+#define _GLFW_INSERT_LAST       1
+
+#define _GLFW_POLL_PRESENCE     0
+#define _GLFW_POLL_AXES         1
+#define _GLFW_POLL_BUTTONS      2
+#define _GLFW_POLL_ALL          (_GLFW_POLL_AXES | _GLFW_POLL_BUTTONS)
+
+#define _GLFW_MESSAGE_SIZE      1024
+
+typedef int GLFWbool;
+
+typedef struct _GLFWerror       _GLFWerror;
+typedef struct _GLFWinitconfig  _GLFWinitconfig;
+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 struct _GLFWmapelement  _GLFWmapelement;
+typedef struct _GLFWmapping     _GLFWmapping;
+typedef struct _GLFWjoystick    _GLFWjoystick;
+typedef struct _GLFWtls         _GLFWtls;
+typedef struct _GLFWmutex       _GLFWmutex;
+
+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_UNSIGNED_BYTE 0x1401
+#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_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+    VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
+    VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT = 1000217000,
+    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)
+ #include "win32_platform.h"
+#elif defined(_GLFW_X11)
+ #include "x11_platform.h"
+#elif defined(_GLFW_WAYLAND)
+ #include "wl_platform.h"
+#elif defined(_GLFW_OSMESA)
+ #include "null_platform.h"
+#else
+ #error "No supported window creation API selected"
+#endif
+
+// 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 (!_glfw.initialized)                          \
+    {                                                \
+        _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
+        return;                                      \
+    }
+#define _GLFW_REQUIRE_INIT_OR_RETURN(x)              \
+    if (!_glfw.initialized)                          \
+    {                                                \
+        _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
+        return x;                                    \
+    }
+
+// Swaps the provided pointers
+#define _GLFW_SWAP_POINTERS(x, y) \
+    {                             \
+        void* t;                  \
+        t = x;                    \
+        x = y;                    \
+        y = t;                    \
+    }
+
+// Per-thread error structure
+//
+struct _GLFWerror
+{
+    _GLFWerror*     next;
+    int             code;
+    char            description[_GLFW_MESSAGE_SIZE];
+};
+
+// Initialization configuration
+//
+// Parameters relating to the initialization of the library
+//
+struct _GLFWinitconfig
+{
+    GLFWbool      hatButtons;
+    struct {
+        GLFWbool  menubar;
+        GLFWbool  chdir;
+    } ns;
+};
+
+// Window configuration
+//
+// Parameters relating to the creation of the window but not directly related
+// to the framebuffer.  This is used to pass window creation parameters from
+// shared code to the platform API.
+//
+struct _GLFWwndconfig
+{
+    int           width;
+    int           height;
+    const char*   title;
+    GLFWbool      resizable;
+    GLFWbool      visible;
+    GLFWbool      decorated;
+    GLFWbool      focused;
+    GLFWbool      autoIconify;
+    GLFWbool      floating;
+    GLFWbool      maximized;
+    GLFWbool      centerCursor;
+    GLFWbool      focusOnShow;
+    GLFWbool      scaleToMonitor;
+    struct {
+        GLFWbool  retina;
+        char      frameName[256];
+    } ns;
+    struct {
+        char      className[256];
+        char      instanceName[256];
+    } x11;
+};
+
+// Context configuration
+//
+// Parameters relating to the creation of the context but not directly related
+// to the framebuffer.  This is used to pass context creation parameters from
+// shared code to the platform API.
+//
+struct _GLFWctxconfig
+{
+    int           client;
+    int           source;
+    int           major;
+    int           minor;
+    GLFWbool      forward;
+    GLFWbool      debug;
+    GLFWbool      noerror;
+    int           profile;
+    int           robustness;
+    int           release;
+    _GLFWwindow*  share;
+    struct {
+        GLFWbool  offline;
+    } nsgl;
+};
+
+// Framebuffer configuration
+//
+// This describes buffers and their sizes.  It also contains
+// a platform-specific ID used to map back to the backend API object.
+//
+// It is used to pass framebuffer parameters from shared code to the platform
+// API and also to enumerate and select available framebuffer configs.
+//
+struct _GLFWfbconfig
+{
+    int         redBits;
+    int         greenBits;
+    int         blueBits;
+    int         alphaBits;
+    int         depthBits;
+    int         stencilBits;
+    int         accumRedBits;
+    int         accumGreenBits;
+    int         accumBlueBits;
+    int         accumAlphaBits;
+    int         auxBuffers;
+    GLFWbool    stereo;
+    int         samples;
+    GLFWbool    sRGB;
+    GLFWbool    doublebuffer;
+    GLFWbool    transparent;
+    uintptr_t   handle;
+};
+
+// 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_CONTEXT_STATE;
+    // This is defined in egl_context.h
+    _GLFW_EGL_CONTEXT_STATE;
+    // This is defined in osmesa_context.h
+    _GLFW_OSMESA_CONTEXT_STATE;
+};
+
+// Window and context structure
+//
+struct _GLFWwindow
+{
+    struct _GLFWwindow* next;
+
+    // Window settings and state
+    GLFWbool            resizable;
+    GLFWbool            decorated;
+    GLFWbool            autoIconify;
+    GLFWbool            floating;
+    GLFWbool            focusOnShow;
+    GLFWbool            shouldClose;
+    void*               userPointer;
+    GLFWvidmode         videoMode;
+    _GLFWmonitor*       monitor;
+    _GLFWcursor*        cursor;
+
+    int                 minwidth, minheight;
+    int                 maxwidth, maxheight;
+    int                 numer, denom;
+
+    GLFWbool            stickyKeys;
+    GLFWbool            stickyMouseButtons;
+    GLFWbool            lockKeyMods;
+    int                 cursorMode;
+    char                mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
+    char                keys[GLFW_KEY_LAST + 1];
+    // Virtual cursor position when cursor is disabled
+    double              virtualCursorPosX, virtualCursorPosY;
+    GLFWbool            rawMouseMotion;
+
+    _GLFWcontext        context;
+
+    struct {
+        GLFWwindowposfun        pos;
+        GLFWwindowsizefun       size;
+        GLFWwindowclosefun      close;
+        GLFWwindowrefreshfun    refresh;
+        GLFWwindowfocusfun      focus;
+        GLFWwindowiconifyfun    iconify;
+        GLFWwindowmaximizefun   maximize;
+        GLFWframebuffersizefun  fbsize;
+        GLFWwindowcontentscalefun scale;
+        GLFWmousebuttonfun      mouseButton;
+        GLFWcursorposfun        cursorPos;
+        GLFWcursorenterfun      cursorEnter;
+        GLFWscrollfun           scroll;
+        GLFWkeyfun              key;
+        GLFWcharfun             character;
+        GLFWcharmodsfun         charmods;
+        GLFWdropfun             drop;
+    } callbacks;
+
+    // This is defined in the window API's platform.h
+    _GLFW_PLATFORM_WINDOW_STATE;
+};
+
+// Monitor structure
+//
+struct _GLFWmonitor
+{
+    char*           name;
+    void*           userPointer;
+
+    // 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;
+
+    GLFWgammaramp   originalRamp;
+    GLFWgammaramp   currentRamp;
+
+    // This is defined in the window API's platform.h
+    _GLFW_PLATFORM_MONITOR_STATE;
+};
+
+// Cursor structure
+//
+struct _GLFWcursor
+{
+    _GLFWcursor*    next;
+
+    // This is defined in the window API's platform.h
+    _GLFW_PLATFORM_CURSOR_STATE;
+};
+
+// Gamepad mapping element structure
+//
+struct _GLFWmapelement
+{
+    uint8_t         type;
+    uint8_t         index;
+    int8_t          axisScale;
+    int8_t          axisOffset;
+};
+
+// Gamepad mapping structure
+//
+struct _GLFWmapping
+{
+    char            name[128];
+    char            guid[33];
+    _GLFWmapelement buttons[15];
+    _GLFWmapelement axes[6];
+};
+
+// Joystick structure
+//
+struct _GLFWjoystick
+{
+    GLFWbool        present;
+    float*          axes;
+    int             axisCount;
+    unsigned char*  buttons;
+    int             buttonCount;
+    unsigned char*  hats;
+    int             hatCount;
+    char*           name;
+    void*           userPointer;
+    char            guid[33];
+    _GLFWmapping*   mapping;
+
+    // This is defined in the joystick API's joystick.h
+    _GLFW_PLATFORM_JOYSTICK_STATE;
+};
+
+// Thread local storage structure
+//
+struct _GLFWtls
+{
+    // This is defined in the platform's thread.h
+    _GLFW_PLATFORM_TLS_STATE;
+};
+
+// Mutex structure
+//
+struct _GLFWmutex
+{
+    // This is defined in the platform's thread.h
+    _GLFW_PLATFORM_MUTEX_STATE;
+};
+
+// Library global data
+//
+struct _GLFWlibrary
+{
+    GLFWbool            initialized;
+
+    struct {
+        _GLFWinitconfig init;
+        _GLFWfbconfig   framebuffer;
+        _GLFWwndconfig  window;
+        _GLFWctxconfig  context;
+        int             refreshRate;
+    } hints;
+
+    _GLFWerror*         errorListHead;
+    _GLFWcursor*        cursorListHead;
+    _GLFWwindow*        windowListHead;
+
+    _GLFWmonitor**      monitors;
+    int                 monitorCount;
+
+    _GLFWjoystick       joysticks[GLFW_JOYSTICK_LAST + 1];
+    _GLFWmapping*       mappings;
+    int                 mappingCount;
+
+    _GLFWtls            errorSlot;
+    _GLFWtls            contextSlot;
+    _GLFWmutex          errorLock;
+
+    struct {
+        uint64_t        offset;
+        // This is defined in the platform's time.h
+        _GLFW_PLATFORM_LIBRARY_TIMER_STATE;
+    } timer;
+
+    struct {
+        GLFWbool        available;
+        void*           handle;
+        char*           extensions[2];
+#if !defined(_GLFW_VULKAN_STATIC)
+        PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+        PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+#endif
+        GLFWbool        KHR_surface;
+#if defined(_GLFW_WIN32)
+        GLFWbool        KHR_win32_surface;
+#elif defined(_GLFW_COCOA)
+        GLFWbool        MVK_macos_surface;
+        GLFWbool        EXT_metal_surface;
+#elif defined(_GLFW_X11)
+        GLFWbool        KHR_xlib_surface;
+        GLFWbool        KHR_xcb_surface;
+#elif defined(_GLFW_WAYLAND)
+        GLFWbool        KHR_wayland_surface;
+#endif
+    } vk;
+
+    struct {
+        GLFWmonitorfun  monitor;
+        GLFWjoystickfun joystick;
+    } callbacks;
+
+    // This is defined in the window API's platform.h
+    _GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
+    // This is defined in the context API's context.h
+    _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE;
+    // This is defined in the platform's joystick.h
+    _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
+    // This is defined in egl_context.h
+    _GLFW_EGL_LIBRARY_CONTEXT_STATE;
+    // This is defined in osmesa_context.h
+    _GLFW_OSMESA_LIBRARY_CONTEXT_STATE;
+};
+
+// Global state shared between compilation units of GLFW
+//
+extern _GLFWlibrary _glfw;
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void);
+void _glfwPlatformTerminate(void);
+const char* _glfwPlatformGetVersionString(void);
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled);
+GLFWbool _glfwPlatformRawMouseMotionSupported(void);
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+                              const GLFWimage* image, int xhot, int yhot);
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
+
+const char* _glfwPlatformGetScancodeName(int scancode);
+int _glfwPlatformGetKeyScancode(int key);
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor);
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale);
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height);
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+void _glfwPlatformSetClipboardString(const char* string);
+const char* _glfwPlatformGetClipboardString(void);
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode);
+void _glfwPlatformUpdateGamepadGUID(char* guid);
+
+uint64_t _glfwPlatformGetTimerValue(void);
+uint64_t _glfwPlatformGetTimerFrequency(void);
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+                              const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig);
+void _glfwPlatformDestroyWindow(_GLFWwindow* window);
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+                                int count, const GLFWimage* images);
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+                                      int minwidth, int minheight,
+                                      int maxwidth, int maxheight);
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+                                     int* left, int* top,
+                                     int* right, int* bottom);
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale);
+void _glfwPlatformIconifyWindow(_GLFWwindow* window);
+void _glfwPlatformRestoreWindow(_GLFWwindow* window);
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
+void _glfwPlatformShowWindow(_GLFWwindow* window);
+void _glfwPlatformHideWindow(_GLFWwindow* window);
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
+void _glfwPlatformFocusWindow(_GLFWwindow* window);
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
+                                   int xpos, int ypos, int width, int height,
+                                   int refreshRate);
+int _glfwPlatformWindowFocused(_GLFWwindow* window);
+int _glfwPlatformWindowIconified(_GLFWwindow* window);
+int _glfwPlatformWindowVisible(_GLFWwindow* window);
+int _glfwPlatformWindowMaximized(_GLFWwindow* window);
+int _glfwPlatformWindowHovered(_GLFWwindow* window);
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window);
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window);
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled);
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity);
+
+void _glfwPlatformPollEvents(void);
+void _glfwPlatformWaitEvents(void);
+void _glfwPlatformWaitEventsTimeout(double timeout);
+void _glfwPlatformPostEmptyEvent(void);
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions);
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+                                                      VkPhysicalDevice device,
+                                                      uint32_t queuefamily);
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+                                          _GLFWwindow* window,
+                                          const VkAllocationCallbacks* allocator,
+                                          VkSurfaceKHR* surface);
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls);
+void _glfwPlatformDestroyTls(_GLFWtls* tls);
+void* _glfwPlatformGetTls(_GLFWtls* tls);
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value);
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex);
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex);
+void _glfwPlatformLockMutex(_GLFWmutex* mutex);
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex);
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
+void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
+void _glfwInputWindowContentScale(_GLFWwindow* window,
+                                  float xscale, float yscale);
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized);
+void _glfwInputWindowDamage(_GLFWwindow* window);
+void _glfwInputWindowCloseRequest(_GLFWwindow* window);
+void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor);
+
+void _glfwInputKey(_GLFWwindow* window,
+                   int key, int scancode, int action, int mods);
+void _glfwInputChar(_GLFWwindow* window,
+                    unsigned int codepoint, int mods, GLFWbool plain);
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
+void _glfwInputJoystick(_GLFWjoystick* js, int event);
+void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value);
+void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value);
+void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value);
+
+void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement);
+void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window);
+
+#if defined(__GNUC__)
+void _glfwInputError(int code, const char* format, ...)
+    __attribute__((format(printf, 2, 3)));
+#else
+void _glfwInputError(int code, const char* format, ...);
+#endif
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
+const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
+                                         const _GLFWfbconfig* alternatives,
+                                         unsigned int count);
+GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
+                                    const _GLFWctxconfig* ctxconfig);
+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig);
+
+const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
+                                        const GLFWvidmode* desired);
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
+void _glfwFreeMonitor(_GLFWmonitor* monitor);
+void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
+
+_GLFWjoystick* _glfwAllocJoystick(const char* name,
+                                  const char* guid,
+                                  int axisCount,
+                                  int buttonCount,
+                                  int hatCount);
+void _glfwFreeJoystick(_GLFWjoystick* js);
+void _glfwCenterCursorInContentArea(_GLFWwindow* window);
+
+GLFWbool _glfwInitVulkan(int mode);
+void _glfwTerminateVulkan(void);
+const char* _glfwGetVulkanResultString(VkResult result);
+
+char* _glfw_strdup(const char* source);
+float _glfw_fminf(float a, float b);
+float _glfw_fmaxf(float a, float b);
+
diff --git a/glfw/src/linux_joystick.c b/glfw/src/linux_joystick.c
--- a/glfw/src/linux_joystick.c
+++ b/glfw/src/linux_joystick.c
@@ -1,433 +1,433 @@
-//========================================================================
-// GLFW 3.3 Linux - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/inotify.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifndef SYN_DROPPED // < v2.6.39 kernel headers
-// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
-#define SYN_DROPPED 3
-#endif
-
-// Apply an EV_KEY event to the specified joystick
-//
-static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
-{
-    _glfwInputJoystickButton(js,
-                             js->linjs.keyMap[code - BTN_MISC],
-                             value ? GLFW_PRESS : GLFW_RELEASE);
-}
-
-// Apply an EV_ABS event to the specified joystick
-//
-static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
-{
-    const int index = js->linjs.absMap[code];
-
-    if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
-    {
-        static const char stateMap[3][3] =
-        {
-            { GLFW_HAT_CENTERED, GLFW_HAT_UP,       GLFW_HAT_DOWN },
-            { GLFW_HAT_LEFT,     GLFW_HAT_LEFT_UP,  GLFW_HAT_LEFT_DOWN },
-            { GLFW_HAT_RIGHT,    GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
-        };
-
-        const int hat = (code - ABS_HAT0X) / 2;
-        const int axis = (code - ABS_HAT0X) % 2;
-        int* state = js->linjs.hats[hat];
-
-        // NOTE: Looking at several input drivers, it seems all hat events use
-        //       -1 for left / up, 0 for centered and 1 for right / down
-        if (value == 0)
-            state[axis] = 0;
-        else if (value < 0)
-            state[axis] = 1;
-        else if (value > 0)
-            state[axis] = 2;
-
-        _glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
-    }
-    else
-    {
-        const struct input_absinfo* info = &js->linjs.absInfo[code];
-        float normalized = value;
-
-        const int range = info->maximum - info->minimum;
-        if (range)
-        {
-            // Normalize to 0.0 -> 1.0
-            normalized = (normalized - info->minimum) / range;
-            // Normalize to -1.0 -> 1.0
-            normalized = normalized * 2.0f - 1.0f;
-        }
-
-        _glfwInputJoystickAxis(js, index, normalized);
-    }
-}
-
-// Poll state of absolute axes
-//
-static void pollAbsState(_GLFWjoystick* js)
-{
-    for (int code = 0;  code < ABS_CNT;  code++)
-    {
-        if (js->linjs.absMap[code] < 0)
-            continue;
-
-        struct input_absinfo* info = &js->linjs.absInfo[code];
-
-        if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
-            continue;
-
-        handleAbsEvent(js, code, info->value);
-    }
-}
-
-#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
-
-// Attempt to open the specified joystick device
-//
-static GLFWbool openJoystickDevice(const char* path)
-{
-    for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        if (!_glfw.joysticks[jid].present)
-            continue;
-        if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
-            return GLFW_FALSE;
-    }
-
-    _GLFWjoystickLinux linjs = {0};
-    linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
-    if (linjs.fd == -1)
-        return GLFW_FALSE;
-
-    char evBits[(EV_CNT + 7) / 8] = {0};
-    char keyBits[(KEY_CNT + 7) / 8] = {0};
-    char absBits[(ABS_CNT + 7) / 8] = {0};
-    struct input_id id;
-
-    if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
-        ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
-        ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
-        ioctl(linjs.fd, EVIOCGID, &id) < 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Linux: Failed to query input device: %s",
-                        strerror(errno));
-        close(linjs.fd);
-        return GLFW_FALSE;
-    }
-
-    // Ensure this device supports the events expected of a joystick
-    if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
-    {
-        close(linjs.fd);
-        return GLFW_FALSE;
-    }
-
-    char name[256] = "";
-
-    if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
-        strncpy(name, "Unknown", sizeof(name));
-
-    char guid[33] = "";
-
-    // Generate a joystick GUID that matches the SDL 2.0.5+ one
-    if (id.vendor && id.product && id.version)
-    {
-        sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
-                id.bustype & 0xff, id.bustype >> 8,
-                id.vendor & 0xff,  id.vendor >> 8,
-                id.product & 0xff, id.product >> 8,
-                id.version & 0xff, id.version >> 8);
-    }
-    else
-    {
-        sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
-                id.bustype & 0xff, id.bustype >> 8,
-                name[0], name[1], name[2], name[3],
-                name[4], name[5], name[6], name[7],
-                name[8], name[9], name[10]);
-    }
-
-    int axisCount = 0, buttonCount = 0, hatCount = 0;
-
-    for (int code = BTN_MISC;  code < KEY_CNT;  code++)
-    {
-        if (!isBitSet(code, keyBits))
-            continue;
-
-        linjs.keyMap[code - BTN_MISC] = buttonCount;
-        buttonCount++;
-    }
-
-    for (int code = 0;  code < ABS_CNT;  code++)
-    {
-        linjs.absMap[code] = -1;
-        if (!isBitSet(code, absBits))
-            continue;
-
-        if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
-        {
-            linjs.absMap[code] = hatCount;
-            hatCount++;
-            // Skip the Y axis
-            code++;
-        }
-        else
-        {
-            if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
-                continue;
-
-            linjs.absMap[code] = axisCount;
-            axisCount++;
-        }
-    }
-
-    _GLFWjoystick* js =
-        _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
-    if (!js)
-    {
-        close(linjs.fd);
-        return GLFW_FALSE;
-    }
-
-    strncpy(linjs.path, path, sizeof(linjs.path) - 1);
-    memcpy(&js->linjs, &linjs, sizeof(linjs));
-
-    pollAbsState(js);
-
-    _glfwInputJoystick(js, GLFW_CONNECTED);
-    return GLFW_TRUE;
-}
-
-#undef isBitSet
-
-// Frees all resources associated with the specified joystick
-//
-static void closeJoystick(_GLFWjoystick* js)
-{
-    close(js->linjs.fd);
-    _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
-}
-
-// Lexically compare joysticks by name; used by qsort
-//
-static int compareJoysticks(const void* fp, const void* sp)
-{
-    const _GLFWjoystick* fj = fp;
-    const _GLFWjoystick* sj = sp;
-    return strcmp(fj->linjs.path, sj->linjs.path);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialize joystick interface
-//
-GLFWbool _glfwInitJoysticksLinux(void)
-{
-    const char* dirname = "/dev/input";
-
-    _glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
-    if (_glfw.linjs.inotify > 0)
-    {
-        // HACK: Register for IN_ATTRIB to get notified when udev is done
-        //       This works well in practice but the true way is libudev
-
-        _glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
-                                              dirname,
-                                              IN_CREATE | IN_ATTRIB | IN_DELETE);
-    }
-
-    // Continue without device connection notifications if inotify fails
-
-    if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
-        return GLFW_FALSE;
-    }
-
-    int count = 0;
-
-    DIR* dir = opendir(dirname);
-    if (dir)
-    {
-        struct dirent* entry;
-
-        while ((entry = readdir(dir)))
-        {
-            regmatch_t match;
-
-            if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
-                continue;
-
-            char path[PATH_MAX];
-
-            snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
-
-            if (openJoystickDevice(path))
-                count++;
-        }
-
-        closedir(dir);
-    }
-
-    // Continue with no joysticks if enumeration fails
-
-    qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
-    return GLFW_TRUE;
-}
-
-// Close all opened joystick handles
-//
-void _glfwTerminateJoysticksLinux(void)
-{
-    int jid;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
-            closeJoystick(js);
-    }
-
-    regfree(&_glfw.linjs.regex);
-
-    if (_glfw.linjs.inotify > 0)
-    {
-        if (_glfw.linjs.watch > 0)
-            inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
-
-        close(_glfw.linjs.inotify);
-    }
-}
-
-void _glfwDetectJoystickConnectionLinux(void)
-{
-    if (_glfw.linjs.inotify <= 0)
-        return;
-
-    ssize_t offset = 0;
-    char buffer[16384];
-    const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
-
-    while (size > offset)
-    {
-        regmatch_t match;
-        const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
-
-        offset += sizeof(struct inotify_event) + e->len;
-
-        if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
-            continue;
-
-        char path[PATH_MAX];
-        snprintf(path, sizeof(path), "/dev/input/%s", e->name);
-
-        if (e->mask & (IN_CREATE | IN_ATTRIB))
-            openJoystickDevice(path);
-        else if (e->mask & IN_DELETE)
-        {
-            for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-            {
-                if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
-                {
-                    closeJoystick(_glfw.joysticks + jid);
-                    break;
-                }
-            }
-        }
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
-{
-    // Read all queued events (non-blocking)
-    for (;;)
-    {
-        struct input_event e;
-
-        errno = 0;
-        if (read(js->linjs.fd, &e, sizeof(e)) < 0)
-        {
-            // Reset the joystick slot if the device was disconnected
-            if (errno == ENODEV)
-                closeJoystick(js);
-
-            break;
-        }
-
-        if (e.type == EV_SYN)
-        {
-            if (e.code == SYN_DROPPED)
-                _glfw.linjs.dropped = GLFW_TRUE;
-            else if (e.code == SYN_REPORT)
-            {
-                _glfw.linjs.dropped = GLFW_FALSE;
-                pollAbsState(js);
-            }
-        }
-
-        if (_glfw.linjs.dropped)
-            continue;
-
-        if (e.type == EV_KEY)
-            handleKeyEvent(js, e.code, e.value);
-        else if (e.type == EV_ABS)
-            handleAbsEvent(js, e.code, e.value);
-    }
-
-    return js->present;
-}
-
-void _glfwPlatformUpdateGamepadGUID(char* guid)
-{
-}
-
+//========================================================================
+// GLFW 3.3 Linux - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/inotify.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef SYN_DROPPED // < v2.6.39 kernel headers
+// Workaround for CentOS-6, which is supported till 2020-11-30, but still on v2.6.32
+#define SYN_DROPPED 3
+#endif
+
+// Apply an EV_KEY event to the specified joystick
+//
+static void handleKeyEvent(_GLFWjoystick* js, int code, int value)
+{
+    _glfwInputJoystickButton(js,
+                             js->linjs.keyMap[code - BTN_MISC],
+                             value ? GLFW_PRESS : GLFW_RELEASE);
+}
+
+// Apply an EV_ABS event to the specified joystick
+//
+static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
+{
+    const int index = js->linjs.absMap[code];
+
+    if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
+    {
+        static const char stateMap[3][3] =
+        {
+            { GLFW_HAT_CENTERED, GLFW_HAT_UP,       GLFW_HAT_DOWN },
+            { GLFW_HAT_LEFT,     GLFW_HAT_LEFT_UP,  GLFW_HAT_LEFT_DOWN },
+            { GLFW_HAT_RIGHT,    GLFW_HAT_RIGHT_UP, GLFW_HAT_RIGHT_DOWN },
+        };
+
+        const int hat = (code - ABS_HAT0X) / 2;
+        const int axis = (code - ABS_HAT0X) % 2;
+        int* state = js->linjs.hats[hat];
+
+        // NOTE: Looking at several input drivers, it seems all hat events use
+        //       -1 for left / up, 0 for centered and 1 for right / down
+        if (value == 0)
+            state[axis] = 0;
+        else if (value < 0)
+            state[axis] = 1;
+        else if (value > 0)
+            state[axis] = 2;
+
+        _glfwInputJoystickHat(js, index, stateMap[state[0]][state[1]]);
+    }
+    else
+    {
+        const struct input_absinfo* info = &js->linjs.absInfo[code];
+        float normalized = value;
+
+        const int range = info->maximum - info->minimum;
+        if (range)
+        {
+            // Normalize to 0.0 -> 1.0
+            normalized = (normalized - info->minimum) / range;
+            // Normalize to -1.0 -> 1.0
+            normalized = normalized * 2.0f - 1.0f;
+        }
+
+        _glfwInputJoystickAxis(js, index, normalized);
+    }
+}
+
+// Poll state of absolute axes
+//
+static void pollAbsState(_GLFWjoystick* js)
+{
+    for (int code = 0;  code < ABS_CNT;  code++)
+    {
+        if (js->linjs.absMap[code] < 0)
+            continue;
+
+        struct input_absinfo* info = &js->linjs.absInfo[code];
+
+        if (ioctl(js->linjs.fd, EVIOCGABS(code), info) < 0)
+            continue;
+
+        handleAbsEvent(js, code, info->value);
+    }
+}
+
+#define isBitSet(bit, arr) (arr[(bit) / 8] & (1 << ((bit) % 8)))
+
+// Attempt to open the specified joystick device
+//
+static GLFWbool openJoystickDevice(const char* path)
+{
+    for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        if (!_glfw.joysticks[jid].present)
+            continue;
+        if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
+            return GLFW_FALSE;
+    }
+
+    _GLFWjoystickLinux linjs = {0};
+    linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
+    if (linjs.fd == -1)
+        return GLFW_FALSE;
+
+    char evBits[(EV_CNT + 7) / 8] = {0};
+    char keyBits[(KEY_CNT + 7) / 8] = {0};
+    char absBits[(ABS_CNT + 7) / 8] = {0};
+    struct input_id id;
+
+    if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 ||
+        ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 ||
+        ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 ||
+        ioctl(linjs.fd, EVIOCGID, &id) < 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Linux: Failed to query input device: %s",
+                        strerror(errno));
+        close(linjs.fd);
+        return GLFW_FALSE;
+    }
+
+    // Ensure this device supports the events expected of a joystick
+    if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits))
+    {
+        close(linjs.fd);
+        return GLFW_FALSE;
+    }
+
+    char name[256] = "";
+
+    if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0)
+        strncpy(name, "Unknown", sizeof(name));
+
+    char guid[33] = "";
+
+    // Generate a joystick GUID that matches the SDL 2.0.5+ one
+    if (id.vendor && id.product && id.version)
+    {
+        sprintf(guid, "%02x%02x0000%02x%02x0000%02x%02x0000%02x%02x0000",
+                id.bustype & 0xff, id.bustype >> 8,
+                id.vendor & 0xff,  id.vendor >> 8,
+                id.product & 0xff, id.product >> 8,
+                id.version & 0xff, id.version >> 8);
+    }
+    else
+    {
+        sprintf(guid, "%02x%02x0000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+                id.bustype & 0xff, id.bustype >> 8,
+                name[0], name[1], name[2], name[3],
+                name[4], name[5], name[6], name[7],
+                name[8], name[9], name[10]);
+    }
+
+    int axisCount = 0, buttonCount = 0, hatCount = 0;
+
+    for (int code = BTN_MISC;  code < KEY_CNT;  code++)
+    {
+        if (!isBitSet(code, keyBits))
+            continue;
+
+        linjs.keyMap[code - BTN_MISC] = buttonCount;
+        buttonCount++;
+    }
+
+    for (int code = 0;  code < ABS_CNT;  code++)
+    {
+        linjs.absMap[code] = -1;
+        if (!isBitSet(code, absBits))
+            continue;
+
+        if (code >= ABS_HAT0X && code <= ABS_HAT3Y)
+        {
+            linjs.absMap[code] = hatCount;
+            hatCount++;
+            // Skip the Y axis
+            code++;
+        }
+        else
+        {
+            if (ioctl(linjs.fd, EVIOCGABS(code), &linjs.absInfo[code]) < 0)
+                continue;
+
+            linjs.absMap[code] = axisCount;
+            axisCount++;
+        }
+    }
+
+    _GLFWjoystick* js =
+        _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
+    if (!js)
+    {
+        close(linjs.fd);
+        return GLFW_FALSE;
+    }
+
+    strncpy(linjs.path, path, sizeof(linjs.path) - 1);
+    memcpy(&js->linjs, &linjs, sizeof(linjs));
+
+    pollAbsState(js);
+
+    _glfwInputJoystick(js, GLFW_CONNECTED);
+    return GLFW_TRUE;
+}
+
+#undef isBitSet
+
+// Frees all resources associated with the specified joystick
+//
+static void closeJoystick(_GLFWjoystick* js)
+{
+    close(js->linjs.fd);
+    _glfwFreeJoystick(js);
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// Lexically compare joysticks by name; used by qsort
+//
+static int compareJoysticks(const void* fp, const void* sp)
+{
+    const _GLFWjoystick* fj = fp;
+    const _GLFWjoystick* sj = sp;
+    return strcmp(fj->linjs.path, sj->linjs.path);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+GLFWbool _glfwInitJoysticksLinux(void)
+{
+    const char* dirname = "/dev/input";
+
+    _glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+    if (_glfw.linjs.inotify > 0)
+    {
+        // HACK: Register for IN_ATTRIB to get notified when udev is done
+        //       This works well in practice but the true way is libudev
+
+        _glfw.linjs.watch = inotify_add_watch(_glfw.linjs.inotify,
+                                              dirname,
+                                              IN_CREATE | IN_ATTRIB | IN_DELETE);
+    }
+
+    // Continue without device connection notifications if inotify fails
+
+    if (regcomp(&_glfw.linjs.regex, "^event[0-9]\\+$", 0) != 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
+        return GLFW_FALSE;
+    }
+
+    int count = 0;
+
+    DIR* dir = opendir(dirname);
+    if (dir)
+    {
+        struct dirent* entry;
+
+        while ((entry = readdir(dir)))
+        {
+            regmatch_t match;
+
+            if (regexec(&_glfw.linjs.regex, entry->d_name, 1, &match, 0) != 0)
+                continue;
+
+            char path[PATH_MAX];
+
+            snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
+
+            if (openJoystickDevice(path))
+                count++;
+        }
+
+        closedir(dir);
+    }
+
+    // Continue with no joysticks if enumeration fails
+
+    qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks);
+    return GLFW_TRUE;
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksLinux(void)
+{
+    int jid;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        _GLFWjoystick* js = _glfw.joysticks + jid;
+        if (js->present)
+            closeJoystick(js);
+    }
+
+    regfree(&_glfw.linjs.regex);
+
+    if (_glfw.linjs.inotify > 0)
+    {
+        if (_glfw.linjs.watch > 0)
+            inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch);
+
+        close(_glfw.linjs.inotify);
+    }
+}
+
+void _glfwDetectJoystickConnectionLinux(void)
+{
+    if (_glfw.linjs.inotify <= 0)
+        return;
+
+    ssize_t offset = 0;
+    char buffer[16384];
+    const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
+
+    while (size > offset)
+    {
+        regmatch_t match;
+        const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
+
+        offset += sizeof(struct inotify_event) + e->len;
+
+        if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0)
+            continue;
+
+        char path[PATH_MAX];
+        snprintf(path, sizeof(path), "/dev/input/%s", e->name);
+
+        if (e->mask & (IN_CREATE | IN_ATTRIB))
+            openJoystickDevice(path);
+        else if (e->mask & IN_DELETE)
+        {
+            for (int jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+            {
+                if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
+                {
+                    closeJoystick(_glfw.joysticks + jid);
+                    break;
+                }
+            }
+        }
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+    // Read all queued events (non-blocking)
+    for (;;)
+    {
+        struct input_event e;
+
+        errno = 0;
+        if (read(js->linjs.fd, &e, sizeof(e)) < 0)
+        {
+            // Reset the joystick slot if the device was disconnected
+            if (errno == ENODEV)
+                closeJoystick(js);
+
+            break;
+        }
+
+        if (e.type == EV_SYN)
+        {
+            if (e.code == SYN_DROPPED)
+                _glfw.linjs.dropped = GLFW_TRUE;
+            else if (e.code == SYN_REPORT)
+            {
+                _glfw.linjs.dropped = GLFW_FALSE;
+                pollAbsState(js);
+            }
+        }
+
+        if (_glfw.linjs.dropped)
+            continue;
+
+        if (e.type == EV_KEY)
+            handleKeyEvent(js, e.code, e.value);
+        else if (e.type == EV_ABS)
+            handleAbsEvent(js, e.code, e.value);
+    }
+
+    return js->present;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+}
+
diff --git a/glfw/src/mappings.h b/glfw/src/mappings.h
--- a/glfw/src/mappings.h
+++ b/glfw/src/mappings.h
@@ -1,476 +1,476 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2006-2018 Camilla Löwy <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.
-//
-//========================================================================
-// As mappings.h.in, this file is used by CMake to produce the mappings.h
-// header file.  If you are adding a GLFW specific gamepad mapping, this is
-// where to put it.
-//========================================================================
-// As mappings.h, this provides all pre-defined gamepad mappings, including
-// all available in SDL_GameControllerDB.  Do not edit this file.  Any gamepad
-// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
-// This file can be re-generated from mappings.h.in and the upstream
-// gamecontrollerdb.txt with the GenerateMappings.cmake script.
-//========================================================================
-
-// All gamepad mappings not labeled GLFW are copied from the
-// SDL_GameControllerDB project under the following license:
-//
-// Simple DirectMedia Layer
-// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.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.
-
-const char* _glfwDefaultMappings[] =
-{
-"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
-"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
-"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
-"03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",
-"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
-"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
-"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
-"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
-"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
-"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
-"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
-"03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",
-"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
-"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
-"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
-"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",
-"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
-"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
-"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
-"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
-"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
-"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
-"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
-"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
-"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
-"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
-"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
-"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
-"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
-"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
-"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
-"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
-"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
-"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
-"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
-"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
-"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
-"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
-"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
-"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
-"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
-"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
-"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
-"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",
-"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
-"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
-"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
-"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
-"03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
-"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
-"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
-"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
-"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
-"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
-"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
-"03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
-"03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
-"03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",
-"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
-"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
-"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
-"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
-"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
-"030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",
-"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,",
-"03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
-"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
-"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
-"030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,",
-"03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,",
-"030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
-"030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,",
-"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
-"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
-"03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
-"03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
-"030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",
-"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",
-"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
-"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",
-"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,",
-"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,",
-"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",
-"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
-"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
-"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
-"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
-"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
-"03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
-"05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
-"03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
-"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
-"05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
-"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
-"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
-"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
-"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",
-"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",
-"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,",
-"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",
-"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
-"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
-"030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,",
-"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
-"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
-"0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,",
-"03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,",
-"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",
-"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
-"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",
-"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,",
-"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
-"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
-"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
-"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
-"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
-"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
-"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
-"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",
-"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",
-"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",
-"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,",
-"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
-"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
-"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
-"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
-"030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
-"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
-"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
-"030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
-"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
-"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
-"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
-"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",
-"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
-"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
-"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
-"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
-"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
-"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",
-"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
-"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
-"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
-"03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
-"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
-"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
-"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
-"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",
-"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
-"03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",
-"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
-"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",
-"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
-"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",
-"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
-"050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
-"050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",
-"03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
-"05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,",
-"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
-"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
-"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",
-"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
-"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
-"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
-"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",
-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",
-"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",
-"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",
-"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",
-"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",
-"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",
-
-"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
-NULL
-};
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2018 Camilla Löwy <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.
+//
+//========================================================================
+// As mappings.h.in, this file is used by CMake to produce the mappings.h
+// header file.  If you are adding a GLFW specific gamepad mapping, this is
+// where to put it.
+//========================================================================
+// As mappings.h, this provides all pre-defined gamepad mappings, including
+// all available in SDL_GameControllerDB.  Do not edit this file.  Any gamepad
+// mappings not specific to GLFW should be submitted to SDL_GameControllerDB.
+// This file can be re-generated from mappings.h.in and the upstream
+// gamecontrollerdb.txt with the GenerateMappings.cmake script.
+//========================================================================
+
+// All gamepad mappings not labeled GLFW are copied from the
+// SDL_GameControllerDB project under the following license:
+//
+// Simple DirectMedia Layer
+// Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.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.
+
+const char* _glfwDefaultMappings[] =
+{
+"03000000fa2d00000100000000000000,3DRUDDER,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,",
+"03000000022000000090000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000203800000900000000000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000102800000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,",
+"03000000a00500003232000000000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,",
+"030000008f0e00001200000000000000,Acme,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00003608000000000000,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,",
+"030000006b1400000055000000000000,bigben ps3padstreetnew,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"0300000066f700000500000000000000,BrutalLegendTest,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000d81d00000b00000000000000,BUFFALO BSGP1601 Series ,a:b5,b:b3,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b4,y:b2,platform:Windows,",
+"03000000e82000006058000000000000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"030000005e0400008e02000000000000,Controller (XBOX 360 For Windows),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000260900008888000000000000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a4,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000a306000022f6000000000000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000791d00000103000000000000,Dual Box WII,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"030000004f04000023b3000000000000,Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000341a00000108000000000000,EXEQ RF USB Gamepad 8206,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"030000000d0f00008500000000000000,Fighting Commander 2016 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008400000000000000,Fighting Commander 5,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008800000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008700000000000000,Fighting Stick mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00002700000000000000,FIGHTING STICK V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"78696e70757403000000000000000000,Fightstick TES,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000260900002625000000000000,Gamecube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,",
+"030000008f0e00000d31000000000000,GAMEPAD 3 TURBO,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000280400000140000000000000,GamePad Pro USB,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000ffff00000000000000000000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000451300000010000000000000,Generic USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00000302000000000000,Hama Scorpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004900000000000000,Hatsune Miku Sho Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000d81400000862000000000000,HitBox Edition Cthulhu+,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005f00000000000000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005e00000000000000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004000000000000000,Hori Fighting Stick Mini 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b4,rightshoulder:b7,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006e00000000000000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006600000000000000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f0000ee00000000000000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00004d00000000000000,HORIPAD3 A,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000250900000017000000000000,HRAP2 on PS/SS/N64 Joypad to USB BOX,a:b2,b:b1,back:b9,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b8,x:b3,y:b0,platform:Windows,",
+"030000008f0e00001330000000000000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d81d00000f00000000000000,iBUFFALO BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d81d00001000000000000000,iBUFFALO BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000830500006020000000000000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Windows,",
+"03000000b50700001403000000000000,IMPACT BLACK,a:b2,b:b3,back:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"030000006f0e00002401000000000000,INJUSTICE FightStick for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000491900000204000000000000,Ipega PG-9023,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,",
+"030000006d04000011c2000000000000,Logitech Cordless Wingman,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,",
+"030000006d04000016c2000000000000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006d04000018c2000000000000,Logitech F510 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006d04000019c2000000000000,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700005032000000000000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700005082000000000000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008433000000000000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008483000000000000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b6,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008134000000000000,Mad Catz FightStick TE2+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b7,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b4,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008184000000000000,Mad Catz FightStick TE2+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,leftstick:b10,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008034000000000000,Mad Catz TE2 PS3 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008084000000000000,Mad Catz TE2 PS4 Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700008532000000000000,Madcatz Arcade Fightstick TE S PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700003888000000000000,Madcatz Arcade Fightstick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000380700001888000000000000,MadCatz SFIV FightStick PS3,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000380700008081000000000000,MADCATZ SFV Arcade FightStick Alpha PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008305000031b0000000000000,MaxfireBlaze3,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,",
+"03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000790000004318000000000000,Mayflash GameCube Controller Adapter,a:b1,b:b2,back:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b0,leftshoulder:b4,leftstick:b0,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b0,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00001030000000000000,Mayflash USB Adapter for original Sega Saturn controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b5,rightshoulder:b2,righttrigger:b7,start:b9,x:b3,y:b4,platform:Windows,",
+"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,",
+"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000001008000001e5000000000000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000bd12000015d0000000000000,Nintendo Retrolink USB Super SNES Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
+"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"030000004b120000014d000000000000,NYKO AIRFLO,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:a3,leftstick:a0,lefttrigger:b6,leftx:h0.6,lefty:h0.12,rightshoulder:b5,rightstick:a2,righttrigger:b7,rightx:h0.9,righty:h0.4,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000362800000100000000000000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b13,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,",
+"03000000120c0000f60e000000000000,P4 Wired Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000d62000006dca000000000000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000008f0e00007530000000000000,PS (R) Gamepad,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b1,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000e30500009605000000000000,PS to USB convert cable,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
+"03000000100800000100000000000000,PS1 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000100800000300000000000000,PS2 USB,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,",
+"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,",
+"03000000250900000500000000000000,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000100000008200000000000000,PS360+ v1.66,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:h0.4,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000a00b000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004c050000cc09000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00000011000000000000,QanBa Arcade JoyStick 1008,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b10,x:b0,y:b3,platform:Windows,",
+"03000000300f00001611000000000000,QanBa Arcade JoyStick 4018,a:b1,b:b2,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000222c00000020000000000000,QANBA DRONE ARCADE JOYSTICK,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001210000000000000,QanBa Joystick Plus,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000341a00000104000000000000,QanBa Joystick Q4RAF,a:b5,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b1,y:b2,platform:Windows,",
+"03000000222c00000223000000000000,Qanba Obsidian Arcade Joystick PS3 Mode,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000222c00000023000000000000,Qanba Obsidian Arcade Joystick PS4 Mode,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"030000000d0f00001100000000000000,REAL ARCADE PRO.3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00008a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006b00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00006a00000000000000,Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00007000000000000000,REAL ARCADE PRO.4 VLX,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00002200000000000000,REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005c00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000000d0f00005b00000000000000,Real Arcade Pro.V4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000790000001100000000000000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,",
+"0300000000f000000300000000000000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
+"0300000000f00000f100000000000000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Windows,",
+"030000006b140000010d000000000000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000006f0e00001e01000000000000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,",
+"030000004f04000003d0000000000000,run'n'drive,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a30600001af5000000000000,Saitek Cyborg,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a306000023f6000000000000,Saitek Cyborg V.1 Game pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001201000000000000,Saitek Dual Analog Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"03000000a30600000cff000000000000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,x:b0,y:b1,platform:Windows,",
+"03000000a30600000c04000000000000,Saitek P2900,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000300f00001001000000000000,Saitek P480 Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"03000000a30600000b04000000000000,Saitek P990,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Windows,",
+"03000000300f00001101000000000000,saitek rumble pad,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"0300000000050000289b000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
+"030000009b2800000500000000000000,Saturn_Adapter_2.0,a:b1,b:b2,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000341a00000208000000000000,SL-6555-SBK,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,",
+"030000008f0e00000800000000000000,SpeedLink Strike FX Wireless,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000ff1100003133000000000000,SVEN X-PAD,a:b2,b:b3,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a4,start:b5,x:b0,y:b1,platform:Windows,",
+"03000000fa1900000706000000000000,Team 5,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,",
+"030000004f04000015b3000000000000,Thrustmaster Dual Analog 2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
+"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,",
+"030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power 3,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,",
+"03000000666600000488000000000000,TigerGame PS/PS2 Game Controller Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,",
+"03000000d90400000200000000000000,TwinShock PS2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000380700006652000000000000,UnKnown,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000632500002305000000000000,USB Vibration Joystick (BM),a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,",
+"03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,",
+"03000000450c00002043000000000000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,",
+"03000000172700004431000000000000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a7,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,",
+"03000000786901006e70000000000000,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,",
+"03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
+"030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X,",
+"03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
+"03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X,",
+"030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X,",
+"03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,",
+"03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,",
+"030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
+"030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,",
+"030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X,",
+"03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X,",
+"030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X,",
+"030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"030000005e0400008e02000001000000,Steam Virtual GamePad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
+"03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X,",
+"030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,",
+"030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,",
+"03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,",
+"03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X,",
+"050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X,",
+"050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X,",
+"030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,",
+"030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,",
+"03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,",
+"03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,",
+"05000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"03000000022000000090000011010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000c82d00002038000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"03000000c82d00000190000011010000,8Bitdo NES30 Pro 8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000c82d00003028000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,",
+"05000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
+"05000000a00500003232000001000000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,",
+"030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"05000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,",
+"03000000666600006706000000010000,boom PSX to PC Converter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,",
+"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000a306000022f6000011010000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000b40400000a01000000010000,CYPRESS USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,",
+"03000000790000000600000010010000,DragonRise Inc. Generic USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00003001000001010000,EA Sports PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
+"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006f0e00001304000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:a0,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:a3,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006f0e00001f01000000010000,Generic X-Box pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000280400000140000000010000,Gravis GamePad Pro USB ,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000008f0e00000610000000010000,GreenAsia Electronics 4Axes 12Keys GamePad ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,",
+"030000008f0e00001200000010010000,GreenAsia Inc. USB Joystick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
+"030000008f0e00000300000010010000,GreenAsia Inc. USB Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"0500000047532067616d657061640000,GS gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"06000000adde0000efbe000002010000,Hidromancer Game Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,a:b1,b:b2,back:b8,guide:b9,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b12,x:b0,y:b3,platform:Linux,",
+"03000000c9110000f055000011010000,HJC Game GAMEPAD,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000000d0f00000d00000000010000,hori,a:b0,b:b6,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftx:b4,lefty:b5,rightshoulder:b7,start:b9,x:b1,y:b2,platform:Linux,",
+"030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006a00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006b00000011010000,HORI CO. LTD. Real Arcade Pro.4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00005f00000011010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00005e00000011010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000000d0f00006e00000011010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006600000011010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000000d0f00006700000001010000,HORIPAD ONE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000008f0e00001330000010010000,HuiJia SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,",
+"050000006964726f69643a636f6e0000,idroid:con,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
+"03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),a:b3,b:b4,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,start:b7,x:b0,y:b1,platform:Linux,",
+"030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Linux,",
+"03000000300f00001001000010010000,Jess Tech Dual Analog Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,",
+"03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000006d04000015c2000010010000,Logitech Logitech Extreme 3D,a:b0,b:b4,back:b6,guide:b8,leftshoulder:b9,leftstick:h0.8,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:h0.2,start:b7,x:b2,y:b5,platform:Linux,",
+"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,",
+"05000000380700006652000025010000,Mad Catz C.T.R.L.R ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700005032000011010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700005082000011010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000380700003888000010010000,MadCatz PC USB Wired Stick 8838,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:a0,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000780000000600000010010000,Microntek USB Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"030000005e0400008e02000004010000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000062230000,Microsoft X-Box 360 pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000d102000001010000,Microsoft X-Box One pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000d102000003020000,Microsoft X-Box One pad v2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008502000000010000,Microsoft X-Box pad (Japan),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"05000000d6200000ad0d000001000000,Moga Pro,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,",
+"030000001008000001e5000010010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Linux,",
+"050000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,",
+"05000000010000000100000003000000,Nintendo Wiimote,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"030000000d0500000308000010010000,Nostromo n45 Dual Analog Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,",
+"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000451300000830000010010000,NYKO CORE,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000005e0400000202000000010000,Old Xbox pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,",
+"05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
+"05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Linux,",
+"03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"030000006f0e00006401000001010000,PDP Battlefield One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"030000004c0500006802000010010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"050000004c0500006802000000810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c0500006802000011810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:a12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:a13,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"030000004c0500006802000010810000,PS3 Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"05000000504c415953544154494f4e00,PS3 Controller (Bluetooth),a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,",
+"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000a00b000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"050000004c050000cc09000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000cc09000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,",
+"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,",
+"030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,",
+"030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000321500000010000011010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"0300000032150000030a000001010000,Razer Wildcat,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000790000001100000010010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
+"0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,",
+"030000006b140000010d000011010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000a30600000cff000010010000,Saitek P2500 Force Rumble Pad,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
+"03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,",
+"03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,x:b0,y:b1,platform:Linux,",
+"03000000a30600000b04000000010000,Saitek P990 Dual Analog Pad,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,",
+"03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000c01600008704000011010000,Serial/Keyboard/Mouse/Joystick,a:b12,b:b10,back:b4,dpdown:b2,dpleft:b3,dpright:b1,dpup:b0,leftshoulder:b9,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b8,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b5,x:b13,y:b11,platform:Linux,",
+"03000000f025000021c1000010010000,ShanWan Gioteck PS3 Wired Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
+"030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"05000000de2800000212000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de2800004211000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000de280000ff11000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,",
+"030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
+"030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,",
+"030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Linux,",
+"030000004f04000008d0000000010000,Thrustmaster Run N Drive Wireless,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,",
+"03000000bd12000015d0000010010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,a:b0,b:b1,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,",
+"03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000100800000300000010010000,USB Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,",
+"03000000790000001100000000010000,USB Gamepad1,a:b2,b:b1,back:b8,dpdown:a0,dpleft:a1,dpright:a2,dpup:a4,start:b9,platform:Linux,",
+"05000000ac0500003232000001000000,VR-BOX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000a102000007010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"0000000058626f782033363020576900,Xbox 360 Wireless Controller,a:b0,b:b1,back:b14,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b7,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Linux,",
+"0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,",
+"050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,",
+"050000005e040000fd02000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,",
+"03000000450c00002043000010010000,XEOX Gamepad SL-6556-BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,",
+"05000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,",
+"03000000c0160000e105000001010000,Xin-Mo Xin-Mo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,",
+"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
+"64633436313965656664373634323364,Microsoft X-Box 360 pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,",
+"61363931656135336130663561616264,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"4e564944494120436f72706f72617469,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"37336435666338653565313731303834,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,",
+"35643031303033326130316330353564,PS4 Controller,a:b1,b:b17,back:b15,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:+a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,",
+"5477696e20555342204a6f7973746963,Twin USB Joystick,a:b22,b:b21,back:b28,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,",
+"34356136633366613530316338376136,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b3,leftstick:b15,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b16,righttrigger:a5,rightx:a3,righty:a4,x:b17,y:b2,platform:Android,",
+"4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,",
+"4d466947616d65706164020000000000,MFi Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b6,x:b2,y:b3,platform:iOS,",
+"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:iOS,",
+
+"78696e70757401000000000000000000,XInput Gamepad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757402000000000000000000,XInput Wheel (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757403000000000000000000,XInput Arcade Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757404000000000000000000,XInput Flight Stick (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757405000000000000000000,XInput Dance Pad (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757406000000000000000000,XInput Guitar (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+"78696e70757408000000000000000000,XInput Drum Kit (GLFW),platform:Windows,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,",
+NULL
+};
+
diff --git a/glfw/src/monitor.c b/glfw/src/monitor.c
--- a/glfw/src/monitor.c
+++ b/glfw/src/monitor.c
@@ -1,544 +1,544 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-
-
-// Lexically compare video modes, used by qsort
-//
-static int compareVideoModes(const void* fp, const void* sp)
-{
-    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
-    if (fbpp != sbpp)
-        return fbpp - sbpp;
-
-    // Then sort on screen area
-    if (farea != sarea)
-        return farea - sarea;
-
-    // Then sort on width
-    if (fm->width != sm->width)
-        return fm->width - sm->width;
-
-    // Lastly sort on refresh rate
-    return fm->refreshRate - sm->refreshRate;
-}
-
-// Retrieves the available modes for the specified monitor
-//
-static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
-{
-    int modeCount;
-    GLFWvidmode* modes;
-
-    if (monitor->modes)
-        return GLFW_TRUE;
-
-    modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
-    if (!modes)
-        return GLFW_FALSE;
-
-    qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
-
-    free(monitor->modes);
-    monitor->modes = modes;
-    monitor->modeCount = modeCount;
-
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                         GLFW event API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-// Notifies shared code of a monitor connection or disconnection
-//
-void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
-{
-    if (action == GLFW_CONNECTED)
-    {
-        _glfw.monitorCount++;
-        _glfw.monitors =
-            realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
-
-        if (placement == _GLFW_INSERT_FIRST)
-        {
-            memmove(_glfw.monitors + 1,
-                    _glfw.monitors,
-                    ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
-            _glfw.monitors[0] = monitor;
-        }
-        else
-            _glfw.monitors[_glfw.monitorCount - 1] = monitor;
-    }
-    else if (action == GLFW_DISCONNECTED)
-    {
-        int i;
-        _GLFWwindow* window;
-
-        for (window = _glfw.windowListHead;  window;  window = window->next)
-        {
-            if (window->monitor == monitor)
-            {
-                int width, height, xoff, yoff;
-                _glfwPlatformGetWindowSize(window, &width, &height);
-                _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
-                _glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
-                _glfwPlatformSetWindowPos(window, xoff, yoff);
-            }
-        }
-
-        for (i = 0;  i < _glfw.monitorCount;  i++)
-        {
-            if (_glfw.monitors[i] == monitor)
-            {
-                _glfw.monitorCount--;
-                memmove(_glfw.monitors + i,
-                        _glfw.monitors + i + 1,
-                        ((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
-                break;
-            }
-        }
-    }
-
-    if (_glfw.callbacks.monitor)
-        _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
-
-    if (action == GLFW_DISCONNECTED)
-        _glfwFreeMonitor(monitor);
-}
-
-// Notifies shared code that a full screen window has acquired or released
-// a monitor
-//
-void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
-{
-    monitor->window = window;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Allocates and returns a monitor object with the specified name and dimensions
-//
-_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
-{
-    _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
-    monitor->widthMM = widthMM;
-    monitor->heightMM = heightMM;
-
-    if (name)
-        monitor->name = _glfw_strdup(name);
-
-    return monitor;
-}
-
-// Frees a monitor object and any data associated with it
-//
-void _glfwFreeMonitor(_GLFWmonitor* monitor)
-{
-    if (monitor == NULL)
-        return;
-
-    _glfwPlatformFreeMonitor(monitor);
-
-    _glfwFreeGammaArrays(&monitor->originalRamp);
-    _glfwFreeGammaArrays(&monitor->currentRamp);
-
-    free(monitor->modes);
-    free(monitor->name);
-    free(monitor);
-}
-
-// Allocates red, green and blue value arrays of the specified size
-//
-void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
-{
-    ramp->red = calloc(size, sizeof(unsigned short));
-    ramp->green = calloc(size, sizeof(unsigned short));
-    ramp->blue = calloc(size, sizeof(unsigned short));
-    ramp->size = size;
-}
-
-// Frees the red, green and blue value arrays and clears the struct
-//
-void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
-{
-    free(ramp->red);
-    free(ramp->green);
-    free(ramp->blue);
-
-    memset(ramp, 0, sizeof(GLFWgammaramp));
-}
-
-// Chooses the video mode most closely matching the desired one
-//
-const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
-                                        const GLFWvidmode* desired)
-{
-    int i;
-    unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
-    unsigned int rateDiff, leastRateDiff = UINT_MAX;
-    unsigned int colorDiff, leastColorDiff = UINT_MAX;
-    const GLFWvidmode* current;
-    const GLFWvidmode* closest = NULL;
-
-    if (!refreshVideoModes(monitor))
-        return NULL;
-
-    for (i = 0;  i < monitor->modeCount;  i++)
-    {
-        current = monitor->modes + i;
-
-        colorDiff = 0;
-
-        if (desired->redBits != GLFW_DONT_CARE)
-            colorDiff += abs(current->redBits - desired->redBits);
-        if (desired->greenBits != GLFW_DONT_CARE)
-            colorDiff += abs(current->greenBits - desired->greenBits);
-        if (desired->blueBits != GLFW_DONT_CARE)
-            colorDiff += abs(current->blueBits - desired->blueBits);
-
-        sizeDiff = abs((current->width - desired->width) *
-                       (current->width - desired->width) +
-                       (current->height - desired->height) *
-                       (current->height - desired->height));
-
-        if (desired->refreshRate != GLFW_DONT_CARE)
-            rateDiff = abs(current->refreshRate - desired->refreshRate);
-        else
-            rateDiff = UINT_MAX - current->refreshRate;
-
-        if ((colorDiff < leastColorDiff) ||
-            (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
-            (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
-        {
-            closest = current;
-            leastSizeDiff = sizeDiff;
-            leastRateDiff = rateDiff;
-            leastColorDiff = colorDiff;
-        }
-    }
-
-    return closest;
-}
-
-// Performs lexical comparison between two @ref GLFWvidmode structures
-//
-int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
-{
-    return compareVideoModes(fm, sm);
-}
-
-// Splits a color depth into red, green and blue bit depths
-//
-void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
-{
-    int delta;
-
-    // We assume that by 32 the user really meant 24
-    if (bpp == 32)
-        bpp = 24;
-
-    // Convert "bits per pixel" to red, green & blue sizes
-
-    *red = *green = *blue = bpp / 3;
-    delta = bpp - (*red * 3);
-    if (delta >= 1)
-        *green = *green + 1;
-
-    if (delta == 2)
-        *red = *red + 1;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
-{
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    *count = _glfw.monitorCount;
-    return (GLFWmonitor**) _glfw.monitors;
-}
-
-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;
-    if (ypos)
-        *ypos = 0;
-
-    _GLFW_REQUIRE_INIT();
-
-    _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
-}
-
-GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
-                                    int* xpos, int* ypos,
-                                    int* width, int* height)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    if (xpos)
-        *xpos = 0;
-    if (ypos)
-        *ypos = 0;
-    if (width)
-        *width = 0;
-    if (height)
-        *height = 0;
-
-    _GLFW_REQUIRE_INIT();
-
-    _glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
-}
-
-GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    if (widthMM)
-        *widthMM = 0;
-    if (heightMM)
-        *heightMM = 0;
-
-    _GLFW_REQUIRE_INIT();
-
-    if (widthMM)
-        *widthMM = monitor->widthMM;
-    if (heightMM)
-        *heightMM = monitor->heightMM;
-}
-
-GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
-                                        float* xscale, float* yscale)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    if (xscale)
-        *xscale = 0.f;
-    if (yscale)
-        *yscale = 0.f;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
-}
-
-GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return monitor->name;
-}
-
-GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    _GLFW_REQUIRE_INIT();
-    monitor->userPointer = pointer;
-}
-
-GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return monitor->userPointer;
-}
-
-GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
-    return cbfun;
-}
-
-GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (!refreshVideoModes(monitor))
-        return NULL;
-
-    *count = monitor->modeCount;
-    return monitor->modes;
-}
-
-GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    _glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
-    return &monitor->currentMode;
-}
-
-GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
-{
-    unsigned int i;
-    unsigned short* values;
-    GLFWgammaramp ramp;
-    const GLFWgammaramp* original;
-    assert(handle != NULL);
-    assert(gamma > 0.f);
-    assert(gamma <= FLT_MAX);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
-        return;
-    }
-
-    original = glfwGetGammaRamp(handle);
-    if (!original)
-        return;
-
-    values = calloc(original->size, sizeof(unsigned short));
-
-    for (i = 0;  i < original->size;  i++)
-    {
-        float value;
-
-        // Calculate intensity
-        value = i / (float) (original->size - 1);
-        // Apply gamma curve
-        value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
-        // Clamp to value range
-        value = _glfw_fminf(value, 65535.f);
-
-        values[i] = (unsigned short) value;
-    }
-
-    ramp.red = values;
-    ramp.green = values;
-    ramp.blue = values;
-    ramp.size = original->size;
-
-    glfwSetGammaRamp(handle, &ramp);
-    free(values);
-}
-
-GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    _glfwFreeGammaArrays(&monitor->currentRamp);
-    if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
-        return NULL;
-
-    return &monitor->currentRamp;
-}
-
-GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    assert(monitor != NULL);
-    assert(ramp != NULL);
-    assert(ramp->size > 0);
-    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();
-
-    if (!monitor->originalRamp.size)
-    {
-        if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
-            return;
-    }
-
-    _glfwPlatformSetGammaRamp(monitor, ramp);
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdlib.h>
+#include <limits.h>
+
+
+// Lexically compare video modes, used by qsort
+//
+static int compareVideoModes(const void* fp, const void* sp)
+{
+    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
+    if (fbpp != sbpp)
+        return fbpp - sbpp;
+
+    // Then sort on screen area
+    if (farea != sarea)
+        return farea - sarea;
+
+    // Then sort on width
+    if (fm->width != sm->width)
+        return fm->width - sm->width;
+
+    // Lastly sort on refresh rate
+    return fm->refreshRate - sm->refreshRate;
+}
+
+// Retrieves the available modes for the specified monitor
+//
+static GLFWbool refreshVideoModes(_GLFWmonitor* monitor)
+{
+    int modeCount;
+    GLFWvidmode* modes;
+
+    if (monitor->modes)
+        return GLFW_TRUE;
+
+    modes = _glfwPlatformGetVideoModes(monitor, &modeCount);
+    if (!modes)
+        return GLFW_FALSE;
+
+    qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes);
+
+    free(monitor->modes);
+    monitor->modes = modes;
+    monitor->modeCount = modeCount;
+
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code of a monitor connection or disconnection
+//
+void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
+{
+    if (action == GLFW_CONNECTED)
+    {
+        _glfw.monitorCount++;
+        _glfw.monitors =
+            realloc(_glfw.monitors, sizeof(_GLFWmonitor*) * _glfw.monitorCount);
+
+        if (placement == _GLFW_INSERT_FIRST)
+        {
+            memmove(_glfw.monitors + 1,
+                    _glfw.monitors,
+                    ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
+            _glfw.monitors[0] = monitor;
+        }
+        else
+            _glfw.monitors[_glfw.monitorCount - 1] = monitor;
+    }
+    else if (action == GLFW_DISCONNECTED)
+    {
+        int i;
+        _GLFWwindow* window;
+
+        for (window = _glfw.windowListHead;  window;  window = window->next)
+        {
+            if (window->monitor == monitor)
+            {
+                int width, height, xoff, yoff;
+                _glfwPlatformGetWindowSize(window, &width, &height);
+                _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
+                _glfwPlatformGetWindowFrameSize(window, &xoff, &yoff, NULL, NULL);
+                _glfwPlatformSetWindowPos(window, xoff, yoff);
+            }
+        }
+
+        for (i = 0;  i < _glfw.monitorCount;  i++)
+        {
+            if (_glfw.monitors[i] == monitor)
+            {
+                _glfw.monitorCount--;
+                memmove(_glfw.monitors + i,
+                        _glfw.monitors + i + 1,
+                        ((size_t) _glfw.monitorCount - i) * sizeof(_GLFWmonitor*));
+                break;
+            }
+        }
+    }
+
+    if (_glfw.callbacks.monitor)
+        _glfw.callbacks.monitor((GLFWmonitor*) monitor, action);
+
+    if (action == GLFW_DISCONNECTED)
+        _glfwFreeMonitor(monitor);
+}
+
+// Notifies shared code that a full screen window has acquired or released
+// a monitor
+//
+void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window)
+{
+    monitor->window = window;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Allocates and returns a monitor object with the specified name and dimensions
+//
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
+{
+    _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
+    monitor->widthMM = widthMM;
+    monitor->heightMM = heightMM;
+
+    if (name)
+        monitor->name = _glfw_strdup(name);
+
+    return monitor;
+}
+
+// Frees a monitor object and any data associated with it
+//
+void _glfwFreeMonitor(_GLFWmonitor* monitor)
+{
+    if (monitor == NULL)
+        return;
+
+    _glfwPlatformFreeMonitor(monitor);
+
+    _glfwFreeGammaArrays(&monitor->originalRamp);
+    _glfwFreeGammaArrays(&monitor->currentRamp);
+
+    free(monitor->modes);
+    free(monitor->name);
+    free(monitor);
+}
+
+// Allocates red, green and blue value arrays of the specified size
+//
+void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size)
+{
+    ramp->red = calloc(size, sizeof(unsigned short));
+    ramp->green = calloc(size, sizeof(unsigned short));
+    ramp->blue = calloc(size, sizeof(unsigned short));
+    ramp->size = size;
+}
+
+// Frees the red, green and blue value arrays and clears the struct
+//
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
+{
+    free(ramp->red);
+    free(ramp->green);
+    free(ramp->blue);
+
+    memset(ramp, 0, sizeof(GLFWgammaramp));
+}
+
+// Chooses the video mode most closely matching the desired one
+//
+const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
+                                        const GLFWvidmode* desired)
+{
+    int i;
+    unsigned int sizeDiff, leastSizeDiff = UINT_MAX;
+    unsigned int rateDiff, leastRateDiff = UINT_MAX;
+    unsigned int colorDiff, leastColorDiff = UINT_MAX;
+    const GLFWvidmode* current;
+    const GLFWvidmode* closest = NULL;
+
+    if (!refreshVideoModes(monitor))
+        return NULL;
+
+    for (i = 0;  i < monitor->modeCount;  i++)
+    {
+        current = monitor->modes + i;
+
+        colorDiff = 0;
+
+        if (desired->redBits != GLFW_DONT_CARE)
+            colorDiff += abs(current->redBits - desired->redBits);
+        if (desired->greenBits != GLFW_DONT_CARE)
+            colorDiff += abs(current->greenBits - desired->greenBits);
+        if (desired->blueBits != GLFW_DONT_CARE)
+            colorDiff += abs(current->blueBits - desired->blueBits);
+
+        sizeDiff = abs((current->width - desired->width) *
+                       (current->width - desired->width) +
+                       (current->height - desired->height) *
+                       (current->height - desired->height));
+
+        if (desired->refreshRate != GLFW_DONT_CARE)
+            rateDiff = abs(current->refreshRate - desired->refreshRate);
+        else
+            rateDiff = UINT_MAX - current->refreshRate;
+
+        if ((colorDiff < leastColorDiff) ||
+            (colorDiff == leastColorDiff && sizeDiff < leastSizeDiff) ||
+            (colorDiff == leastColorDiff && sizeDiff == leastSizeDiff && rateDiff < leastRateDiff))
+        {
+            closest = current;
+            leastSizeDiff = sizeDiff;
+            leastRateDiff = rateDiff;
+            leastColorDiff = colorDiff;
+        }
+    }
+
+    return closest;
+}
+
+// Performs lexical comparison between two @ref GLFWvidmode structures
+//
+int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
+{
+    return compareVideoModes(fm, sm);
+}
+
+// Splits a color depth into red, green and blue bit depths
+//
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue)
+{
+    int delta;
+
+    // We assume that by 32 the user really meant 24
+    if (bpp == 32)
+        bpp = 24;
+
+    // Convert "bits per pixel" to red, green & blue sizes
+
+    *red = *green = *blue = bpp / 3;
+    delta = bpp - (*red * 3);
+    if (delta >= 1)
+        *green = *green + 1;
+
+    if (delta == 2)
+        *red = *red + 1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWmonitor** glfwGetMonitors(int* count)
+{
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    *count = _glfw.monitorCount;
+    return (GLFWmonitor**) _glfw.monitors;
+}
+
+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;
+    if (ypos)
+        *ypos = 0;
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
+}
+
+GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
+                                    int* xpos, int* ypos,
+                                    int* width, int* height)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    if (xpos)
+        *xpos = 0;
+    if (ypos)
+        *ypos = 0;
+    if (width)
+        *width = 0;
+    if (height)
+        *height = 0;
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformGetMonitorWorkarea(monitor, xpos, ypos, width, height);
+}
+
+GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* handle, int* widthMM, int* heightMM)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    if (widthMM)
+        *widthMM = 0;
+    if (heightMM)
+        *heightMM = 0;
+
+    _GLFW_REQUIRE_INIT();
+
+    if (widthMM)
+        *widthMM = monitor->widthMM;
+    if (heightMM)
+        *heightMM = monitor->heightMM;
+}
+
+GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* handle,
+                                        float* xscale, float* yscale)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    if (xscale)
+        *xscale = 0.f;
+    if (yscale)
+        *yscale = 0.f;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetMonitorContentScale(monitor, xscale, yscale);
+}
+
+GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return monitor->name;
+}
+
+GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* handle, void* pointer)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    monitor->userPointer = pointer;
+}
+
+GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return monitor->userPointer;
+}
+
+GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun cbfun)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(_glfw.callbacks.monitor, cbfun);
+    return cbfun;
+}
+
+GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* handle, int* count)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (!refreshVideoModes(monitor))
+        return NULL;
+
+    *count = monitor->modeCount;
+    return monitor->modes;
+}
+
+GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    _glfwPlatformGetVideoMode(monitor, &monitor->currentMode);
+    return &monitor->currentMode;
+}
+
+GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
+{
+    unsigned int i;
+    unsigned short* values;
+    GLFWgammaramp ramp;
+    const GLFWgammaramp* original;
+    assert(handle != NULL);
+    assert(gamma > 0.f);
+    assert(gamma <= FLT_MAX);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
+        return;
+    }
+
+    original = glfwGetGammaRamp(handle);
+    if (!original)
+        return;
+
+    values = calloc(original->size, sizeof(unsigned short));
+
+    for (i = 0;  i < original->size;  i++)
+    {
+        float value;
+
+        // Calculate intensity
+        value = i / (float) (original->size - 1);
+        // Apply gamma curve
+        value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
+        // Clamp to value range
+        value = _glfw_fminf(value, 65535.f);
+
+        values[i] = (unsigned short) value;
+    }
+
+    ramp.red = values;
+    ramp.green = values;
+    ramp.blue = values;
+    ramp.size = original->size;
+
+    glfwSetGammaRamp(handle, &ramp);
+    free(values);
+}
+
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    _glfwFreeGammaArrays(&monitor->currentRamp);
+    if (!_glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp))
+        return NULL;
+
+    return &monitor->currentRamp;
+}
+
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    assert(monitor != NULL);
+    assert(ramp != NULL);
+    assert(ramp->size > 0);
+    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();
+
+    if (!monitor->originalRamp.size)
+    {
+        if (!_glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp))
+            return;
+    }
+
+    _glfwPlatformSetGammaRamp(monitor, ramp);
+}
+
diff --git a/glfw/src/nsgl_context.h b/glfw/src/nsgl_context.h
--- a/glfw/src/nsgl_context.h
+++ b/glfw/src/nsgl_context.h
@@ -1,66 +1,66 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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.
-//
-//========================================================================
-
-// NOTE: Many Cocoa enum values have been renamed and we need to build across
-//       SDK versions where one is unavailable or the other deprecated
-//       We use the newer names in code and these macros to handle compatibility
-#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
- #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
- #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
-#endif
-
-#define _GLFW_PLATFORM_CONTEXT_STATE            _GLFWcontextNSGL nsgl
-#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE    _GLFWlibraryNSGL nsgl
-
-#include <stdatomic.h>
-
-
-// NSGL-specific per-context data
-//
-typedef struct _GLFWcontextNSGL
-{
-    id                pixelFormat;
-    id                object;
-
-} _GLFWcontextNSGL;
-
-// NSGL-specific global data
-//
-typedef struct _GLFWlibraryNSGL
-{
-    // dlopen handle for OpenGL.framework (for glfwGetProcAddress)
-    CFBundleRef     framework;
-
-} _GLFWlibraryNSGL;
-
-
-GLFWbool _glfwInitNSGL(void);
-void _glfwTerminateNSGL(void);
-GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
-                                const _GLFWctxconfig* ctxconfig,
-                                const _GLFWfbconfig* fbconfig);
-void _glfwDestroyContextNSGL(_GLFWwindow* window);
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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.
+//
+//========================================================================
+
+// NOTE: Many Cocoa enum values have been renamed and we need to build across
+//       SDK versions where one is unavailable or the other deprecated
+//       We use the newer names in code and these macros to handle compatibility
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 101400
+ #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval
+ #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity
+#endif
+
+#define _GLFW_PLATFORM_CONTEXT_STATE            _GLFWcontextNSGL nsgl
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE    _GLFWlibraryNSGL nsgl
+
+#include <stdatomic.h>
+
+
+// NSGL-specific per-context data
+//
+typedef struct _GLFWcontextNSGL
+{
+    id                pixelFormat;
+    id                object;
+
+} _GLFWcontextNSGL;
+
+// NSGL-specific global data
+//
+typedef struct _GLFWlibraryNSGL
+{
+    // dlopen handle for OpenGL.framework (for glfwGetProcAddress)
+    CFBundleRef     framework;
+
+} _GLFWlibraryNSGL;
+
+
+GLFWbool _glfwInitNSGL(void);
+void _glfwTerminateNSGL(void);
+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+                                const _GLFWctxconfig* ctxconfig,
+                                const _GLFWfbconfig* fbconfig);
+void _glfwDestroyContextNSGL(_GLFWwindow* window);
+
diff --git a/glfw/src/nsgl_context.m b/glfw/src/nsgl_context.m
--- a/glfw/src/nsgl_context.m
+++ b/glfw/src/nsgl_context.m
@@ -1,376 +1,376 @@
-//========================================================================
-// GLFW 3.3 macOS - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2009-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <unistd.h>
-#include <math.h>
-
-static void makeContextCurrentNSGL(_GLFWwindow* window)
-{
-    @autoreleasepool {
-
-    if (window)
-        [window->context.nsgl.object makeCurrentContext];
-    else
-        [NSOpenGLContext clearCurrentContext];
-
-    _glfwPlatformSetTls(&_glfw.contextSlot, window);
-
-    } // autoreleasepool
-}
-
-static void swapBuffersNSGL(_GLFWwindow* window)
-{
-    @autoreleasepool {
-
-    // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
-    //       windows with a non-visible occlusion state
-    if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))
-    {
-        int interval = 0;
-        [window->context.nsgl.object getValues:&interval
-                                  forParameter:NSOpenGLContextParameterSwapInterval];
-
-        if (interval > 0)
-        {
-            const double framerate = 60.0;
-            const uint64_t frequency = _glfwPlatformGetTimerFrequency();
-            const uint64_t value = _glfwPlatformGetTimerValue();
-
-            const double elapsed = value / (double) frequency;
-            const double period = 1.0 / framerate;
-            const double delay = period - fmod(elapsed, period);
-
-            usleep(floorl(delay * 1e6));
-        }
-    }
-
-    [window->context.nsgl.object flushBuffer];
-
-    } // autoreleasepool
-}
-
-static void swapIntervalNSGL(int interval)
-{
-    @autoreleasepool {
-
-    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
-    if (window)
-    {
-        [window->context.nsgl.object setValues:&interval
-                                  forParameter:NSOpenGLContextParameterSwapInterval];
-    }
-
-    } // autoreleasepool
-}
-
-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;
-}
-
-static void destroyContextNSGL(_GLFWwindow* window)
-{
-    @autoreleasepool {
-
-    [window->context.nsgl.pixelFormat release];
-    window->context.nsgl.pixelFormat = nil;
-
-    [window->context.nsgl.object release];
-    window->context.nsgl.object = nil;
-
-    } // autoreleasepool
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialize OpenGL support
-//
-GLFWbool _glfwInitNSGL(void)
-{
-    if (_glfw.nsgl.framework)
-        return GLFW_TRUE;
-
-    _glfw.nsgl.framework =
-        CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
-    if (_glfw.nsgl.framework == NULL)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "NSGL: Failed to locate OpenGL framework");
-        return GLFW_FALSE;
-    }
-
-    return GLFW_TRUE;
-}
-
-// Terminate OpenGL support
-//
-void _glfwTerminateNSGL(void)
-{
-}
-
-// Create the OpenGL context
-//
-GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
-                                const _GLFWctxconfig* ctxconfig,
-                                const _GLFWfbconfig* fbconfig)
-{
-    if (ctxconfig->client == GLFW_OPENGL_ES_API)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "NSGL: OpenGL ES is not available on macOS");
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->major > 2)
-    {
-        if (ctxconfig->major == 3 && ctxconfig->minor < 2)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
-            return GLFW_FALSE;
-        }
-
-        if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
-            return GLFW_FALSE;
-        }
-    }
-
-    // Context robustness modes (GL_KHR_robustness) are not yet supported by
-    // macOS but are not a hard constraint, so ignore and continue
-
-    // Context release behaviors (GL_KHR_context_flush_control) are not yet
-    // supported by macOS but are not a hard constraint, so ignore and continue
-
-    // Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
-    // a hard constraint, so ignore and continue
-
-    // No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
-    // are not a hard constraint, so ignore and continue
-
-#define addAttrib(a) \
-{ \
-    assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[index++] = a; \
-}
-#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
-
-    NSOpenGLPixelFormatAttribute attribs[40];
-    int index = 0;
-
-    addAttrib(NSOpenGLPFAAccelerated);
-    addAttrib(NSOpenGLPFAClosestPolicy);
-
-    if (ctxconfig->nsgl.offline)
-    {
-        addAttrib(NSOpenGLPFAAllowOfflineRenderers);
-        // NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
-        //       Info.plist for unbundled applications
-        // HACK: This assumes that NSOpenGLPixelFormat will remain
-        //       a straightforward wrapper of its CGL counterpart
-        addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
-    }
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
-    if (ctxconfig->major >= 4)
-    {
-        setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
-    }
-    else
-#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
-    if (ctxconfig->major >= 3)
-    {
-        setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
-    }
-
-    if (ctxconfig->major <= 2)
-    {
-        if (fbconfig->auxBuffers != GLFW_DONT_CARE)
-            setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
-
-        if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
-            fbconfig->accumGreenBits != GLFW_DONT_CARE &&
-            fbconfig->accumBlueBits != GLFW_DONT_CARE &&
-            fbconfig->accumAlphaBits != GLFW_DONT_CARE)
-        {
-            const int accumBits = fbconfig->accumRedBits +
-                                  fbconfig->accumGreenBits +
-                                  fbconfig->accumBlueBits +
-                                  fbconfig->accumAlphaBits;
-
-            setAttrib(NSOpenGLPFAAccumSize, accumBits);
-        }
-    }
-
-    if (fbconfig->redBits != GLFW_DONT_CARE &&
-        fbconfig->greenBits != GLFW_DONT_CARE &&
-        fbconfig->blueBits != GLFW_DONT_CARE)
-    {
-        int colorBits = fbconfig->redBits +
-                        fbconfig->greenBits +
-                        fbconfig->blueBits;
-
-        // macOS needs non-zero color size, so set reasonable values
-        if (colorBits == 0)
-            colorBits = 24;
-        else if (colorBits < 15)
-            colorBits = 15;
-
-        setAttrib(NSOpenGLPFAColorSize, colorBits);
-    }
-
-    if (fbconfig->alphaBits != GLFW_DONT_CARE)
-        setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
-
-    if (fbconfig->depthBits != GLFW_DONT_CARE)
-        setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
-
-    if (fbconfig->stencilBits != GLFW_DONT_CARE)
-        setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
-
-    if (fbconfig->stereo)
-    {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "NSGL: Stereo rendering is deprecated");
-        return GLFW_FALSE;
-#else
-        addAttrib(NSOpenGLPFAStereo);
-#endif
-    }
-
-    if (fbconfig->doublebuffer)
-        addAttrib(NSOpenGLPFADoubleBuffer);
-
-    if (fbconfig->samples != GLFW_DONT_CARE)
-    {
-        if (fbconfig->samples == 0)
-        {
-            setAttrib(NSOpenGLPFASampleBuffers, 0);
-        }
-        else
-        {
-            setAttrib(NSOpenGLPFASampleBuffers, 1);
-            setAttrib(NSOpenGLPFASamples, fbconfig->samples);
-        }
-    }
-
-    // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
-    //       framebuffer, so there's no need (and no way) to request it
-
-    addAttrib(0);
-
-#undef addAttrib
-#undef setAttrib
-
-    window->context.nsgl.pixelFormat =
-        [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
-    if (window->context.nsgl.pixelFormat == nil)
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "NSGL: Failed to find a suitable pixel format");
-        return GLFW_FALSE;
-    }
-
-    NSOpenGLContext* share = nil;
-
-    if (ctxconfig->share)
-        share = ctxconfig->share->context.nsgl.object;
-
-    window->context.nsgl.object =
-        [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
-                                   shareContext:share];
-    if (window->context.nsgl.object == nil)
-    {
-        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                        "NSGL: Failed to create OpenGL context");
-        return GLFW_FALSE;
-    }
-
-    if (fbconfig->transparent)
-    {
-        GLint opaque = 0;
-        [window->context.nsgl.object setValues:&opaque
-                                  forParameter:NSOpenGLContextParameterSurfaceOpacity];
-    }
-
-    [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
-
-    [window->context.nsgl.object setView:window->ns.view];
-
-    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 GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(nil);
-
-    if (window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-        return nil;
-    }
-
-    return window->context.nsgl.object;
-}
-
+//========================================================================
+// GLFW 3.3 macOS - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <unistd.h>
+#include <math.h>
+
+static void makeContextCurrentNSGL(_GLFWwindow* window)
+{
+    @autoreleasepool {
+
+    if (window)
+        [window->context.nsgl.object makeCurrentContext];
+    else
+        [NSOpenGLContext clearCurrentContext];
+
+    _glfwPlatformSetTls(&_glfw.contextSlot, window);
+
+    } // autoreleasepool
+}
+
+static void swapBuffersNSGL(_GLFWwindow* window)
+{
+    @autoreleasepool {
+
+    // HACK: Simulate vsync with usleep as NSGL swap interval does not apply to
+    //       windows with a non-visible occlusion state
+    if (!([window->ns.object occlusionState] & NSWindowOcclusionStateVisible))
+    {
+        int interval = 0;
+        [window->context.nsgl.object getValues:&interval
+                                  forParameter:NSOpenGLContextParameterSwapInterval];
+
+        if (interval > 0)
+        {
+            const double framerate = 60.0;
+            const uint64_t frequency = _glfwPlatformGetTimerFrequency();
+            const uint64_t value = _glfwPlatformGetTimerValue();
+
+            const double elapsed = value / (double) frequency;
+            const double period = 1.0 / framerate;
+            const double delay = period - fmod(elapsed, period);
+
+            usleep(floorl(delay * 1e6));
+        }
+    }
+
+    [window->context.nsgl.object flushBuffer];
+
+    } // autoreleasepool
+}
+
+static void swapIntervalNSGL(int interval)
+{
+    @autoreleasepool {
+
+    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+    if (window)
+    {
+        [window->context.nsgl.object setValues:&interval
+                                  forParameter:NSOpenGLContextParameterSwapInterval];
+    }
+
+    } // autoreleasepool
+}
+
+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;
+}
+
+static void destroyContextNSGL(_GLFWwindow* window)
+{
+    @autoreleasepool {
+
+    [window->context.nsgl.pixelFormat release];
+    window->context.nsgl.pixelFormat = nil;
+
+    [window->context.nsgl.object release];
+    window->context.nsgl.object = nil;
+
+    } // autoreleasepool
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize OpenGL support
+//
+GLFWbool _glfwInitNSGL(void)
+{
+    if (_glfw.nsgl.framework)
+        return GLFW_TRUE;
+
+    _glfw.nsgl.framework =
+        CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+    if (_glfw.nsgl.framework == NULL)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "NSGL: Failed to locate OpenGL framework");
+        return GLFW_FALSE;
+    }
+
+    return GLFW_TRUE;
+}
+
+// Terminate OpenGL support
+//
+void _glfwTerminateNSGL(void)
+{
+}
+
+// Create the OpenGL context
+//
+GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
+                                const _GLFWctxconfig* ctxconfig,
+                                const _GLFWfbconfig* fbconfig)
+{
+    if (ctxconfig->client == GLFW_OPENGL_ES_API)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "NSGL: OpenGL ES is not available on macOS");
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->major > 2)
+    {
+        if (ctxconfig->major == 3 && ctxconfig->minor < 2)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
+            return GLFW_FALSE;
+        }
+
+        if (!ctxconfig->forward || ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "NSGL: The targeted version of macOS only supports forward-compatible core profile contexts for OpenGL 3.2 and above");
+            return GLFW_FALSE;
+        }
+    }
+
+    // Context robustness modes (GL_KHR_robustness) are not yet supported by
+    // macOS but are not a hard constraint, so ignore and continue
+
+    // Context release behaviors (GL_KHR_context_flush_control) are not yet
+    // supported by macOS but are not a hard constraint, so ignore and continue
+
+    // Debug contexts (GL_KHR_debug) are not yet supported by macOS but are not
+    // a hard constraint, so ignore and continue
+
+    // No-error contexts (GL_KHR_no_error) are not yet supported by macOS but
+    // are not a hard constraint, so ignore and continue
+
+#define addAttrib(a) \
+{ \
+    assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+}
+#define setAttrib(a, v) { addAttrib(a); addAttrib(v); }
+
+    NSOpenGLPixelFormatAttribute attribs[40];
+    int index = 0;
+
+    addAttrib(NSOpenGLPFAAccelerated);
+    addAttrib(NSOpenGLPFAClosestPolicy);
+
+    if (ctxconfig->nsgl.offline)
+    {
+        addAttrib(NSOpenGLPFAAllowOfflineRenderers);
+        // NOTE: This replaces the NSSupportsAutomaticGraphicsSwitching key in
+        //       Info.plist for unbundled applications
+        // HACK: This assumes that NSOpenGLPixelFormat will remain
+        //       a straightforward wrapper of its CGL counterpart
+        addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
+    }
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+    if (ctxconfig->major >= 4)
+    {
+        setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
+    }
+    else
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+    if (ctxconfig->major >= 3)
+    {
+        setAttrib(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+    }
+
+    if (ctxconfig->major <= 2)
+    {
+        if (fbconfig->auxBuffers != GLFW_DONT_CARE)
+            setAttrib(NSOpenGLPFAAuxBuffers, fbconfig->auxBuffers);
+
+        if (fbconfig->accumRedBits != GLFW_DONT_CARE &&
+            fbconfig->accumGreenBits != GLFW_DONT_CARE &&
+            fbconfig->accumBlueBits != GLFW_DONT_CARE &&
+            fbconfig->accumAlphaBits != GLFW_DONT_CARE)
+        {
+            const int accumBits = fbconfig->accumRedBits +
+                                  fbconfig->accumGreenBits +
+                                  fbconfig->accumBlueBits +
+                                  fbconfig->accumAlphaBits;
+
+            setAttrib(NSOpenGLPFAAccumSize, accumBits);
+        }
+    }
+
+    if (fbconfig->redBits != GLFW_DONT_CARE &&
+        fbconfig->greenBits != GLFW_DONT_CARE &&
+        fbconfig->blueBits != GLFW_DONT_CARE)
+    {
+        int colorBits = fbconfig->redBits +
+                        fbconfig->greenBits +
+                        fbconfig->blueBits;
+
+        // macOS needs non-zero color size, so set reasonable values
+        if (colorBits == 0)
+            colorBits = 24;
+        else if (colorBits < 15)
+            colorBits = 15;
+
+        setAttrib(NSOpenGLPFAColorSize, colorBits);
+    }
+
+    if (fbconfig->alphaBits != GLFW_DONT_CARE)
+        setAttrib(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
+
+    if (fbconfig->depthBits != GLFW_DONT_CARE)
+        setAttrib(NSOpenGLPFADepthSize, fbconfig->depthBits);
+
+    if (fbconfig->stencilBits != GLFW_DONT_CARE)
+        setAttrib(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
+
+    if (fbconfig->stereo)
+    {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "NSGL: Stereo rendering is deprecated");
+        return GLFW_FALSE;
+#else
+        addAttrib(NSOpenGLPFAStereo);
+#endif
+    }
+
+    if (fbconfig->doublebuffer)
+        addAttrib(NSOpenGLPFADoubleBuffer);
+
+    if (fbconfig->samples != GLFW_DONT_CARE)
+    {
+        if (fbconfig->samples == 0)
+        {
+            setAttrib(NSOpenGLPFASampleBuffers, 0);
+        }
+        else
+        {
+            setAttrib(NSOpenGLPFASampleBuffers, 1);
+            setAttrib(NSOpenGLPFASamples, fbconfig->samples);
+        }
+    }
+
+    // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
+    //       framebuffer, so there's no need (and no way) to request it
+
+    addAttrib(0);
+
+#undef addAttrib
+#undef setAttrib
+
+    window->context.nsgl.pixelFormat =
+        [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
+    if (window->context.nsgl.pixelFormat == nil)
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "NSGL: Failed to find a suitable pixel format");
+        return GLFW_FALSE;
+    }
+
+    NSOpenGLContext* share = nil;
+
+    if (ctxconfig->share)
+        share = ctxconfig->share->context.nsgl.object;
+
+    window->context.nsgl.object =
+        [[NSOpenGLContext alloc] initWithFormat:window->context.nsgl.pixelFormat
+                                   shareContext:share];
+    if (window->context.nsgl.object == nil)
+    {
+        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                        "NSGL: Failed to create OpenGL context");
+        return GLFW_FALSE;
+    }
+
+    if (fbconfig->transparent)
+    {
+        GLint opaque = 0;
+        [window->context.nsgl.object setValues:&opaque
+                                  forParameter:NSOpenGLContextParameterSurfaceOpacity];
+    }
+
+    [window->ns.view setWantsBestResolutionOpenGLSurface:window->ns.retina];
+
+    [window->context.nsgl.object setView:window->ns.view];
+
+    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 GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI id glfwGetNSGLContext(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(nil);
+
+    if (window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+        return nil;
+    }
+
+    return window->context.nsgl.object;
+}
+
diff --git a/glfw/src/null_init.c b/glfw/src/null_init.c
--- a/glfw/src/null_init.c
+++ b/glfw/src/null_init.c
@@ -1,52 +1,52 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016 Google Inc.
-// Copyright (c) 2016-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void)
-{
-    _glfwInitTimerPOSIX();
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformTerminate(void)
-{
-    _glfwTerminateOSMesa();
-}
-
-const char* _glfwPlatformGetVersionString(void)
-{
-    return _GLFW_VERSION_NUMBER " null OSMesa";
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2016-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+    _glfwInitTimerPOSIX();
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+    _glfwTerminateOSMesa();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+    return _GLFW_VERSION_NUMBER " null OSMesa";
+}
+
diff --git a/glfw/src/null_joystick.c b/glfw/src/null_joystick.c
--- a/glfw/src/null_joystick.c
+++ b/glfw/src/null_joystick.c
@@ -1,44 +1,44 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformUpdateGamepadGUID(char* guid)
-{
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+}
+
diff --git a/glfw/src/null_joystick.h b/glfw/src/null_joystick.h
--- a/glfw/src/null_joystick.h
+++ b/glfw/src/null_joystick.h
@@ -1,31 +1,31 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-
-#define _GLFW_PLATFORM_JOYSTICK_STATE         struct { int dummyJoystick; }
-#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
-
-#define _GLFW_PLATFORM_MAPPING_NAME ""
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE         struct { int dummyJoystick; }
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
+
+#define _GLFW_PLATFORM_MAPPING_NAME ""
+
diff --git a/glfw/src/null_monitor.c b/glfw/src/null_monitor.c
--- a/glfw/src/null_monitor.c
+++ b/glfw/src/null_monitor.c
@@ -1,77 +1,77 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016 Google Inc.
-// Copyright (c) 2016-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
-{
-}
-
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
-{
-}
-
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = 1.f;
-    if (yscale)
-        *yscale = 1.f;
-}
-
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
-                                     int* xpos, int* ypos,
-                                     int* width, int* height)
-{
-}
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
-{
-    return NULL;
-}
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-}
-
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
-{
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2016-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = 1.f;
+    if (yscale)
+        *yscale = 1.f;
+}
+
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
+                                     int* xpos, int* ypos,
+                                     int* width, int* height)
+{
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+    return NULL;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+}
+
diff --git a/glfw/src/null_platform.h b/glfw/src/null_platform.h
--- a/glfw/src/null_platform.h
+++ b/glfw/src/null_platform.h
@@ -1,62 +1,62 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016 Google Inc.
-// Copyright (c) 2016-2017 Camilla Löwy <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 <dlfcn.h>
-
-#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
-
-#define _GLFW_PLATFORM_CONTEXT_STATE         struct { int dummyContext; }
-#define _GLFW_PLATFORM_MONITOR_STATE         struct { int dummyMonitor; }
-#define _GLFW_PLATFORM_CURSOR_STATE          struct { int dummyCursor; }
-#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE  struct { int dummyLibraryWindow; }
-#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
-#define _GLFW_EGL_CONTEXT_STATE              struct { int dummyEGLContext; }
-#define _GLFW_EGL_LIBRARY_CONTEXT_STATE      struct { int dummyEGLLibraryContext; }
-
-#include "osmesa_context.h"
-#include "posix_time.h"
-#include "posix_thread.h"
-#include "null_joystick.h"
-
-#if defined(_GLFW_WIN32)
- #define _glfw_dlopen(name) LoadLibraryA(name)
- #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
- #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
-#else
- #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
- #define _glfw_dlclose(handle) dlclose(handle)
- #define _glfw_dlsym(handle, name) dlsym(handle, name)
-#endif
-
-// Null-specific per-window data
-//
-typedef struct _GLFWwindowNull
-{
-    int width;
-    int height;
-} _GLFWwindowNull;
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2016-2017 Camilla Löwy <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 <dlfcn.h>
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowNull null
+
+#define _GLFW_PLATFORM_CONTEXT_STATE         struct { int dummyContext; }
+#define _GLFW_PLATFORM_MONITOR_STATE         struct { int dummyMonitor; }
+#define _GLFW_PLATFORM_CURSOR_STATE          struct { int dummyCursor; }
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE  struct { int dummyLibraryWindow; }
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
+#define _GLFW_EGL_CONTEXT_STATE              struct { int dummyEGLContext; }
+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE      struct { int dummyEGLLibraryContext; }
+
+#include "osmesa_context.h"
+#include "posix_time.h"
+#include "posix_thread.h"
+#include "null_joystick.h"
+
+#if defined(_GLFW_WIN32)
+ #define _glfw_dlopen(name) LoadLibraryA(name)
+ #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
+ #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
+#else
+ #define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+ #define _glfw_dlclose(handle) dlclose(handle)
+ #define _glfw_dlsym(handle, name) dlsym(handle, name)
+#endif
+
+// Null-specific per-window data
+//
+typedef struct _GLFWwindowNull
+{
+    int width;
+    int height;
+} _GLFWwindowNull;
+
diff --git a/glfw/src/null_window.c b/glfw/src/null_window.c
--- a/glfw/src/null_window.c
+++ b/glfw/src/null_window.c
@@ -1,332 +1,332 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016 Google Inc.
-// Copyright (c) 2016-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-
-static int createNativeWindow(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig)
-{
-    window->null.width = wndconfig->width;
-    window->null.height = wndconfig->height;
-
-    return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       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 ||
-            ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwInitOSMesa())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-        else
-        {
-            _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
-            return GLFW_FALSE;
-        }
-    }
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyWindow(_GLFWwindow* window)
-{
-    if (window->context.destroy)
-        window->context.destroy(window);
-}
-
-void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
-{
-}
-
-void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
-                                const GLFWimage* images)
-{
-}
-
-void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
-                                   _GLFWmonitor* monitor,
-                                   int xpos, int ypos,
-                                   int width, int height,
-                                   int refreshRate)
-{
-}
-
-void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
-{
-}
-
-void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
-{
-}
-
-void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
-{
-    if (width)
-        *width = window->null.width;
-    if (height)
-        *height = window->null.height;
-}
-
-void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
-{
-    window->null.width = width;
-    window->null.height = height;
-}
-
-void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
-                                      int minwidth, int minheight,
-                                      int maxwidth, int maxheight)
-{
-}
-
-void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
-{
-}
-
-void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
-{
-    if (width)
-        *width = window->null.width;
-    if (height)
-        *height = window->null.height;
-}
-
-void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
-                                     int* left, int* top,
-                                     int* right, int* bottom)
-{
-}
-
-void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = 1.f;
-    if (yscale)
-        *yscale = 1.f;
-}
-
-void _glfwPlatformIconifyWindow(_GLFWwindow* window)
-{
-}
-
-void _glfwPlatformRestoreWindow(_GLFWwindow* window)
-{
-}
-
-void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
-{
-}
-
-int _glfwPlatformWindowMaximized(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformWindowHovered(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
-{
-}
-
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
-{
-}
-
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
-{
-}
-
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
-{
-    return 1.f;
-}
-
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
-{
-}
-
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
-{
-}
-
-GLFWbool _glfwPlatformRawMouseMotionSupported(void)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformShowWindow(_GLFWwindow* window)
-{
-}
-
-
-void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
-{
-}
-
-void _glfwPlatformUnhideWindow(_GLFWwindow* window)
-{
-}
-
-void _glfwPlatformHideWindow(_GLFWwindow* window)
-{
-}
-
-void _glfwPlatformFocusWindow(_GLFWwindow* window)
-{
-}
-
-int _glfwPlatformWindowFocused(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformWindowIconified(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformWindowVisible(_GLFWwindow* window)
-{
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformPollEvents(void)
-{
-}
-
-void _glfwPlatformWaitEvents(void)
-{
-}
-
-void _glfwPlatformWaitEventsTimeout(double timeout)
-{
-}
-
-void _glfwPlatformPostEmptyEvent(void)
-{
-}
-
-void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
-{
-}
-
-void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
-{
-}
-
-void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
-{
-}
-
-int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
-                              const GLFWimage* image,
-                              int xhot, int yhot)
-{
-    return GLFW_TRUE;
-}
-
-int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
-{
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
-{
-}
-
-void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
-{
-}
-
-void _glfwPlatformSetClipboardString(const char* string)
-{
-}
-
-const char* _glfwPlatformGetClipboardString(void)
-{
-    return NULL;
-}
-
-const char* _glfwPlatformGetScancodeName(int scancode)
-{
-    return "";
-}
-
-int _glfwPlatformGetKeyScancode(int key)
-{
-    return -1;
-}
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
-{
-}
-
-int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
-                                                      VkPhysicalDevice device,
-                                                      uint32_t queuefamily)
-{
-    return GLFW_FALSE;
-}
-
-VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
-                                          _GLFWwindow* window,
-                                          const VkAllocationCallbacks* allocator,
-                                          VkSurfaceKHR* surface)
-{
-    // This seems like the most appropriate error to return here
-    return VK_ERROR_INITIALIZATION_FAILED;
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2016-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+
+static int createNativeWindow(_GLFWwindow* window,
+                              const _GLFWwndconfig* wndconfig)
+{
+    window->null.width = wndconfig->width;
+    window->null.height = wndconfig->height;
+
+    return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       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 ||
+            ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwInitOSMesa())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+        else
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE, "Null: EGL not available");
+            return GLFW_FALSE;
+        }
+    }
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+    if (window->context.destroy)
+        window->context.destroy(window);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count,
+                                const GLFWimage* images)
+{
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+                                   _GLFWmonitor* monitor,
+                                   int xpos, int ypos,
+                                   int width, int height,
+                                   int refreshRate)
+{
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+    if (width)
+        *width = window->null.width;
+    if (height)
+        *height = window->null.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+    window->null.width = width;
+    window->null.height = height;
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+                                      int minwidth, int minheight,
+                                      int maxwidth, int maxheight)
+{
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int n, int d)
+{
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+    if (width)
+        *width = window->null.width;
+    if (height)
+        *height = window->null.height;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+                                     int* left, int* top,
+                                     int* right, int* bottom)
+{
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = 1.f;
+    if (yscale)
+        *yscale = 1.f;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+    return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+}
+
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+{
+}
+
+GLFWbool _glfwPlatformRawMouseMotionSupported(void)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+}
+
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformUnhideWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+                              const GLFWimage* image,
+                              int xhot, int yhot)
+{
+    return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+    return NULL;
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+    return "";
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+    return -1;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+                                                      VkPhysicalDevice device,
+                                                      uint32_t queuefamily)
+{
+    return GLFW_FALSE;
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+                                          _GLFWwindow* window,
+                                          const VkAllocationCallbacks* allocator,
+                                          VkSurfaceKHR* surface)
+{
+    // This seems like the most appropriate error to return here
+    return VK_ERROR_INITIALIZATION_FAILED;
+}
+
diff --git a/glfw/src/osmesa_context.c b/glfw/src/osmesa_context.c
--- a/glfw/src/osmesa_context.c
+++ b/glfw/src/osmesa_context.c
@@ -1,372 +1,372 @@
-//========================================================================
-// GLFW 3.3 OSMesa - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2016 Google Inc.
-// Copyright (c) 2016-2017 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "internal.h"
-
-
-static void makeContextCurrentOSMesa(_GLFWwindow* window)
-{
-    if (window)
-    {
-        int width, height;
-        _glfwPlatformGetFramebufferSize(window, &width, &height);
-
-        // Check to see if we need to allocate a new buffer
-        if ((window->context.osmesa.buffer == NULL) ||
-            (width != window->context.osmesa.width) ||
-            (height != window->context.osmesa.height))
-        {
-            free(window->context.osmesa.buffer);
-
-            // Allocate the new buffer (width * height * 8-bit RGBA)
-            window->context.osmesa.buffer = calloc(4, (size_t) width * height);
-            window->context.osmesa.width  = width;
-            window->context.osmesa.height = height;
-        }
-
-        if (!OSMesaMakeCurrent(window->context.osmesa.handle,
-                               window->context.osmesa.buffer,
-                               GL_UNSIGNED_BYTE,
-                               width, height))
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "OSMesa: Failed to make context current");
-            return;
-        }
-    }
-
-    _glfwPlatformSetTls(&_glfw.contextSlot, window);
-}
-
-static GLFWglproc getProcAddressOSMesa(const char* procname)
-{
-    return (GLFWglproc) OSMesaGetProcAddress(procname);
-}
-
-static void destroyContextOSMesa(_GLFWwindow* window)
-{
-    if (window->context.osmesa.handle)
-    {
-        OSMesaDestroyContext(window->context.osmesa.handle);
-        window->context.osmesa.handle = NULL;
-    }
-
-    if (window->context.osmesa.buffer)
-    {
-        free(window->context.osmesa.buffer);
-        window->context.osmesa.width = 0;
-        window->context.osmesa.height = 0;
-    }
-}
-
-static void swapBuffersOSMesa(_GLFWwindow* window)
-{
-    // No double buffering on OSMesa
-}
-
-static void swapIntervalOSMesa(int interval)
-{
-    // No swap interval on OSMesa
-}
-
-static int extensionSupportedOSMesa(const char* extension)
-{
-    // OSMesa does not have extensions
-    return GLFW_FALSE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWbool _glfwInitOSMesa(void)
-{
-    int i;
-    const char* sonames[] =
-    {
-#if defined(_GLFW_OSMESA_LIBRARY)
-        _GLFW_OSMESA_LIBRARY,
-#elif defined(_WIN32)
-        "libOSMesa.dll",
-        "OSMesa.dll",
-#elif defined(__APPLE__)
-        "libOSMesa.8.dylib",
-#elif defined(__CYGWIN__)
-        "libOSMesa-8.so",
-#else
-        "libOSMesa.so.8",
-        "libOSMesa.so.6",
-#endif
-        NULL
-    };
-
-    if (_glfw.osmesa.handle)
-        return GLFW_TRUE;
-
-    for (i = 0;  sonames[i];  i++)
-    {
-        _glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
-        if (_glfw.osmesa.handle)
-            break;
-    }
-
-    if (!_glfw.osmesa.handle)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
-        return GLFW_FALSE;
-    }
-
-    _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
-    _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
-    _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
-    _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
-    _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
-    _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
-    _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
-        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
-
-    if (!_glfw.osmesa.CreateContextExt ||
-        !_glfw.osmesa.DestroyContext ||
-        !_glfw.osmesa.MakeCurrent ||
-        !_glfw.osmesa.GetColorBuffer ||
-        !_glfw.osmesa.GetDepthBuffer ||
-        !_glfw.osmesa.GetProcAddress)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "OSMesa: Failed to load required entry points");
-
-        _glfwTerminateOSMesa();
-        return GLFW_FALSE;
-    }
-
-    return GLFW_TRUE;
-}
-
-void _glfwTerminateOSMesa(void)
-{
-    if (_glfw.osmesa.handle)
-    {
-        _glfw_dlclose(_glfw.osmesa.handle);
-        _glfw.osmesa.handle = NULL;
-    }
-}
-
-#define setAttrib(a, v) \
-{ \
-    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[index++] = a; \
-    attribs[index++] = v; \
-}
-
-GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
-                                  const _GLFWctxconfig* ctxconfig,
-                                  const _GLFWfbconfig* fbconfig)
-{
-    OSMesaContext share = NULL;
-    const int accumBits = fbconfig->accumRedBits +
-                          fbconfig->accumGreenBits +
-                          fbconfig->accumBlueBits +
-                          fbconfig->accumAlphaBits;
-
-    if (ctxconfig->client == GLFW_OPENGL_ES_API)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "OSMesa: OpenGL ES is not available on OSMesa");
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->share)
-        share = ctxconfig->share->context.osmesa.handle;
-
-    if (OSMesaCreateContextAttribs)
-    {
-        int index = 0, attribs[40];
-
-        setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
-        setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
-        setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
-        setAttrib(OSMESA_ACCUM_BITS, accumBits);
-
-        if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
-        {
-            setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
-        }
-        else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
-        {
-            setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
-        }
-
-        if (ctxconfig->major != 1 || ctxconfig->minor != 0)
-        {
-            setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
-            setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
-        }
-
-        if (ctxconfig->forward)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "OSMesa: Forward-compatible contexts not supported");
-            return GLFW_FALSE;
-        }
-
-        setAttrib(0, 0);
-
-        window->context.osmesa.handle =
-            OSMesaCreateContextAttribs(attribs, share);
-    }
-    else
-    {
-        if (ctxconfig->profile)
-        {
-            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                            "OSMesa: OpenGL profiles unavailable");
-            return GLFW_FALSE;
-        }
-
-        window->context.osmesa.handle =
-            OSMesaCreateContextExt(OSMESA_RGBA,
-                                   fbconfig->depthBits,
-                                   fbconfig->stencilBits,
-                                   accumBits,
-                                   share);
-    }
-
-    if (window->context.osmesa.handle == NULL)
-    {
-        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                        "OSMesa: Failed to create context");
-        return GLFW_FALSE;
-    }
-
-    window->context.makeCurrent = makeContextCurrentOSMesa;
-    window->context.swapBuffers = swapBuffersOSMesa;
-    window->context.swapInterval = swapIntervalOSMesa;
-    window->context.extensionSupported = extensionSupportedOSMesa;
-    window->context.getProcAddress = getProcAddressOSMesa;
-    window->context.destroy = destroyContextOSMesa;
-
-    return GLFW_TRUE;
-}
-
-#undef setAttrib
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
-                                     int* height, int* format, void** buffer)
-{
-    void* mesaBuffer;
-    GLint mesaWidth, mesaHeight, mesaFormat;
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
-                              &mesaWidth, &mesaHeight,
-                              &mesaFormat, &mesaBuffer))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "OSMesa: Failed to retrieve color buffer");
-        return GLFW_FALSE;
-    }
-
-    if (width)
-        *width = mesaWidth;
-    if (height)
-        *height = mesaHeight;
-    if (format)
-        *format = mesaFormat;
-    if (buffer)
-        *buffer = mesaBuffer;
-
-    return GLFW_TRUE;
-}
-
-GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
-                                     int* width, int* height,
-                                     int* bytesPerValue,
-                                     void** buffer)
-{
-    void* mesaBuffer;
-    GLint mesaWidth, mesaHeight, mesaBytes;
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
-                              &mesaWidth, &mesaHeight,
-                              &mesaBytes, &mesaBuffer))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "OSMesa: Failed to retrieve depth buffer");
-        return GLFW_FALSE;
-    }
-
-    if (width)
-        *width = mesaWidth;
-    if (height)
-        *height = mesaHeight;
-    if (bytesPerValue)
-        *bytesPerValue = mesaBytes;
-    if (buffer)
-        *buffer = mesaBuffer;
-
-    return GLFW_TRUE;
-}
-
-GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-        return NULL;
-    }
-
-    return window->context.osmesa.handle;
-}
-
+//========================================================================
+// GLFW 3.3 OSMesa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2016 Google Inc.
+// Copyright (c) 2016-2017 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "internal.h"
+
+
+static void makeContextCurrentOSMesa(_GLFWwindow* window)
+{
+    if (window)
+    {
+        int width, height;
+        _glfwPlatformGetFramebufferSize(window, &width, &height);
+
+        // Check to see if we need to allocate a new buffer
+        if ((window->context.osmesa.buffer == NULL) ||
+            (width != window->context.osmesa.width) ||
+            (height != window->context.osmesa.height))
+        {
+            free(window->context.osmesa.buffer);
+
+            // Allocate the new buffer (width * height * 8-bit RGBA)
+            window->context.osmesa.buffer = calloc(4, (size_t) width * height);
+            window->context.osmesa.width  = width;
+            window->context.osmesa.height = height;
+        }
+
+        if (!OSMesaMakeCurrent(window->context.osmesa.handle,
+                               window->context.osmesa.buffer,
+                               GL_UNSIGNED_BYTE,
+                               width, height))
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "OSMesa: Failed to make context current");
+            return;
+        }
+    }
+
+    _glfwPlatformSetTls(&_glfw.contextSlot, window);
+}
+
+static GLFWglproc getProcAddressOSMesa(const char* procname)
+{
+    return (GLFWglproc) OSMesaGetProcAddress(procname);
+}
+
+static void destroyContextOSMesa(_GLFWwindow* window)
+{
+    if (window->context.osmesa.handle)
+    {
+        OSMesaDestroyContext(window->context.osmesa.handle);
+        window->context.osmesa.handle = NULL;
+    }
+
+    if (window->context.osmesa.buffer)
+    {
+        free(window->context.osmesa.buffer);
+        window->context.osmesa.width = 0;
+        window->context.osmesa.height = 0;
+    }
+}
+
+static void swapBuffersOSMesa(_GLFWwindow* window)
+{
+    // No double buffering on OSMesa
+}
+
+static void swapIntervalOSMesa(int interval)
+{
+    // No swap interval on OSMesa
+}
+
+static int extensionSupportedOSMesa(const char* extension)
+{
+    // OSMesa does not have extensions
+    return GLFW_FALSE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitOSMesa(void)
+{
+    int i;
+    const char* sonames[] =
+    {
+#if defined(_GLFW_OSMESA_LIBRARY)
+        _GLFW_OSMESA_LIBRARY,
+#elif defined(_WIN32)
+        "libOSMesa.dll",
+        "OSMesa.dll",
+#elif defined(__APPLE__)
+        "libOSMesa.8.dylib",
+#elif defined(__CYGWIN__)
+        "libOSMesa-8.so",
+#else
+        "libOSMesa.so.8",
+        "libOSMesa.so.6",
+#endif
+        NULL
+    };
+
+    if (_glfw.osmesa.handle)
+        return GLFW_TRUE;
+
+    for (i = 0;  sonames[i];  i++)
+    {
+        _glfw.osmesa.handle = _glfw_dlopen(sonames[i]);
+        if (_glfw.osmesa.handle)
+            break;
+    }
+
+    if (!_glfw.osmesa.handle)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
+        return GLFW_FALSE;
+    }
+
+    _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt");
+    _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
+    _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext");
+    _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
+    _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
+    _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
+    _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
+        _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
+
+    if (!_glfw.osmesa.CreateContextExt ||
+        !_glfw.osmesa.DestroyContext ||
+        !_glfw.osmesa.MakeCurrent ||
+        !_glfw.osmesa.GetColorBuffer ||
+        !_glfw.osmesa.GetDepthBuffer ||
+        !_glfw.osmesa.GetProcAddress)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "OSMesa: Failed to load required entry points");
+
+        _glfwTerminateOSMesa();
+        return GLFW_FALSE;
+    }
+
+    return GLFW_TRUE;
+}
+
+void _glfwTerminateOSMesa(void)
+{
+    if (_glfw.osmesa.handle)
+    {
+        _glfw_dlclose(_glfw.osmesa.handle);
+        _glfw.osmesa.handle = NULL;
+    }
+}
+
+#define setAttrib(a, v) \
+{ \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+    attribs[index++] = v; \
+}
+
+GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
+                                  const _GLFWctxconfig* ctxconfig,
+                                  const _GLFWfbconfig* fbconfig)
+{
+    OSMesaContext share = NULL;
+    const int accumBits = fbconfig->accumRedBits +
+                          fbconfig->accumGreenBits +
+                          fbconfig->accumBlueBits +
+                          fbconfig->accumAlphaBits;
+
+    if (ctxconfig->client == GLFW_OPENGL_ES_API)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "OSMesa: OpenGL ES is not available on OSMesa");
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->share)
+        share = ctxconfig->share->context.osmesa.handle;
+
+    if (OSMesaCreateContextAttribs)
+    {
+        int index = 0, attribs[40];
+
+        setAttrib(OSMESA_FORMAT, OSMESA_RGBA);
+        setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits);
+        setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
+        setAttrib(OSMESA_ACCUM_BITS, accumBits);
+
+        if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
+        {
+            setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
+        }
+        else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
+        {
+            setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
+        }
+
+        if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+        {
+            setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
+            setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
+        }
+
+        if (ctxconfig->forward)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "OSMesa: Forward-compatible contexts not supported");
+            return GLFW_FALSE;
+        }
+
+        setAttrib(0, 0);
+
+        window->context.osmesa.handle =
+            OSMesaCreateContextAttribs(attribs, share);
+    }
+    else
+    {
+        if (ctxconfig->profile)
+        {
+            _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                            "OSMesa: OpenGL profiles unavailable");
+            return GLFW_FALSE;
+        }
+
+        window->context.osmesa.handle =
+            OSMesaCreateContextExt(OSMESA_RGBA,
+                                   fbconfig->depthBits,
+                                   fbconfig->stencilBits,
+                                   accumBits,
+                                   share);
+    }
+
+    if (window->context.osmesa.handle == NULL)
+    {
+        _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                        "OSMesa: Failed to create context");
+        return GLFW_FALSE;
+    }
+
+    window->context.makeCurrent = makeContextCurrentOSMesa;
+    window->context.swapBuffers = swapBuffersOSMesa;
+    window->context.swapInterval = swapIntervalOSMesa;
+    window->context.extensionSupported = extensionSupportedOSMesa;
+    window->context.getProcAddress = getProcAddressOSMesa;
+    window->context.destroy = destroyContextOSMesa;
+
+    return GLFW_TRUE;
+}
+
+#undef setAttrib
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
+                                     int* height, int* format, void** buffer)
+{
+    void* mesaBuffer;
+    GLint mesaWidth, mesaHeight, mesaFormat;
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
+                              &mesaWidth, &mesaHeight,
+                              &mesaFormat, &mesaBuffer))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "OSMesa: Failed to retrieve color buffer");
+        return GLFW_FALSE;
+    }
+
+    if (width)
+        *width = mesaWidth;
+    if (height)
+        *height = mesaHeight;
+    if (format)
+        *format = mesaFormat;
+    if (buffer)
+        *buffer = mesaBuffer;
+
+    return GLFW_TRUE;
+}
+
+GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
+                                     int* width, int* height,
+                                     int* bytesPerValue,
+                                     void** buffer)
+{
+    void* mesaBuffer;
+    GLint mesaWidth, mesaHeight, mesaBytes;
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
+                              &mesaWidth, &mesaHeight,
+                              &mesaBytes, &mesaBuffer))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "OSMesa: Failed to retrieve depth buffer");
+        return GLFW_FALSE;
+    }
+
+    if (width)
+        *width = mesaWidth;
+    if (height)
+        *height = mesaHeight;
+    if (bytesPerValue)
+        *bytesPerValue = mesaBytes;
+    if (buffer)
+        *buffer = mesaBuffer;
+
+    return GLFW_TRUE;
+}
+
+GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+        return NULL;
+    }
+
+    return window->context.osmesa.handle;
+}
+
diff --git a/glfw/src/posix_thread.c b/glfw/src/posix_thread.c
--- a/glfw/src/posix_thread.c
+++ b/glfw/src/posix_thread.c
@@ -1,105 +1,105 @@
-//========================================================================
-// GLFW 3.3 POSIX - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
-{
-    assert(tls->posix.allocated == GLFW_FALSE);
-
-    if (pthread_key_create(&tls->posix.key, NULL) != 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "POSIX: Failed to create context TLS");
-        return GLFW_FALSE;
-    }
-
-    tls->posix.allocated = GLFW_TRUE;
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyTls(_GLFWtls* tls)
-{
-    if (tls->posix.allocated)
-        pthread_key_delete(tls->posix.key);
-    memset(tls, 0, sizeof(_GLFWtls));
-}
-
-void* _glfwPlatformGetTls(_GLFWtls* tls)
-{
-    assert(tls->posix.allocated == GLFW_TRUE);
-    return pthread_getspecific(tls->posix.key);
-}
-
-void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
-{
-    assert(tls->posix.allocated == GLFW_TRUE);
-    pthread_setspecific(tls->posix.key, value);
-}
-
-GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->posix.allocated == GLFW_FALSE);
-
-    if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
-        return GLFW_FALSE;
-    }
-
-    return mutex->posix.allocated = GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
-{
-    if (mutex->posix.allocated)
-        pthread_mutex_destroy(&mutex->posix.handle);
-    memset(mutex, 0, sizeof(_GLFWmutex));
-}
-
-void _glfwPlatformLockMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->posix.allocated == GLFW_TRUE);
-    pthread_mutex_lock(&mutex->posix.handle);
-}
-
-void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->posix.allocated == GLFW_TRUE);
-    pthread_mutex_unlock(&mutex->posix.handle);
-}
-
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
+{
+    assert(tls->posix.allocated == GLFW_FALSE);
+
+    if (pthread_key_create(&tls->posix.key, NULL) != 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "POSIX: Failed to create context TLS");
+        return GLFW_FALSE;
+    }
+
+    tls->posix.allocated = GLFW_TRUE;
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyTls(_GLFWtls* tls)
+{
+    if (tls->posix.allocated)
+        pthread_key_delete(tls->posix.key);
+    memset(tls, 0, sizeof(_GLFWtls));
+}
+
+void* _glfwPlatformGetTls(_GLFWtls* tls)
+{
+    assert(tls->posix.allocated == GLFW_TRUE);
+    return pthread_getspecific(tls->posix.key);
+}
+
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
+{
+    assert(tls->posix.allocated == GLFW_TRUE);
+    pthread_setspecific(tls->posix.key, value);
+}
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->posix.allocated == GLFW_FALSE);
+
+    if (pthread_mutex_init(&mutex->posix.handle, NULL) != 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "POSIX: Failed to create mutex");
+        return GLFW_FALSE;
+    }
+
+    return mutex->posix.allocated = GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
+{
+    if (mutex->posix.allocated)
+        pthread_mutex_destroy(&mutex->posix.handle);
+    memset(mutex, 0, sizeof(_GLFWmutex));
+}
+
+void _glfwPlatformLockMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->posix.allocated == GLFW_TRUE);
+    pthread_mutex_lock(&mutex->posix.handle);
+}
+
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->posix.allocated == GLFW_TRUE);
+    pthread_mutex_unlock(&mutex->posix.handle);
+}
+
diff --git a/glfw/src/posix_time.c b/glfw/src/posix_time.c
--- a/glfw/src/posix_time.c
+++ b/glfw/src/posix_time.c
@@ -1,87 +1,87 @@
-//========================================================================
-// GLFW 3.3 POSIX - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <sys/time.h>
-#include <time.h>
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialise timer
-//
-void _glfwInitTimerPOSIX(void)
-{
-#if defined(CLOCK_MONOTONIC)
-    struct timespec ts;
-
-    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
-    {
-        _glfw.timer.posix.monotonic = GLFW_TRUE;
-        _glfw.timer.posix.frequency = 1000000000;
-    }
-    else
-#endif
-    {
-        _glfw.timer.posix.monotonic = GLFW_FALSE;
-        _glfw.timer.posix.frequency = 1000000;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-uint64_t _glfwPlatformGetTimerValue(void)
-{
-#if defined(CLOCK_MONOTONIC)
-    if (_glfw.timer.posix.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;
-    }
-}
-
-uint64_t _glfwPlatformGetTimerFrequency(void)
-{
-    return _glfw.timer.posix.frequency;
-}
-
+//========================================================================
+// GLFW 3.3 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <sys/time.h>
+#include <time.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerPOSIX(void)
+{
+#if defined(CLOCK_MONOTONIC)
+    struct timespec ts;
+
+    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+    {
+        _glfw.timer.posix.monotonic = GLFW_TRUE;
+        _glfw.timer.posix.frequency = 1000000000;
+    }
+    else
+#endif
+    {
+        _glfw.timer.posix.monotonic = GLFW_FALSE;
+        _glfw.timer.posix.frequency = 1000000;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+#if defined(CLOCK_MONOTONIC)
+    if (_glfw.timer.posix.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;
+    }
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+    return _glfw.timer.posix.frequency;
+}
+
diff --git a/glfw/src/vulkan.c b/glfw/src/vulkan.c
--- a/glfw/src/vulkan.c
+++ b/glfw/src/vulkan.c
@@ -1,328 +1,332 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2018 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-
-#define _GLFW_FIND_LOADER    1
-#define _GLFW_REQUIRE_LOADER 2
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWbool _glfwInitVulkan(int mode)
-{
-    VkResult err;
-    VkExtensionProperties* ep;
-    uint32_t i, count;
-
-    if (_glfw.vk.available)
-        return GLFW_TRUE;
-
-#if !defined(_GLFW_VULKAN_STATIC)
-#if defined(_GLFW_VULKAN_LIBRARY)
-    _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
-#elif defined(_GLFW_WIN32)
-    _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
-#elif defined(_GLFW_COCOA)
-    _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
-#else
-    _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
-#endif
-    if (!_glfw.vk.handle)
-    {
-        if (mode == _GLFW_REQUIRE_LOADER)
-            _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
-
-        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)
-    {
-        // NOTE: This happens on systems with a loader but without any Vulkan ICD
-        if (mode == _GLFW_REQUIRE_LOADER)
-        {
-            _glfwInputError(GLFW_API_UNAVAILABLE,
-                            "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_API_UNAVAILABLE,
-                        "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 defined(_GLFW_WIN32)
-        else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
-            _glfw.vk.KHR_win32_surface = GLFW_TRUE;
-#elif defined(_GLFW_COCOA)
-        else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
-            _glfw.vk.MVK_macos_surface = GLFW_TRUE;
-#elif defined(_GLFW_X11)
-        else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
-            _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
-        else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
-            _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
-#elif defined(_GLFW_WAYLAND)
-        else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
-            _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
-#endif
-    }
-
-    free(ep);
-
-    _glfw.vk.available = GLFW_TRUE;
-
-    _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
-
-    return GLFW_TRUE;
-}
-
-void _glfwTerminateVulkan(void)
-{
-#if !defined(_GLFW_VULKAN_STATIC)
-    if (_glfw.vk.handle)
-        _glfw_dlclose(_glfw.vk.handle);
-#endif
-}
-
-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(_GLFW_FIND_LOADER);
-}
-
-GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
-{
-    assert(count != NULL);
-
-    *count = 0;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
-        return NULL;
-
-    if (!_glfw.vk.extensions[0])
-        return NULL;
-
-    *count = 2;
-    return (const char**) _glfw.vk.extensions;
-}
-
-GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
-                                              const char* procname)
-{
-    GLFWvkproc proc;
-    assert(procname != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
-        return NULL;
-
-    proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
-#if defined(_GLFW_VULKAN_STATIC)
-    if (!proc)
-    {
-        if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
-            return (GLFWvkproc) vkGetInstanceProcAddr;
-    }
-#else
-    if (!proc)
-        proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
-#endif
-
-    return proc;
-}
-
-GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
-                                                     VkPhysicalDevice device,
-                                                     uint32_t queuefamily)
-{
-    assert(instance != VK_NULL_HANDLE);
-    assert(device != VK_NULL_HANDLE);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
-
-    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
-        return GLFW_FALSE;
-
-    if (!_glfw.vk.extensions[0])
-    {
-        _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(instance != VK_NULL_HANDLE);
-    assert(window != NULL);
-    assert(surface != NULL);
-
-    *surface = VK_NULL_HANDLE;
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
-
-    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
-        return VK_ERROR_INITIALIZATION_FAILED;
-
-    if (!_glfw.vk.extensions[0])
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "Vulkan: Window surface creation extensions not found");
-        return VK_ERROR_EXTENSION_NOT_PRESENT;
-    }
-
-    if (window->context.client != GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_INVALID_VALUE,
-                        "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
-        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
-    }
-
-    return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
-}
-
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2018 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define _GLFW_FIND_LOADER    1
+#define _GLFW_REQUIRE_LOADER 2
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitVulkan(int mode)
+{
+    VkResult err;
+    VkExtensionProperties* ep;
+    uint32_t i, count;
+
+    if (_glfw.vk.available)
+        return GLFW_TRUE;
+
+#if !defined(_GLFW_VULKAN_STATIC)
+#if defined(_GLFW_VULKAN_LIBRARY)
+    _glfw.vk.handle = _glfw_dlopen(_GLFW_VULKAN_LIBRARY);
+#elif defined(_GLFW_WIN32)
+    _glfw.vk.handle = _glfw_dlopen("vulkan-1.dll");
+#elif defined(_GLFW_COCOA)
+    _glfw.vk.handle = _glfw_dlopen("libvulkan.1.dylib");
+    if (!_glfw.vk.handle)
+        _glfw.vk.handle = _glfwLoadLocalVulkanLoaderNS();
+#else
+    _glfw.vk.handle = _glfw_dlopen("libvulkan.so.1");
+#endif
+    if (!_glfw.vk.handle)
+    {
+        if (mode == _GLFW_REQUIRE_LOADER)
+            _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: Loader not found");
+
+        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)
+    {
+        // NOTE: This happens on systems with a loader but without any Vulkan ICD
+        if (mode == _GLFW_REQUIRE_LOADER)
+        {
+            _glfwInputError(GLFW_API_UNAVAILABLE,
+                            "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_API_UNAVAILABLE,
+                        "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 defined(_GLFW_WIN32)
+        else if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
+            _glfw.vk.KHR_win32_surface = GLFW_TRUE;
+#elif defined(_GLFW_COCOA)
+        else if (strcmp(ep[i].extensionName, "VK_MVK_macos_surface") == 0)
+            _glfw.vk.MVK_macos_surface = GLFW_TRUE;
+        else if (strcmp(ep[i].extensionName, "VK_EXT_metal_surface") == 0)
+            _glfw.vk.EXT_metal_surface = GLFW_TRUE;
+#elif defined(_GLFW_X11)
+        else if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
+            _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
+        else if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
+            _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
+#elif defined(_GLFW_WAYLAND)
+        else if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
+            _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
+#endif
+    }
+
+    free(ep);
+
+    _glfw.vk.available = GLFW_TRUE;
+
+    _glfwPlatformGetRequiredInstanceExtensions(_glfw.vk.extensions);
+
+    return GLFW_TRUE;
+}
+
+void _glfwTerminateVulkan(void)
+{
+#if !defined(_GLFW_VULKAN_STATIC)
+    if (_glfw.vk.handle)
+        _glfw_dlclose(_glfw.vk.handle);
+#endif
+}
+
+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(_GLFW_FIND_LOADER);
+}
+
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
+{
+    assert(count != NULL);
+
+    *count = 0;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+        return NULL;
+
+    if (!_glfw.vk.extensions[0])
+        return NULL;
+
+    *count = 2;
+    return (const char**) _glfw.vk.extensions;
+}
+
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
+                                              const char* procname)
+{
+    GLFWvkproc proc;
+    assert(procname != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+        return NULL;
+
+    proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
+#if defined(_GLFW_VULKAN_STATIC)
+    if (!proc)
+    {
+        if (strcmp(procname, "vkGetInstanceProcAddr") == 0)
+            return (GLFWvkproc) vkGetInstanceProcAddr;
+    }
+#else
+    if (!proc)
+        proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
+#endif
+
+    return proc;
+}
+
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
+                                                     VkPhysicalDevice device,
+                                                     uint32_t queuefamily)
+{
+    assert(instance != VK_NULL_HANDLE);
+    assert(device != VK_NULL_HANDLE);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+        return GLFW_FALSE;
+
+    if (!_glfw.vk.extensions[0])
+    {
+        _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(instance != VK_NULL_HANDLE);
+    assert(window != NULL);
+    assert(surface != NULL);
+
+    *surface = VK_NULL_HANDLE;
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
+
+    if (!_glfwInitVulkan(_GLFW_REQUIRE_LOADER))
+        return VK_ERROR_INITIALIZATION_FAILED;
+
+    if (!_glfw.vk.extensions[0])
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "Vulkan: Window surface creation extensions not found");
+        return VK_ERROR_EXTENSION_NOT_PRESENT;
+    }
+
+    if (window->context.client != GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE,
+                        "Vulkan: Window surface creation requires the window to have the client API set to GLFW_NO_API");
+        return VK_ERROR_NATIVE_WINDOW_IN_USE_KHR;
+    }
+
+    return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
+}
+
diff --git a/glfw/src/wgl_context.c b/glfw/src/wgl_context.c
--- a/glfw/src/wgl_context.c
+++ b/glfw/src/wgl_context.c
@@ -1,796 +1,796 @@
-//========================================================================
-// GLFW 3.3 WGL - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <malloc.h>
-#include <assert.h>
-
-// Return the value corresponding to the specified attribute
-//
-static int findPixelFormatAttribValue(const int* attribs,
-                                      int attribCount,
-                                      const int* values,
-                                      int attrib)
-{
-    int i;
-
-    for (i = 0;  i < attribCount;  i++)
-    {
-        if (attribs[i] == attrib)
-            return values[i];
-    }
-
-    _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                         "WGL: Unknown pixel format attribute requested");
-    return 0;
-}
-
-#define addAttrib(a) \
-{ \
-    assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[attribCount++] = a; \
-}
-#define findAttribValue(a) \
-    findPixelFormatAttribValue(attribs, attribCount, values, a)
-
-// Return a list of available and usable framebuffer configs
-//
-static int choosePixelFormat(_GLFWwindow* window,
-                             const _GLFWctxconfig* ctxconfig,
-                             const _GLFWfbconfig* fbconfig)
-{
-    _GLFWfbconfig* usableConfigs;
-    const _GLFWfbconfig* closest;
-    int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
-    int attribs[40];
-    int values[sizeof(attribs) / sizeof(attribs[0])];
-
-    if (_glfw.wgl.ARB_pixel_format)
-    {
-        const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
-
-        if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
-                                          1, 0, 1, &attrib, &nativeCount))
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "WGL: Failed to retrieve pixel format attribute");
-            return 0;
-        }
-
-        addAttrib(WGL_SUPPORT_OPENGL_ARB);
-        addAttrib(WGL_DRAW_TO_WINDOW_ARB);
-        addAttrib(WGL_PIXEL_TYPE_ARB);
-        addAttrib(WGL_ACCELERATION_ARB);
-        addAttrib(WGL_RED_BITS_ARB);
-        addAttrib(WGL_RED_SHIFT_ARB);
-        addAttrib(WGL_GREEN_BITS_ARB);
-        addAttrib(WGL_GREEN_SHIFT_ARB);
-        addAttrib(WGL_BLUE_BITS_ARB);
-        addAttrib(WGL_BLUE_SHIFT_ARB);
-        addAttrib(WGL_ALPHA_BITS_ARB);
-        addAttrib(WGL_ALPHA_SHIFT_ARB);
-        addAttrib(WGL_DEPTH_BITS_ARB);
-        addAttrib(WGL_STENCIL_BITS_ARB);
-        addAttrib(WGL_ACCUM_BITS_ARB);
-        addAttrib(WGL_ACCUM_RED_BITS_ARB);
-        addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
-        addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
-        addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
-        addAttrib(WGL_AUX_BUFFERS_ARB);
-        addAttrib(WGL_STEREO_ARB);
-        addAttrib(WGL_DOUBLE_BUFFER_ARB);
-
-        if (_glfw.wgl.ARB_multisample)
-            addAttrib(WGL_SAMPLES_ARB);
-
-        if (ctxconfig->client == GLFW_OPENGL_API)
-        {
-            if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
-                addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
-        }
-        else
-        {
-            if (_glfw.wgl.EXT_colorspace)
-                addAttrib(WGL_COLORSPACE_EXT);
-        }
-    }
-    else
-    {
-        nativeCount = DescribePixelFormat(window->context.wgl.dc,
-                                          1,
-                                          sizeof(PIXELFORMATDESCRIPTOR),
-                                          NULL);
-    }
-
-    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
-
-    for (i = 0;  i < nativeCount;  i++)
-    {
-        _GLFWfbconfig* u = usableConfigs + usableCount;
-        pixelFormat = i + 1;
-
-        if (_glfw.wgl.ARB_pixel_format)
-        {
-            // Get pixel format attributes through "modern" extension
-
-            if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
-                                              pixelFormat, 0,
-                                              attribCount,
-                                              attribs, values))
-            {
-                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                    "WGL: Failed to retrieve pixel format attributes");
-
-                free(usableConfigs);
-                return 0;
-            }
-
-            if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
-                !findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
-            {
-                continue;
-            }
-
-            if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
-                continue;
-
-            if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
-                continue;
-
-            u->redBits = findAttribValue(WGL_RED_BITS_ARB);
-            u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
-            u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
-            u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
-
-            u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
-            u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
-
-            u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
-            u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
-            u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
-            u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
-
-            u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
-
-            if (findAttribValue(WGL_STEREO_ARB))
-                u->stereo = GLFW_TRUE;
-            if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))
-                u->doublebuffer = GLFW_TRUE;
-
-            if (_glfw.wgl.ARB_multisample)
-                u->samples = findAttribValue(WGL_SAMPLES_ARB);
-
-            if (ctxconfig->client == GLFW_OPENGL_API)
-            {
-                if (_glfw.wgl.ARB_framebuffer_sRGB ||
-                    _glfw.wgl.EXT_framebuffer_sRGB)
-                {
-                    if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
-                        u->sRGB = GLFW_TRUE;
-                }
-            }
-            else
-            {
-                if (_glfw.wgl.EXT_colorspace)
-                {
-                    if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
-                        u->sRGB = GLFW_TRUE;
-                }
-            }
-        }
-        else
-        {
-            // Get pixel format attributes through legacy PFDs
-
-            PIXELFORMATDESCRIPTOR pfd;
-
-            if (!DescribePixelFormat(window->context.wgl.dc,
-                                     pixelFormat,
-                                     sizeof(PIXELFORMATDESCRIPTOR),
-                                     &pfd))
-            {
-                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                    "WGL: Failed to describe pixel format");
-
-                free(usableConfigs);
-                return 0;
-            }
-
-            if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
-                !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
-            {
-                continue;
-            }
-
-            if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
-                (pfd.dwFlags & PFD_GENERIC_FORMAT))
-            {
-                continue;
-            }
-
-            if (pfd.iPixelType != PFD_TYPE_RGBA)
-                continue;
-
-            u->redBits = pfd.cRedBits;
-            u->greenBits = pfd.cGreenBits;
-            u->blueBits = pfd.cBlueBits;
-            u->alphaBits = pfd.cAlphaBits;
-
-            u->depthBits = pfd.cDepthBits;
-            u->stencilBits = pfd.cStencilBits;
-
-            u->accumRedBits = pfd.cAccumRedBits;
-            u->accumGreenBits = pfd.cAccumGreenBits;
-            u->accumBlueBits = pfd.cAccumBlueBits;
-            u->accumAlphaBits = pfd.cAccumAlphaBits;
-
-            u->auxBuffers = pfd.cAuxBuffers;
-
-            if (pfd.dwFlags & PFD_STEREO)
-                u->stereo = GLFW_TRUE;
-            if (pfd.dwFlags & PFD_DOUBLEBUFFER)
-                u->doublebuffer = GLFW_TRUE;
-        }
-
-        u->handle = pixelFormat;
-        usableCount++;
-    }
-
-    if (!usableCount)
-    {
-        _glfwInputError(GLFW_API_UNAVAILABLE,
-                        "WGL: The driver does not appear to support OpenGL");
-
-        free(usableConfigs);
-        return 0;
-    }
-
-    closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
-    if (!closest)
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "WGL: Failed to find a suitable pixel format");
-
-        free(usableConfigs);
-        return 0;
-    }
-
-    pixelFormat = (int) closest->handle;
-    free(usableConfigs);
-
-    return pixelFormat;
-}
-
-#undef addAttrib
-#undef findAttribValue
-
-static void makeContextCurrentWGL(_GLFWwindow* window)
-{
-    if (window)
-    {
-        if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
-            _glfwPlatformSetTls(&_glfw.contextSlot, window);
-        else
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "WGL: Failed to make context current");
-            _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
-        }
-    }
-    else
-    {
-        if (!wglMakeCurrent(NULL, NULL))
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "WGL: Failed to clear current context");
-        }
-
-        _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
-    }
-}
-
-static void swapBuffersWGL(_GLFWwindow* window)
-{
-    if (!window->monitor)
-    {
-        if (IsWindowsVistaOrGreater())
-        {
-            // DWM Composition is always enabled on Win8+
-            BOOL enabled = IsWindows8OrGreater();
-
-            // HACK: Use DwmFlush when desktop composition is enabled
-            if (enabled ||
-                (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
-            {
-                int count = abs(window->context.wgl.interval);
-                while (count--)
-                    DwmFlush();
-            }
-        }
-    }
-
-    SwapBuffers(window->context.wgl.dc);
-}
-
-static void swapIntervalWGL(int interval)
-{
-    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
-
-    window->context.wgl.interval = interval;
-
-    if (!window->monitor)
-    {
-        if (IsWindowsVistaOrGreater())
-        {
-            // DWM Composition is always enabled on Win8+
-            BOOL enabled = IsWindows8OrGreater();
-
-            // HACK: Disable WGL swap interval when desktop composition is enabled to
-            //       avoid interfering with DWM vsync
-            if (enabled ||
-                (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
-                interval = 0;
-        }
-    }
-
-    if (_glfw.wgl.EXT_swap_control)
-        wglSwapIntervalEXT(interval);
-}
-
-static int extensionSupportedWGL(const char* extension)
-{
-    const char* extensions = NULL;
-
-    if (_glfw.wgl.GetExtensionsStringARB)
-        extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
-    else if (_glfw.wgl.GetExtensionsStringEXT)
-        extensions = wglGetExtensionsStringEXT();
-
-    if (!extensions)
-        return GLFW_FALSE;
-
-    return _glfwStringInExtensionString(extension, extensions);
-}
-
-static GLFWglproc getProcAddressWGL(const char* procname)
-{
-    const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
-    if (proc)
-        return proc;
-
-    return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
-}
-
-static void destroyContextWGL(_GLFWwindow* window)
-{
-    if (window->context.wgl.handle)
-    {
-        wglDeleteContext(window->context.wgl.handle);
-        window->context.wgl.handle = NULL;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialize WGL
-//
-GLFWbool _glfwInitWGL(void)
-{
-    PIXELFORMATDESCRIPTOR pfd;
-    HGLRC prc, rc;
-    HDC pdc, dc;
-
-    if (_glfw.wgl.instance)
-        return GLFW_TRUE;
-
-    _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
-    if (!_glfw.wgl.instance)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to load opengl32.dll");
-        return GLFW_FALSE;
-    }
-
-    _glfw.wgl.CreateContext = (PFN_wglCreateContext)
-        GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
-    _glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
-        GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
-    _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
-        GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
-    _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
-        GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
-    _glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
-        GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
-    _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
-        GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
-    _glfw.wgl.ShareLists = (PFN_wglShareLists)
-        GetProcAddress(_glfw.wgl.instance, "wglShareLists");
-
-    // 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
-
-    dc = GetDC(_glfw.win32.helperWindowHandle);
-
-    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))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to set pixel format for dummy context");
-        return GLFW_FALSE;
-    }
-
-    rc = wglCreateContext(dc);
-    if (!rc)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to create dummy context");
-        return GLFW_FALSE;
-    }
-
-    pdc = wglGetCurrentDC();
-    prc = wglGetCurrentContext();
-
-    if (!wglMakeCurrent(dc, rc))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to make dummy context current");
-        wglMakeCurrent(pdc, prc);
-        wglDeleteContext(rc);
-        return GLFW_FALSE;
-    }
-
-    // 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.ARB_create_context_no_error =
-        extensionSupportedWGL("WGL_ARB_create_context_no_error");
-    _glfw.wgl.EXT_swap_control =
-        extensionSupportedWGL("WGL_EXT_swap_control");
-    _glfw.wgl.EXT_colorspace =
-        extensionSupportedWGL("WGL_EXT_colorspace");
-    _glfw.wgl.ARB_pixel_format =
-        extensionSupportedWGL("WGL_ARB_pixel_format");
-    _glfw.wgl.ARB_context_flush_control =
-        extensionSupportedWGL("WGL_ARB_context_flush_control");
-
-    wglMakeCurrent(pdc, prc);
-    wglDeleteContext(rc);
-    return GLFW_TRUE;
-}
-
-// Terminate WGL
-//
-void _glfwTerminateWGL(void)
-{
-    if (_glfw.wgl.instance)
-        FreeLibrary(_glfw.wgl.instance);
-}
-
-#define setAttrib(a, v) \
-{ \
-    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
-    attribs[index++] = a; \
-    attribs[index++] = v; \
-}
-
-// Create the OpenGL or OpenGL ES context
-//
-GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig)
-{
-    int attribs[40];
-    int pixelFormat;
-    PIXELFORMATDESCRIPTOR pfd;
-    HGLRC share = NULL;
-
-    if (ctxconfig->share)
-        share = ctxconfig->share->context.wgl.handle;
-
-    window->context.wgl.dc = GetDC(window->win32.handle);
-    if (!window->context.wgl.dc)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "WGL: Failed to retrieve DC for window");
-        return GLFW_FALSE;
-    }
-
-    pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
-    if (!pixelFormat)
-        return GLFW_FALSE;
-
-    if (!DescribePixelFormat(window->context.wgl.dc,
-                             pixelFormat, sizeof(pfd), &pfd))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to retrieve PFD for selected pixel format");
-        return GLFW_FALSE;
-    }
-
-    if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "WGL: Failed to set selected pixel format");
-        return GLFW_FALSE;
-    }
-
-    if (ctxconfig->client == GLFW_OPENGL_API)
-    {
-        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->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->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->robustness)
-        {
-            if (_glfw.wgl.ARB_create_context_robustness)
-            {
-                if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
-                {
-                    setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
-                              WGL_NO_RESET_NOTIFICATION_ARB);
-                }
-                else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
-                {
-                    setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
-                              WGL_LOSE_CONTEXT_ON_RESET_ARB);
-                }
-
-                flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
-            }
-        }
-
-        if (ctxconfig->release)
-        {
-            if (_glfw.wgl.ARB_context_flush_control)
-            {
-                if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
-                {
-                    setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
-                              WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
-                }
-                else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
-                {
-                    setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
-                              WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
-                }
-            }
-        }
-
-        if (ctxconfig->noerror)
-        {
-            if (_glfw.wgl.ARB_create_context_no_error)
-                setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
-        }
-
-        // 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)
-        {
-            setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
-            setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
-        }
-
-        if (flags)
-            setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
-
-        if (mask)
-            setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
-
-        setAttrib(0, 0);
-
-        window->context.wgl.handle =
-            wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
-        if (!window->context.wgl.handle)
-        {
-            const DWORD error = GetLastError();
-
-            if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
-            {
-                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);
-                }
-            }
-            else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
-            {
-                _glfwInputError(GLFW_VERSION_UNAVAILABLE,
-                                "WGL: Driver does not support the requested OpenGL profile");
-            }
-            else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
-            {
-                _glfwInputError(GLFW_INVALID_VALUE,
-                                "WGL: The share context is not compatible with the requested context");
-            }
-            else
-            {
-                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");
-                }
-            }
-
-            return GLFW_FALSE;
-        }
-    }
-    else
-    {
-        window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
-        if (!window->context.wgl.handle)
-        {
-            _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
-                                 "WGL: Failed to create OpenGL context");
-            return GLFW_FALSE;
-        }
-
-        if (share)
-        {
-            if (!wglShareLists(share, window->context.wgl.handle))
-            {
-                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                     "WGL: Failed to enable sharing with specified OpenGL context");
-                return GLFW_FALSE;
-            }
-        }
-    }
-
-    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 GLFW_TRUE;
-}
-
-#undef setAttrib
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (window->context.client == GLFW_NO_API)
-    {
-        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
-        return NULL;
-    }
-
-    return window->context.wgl.handle;
-}
-
+//========================================================================
+// GLFW 3.3 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <assert.h>
+
+// Return the value corresponding to the specified attribute
+//
+static int findPixelFormatAttribValue(const int* attribs,
+                                      int attribCount,
+                                      const int* values,
+                                      int attrib)
+{
+    int i;
+
+    for (i = 0;  i < attribCount;  i++)
+    {
+        if (attribs[i] == attrib)
+            return values[i];
+    }
+
+    _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                         "WGL: Unknown pixel format attribute requested");
+    return 0;
+}
+
+#define addAttrib(a) \
+{ \
+    assert((size_t) attribCount < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[attribCount++] = a; \
+}
+#define findAttribValue(a) \
+    findPixelFormatAttribValue(attribs, attribCount, values, a)
+
+// Return a list of available and usable framebuffer configs
+//
+static int choosePixelFormat(_GLFWwindow* window,
+                             const _GLFWctxconfig* ctxconfig,
+                             const _GLFWfbconfig* fbconfig)
+{
+    _GLFWfbconfig* usableConfigs;
+    const _GLFWfbconfig* closest;
+    int i, pixelFormat, nativeCount, usableCount = 0, attribCount = 0;
+    int attribs[40];
+    int values[sizeof(attribs) / sizeof(attribs[0])];
+
+    if (_glfw.wgl.ARB_pixel_format)
+    {
+        const int attrib = WGL_NUMBER_PIXEL_FORMATS_ARB;
+
+        if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
+                                          1, 0, 1, &attrib, &nativeCount))
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "WGL: Failed to retrieve pixel format attribute");
+            return 0;
+        }
+
+        addAttrib(WGL_SUPPORT_OPENGL_ARB);
+        addAttrib(WGL_DRAW_TO_WINDOW_ARB);
+        addAttrib(WGL_PIXEL_TYPE_ARB);
+        addAttrib(WGL_ACCELERATION_ARB);
+        addAttrib(WGL_RED_BITS_ARB);
+        addAttrib(WGL_RED_SHIFT_ARB);
+        addAttrib(WGL_GREEN_BITS_ARB);
+        addAttrib(WGL_GREEN_SHIFT_ARB);
+        addAttrib(WGL_BLUE_BITS_ARB);
+        addAttrib(WGL_BLUE_SHIFT_ARB);
+        addAttrib(WGL_ALPHA_BITS_ARB);
+        addAttrib(WGL_ALPHA_SHIFT_ARB);
+        addAttrib(WGL_DEPTH_BITS_ARB);
+        addAttrib(WGL_STENCIL_BITS_ARB);
+        addAttrib(WGL_ACCUM_BITS_ARB);
+        addAttrib(WGL_ACCUM_RED_BITS_ARB);
+        addAttrib(WGL_ACCUM_GREEN_BITS_ARB);
+        addAttrib(WGL_ACCUM_BLUE_BITS_ARB);
+        addAttrib(WGL_ACCUM_ALPHA_BITS_ARB);
+        addAttrib(WGL_AUX_BUFFERS_ARB);
+        addAttrib(WGL_STEREO_ARB);
+        addAttrib(WGL_DOUBLE_BUFFER_ARB);
+
+        if (_glfw.wgl.ARB_multisample)
+            addAttrib(WGL_SAMPLES_ARB);
+
+        if (ctxconfig->client == GLFW_OPENGL_API)
+        {
+            if (_glfw.wgl.ARB_framebuffer_sRGB || _glfw.wgl.EXT_framebuffer_sRGB)
+                addAttrib(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB);
+        }
+        else
+        {
+            if (_glfw.wgl.EXT_colorspace)
+                addAttrib(WGL_COLORSPACE_EXT);
+        }
+    }
+    else
+    {
+        nativeCount = DescribePixelFormat(window->context.wgl.dc,
+                                          1,
+                                          sizeof(PIXELFORMATDESCRIPTOR),
+                                          NULL);
+    }
+
+    usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+
+    for (i = 0;  i < nativeCount;  i++)
+    {
+        _GLFWfbconfig* u = usableConfigs + usableCount;
+        pixelFormat = i + 1;
+
+        if (_glfw.wgl.ARB_pixel_format)
+        {
+            // Get pixel format attributes through "modern" extension
+
+            if (!wglGetPixelFormatAttribivARB(window->context.wgl.dc,
+                                              pixelFormat, 0,
+                                              attribCount,
+                                              attribs, values))
+            {
+                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                    "WGL: Failed to retrieve pixel format attributes");
+
+                free(usableConfigs);
+                return 0;
+            }
+
+            if (!findAttribValue(WGL_SUPPORT_OPENGL_ARB) ||
+                !findAttribValue(WGL_DRAW_TO_WINDOW_ARB))
+            {
+                continue;
+            }
+
+            if (findAttribValue(WGL_PIXEL_TYPE_ARB) != WGL_TYPE_RGBA_ARB)
+                continue;
+
+            if (findAttribValue(WGL_ACCELERATION_ARB) == WGL_NO_ACCELERATION_ARB)
+                continue;
+
+            u->redBits = findAttribValue(WGL_RED_BITS_ARB);
+            u->greenBits = findAttribValue(WGL_GREEN_BITS_ARB);
+            u->blueBits = findAttribValue(WGL_BLUE_BITS_ARB);
+            u->alphaBits = findAttribValue(WGL_ALPHA_BITS_ARB);
+
+            u->depthBits = findAttribValue(WGL_DEPTH_BITS_ARB);
+            u->stencilBits = findAttribValue(WGL_STENCIL_BITS_ARB);
+
+            u->accumRedBits = findAttribValue(WGL_ACCUM_RED_BITS_ARB);
+            u->accumGreenBits = findAttribValue(WGL_ACCUM_GREEN_BITS_ARB);
+            u->accumBlueBits = findAttribValue(WGL_ACCUM_BLUE_BITS_ARB);
+            u->accumAlphaBits = findAttribValue(WGL_ACCUM_ALPHA_BITS_ARB);
+
+            u->auxBuffers = findAttribValue(WGL_AUX_BUFFERS_ARB);
+
+            if (findAttribValue(WGL_STEREO_ARB))
+                u->stereo = GLFW_TRUE;
+            if (findAttribValue(WGL_DOUBLE_BUFFER_ARB))
+                u->doublebuffer = GLFW_TRUE;
+
+            if (_glfw.wgl.ARB_multisample)
+                u->samples = findAttribValue(WGL_SAMPLES_ARB);
+
+            if (ctxconfig->client == GLFW_OPENGL_API)
+            {
+                if (_glfw.wgl.ARB_framebuffer_sRGB ||
+                    _glfw.wgl.EXT_framebuffer_sRGB)
+                {
+                    if (findAttribValue(WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
+                        u->sRGB = GLFW_TRUE;
+                }
+            }
+            else
+            {
+                if (_glfw.wgl.EXT_colorspace)
+                {
+                    if (findAttribValue(WGL_COLORSPACE_EXT) == WGL_COLORSPACE_SRGB_EXT)
+                        u->sRGB = GLFW_TRUE;
+                }
+            }
+        }
+        else
+        {
+            // Get pixel format attributes through legacy PFDs
+
+            PIXELFORMATDESCRIPTOR pfd;
+
+            if (!DescribePixelFormat(window->context.wgl.dc,
+                                     pixelFormat,
+                                     sizeof(PIXELFORMATDESCRIPTOR),
+                                     &pfd))
+            {
+                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                    "WGL: Failed to describe pixel format");
+
+                free(usableConfigs);
+                return 0;
+            }
+
+            if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
+                !(pfd.dwFlags & PFD_SUPPORT_OPENGL))
+            {
+                continue;
+            }
+
+            if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
+                (pfd.dwFlags & PFD_GENERIC_FORMAT))
+            {
+                continue;
+            }
+
+            if (pfd.iPixelType != PFD_TYPE_RGBA)
+                continue;
+
+            u->redBits = pfd.cRedBits;
+            u->greenBits = pfd.cGreenBits;
+            u->blueBits = pfd.cBlueBits;
+            u->alphaBits = pfd.cAlphaBits;
+
+            u->depthBits = pfd.cDepthBits;
+            u->stencilBits = pfd.cStencilBits;
+
+            u->accumRedBits = pfd.cAccumRedBits;
+            u->accumGreenBits = pfd.cAccumGreenBits;
+            u->accumBlueBits = pfd.cAccumBlueBits;
+            u->accumAlphaBits = pfd.cAccumAlphaBits;
+
+            u->auxBuffers = pfd.cAuxBuffers;
+
+            if (pfd.dwFlags & PFD_STEREO)
+                u->stereo = GLFW_TRUE;
+            if (pfd.dwFlags & PFD_DOUBLEBUFFER)
+                u->doublebuffer = GLFW_TRUE;
+        }
+
+        u->handle = pixelFormat;
+        usableCount++;
+    }
+
+    if (!usableCount)
+    {
+        _glfwInputError(GLFW_API_UNAVAILABLE,
+                        "WGL: The driver does not appear to support OpenGL");
+
+        free(usableConfigs);
+        return 0;
+    }
+
+    closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
+    if (!closest)
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "WGL: Failed to find a suitable pixel format");
+
+        free(usableConfigs);
+        return 0;
+    }
+
+    pixelFormat = (int) closest->handle;
+    free(usableConfigs);
+
+    return pixelFormat;
+}
+
+#undef addAttrib
+#undef findAttribValue
+
+static void makeContextCurrentWGL(_GLFWwindow* window)
+{
+    if (window)
+    {
+        if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
+            _glfwPlatformSetTls(&_glfw.contextSlot, window);
+        else
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "WGL: Failed to make context current");
+            _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
+        }
+    }
+    else
+    {
+        if (!wglMakeCurrent(NULL, NULL))
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "WGL: Failed to clear current context");
+        }
+
+        _glfwPlatformSetTls(&_glfw.contextSlot, NULL);
+    }
+}
+
+static void swapBuffersWGL(_GLFWwindow* window)
+{
+    if (!window->monitor)
+    {
+        if (IsWindowsVistaOrGreater())
+        {
+            // DWM Composition is always enabled on Win8+
+            BOOL enabled = IsWindows8OrGreater();
+
+            // HACK: Use DwmFlush when desktop composition is enabled
+            if (enabled ||
+                (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
+            {
+                int count = abs(window->context.wgl.interval);
+                while (count--)
+                    DwmFlush();
+            }
+        }
+    }
+
+    SwapBuffers(window->context.wgl.dc);
+}
+
+static void swapIntervalWGL(int interval)
+{
+    _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
+
+    window->context.wgl.interval = interval;
+
+    if (!window->monitor)
+    {
+        if (IsWindowsVistaOrGreater())
+        {
+            // DWM Composition is always enabled on Win8+
+            BOOL enabled = IsWindows8OrGreater();
+
+            // HACK: Disable WGL swap interval when desktop composition is enabled to
+            //       avoid interfering with DWM vsync
+            if (enabled ||
+                (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled))
+                interval = 0;
+        }
+    }
+
+    if (_glfw.wgl.EXT_swap_control)
+        wglSwapIntervalEXT(interval);
+}
+
+static int extensionSupportedWGL(const char* extension)
+{
+    const char* extensions = NULL;
+
+    if (_glfw.wgl.GetExtensionsStringARB)
+        extensions = wglGetExtensionsStringARB(wglGetCurrentDC());
+    else if (_glfw.wgl.GetExtensionsStringEXT)
+        extensions = wglGetExtensionsStringEXT();
+
+    if (!extensions)
+        return GLFW_FALSE;
+
+    return _glfwStringInExtensionString(extension, extensions);
+}
+
+static GLFWglproc getProcAddressWGL(const char* procname)
+{
+    const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
+    if (proc)
+        return proc;
+
+    return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
+}
+
+static void destroyContextWGL(_GLFWwindow* window)
+{
+    if (window->context.wgl.handle)
+    {
+        wglDeleteContext(window->context.wgl.handle);
+        window->context.wgl.handle = NULL;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize WGL
+//
+GLFWbool _glfwInitWGL(void)
+{
+    PIXELFORMATDESCRIPTOR pfd;
+    HGLRC prc, rc;
+    HDC pdc, dc;
+
+    if (_glfw.wgl.instance)
+        return GLFW_TRUE;
+
+    _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
+    if (!_glfw.wgl.instance)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to load opengl32.dll");
+        return GLFW_FALSE;
+    }
+
+    _glfw.wgl.CreateContext = (PFN_wglCreateContext)
+        GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
+    _glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
+        GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
+    _glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
+        GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
+    _glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
+        GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
+    _glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
+        GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
+    _glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
+        GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
+    _glfw.wgl.ShareLists = (PFN_wglShareLists)
+        GetProcAddress(_glfw.wgl.instance, "wglShareLists");
+
+    // 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
+
+    dc = GetDC(_glfw.win32.helperWindowHandle);
+
+    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))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to set pixel format for dummy context");
+        return GLFW_FALSE;
+    }
+
+    rc = wglCreateContext(dc);
+    if (!rc)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to create dummy context");
+        return GLFW_FALSE;
+    }
+
+    pdc = wglGetCurrentDC();
+    prc = wglGetCurrentContext();
+
+    if (!wglMakeCurrent(dc, rc))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to make dummy context current");
+        wglMakeCurrent(pdc, prc);
+        wglDeleteContext(rc);
+        return GLFW_FALSE;
+    }
+
+    // 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.ARB_create_context_no_error =
+        extensionSupportedWGL("WGL_ARB_create_context_no_error");
+    _glfw.wgl.EXT_swap_control =
+        extensionSupportedWGL("WGL_EXT_swap_control");
+    _glfw.wgl.EXT_colorspace =
+        extensionSupportedWGL("WGL_EXT_colorspace");
+    _glfw.wgl.ARB_pixel_format =
+        extensionSupportedWGL("WGL_ARB_pixel_format");
+    _glfw.wgl.ARB_context_flush_control =
+        extensionSupportedWGL("WGL_ARB_context_flush_control");
+
+    wglMakeCurrent(pdc, prc);
+    wglDeleteContext(rc);
+    return GLFW_TRUE;
+}
+
+// Terminate WGL
+//
+void _glfwTerminateWGL(void)
+{
+    if (_glfw.wgl.instance)
+        FreeLibrary(_glfw.wgl.instance);
+}
+
+#define setAttrib(a, v) \
+{ \
+    assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
+    attribs[index++] = a; \
+    attribs[index++] = v; \
+}
+
+// Create the OpenGL or OpenGL ES context
+//
+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig)
+{
+    int attribs[40];
+    int pixelFormat;
+    PIXELFORMATDESCRIPTOR pfd;
+    HGLRC share = NULL;
+
+    if (ctxconfig->share)
+        share = ctxconfig->share->context.wgl.handle;
+
+    window->context.wgl.dc = GetDC(window->win32.handle);
+    if (!window->context.wgl.dc)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "WGL: Failed to retrieve DC for window");
+        return GLFW_FALSE;
+    }
+
+    pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
+    if (!pixelFormat)
+        return GLFW_FALSE;
+
+    if (!DescribePixelFormat(window->context.wgl.dc,
+                             pixelFormat, sizeof(pfd), &pfd))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to retrieve PFD for selected pixel format");
+        return GLFW_FALSE;
+    }
+
+    if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "WGL: Failed to set selected pixel format");
+        return GLFW_FALSE;
+    }
+
+    if (ctxconfig->client == GLFW_OPENGL_API)
+    {
+        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->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->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->robustness)
+        {
+            if (_glfw.wgl.ARB_create_context_robustness)
+            {
+                if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+                {
+                    setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+                              WGL_NO_RESET_NOTIFICATION_ARB);
+                }
+                else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+                {
+                    setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+                              WGL_LOSE_CONTEXT_ON_RESET_ARB);
+                }
+
+                flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
+            }
+        }
+
+        if (ctxconfig->release)
+        {
+            if (_glfw.wgl.ARB_context_flush_control)
+            {
+                if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
+                {
+                    setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+                              WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+                }
+                else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+                {
+                    setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+                              WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+                }
+            }
+        }
+
+        if (ctxconfig->noerror)
+        {
+            if (_glfw.wgl.ARB_create_context_no_error)
+                setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, GLFW_TRUE);
+        }
+
+        // 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)
+        {
+            setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+            setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+        }
+
+        if (flags)
+            setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
+
+        if (mask)
+            setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
+
+        setAttrib(0, 0);
+
+        window->context.wgl.handle =
+            wglCreateContextAttribsARB(window->context.wgl.dc, share, attribs);
+        if (!window->context.wgl.handle)
+        {
+            const DWORD error = GetLastError();
+
+            if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
+            {
+                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);
+                }
+            }
+            else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
+            {
+                _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+                                "WGL: Driver does not support the requested OpenGL profile");
+            }
+            else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
+            {
+                _glfwInputError(GLFW_INVALID_VALUE,
+                                "WGL: The share context is not compatible with the requested context");
+            }
+            else
+            {
+                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");
+                }
+            }
+
+            return GLFW_FALSE;
+        }
+    }
+    else
+    {
+        window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
+        if (!window->context.wgl.handle)
+        {
+            _glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
+                                 "WGL: Failed to create OpenGL context");
+            return GLFW_FALSE;
+        }
+
+        if (share)
+        {
+            if (!wglShareLists(share, window->context.wgl.handle))
+            {
+                _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                     "WGL: Failed to enable sharing with specified OpenGL context");
+                return GLFW_FALSE;
+            }
+        }
+    }
+
+    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 GLFW_TRUE;
+}
+
+#undef setAttrib
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (window->context.client == GLFW_NO_API)
+    {
+        _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+        return NULL;
+    }
+
+    return window->context.wgl.handle;
+}
+
diff --git a/glfw/src/wgl_context.h b/glfw/src/wgl_context.h
--- a/glfw/src/wgl_context.h
+++ b/glfw/src/wgl_context.h
@@ -1,164 +1,164 @@
-//========================================================================
-// GLFW 3.3 WGL - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2018 Camilla Löwy <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.
-//
-//========================================================================
-
-#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 WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
-#define WGL_COLORSPACE_EXT 0x309d
-#define WGL_COLORSPACE_SRGB_EXT 0x3089
-
-#define ERROR_INVALID_VERSION_ARB 0x2095
-#define ERROR_INVALID_PROFILE_ARB 0x2096
-#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
-
-// WGL extension pointer typedefs
-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*);
-#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT
-#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB
-#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT
-#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB
-#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB
-
-// opengl32.dll function pointer typedefs
-typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
-typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
-typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
-typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
-typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
-typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
-typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
-#define wglCreateContext _glfw.wgl.CreateContext
-#define wglDeleteContext _glfw.wgl.DeleteContext
-#define wglGetProcAddress _glfw.wgl.GetProcAddress
-#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
-#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
-#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
-
-
-// WGL-specific per-context data
-//
-typedef struct _GLFWcontextWGL
-{
-    HDC       dc;
-    HGLRC     handle;
-    int       interval;
-
-} _GLFWcontextWGL;
-
-// WGL-specific global data
-//
-typedef struct _GLFWlibraryWGL
-{
-    HINSTANCE                           instance;
-    PFN_wglCreateContext                CreateContext;
-    PFN_wglDeleteContext                DeleteContext;
-    PFN_wglGetProcAddress               GetProcAddress;
-    PFN_wglGetCurrentDC                 GetCurrentDC;
-    PFN_wglGetCurrentContext            GetCurrentContext;
-    PFN_wglMakeCurrent                  MakeCurrent;
-    PFN_wglShareLists                   ShareLists;
-
-    PFNWGLSWAPINTERVALEXTPROC           SwapIntervalEXT;
-    PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
-    PFNWGLGETEXTENSIONSSTRINGEXTPROC    GetExtensionsStringEXT;
-    PFNWGLGETEXTENSIONSSTRINGARBPROC    GetExtensionsStringARB;
-    PFNWGLCREATECONTEXTATTRIBSARBPROC   CreateContextAttribsARB;
-    GLFWbool                            EXT_swap_control;
-    GLFWbool                            EXT_colorspace;
-    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_create_context_no_error;
-    GLFWbool                            ARB_context_flush_control;
-
-} _GLFWlibraryWGL;
-
-
-GLFWbool _glfwInitWGL(void);
-void _glfwTerminateWGL(void);
-GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
-                               const _GLFWctxconfig* ctxconfig,
-                               const _GLFWfbconfig* fbconfig);
-
+//========================================================================
+// GLFW 3.3 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2018 Camilla Löwy <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.
+//
+//========================================================================
+
+#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 WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
+#define WGL_COLORSPACE_EXT 0x309d
+#define WGL_COLORSPACE_SRGB_EXT 0x3089
+
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
+
+// WGL extension pointer typedefs
+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*);
+#define wglSwapIntervalEXT _glfw.wgl.SwapIntervalEXT
+#define wglGetPixelFormatAttribivARB _glfw.wgl.GetPixelFormatAttribivARB
+#define wglGetExtensionsStringEXT _glfw.wgl.GetExtensionsStringEXT
+#define wglGetExtensionsStringARB _glfw.wgl.GetExtensionsStringARB
+#define wglCreateContextAttribsARB _glfw.wgl.CreateContextAttribsARB
+
+// opengl32.dll function pointer typedefs
+typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
+typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
+typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
+typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
+typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
+typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
+typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
+#define wglCreateContext _glfw.wgl.CreateContext
+#define wglDeleteContext _glfw.wgl.DeleteContext
+#define wglGetProcAddress _glfw.wgl.GetProcAddress
+#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
+#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
+#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
+
+
+// WGL-specific per-context data
+//
+typedef struct _GLFWcontextWGL
+{
+    HDC       dc;
+    HGLRC     handle;
+    int       interval;
+
+} _GLFWcontextWGL;
+
+// WGL-specific global data
+//
+typedef struct _GLFWlibraryWGL
+{
+    HINSTANCE                           instance;
+    PFN_wglCreateContext                CreateContext;
+    PFN_wglDeleteContext                DeleteContext;
+    PFN_wglGetProcAddress               GetProcAddress;
+    PFN_wglGetCurrentDC                 GetCurrentDC;
+    PFN_wglGetCurrentContext            GetCurrentContext;
+    PFN_wglMakeCurrent                  MakeCurrent;
+    PFN_wglShareLists                   ShareLists;
+
+    PFNWGLSWAPINTERVALEXTPROC           SwapIntervalEXT;
+    PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
+    PFNWGLGETEXTENSIONSSTRINGEXTPROC    GetExtensionsStringEXT;
+    PFNWGLGETEXTENSIONSSTRINGARBPROC    GetExtensionsStringARB;
+    PFNWGLCREATECONTEXTATTRIBSARBPROC   CreateContextAttribsARB;
+    GLFWbool                            EXT_swap_control;
+    GLFWbool                            EXT_colorspace;
+    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_create_context_no_error;
+    GLFWbool                            ARB_context_flush_control;
+
+} _GLFWlibraryWGL;
+
+
+GLFWbool _glfwInitWGL(void);
+void _glfwTerminateWGL(void);
+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
+                               const _GLFWctxconfig* ctxconfig,
+                               const _GLFWfbconfig* fbconfig);
+
diff --git a/glfw/src/win32_init.c b/glfw/src/win32_init.c
--- a/glfw/src/win32_init.c
+++ b/glfw/src/win32_init.c
@@ -1,631 +1,631 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <malloc.h>
-
-static const GUID _glfw_GUID_DEVINTERFACE_HID =
-    {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
-
-#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
-
-#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
-
-// Executables (but not DLLs) 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;
-
-// Executables (but not DLLs) exporting this symbol with this value will be
-// automatically directed to the high-performance GPU on AMD PowerXpress systems
-// with up-to-date drivers
-//
-__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
-
-#endif // _GLFW_USE_HYBRID_HPG
-
-#if defined(_GLFW_BUILD_DLL)
-
-// GLFW DLL entry point
-//
-BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
-{
-    return TRUE;
-}
-
-#endif // _GLFW_BUILD_DLL
-
-// Load necessary libraries (DLLs)
-//
-static GLFWbool loadLibraries(void)
-{
-    _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
-    if (!_glfw.win32.winmm.instance)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to load winmm.dll");
-        return GLFW_FALSE;
-    }
-
-    _glfw.win32.winmm.GetTime = (PFN_timeGetTime)
-        GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
-
-    _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
-    if (!_glfw.win32.user32.instance)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to load user32.dll");
-        return GLFW_FALSE;
-    }
-
-    _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
-        GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
-    _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
-        GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
-    _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
-        GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
-    _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
-        GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
-    _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
-        GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
-    _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
-        GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
-
-    _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
-    if (_glfw.win32.dinput8.instance)
-    {
-        _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
-            GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
-    }
-
-    {
-        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.GetCapabilities = (PFN_XInputGetCapabilities)
-                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
-                _glfw.win32.xinput.GetState = (PFN_XInputGetState)
-                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
-
-                break;
-            }
-        }
-    }
-
-    _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
-    if (_glfw.win32.dwmapi.instance)
-    {
-        _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
-            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
-        _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
-            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
-        _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
-            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
-    }
-
-    _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
-    if (_glfw.win32.shcore.instance)
-    {
-        _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
-            GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
-        _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
-            GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
-    }
-
-    _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
-    if (_glfw.win32.ntdll.instance)
-    {
-        _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
-            GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
-    }
-
-    return GLFW_TRUE;
-}
-
-// Unload used libraries (DLLs)
-//
-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);
-
-    if (_glfw.win32.user32.instance)
-        FreeLibrary(_glfw.win32.user32.instance);
-
-    if (_glfw.win32.dwmapi.instance)
-        FreeLibrary(_glfw.win32.dwmapi.instance);
-
-    if (_glfw.win32.shcore.instance)
-        FreeLibrary(_glfw.win32.shcore.instance);
-
-    if (_glfw.win32.ntdll.instance)
-        FreeLibrary(_glfw.win32.ntdll.instance);
-}
-
-// Create key code translation tables
-//
-static void createKeyTables(void)
-{
-    int scancode;
-
-    memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
-    memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
-
-    _glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
-    _glfw.win32.keycodes[0x002] = GLFW_KEY_1;
-    _glfw.win32.keycodes[0x003] = GLFW_KEY_2;
-    _glfw.win32.keycodes[0x004] = GLFW_KEY_3;
-    _glfw.win32.keycodes[0x005] = GLFW_KEY_4;
-    _glfw.win32.keycodes[0x006] = GLFW_KEY_5;
-    _glfw.win32.keycodes[0x007] = GLFW_KEY_6;
-    _glfw.win32.keycodes[0x008] = GLFW_KEY_7;
-    _glfw.win32.keycodes[0x009] = GLFW_KEY_8;
-    _glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
-    _glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
-    _glfw.win32.keycodes[0x030] = GLFW_KEY_B;
-    _glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
-    _glfw.win32.keycodes[0x020] = GLFW_KEY_D;
-    _glfw.win32.keycodes[0x012] = GLFW_KEY_E;
-    _glfw.win32.keycodes[0x021] = GLFW_KEY_F;
-    _glfw.win32.keycodes[0x022] = GLFW_KEY_G;
-    _glfw.win32.keycodes[0x023] = GLFW_KEY_H;
-    _glfw.win32.keycodes[0x017] = GLFW_KEY_I;
-    _glfw.win32.keycodes[0x024] = GLFW_KEY_J;
-    _glfw.win32.keycodes[0x025] = GLFW_KEY_K;
-    _glfw.win32.keycodes[0x026] = GLFW_KEY_L;
-    _glfw.win32.keycodes[0x032] = GLFW_KEY_M;
-    _glfw.win32.keycodes[0x031] = GLFW_KEY_N;
-    _glfw.win32.keycodes[0x018] = GLFW_KEY_O;
-    _glfw.win32.keycodes[0x019] = GLFW_KEY_P;
-    _glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
-    _glfw.win32.keycodes[0x013] = GLFW_KEY_R;
-    _glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
-    _glfw.win32.keycodes[0x014] = GLFW_KEY_T;
-    _glfw.win32.keycodes[0x016] = GLFW_KEY_U;
-    _glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
-    _glfw.win32.keycodes[0x011] = GLFW_KEY_W;
-    _glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
-    _glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
-    _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
-
-    _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
-    _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
-    _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
-    _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
-    _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
-    _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
-    _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
-    _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
-    _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
-    _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
-    _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
-    _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
-
-    _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
-    _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
-    _glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
-    _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
-    _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
-    _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
-    _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
-    _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
-    _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
-    _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
-    _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
-    _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
-    _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
-    _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
-    _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
-    _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
-    _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
-    _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
-    _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
-    _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
-    _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
-    _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
-    _glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
-    _glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
-    _glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
-    _glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
-    _glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
-    _glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
-    _glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
-    _glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
-    _glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
-    _glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
-    _glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
-    _glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
-    _glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
-    _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
-    _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
-    _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
-    _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
-    _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
-    _glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
-    _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
-    _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
-    _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
-    _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
-    _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
-    _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
-    _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
-    _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
-    _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
-    _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
-    _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
-    _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
-    _glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
-
-    _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
-    _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
-    _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
-    _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
-    _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
-    _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
-    _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
-    _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
-    _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
-    _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
-    _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
-    _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
-    _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
-    _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
-    _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
-    _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
-    _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
-
-    for (scancode = 0;  scancode < 512;  scancode++)
-    {
-        if (_glfw.win32.keycodes[scancode] > 0)
-            _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
-    }
-}
-
-// Creates a dummy window for behind-the-scenes work
-//
-static GLFWbool createHelperWindow(void)
-{
-    MSG msg;
-
-    _glfw.win32.helperWindowHandle =
-        CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
-                        _GLFW_WNDCLASSNAME,
-                        L"GLFW message window",
-                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
-                        0, 0, 1, 1,
-                        NULL, NULL,
-                        GetModuleHandleW(NULL),
-                        NULL);
-
-    if (!_glfw.win32.helperWindowHandle)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to create helper window");
-        return GLFW_FALSE;
-    }
-
-    // HACK: The command to the first ShowWindow call is ignored if the parent
-    //       process passed along a STARTUPINFO, so clear that with a no-op call
-    ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
-
-    // 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;
-
-        _glfw.win32.deviceNotificationHandle =
-            RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
-                                        (DEV_BROADCAST_HDR*) &dbi,
-                                        DEVICE_NOTIFY_WINDOW_HANDLE);
-    }
-
-    while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
-    {
-        TranslateMessage(&msg);
-        DispatchMessageW(&msg);
-    }
-
-   return GLFW_TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Returns a wide string version of the specified UTF-8 string
-//
-WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
-{
-    WCHAR* target;
-    int count;
-
-    count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
-    if (!count)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to convert string from UTF-8");
-        return NULL;
-    }
-
-    target = calloc(count, sizeof(WCHAR));
-
-    if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to convert string from UTF-8");
-        free(target);
-        return NULL;
-    }
-
-    return target;
-}
-
-// Returns a UTF-8 string version of the specified wide string
-//
-char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
-{
-    char* target;
-    int size;
-
-    size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
-    if (!size)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to convert string to UTF-8");
-        return NULL;
-    }
-
-    target = calloc(size, 1);
-
-    if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to convert string to UTF-8");
-        free(target);
-        return NULL;
-    }
-
-    return target;
-}
-
-// Reports the specified error, appending information about the last Win32 error
-//
-void _glfwInputErrorWin32(int error, const char* description)
-{
-    WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
-    char message[_GLFW_MESSAGE_SIZE] = "";
-
-    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
-                       FORMAT_MESSAGE_IGNORE_INSERTS |
-                       FORMAT_MESSAGE_MAX_WIDTH_MASK,
-                   NULL,
-                   GetLastError() & 0xffff,
-                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                   buffer,
-                   sizeof(buffer) / sizeof(WCHAR),
-                   NULL);
-    WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
-
-    _glfwInputError(error, "%s: %s", description, message);
-}
-
-// Updates key names according to the current keyboard layout
-//
-void _glfwUpdateKeyNamesWin32(void)
-{
-    int key;
-    BYTE state[256] = {0};
-
-    memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
-
-    for (key = GLFW_KEY_SPACE;  key <= GLFW_KEY_LAST;  key++)
-    {
-        UINT vk;
-        int scancode, length;
-        WCHAR chars[16];
-
-        scancode = _glfw.win32.scancodes[key];
-        if (scancode == -1)
-            continue;
-
-        if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
-        {
-            const UINT vks[] = {
-                VK_NUMPAD0,  VK_NUMPAD1,  VK_NUMPAD2, VK_NUMPAD3,
-                VK_NUMPAD4,  VK_NUMPAD5,  VK_NUMPAD6, VK_NUMPAD7,
-                VK_NUMPAD8,  VK_NUMPAD9,  VK_DECIMAL, VK_DIVIDE,
-                VK_MULTIPLY, VK_SUBTRACT, VK_ADD
-            };
-
-            vk = vks[key - GLFW_KEY_KP_0];
-        }
-        else
-            vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
-
-        length = ToUnicode(vk, scancode, state,
-                           chars, sizeof(chars) / sizeof(WCHAR),
-                           0);
-
-        if (length == -1)
-        {
-            length = ToUnicode(vk, scancode, state,
-                               chars, sizeof(chars) / sizeof(WCHAR),
-                               0);
-        }
-
-        if (length < 1)
-            continue;
-
-        WideCharToMultiByte(CP_UTF8, 0, chars, 1,
-                            _glfw.win32.keynames[key],
-                            sizeof(_glfw.win32.keynames[key]),
-                            NULL, NULL);
-    }
-}
-
-// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
-//
-BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
-{
-    OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
-    DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
-    ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
-    cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
-    cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
-    // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
-    //       latter lies unless the user knew to embed a non-default manifest
-    //       announcing support for Windows 10 via supportedOS GUID
-    return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
-}
-
-// Checks whether we are on at least the specified build of Windows 10
-//
-BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
-{
-    OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
-    DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
-    ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
-    cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
-    cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
-    // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
-    //       latter lies unless the user knew to embed a non-default manifest
-    //       announcing support for Windows 10 via supportedOS GUID
-    return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void)
-{
-    // 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)
-    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
-                          &_glfw.win32.foregroundLockTimeout, 0);
-    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
-                          SPIF_SENDCHANGE);
-
-    if (!loadLibraries())
-        return GLFW_FALSE;
-
-    createKeyTables();
-    _glfwUpdateKeyNamesWin32();
-
-    if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
-        SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
-    else if (IsWindows8Point1OrGreater())
-        SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
-    else if (IsWindowsVistaOrGreater())
-        SetProcessDPIAware();
-
-    if (!_glfwRegisterWindowClassWin32())
-        return GLFW_FALSE;
-
-    if (!createHelperWindow())
-        return GLFW_FALSE;
-
-    _glfwInitTimerWin32();
-    _glfwInitJoysticksWin32();
-
-    _glfwPollMonitorsWin32();
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformTerminate(void)
-{
-    if (_glfw.win32.deviceNotificationHandle)
-        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
-
-    if (_glfw.win32.helperWindowHandle)
-        DestroyWindow(_glfw.win32.helperWindowHandle);
-
-    _glfwUnregisterWindowClassWin32();
-
-    // Restore previous foreground lock timeout system setting
-    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
-                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
-                          SPIF_SENDCHANGE);
-
-    free(_glfw.win32.clipboardString);
-    free(_glfw.win32.rawInput);
-
-    _glfwTerminateWGL();
-    _glfwTerminateEGL();
-
-    _glfwTerminateJoysticksWin32();
-
-    freeLibraries();
-}
-
-const char* _glfwPlatformGetVersionString(void)
-{
-    return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa"
-#if defined(__MINGW32__)
-        " MinGW"
-#elif defined(_MSC_VER)
-        " VisualC"
-#endif
-#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
-        " hybrid-GPU"
-#endif
-#if defined(_GLFW_BUILD_DLL)
-        " DLL"
-#endif
-        ;
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+
+static const GUID _glfw_GUID_DEVINTERFACE_HID =
+    {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
+
+#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
+
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+
+// Executables (but not DLLs) 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;
+
+// Executables (but not DLLs) exporting this symbol with this value will be
+// automatically directed to the high-performance GPU on AMD PowerXpress systems
+// with up-to-date drivers
+//
+__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
+
+#endif // _GLFW_USE_HYBRID_HPG
+
+#if defined(_GLFW_BUILD_DLL)
+
+// GLFW DLL entry point
+//
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+    return TRUE;
+}
+
+#endif // _GLFW_BUILD_DLL
+
+// Load necessary libraries (DLLs)
+//
+static GLFWbool loadLibraries(void)
+{
+    _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll");
+    if (!_glfw.win32.winmm.instance)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to load winmm.dll");
+        return GLFW_FALSE;
+    }
+
+    _glfw.win32.winmm.GetTime = (PFN_timeGetTime)
+        GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
+
+    _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
+    if (!_glfw.win32.user32.instance)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to load user32.dll");
+        return GLFW_FALSE;
+    }
+
+    _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
+        GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
+    _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
+        GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
+    _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
+        GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
+    _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
+        GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
+    _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
+        GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow");
+    _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
+        GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
+
+    _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
+    if (_glfw.win32.dinput8.instance)
+    {
+        _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
+            GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create");
+    }
+
+    {
+        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.GetCapabilities = (PFN_XInputGetCapabilities)
+                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
+                _glfw.win32.xinput.GetState = (PFN_XInputGetState)
+                    GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
+
+                break;
+            }
+        }
+    }
+
+    _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
+    if (_glfw.win32.dwmapi.instance)
+    {
+        _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
+            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
+        _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
+            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
+        _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
+            GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
+    }
+
+    _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
+    if (_glfw.win32.shcore.instance)
+    {
+        _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
+            GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
+        _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
+            GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor");
+    }
+
+    _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll");
+    if (_glfw.win32.ntdll.instance)
+    {
+        _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
+            GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
+    }
+
+    return GLFW_TRUE;
+}
+
+// Unload used libraries (DLLs)
+//
+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);
+
+    if (_glfw.win32.user32.instance)
+        FreeLibrary(_glfw.win32.user32.instance);
+
+    if (_glfw.win32.dwmapi.instance)
+        FreeLibrary(_glfw.win32.dwmapi.instance);
+
+    if (_glfw.win32.shcore.instance)
+        FreeLibrary(_glfw.win32.shcore.instance);
+
+    if (_glfw.win32.ntdll.instance)
+        FreeLibrary(_glfw.win32.ntdll.instance);
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+    int scancode;
+
+    memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
+    memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
+
+    _glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
+    _glfw.win32.keycodes[0x002] = GLFW_KEY_1;
+    _glfw.win32.keycodes[0x003] = GLFW_KEY_2;
+    _glfw.win32.keycodes[0x004] = GLFW_KEY_3;
+    _glfw.win32.keycodes[0x005] = GLFW_KEY_4;
+    _glfw.win32.keycodes[0x006] = GLFW_KEY_5;
+    _glfw.win32.keycodes[0x007] = GLFW_KEY_6;
+    _glfw.win32.keycodes[0x008] = GLFW_KEY_7;
+    _glfw.win32.keycodes[0x009] = GLFW_KEY_8;
+    _glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
+    _glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
+    _glfw.win32.keycodes[0x030] = GLFW_KEY_B;
+    _glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
+    _glfw.win32.keycodes[0x020] = GLFW_KEY_D;
+    _glfw.win32.keycodes[0x012] = GLFW_KEY_E;
+    _glfw.win32.keycodes[0x021] = GLFW_KEY_F;
+    _glfw.win32.keycodes[0x022] = GLFW_KEY_G;
+    _glfw.win32.keycodes[0x023] = GLFW_KEY_H;
+    _glfw.win32.keycodes[0x017] = GLFW_KEY_I;
+    _glfw.win32.keycodes[0x024] = GLFW_KEY_J;
+    _glfw.win32.keycodes[0x025] = GLFW_KEY_K;
+    _glfw.win32.keycodes[0x026] = GLFW_KEY_L;
+    _glfw.win32.keycodes[0x032] = GLFW_KEY_M;
+    _glfw.win32.keycodes[0x031] = GLFW_KEY_N;
+    _glfw.win32.keycodes[0x018] = GLFW_KEY_O;
+    _glfw.win32.keycodes[0x019] = GLFW_KEY_P;
+    _glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
+    _glfw.win32.keycodes[0x013] = GLFW_KEY_R;
+    _glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
+    _glfw.win32.keycodes[0x014] = GLFW_KEY_T;
+    _glfw.win32.keycodes[0x016] = GLFW_KEY_U;
+    _glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
+    _glfw.win32.keycodes[0x011] = GLFW_KEY_W;
+    _glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
+    _glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
+    _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
+
+    _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
+    _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
+    _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
+    _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
+    _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
+    _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
+    _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
+    _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
+    _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
+    _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
+    _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
+    _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
+
+    _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
+    _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
+    _glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
+    _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
+    _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
+    _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
+    _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
+    _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
+    _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
+    _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
+    _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE;
+    _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE;
+    _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE;
+    _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB;
+    _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK;
+    _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK;
+    _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK;
+    _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1;
+    _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2;
+    _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3;
+    _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4;
+    _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5;
+    _glfw.win32.keycodes[0x040] = GLFW_KEY_F6;
+    _glfw.win32.keycodes[0x041] = GLFW_KEY_F7;
+    _glfw.win32.keycodes[0x042] = GLFW_KEY_F8;
+    _glfw.win32.keycodes[0x043] = GLFW_KEY_F9;
+    _glfw.win32.keycodes[0x044] = GLFW_KEY_F10;
+    _glfw.win32.keycodes[0x057] = GLFW_KEY_F11;
+    _glfw.win32.keycodes[0x058] = GLFW_KEY_F12;
+    _glfw.win32.keycodes[0x064] = GLFW_KEY_F13;
+    _glfw.win32.keycodes[0x065] = GLFW_KEY_F14;
+    _glfw.win32.keycodes[0x066] = GLFW_KEY_F15;
+    _glfw.win32.keycodes[0x067] = GLFW_KEY_F16;
+    _glfw.win32.keycodes[0x068] = GLFW_KEY_F17;
+    _glfw.win32.keycodes[0x069] = GLFW_KEY_F18;
+    _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19;
+    _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20;
+    _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21;
+    _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22;
+    _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23;
+    _glfw.win32.keycodes[0x076] = GLFW_KEY_F24;
+    _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT;
+    _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL;
+    _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT;
+    _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER;
+    _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN;
+    _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT;
+    _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL;
+    _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT;
+    _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER;
+    _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN;
+    _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT;
+    _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT;
+    _glfw.win32.keycodes[0x148] = GLFW_KEY_UP;
+
+    _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0;
+    _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1;
+    _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2;
+    _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3;
+    _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4;
+    _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5;
+    _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6;
+    _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7;
+    _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8;
+    _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9;
+    _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD;
+    _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL;
+    _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE;
+    _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER;
+    _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL;
+    _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY;
+    _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT;
+
+    for (scancode = 0;  scancode < 512;  scancode++)
+    {
+        if (_glfw.win32.keycodes[scancode] > 0)
+            _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode;
+    }
+}
+
+// Creates a dummy window for behind-the-scenes work
+//
+static GLFWbool createHelperWindow(void)
+{
+    MSG msg;
+
+    _glfw.win32.helperWindowHandle =
+        CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
+                        _GLFW_WNDCLASSNAME,
+                        L"GLFW message window",
+                        WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+                        0, 0, 1, 1,
+                        NULL, NULL,
+                        GetModuleHandleW(NULL),
+                        NULL);
+
+    if (!_glfw.win32.helperWindowHandle)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to create helper window");
+        return GLFW_FALSE;
+    }
+
+    // HACK: The command to the first ShowWindow call is ignored if the parent
+    //       process passed along a STARTUPINFO, so clear that with a no-op call
+    ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
+
+    // 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;
+
+        _glfw.win32.deviceNotificationHandle =
+            RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
+                                        (DEV_BROADCAST_HDR*) &dbi,
+                                        DEVICE_NOTIFY_WINDOW_HANDLE);
+    }
+
+    while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+    }
+
+   return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns a wide string version of the specified UTF-8 string
+//
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
+{
+    WCHAR* target;
+    int count;
+
+    count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
+    if (!count)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to convert string from UTF-8");
+        return NULL;
+    }
+
+    target = calloc(count, sizeof(WCHAR));
+
+    if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to convert string from UTF-8");
+        free(target);
+        return NULL;
+    }
+
+    return target;
+}
+
+// Returns a UTF-8 string version of the specified wide string
+//
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
+{
+    char* target;
+    int size;
+
+    size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+    if (!size)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to convert string to UTF-8");
+        return NULL;
+    }
+
+    target = calloc(size, 1);
+
+    if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to convert string to UTF-8");
+        free(target);
+        return NULL;
+    }
+
+    return target;
+}
+
+// Reports the specified error, appending information about the last Win32 error
+//
+void _glfwInputErrorWin32(int error, const char* description)
+{
+    WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
+    char message[_GLFW_MESSAGE_SIZE] = "";
+
+    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+                       FORMAT_MESSAGE_IGNORE_INSERTS |
+                       FORMAT_MESSAGE_MAX_WIDTH_MASK,
+                   NULL,
+                   GetLastError() & 0xffff,
+                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                   buffer,
+                   sizeof(buffer) / sizeof(WCHAR),
+                   NULL);
+    WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
+
+    _glfwInputError(error, "%s: %s", description, message);
+}
+
+// Updates key names according to the current keyboard layout
+//
+void _glfwUpdateKeyNamesWin32(void)
+{
+    int key;
+    BYTE state[256] = {0};
+
+    memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
+
+    for (key = GLFW_KEY_SPACE;  key <= GLFW_KEY_LAST;  key++)
+    {
+        UINT vk;
+        int scancode, length;
+        WCHAR chars[16];
+
+        scancode = _glfw.win32.scancodes[key];
+        if (scancode == -1)
+            continue;
+
+        if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
+        {
+            const UINT vks[] = {
+                VK_NUMPAD0,  VK_NUMPAD1,  VK_NUMPAD2, VK_NUMPAD3,
+                VK_NUMPAD4,  VK_NUMPAD5,  VK_NUMPAD6, VK_NUMPAD7,
+                VK_NUMPAD8,  VK_NUMPAD9,  VK_DECIMAL, VK_DIVIDE,
+                VK_MULTIPLY, VK_SUBTRACT, VK_ADD
+            };
+
+            vk = vks[key - GLFW_KEY_KP_0];
+        }
+        else
+            vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK);
+
+        length = ToUnicode(vk, scancode, state,
+                           chars, sizeof(chars) / sizeof(WCHAR),
+                           0);
+
+        if (length == -1)
+        {
+            length = ToUnicode(vk, scancode, state,
+                               chars, sizeof(chars) / sizeof(WCHAR),
+                               0);
+        }
+
+        if (length < 1)
+            continue;
+
+        WideCharToMultiByte(CP_UTF8, 0, chars, 1,
+                            _glfw.win32.keynames[key],
+                            sizeof(_glfw.win32.keynames[key]),
+                            NULL, NULL);
+    }
+}
+
+// Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h
+//
+BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
+{
+    OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
+    DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
+    ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+    cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+    cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+    // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+    //       latter lies unless the user knew to embed a non-default manifest
+    //       announcing support for Windows 10 via supportedOS GUID
+    return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+// Checks whether we are on at least the specified build of Windows 10
+//
+BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
+{
+    OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
+    DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
+    ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+    cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+    cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
+    // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+    //       latter lies unless the user knew to embed a non-default manifest
+    //       announcing support for Windows 10 via supportedOS GUID
+    return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+    // 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)
+    SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
+                          &_glfw.win32.foregroundLockTimeout, 0);
+    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
+                          SPIF_SENDCHANGE);
+
+    if (!loadLibraries())
+        return GLFW_FALSE;
+
+    createKeyTables();
+    _glfwUpdateKeyNamesWin32();
+
+    if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+        SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+    else if (IsWindows8Point1OrGreater())
+        SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+    else if (IsWindowsVistaOrGreater())
+        SetProcessDPIAware();
+
+    if (!_glfwRegisterWindowClassWin32())
+        return GLFW_FALSE;
+
+    if (!createHelperWindow())
+        return GLFW_FALSE;
+
+    _glfwInitTimerWin32();
+    _glfwInitJoysticksWin32();
+
+    _glfwPollMonitorsWin32();
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+    if (_glfw.win32.deviceNotificationHandle)
+        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
+
+    if (_glfw.win32.helperWindowHandle)
+        DestroyWindow(_glfw.win32.helperWindowHandle);
+
+    _glfwUnregisterWindowClassWin32();
+
+    // Restore previous foreground lock timeout system setting
+    SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0,
+                          UIntToPtr(_glfw.win32.foregroundLockTimeout),
+                          SPIF_SENDCHANGE);
+
+    free(_glfw.win32.clipboardString);
+    free(_glfw.win32.rawInput);
+
+    _glfwTerminateWGL();
+    _glfwTerminateEGL();
+
+    _glfwTerminateJoysticksWin32();
+
+    freeLibraries();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+    return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa"
+#if defined(__MINGW32__)
+        " MinGW"
+#elif defined(_MSC_VER)
+        " VisualC"
+#endif
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+        " hybrid-GPU"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+        " DLL"
+#endif
+        ;
+}
+
diff --git a/glfw/src/win32_joystick.c b/glfw/src/win32_joystick.c
--- a/glfw/src/win32_joystick.c
+++ b/glfw/src/win32_joystick.c
@@ -1,755 +1,755 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <stdio.h>
-#include <math.h>
-
-#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 local copies of the necessary GUIDs
-//
-static const GUID _glfw_IID_IDirectInput8W =
-    {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
-static const GUID _glfw_GUID_XAxis =
-    {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_YAxis =
-    {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_ZAxis =
-    {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_RxAxis =
-    {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_RyAxis =
-    {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_RzAxis =
-    {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_Slider =
-    {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-static const GUID _glfw_GUID_POV =
-    {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
-
-#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
-#define GUID_XAxis _glfw_GUID_XAxis
-#define GUID_YAxis _glfw_GUID_YAxis
-#define GUID_ZAxis _glfw_GUID_ZAxis
-#define GUID_RxAxis _glfw_GUID_RxAxis
-#define GUID_RyAxis _glfw_GUID_RyAxis
-#define GUID_RzAxis _glfw_GUID_RzAxis
-#define GUID_Slider _glfw_GUID_Slider
-#define GUID_POV _glfw_GUID_POV
-
-// 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 Controller";
-            else
-                return "Xbox 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(_GLFWjoystick* js)
-{
-    if (js->win32.device)
-    {
-        IDirectInputDevice8_Unacquire(js->win32.device);
-        IDirectInputDevice8_Release(js->win32.device);
-    }
-
-    free(js->win32.objects);
-
-    _glfwFreeJoystick(js);
-    _glfwInputJoystick(js, GLFW_DISCONNECTED);
-}
-
-// DirectInput device object enumeration callback
-// Insights gleaned from SDL
-//
-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 jid = 0;
-    DIDEVCAPS dc;
-    DIPROPDWORD dipd;
-    IDirectInputDevice8* device;
-    _GLFWobjenumWin32 data;
-    _GLFWjoystick* js;
-    char guid[33];
-    char name[256];
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
-        {
-            if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
-                return DIENUM_CONTINUE;
-        }
-    }
-
-    if (supportsXInput(&di->guidProduct))
-        return DIENUM_CONTINUE;
-
-    if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
-                                          &di->guidInstance,
-                                          &device,
-                                          NULL)))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
-        return DIENUM_CONTINUE;
-    }
-
-    if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Win32: 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,
-                        "Win32: 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,
-                        "Win32: 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 + (size_t) dc.dwButtons + dc.dwPOVs,
-                          sizeof(_GLFWjoyobjectWin32));
-
-    if (FAILED(IDirectInputDevice8_EnumObjects(device,
-                                               deviceObjectCallback,
-                                               &data,
-                                               DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Win32: Failed to enumerate device objects");
-
-        IDirectInputDevice8_Release(device);
-        free(data.objects);
-        return DIENUM_CONTINUE;
-    }
-
-    qsort(data.objects, data.objectCount,
-          sizeof(_GLFWjoyobjectWin32),
-          compareJoystickObjects);
-
-    if (!WideCharToMultiByte(CP_UTF8, 0,
-                             di->tszInstanceName, -1,
-                             name, sizeof(name),
-                             NULL, NULL))
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Win32: Failed to convert joystick name to UTF-8");
-
-        IDirectInputDevice8_Release(device);
-        free(data.objects);
-        return DIENUM_STOP;
-    }
-
-    // Generate a joystick GUID that matches the SDL 2.0.5+ one
-    if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
-    {
-        sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
-                (uint8_t) di->guidProduct.Data1,
-                (uint8_t) (di->guidProduct.Data1 >> 8),
-                (uint8_t) (di->guidProduct.Data1 >> 16),
-                (uint8_t) (di->guidProduct.Data1 >> 24));
-    }
-    else
-    {
-        sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
-                name[0], name[1], name[2], name[3],
-                name[4], name[5], name[6], name[7],
-                name[8], name[9], name[10]);
-    }
-
-    js = _glfwAllocJoystick(name, guid,
-                            data.axisCount + data.sliderCount,
-                            data.buttonCount,
-                            data.povCount);
-    if (!js)
-    {
-        IDirectInputDevice8_Release(device);
-        free(data.objects);
-        return DIENUM_STOP;
-    }
-
-    js->win32.device = device;
-    js->win32.guid = di->guidInstance;
-    js->win32.objects = data.objects;
-    js->win32.objectCount = data.objectCount;
-
-    _glfwInputJoystick(js, GLFW_CONNECTED);
-    return DIENUM_CONTINUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialize joystick interface
-//
-void _glfwInitJoysticksWin32(void)
-{
-    if (_glfw.win32.dinput8.instance)
-    {
-        if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
-                                      DIRECTINPUT_VERSION,
-                                      &IID_IDirectInput8W,
-                                      (void**) &_glfw.win32.dinput8.api,
-                                      NULL)))
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Win32: Failed to create interface");
-        }
-    }
-
-    _glfwDetectJoystickConnectionWin32();
-}
-
-// Close all opened joystick handles
-//
-void _glfwTerminateJoysticksWin32(void)
-{
-    int jid;
-
-    for (jid = GLFW_JOYSTICK_1;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-        closeJoystick(_glfw.joysticks + jid);
-
-    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 index;
-
-        for (index = 0;  index < XUSER_MAX_COUNT;  index++)
-        {
-            int jid;
-            char guid[33];
-            XINPUT_CAPABILITIES xic;
-            _GLFWjoystick* js;
-
-            for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-            {
-                if (_glfw.joysticks[jid].present &&
-                    _glfw.joysticks[jid].win32.device == NULL &&
-                    _glfw.joysticks[jid].win32.index == index)
-                {
-                    break;
-                }
-            }
-
-            if (jid <= GLFW_JOYSTICK_LAST)
-                continue;
-
-            if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
-                continue;
-
-            // Generate a joystick GUID that matches the SDL 2.0.5+ one
-            sprintf(guid, "78696e707574%02x000000000000000000",
-                    xic.SubType & 0xff);
-
-            js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
-            if (!js)
-                continue;
-
-            js->win32.index = index;
-
-            _glfwInputJoystick(js, GLFW_CONNECTED);
-        }
-    }
-
-    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 jid;
-
-    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
-    {
-        _GLFWjoystick* js = _glfw.joysticks + jid;
-        if (js->present)
-            _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
-{
-    if (js->win32.device)
-    {
-        int i, ai = 0, bi = 0, pi = 0;
-        HRESULT result;
-        DIJOYSTATE state;
-
-        IDirectInputDevice8_Poll(js->win32.device);
-        result = IDirectInputDevice8_GetDeviceState(js->win32.device,
-                                                    sizeof(state),
-                                                    &state);
-        if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
-        {
-            IDirectInputDevice8_Acquire(js->win32.device);
-            IDirectInputDevice8_Poll(js->win32.device);
-            result = IDirectInputDevice8_GetDeviceState(js->win32.device,
-                                                        sizeof(state),
-                                                        &state);
-        }
-
-        if (FAILED(result))
-        {
-            closeJoystick(js);
-            return GLFW_FALSE;
-        }
-
-        if (mode == _GLFW_POLL_PRESENCE)
-            return GLFW_TRUE;
-
-        for (i = 0;  i < js->win32.objectCount;  i++)
-        {
-            const void* data = (char*) &state + js->win32.objects[i].offset;
-
-            switch (js->win32.objects[i].type)
-            {
-                case _GLFW_TYPE_AXIS:
-                case _GLFW_TYPE_SLIDER:
-                {
-                    const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
-                    _glfwInputJoystickAxis(js, ai, value);
-                    ai++;
-                    break;
-                }
-
-                case _GLFW_TYPE_BUTTON:
-                {
-                    const char value = (*((BYTE*) data) & 0x80) != 0;
-                    _glfwInputJoystickButton(js, bi, value);
-                    bi++;
-                    break;
-                }
-
-                case _GLFW_TYPE_POV:
-                {
-                    const int states[9] =
-                    {
-                        GLFW_HAT_UP,
-                        GLFW_HAT_RIGHT_UP,
-                        GLFW_HAT_RIGHT,
-                        GLFW_HAT_RIGHT_DOWN,
-                        GLFW_HAT_DOWN,
-                        GLFW_HAT_LEFT_DOWN,
-                        GLFW_HAT_LEFT,
-                        GLFW_HAT_LEFT_UP,
-                        GLFW_HAT_CENTERED
-                    };
-
-                    // Screams of horror are appropriate at this point
-                    int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
-                    if (state < 0 || state > 8)
-                        state = 8;
-
-                    _glfwInputJoystickHat(js, pi, states[state]);
-                    pi++;
-                    break;
-                }
-            }
-        }
-    }
-    else
-    {
-        int i, dpad = 0;
-        DWORD result;
-        XINPUT_STATE xis;
-        const WORD buttons[10] =
-        {
-            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
-        };
-
-        result = XInputGetState(js->win32.index, &xis);
-        if (result != ERROR_SUCCESS)
-        {
-            if (result == ERROR_DEVICE_NOT_CONNECTED)
-                closeJoystick(js);
-
-            return GLFW_FALSE;
-        }
-
-        if (mode == _GLFW_POLL_PRESENCE)
-            return GLFW_TRUE;
-
-        _glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
-        _glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
-        _glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
-        _glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
-        _glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
-        _glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
-
-        for (i = 0;  i < 10;  i++)
-        {
-            const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
-            _glfwInputJoystickButton(js, i, value);
-        }
-
-        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
-            dpad |= GLFW_HAT_UP;
-        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
-            dpad |= GLFW_HAT_RIGHT;
-        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
-            dpad |= GLFW_HAT_DOWN;
-        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
-            dpad |= GLFW_HAT_LEFT;
-
-        _glfwInputJoystickHat(js, 0, dpad);
-    }
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformUpdateGamepadGUID(char* guid)
-{
-    if (strcmp(guid + 20, "504944564944") == 0)
-    {
-        char original[33];
-        strncpy(original, guid, sizeof(original) - 1);
-        sprintf(guid, "03000000%.4s0000%.4s000000000000",
-                original, original + 4);
-    }
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <math.h>
+
+#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 local copies of the necessary GUIDs
+//
+static const GUID _glfw_IID_IDirectInput8W =
+    {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
+static const GUID _glfw_GUID_XAxis =
+    {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_YAxis =
+    {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_ZAxis =
+    {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RxAxis =
+    {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RyAxis =
+    {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_RzAxis =
+    {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_Slider =
+    {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+static const GUID _glfw_GUID_POV =
+    {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
+
+#define IID_IDirectInput8W _glfw_IID_IDirectInput8W
+#define GUID_XAxis _glfw_GUID_XAxis
+#define GUID_YAxis _glfw_GUID_YAxis
+#define GUID_ZAxis _glfw_GUID_ZAxis
+#define GUID_RxAxis _glfw_GUID_RxAxis
+#define GUID_RyAxis _glfw_GUID_RyAxis
+#define GUID_RzAxis _glfw_GUID_RzAxis
+#define GUID_Slider _glfw_GUID_Slider
+#define GUID_POV _glfw_GUID_POV
+
+// 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 Controller";
+            else
+                return "Xbox 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(_GLFWjoystick* js)
+{
+    if (js->win32.device)
+    {
+        IDirectInputDevice8_Unacquire(js->win32.device);
+        IDirectInputDevice8_Release(js->win32.device);
+    }
+
+    free(js->win32.objects);
+
+    _glfwFreeJoystick(js);
+    _glfwInputJoystick(js, GLFW_DISCONNECTED);
+}
+
+// DirectInput device object enumeration callback
+// Insights gleaned from SDL
+//
+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 jid = 0;
+    DIDEVCAPS dc;
+    DIPROPDWORD dipd;
+    IDirectInputDevice8* device;
+    _GLFWobjenumWin32 data;
+    _GLFWjoystick* js;
+    char guid[33];
+    char name[256];
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        _GLFWjoystick* js = _glfw.joysticks + jid;
+        if (js->present)
+        {
+            if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
+                return DIENUM_CONTINUE;
+        }
+    }
+
+    if (supportsXInput(&di->guidProduct))
+        return DIENUM_CONTINUE;
+
+    if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
+                                          &di->guidInstance,
+                                          &device,
+                                          NULL)))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
+        return DIENUM_CONTINUE;
+    }
+
+    if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: 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,
+                        "Win32: 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,
+                        "Win32: 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 + (size_t) dc.dwButtons + dc.dwPOVs,
+                          sizeof(_GLFWjoyobjectWin32));
+
+    if (FAILED(IDirectInputDevice8_EnumObjects(device,
+                                               deviceObjectCallback,
+                                               &data,
+                                               DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: Failed to enumerate device objects");
+
+        IDirectInputDevice8_Release(device);
+        free(data.objects);
+        return DIENUM_CONTINUE;
+    }
+
+    qsort(data.objects, data.objectCount,
+          sizeof(_GLFWjoyobjectWin32),
+          compareJoystickObjects);
+
+    if (!WideCharToMultiByte(CP_UTF8, 0,
+                             di->tszInstanceName, -1,
+                             name, sizeof(name),
+                             NULL, NULL))
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: Failed to convert joystick name to UTF-8");
+
+        IDirectInputDevice8_Release(device);
+        free(data.objects);
+        return DIENUM_STOP;
+    }
+
+    // Generate a joystick GUID that matches the SDL 2.0.5+ one
+    if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
+    {
+        sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
+                (uint8_t) di->guidProduct.Data1,
+                (uint8_t) (di->guidProduct.Data1 >> 8),
+                (uint8_t) (di->guidProduct.Data1 >> 16),
+                (uint8_t) (di->guidProduct.Data1 >> 24));
+    }
+    else
+    {
+        sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
+                name[0], name[1], name[2], name[3],
+                name[4], name[5], name[6], name[7],
+                name[8], name[9], name[10]);
+    }
+
+    js = _glfwAllocJoystick(name, guid,
+                            data.axisCount + data.sliderCount,
+                            data.buttonCount,
+                            data.povCount);
+    if (!js)
+    {
+        IDirectInputDevice8_Release(device);
+        free(data.objects);
+        return DIENUM_STOP;
+    }
+
+    js->win32.device = device;
+    js->win32.guid = di->guidInstance;
+    js->win32.objects = data.objects;
+    js->win32.objectCount = data.objectCount;
+
+    _glfwInputJoystick(js, GLFW_CONNECTED);
+    return DIENUM_CONTINUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksWin32(void)
+{
+    if (_glfw.win32.dinput8.instance)
+    {
+        if (FAILED(DirectInput8Create(GetModuleHandle(NULL),
+                                      DIRECTINPUT_VERSION,
+                                      &IID_IDirectInput8W,
+                                      (void**) &_glfw.win32.dinput8.api,
+                                      NULL)))
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Win32: Failed to create interface");
+        }
+    }
+
+    _glfwDetectJoystickConnectionWin32();
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksWin32(void)
+{
+    int jid;
+
+    for (jid = GLFW_JOYSTICK_1;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+        closeJoystick(_glfw.joysticks + jid);
+
+    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 index;
+
+        for (index = 0;  index < XUSER_MAX_COUNT;  index++)
+        {
+            int jid;
+            char guid[33];
+            XINPUT_CAPABILITIES xic;
+            _GLFWjoystick* js;
+
+            for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+            {
+                if (_glfw.joysticks[jid].present &&
+                    _glfw.joysticks[jid].win32.device == NULL &&
+                    _glfw.joysticks[jid].win32.index == index)
+                {
+                    break;
+                }
+            }
+
+            if (jid <= GLFW_JOYSTICK_LAST)
+                continue;
+
+            if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
+                continue;
+
+            // Generate a joystick GUID that matches the SDL 2.0.5+ one
+            sprintf(guid, "78696e707574%02x000000000000000000",
+                    xic.SubType & 0xff);
+
+            js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
+            if (!js)
+                continue;
+
+            js->win32.index = index;
+
+            _glfwInputJoystick(js, GLFW_CONNECTED);
+        }
+    }
+
+    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 jid;
+
+    for (jid = 0;  jid <= GLFW_JOYSTICK_LAST;  jid++)
+    {
+        _GLFWjoystick* js = _glfw.joysticks + jid;
+        if (js->present)
+            _glfwPlatformPollJoystick(js, _GLFW_POLL_PRESENCE);
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
+{
+    if (js->win32.device)
+    {
+        int i, ai = 0, bi = 0, pi = 0;
+        HRESULT result;
+        DIJOYSTATE state;
+
+        IDirectInputDevice8_Poll(js->win32.device);
+        result = IDirectInputDevice8_GetDeviceState(js->win32.device,
+                                                    sizeof(state),
+                                                    &state);
+        if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
+        {
+            IDirectInputDevice8_Acquire(js->win32.device);
+            IDirectInputDevice8_Poll(js->win32.device);
+            result = IDirectInputDevice8_GetDeviceState(js->win32.device,
+                                                        sizeof(state),
+                                                        &state);
+        }
+
+        if (FAILED(result))
+        {
+            closeJoystick(js);
+            return GLFW_FALSE;
+        }
+
+        if (mode == _GLFW_POLL_PRESENCE)
+            return GLFW_TRUE;
+
+        for (i = 0;  i < js->win32.objectCount;  i++)
+        {
+            const void* data = (char*) &state + js->win32.objects[i].offset;
+
+            switch (js->win32.objects[i].type)
+            {
+                case _GLFW_TYPE_AXIS:
+                case _GLFW_TYPE_SLIDER:
+                {
+                    const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
+                    _glfwInputJoystickAxis(js, ai, value);
+                    ai++;
+                    break;
+                }
+
+                case _GLFW_TYPE_BUTTON:
+                {
+                    const char value = (*((BYTE*) data) & 0x80) != 0;
+                    _glfwInputJoystickButton(js, bi, value);
+                    bi++;
+                    break;
+                }
+
+                case _GLFW_TYPE_POV:
+                {
+                    const int states[9] =
+                    {
+                        GLFW_HAT_UP,
+                        GLFW_HAT_RIGHT_UP,
+                        GLFW_HAT_RIGHT,
+                        GLFW_HAT_RIGHT_DOWN,
+                        GLFW_HAT_DOWN,
+                        GLFW_HAT_LEFT_DOWN,
+                        GLFW_HAT_LEFT,
+                        GLFW_HAT_LEFT_UP,
+                        GLFW_HAT_CENTERED
+                    };
+
+                    // Screams of horror are appropriate at this point
+                    int state = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
+                    if (state < 0 || state > 8)
+                        state = 8;
+
+                    _glfwInputJoystickHat(js, pi, states[state]);
+                    pi++;
+                    break;
+                }
+            }
+        }
+    }
+    else
+    {
+        int i, dpad = 0;
+        DWORD result;
+        XINPUT_STATE xis;
+        const WORD buttons[10] =
+        {
+            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
+        };
+
+        result = XInputGetState(js->win32.index, &xis);
+        if (result != ERROR_SUCCESS)
+        {
+            if (result == ERROR_DEVICE_NOT_CONNECTED)
+                closeJoystick(js);
+
+            return GLFW_FALSE;
+        }
+
+        if (mode == _GLFW_POLL_PRESENCE)
+            return GLFW_TRUE;
+
+        _glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
+        _glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
+        _glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
+        _glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
+        _glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
+        _glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
+
+        for (i = 0;  i < 10;  i++)
+        {
+            const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
+            _glfwInputJoystickButton(js, i, value);
+        }
+
+        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
+            dpad |= GLFW_HAT_UP;
+        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
+            dpad |= GLFW_HAT_RIGHT;
+        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
+            dpad |= GLFW_HAT_DOWN;
+        if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
+            dpad |= GLFW_HAT_LEFT;
+
+        _glfwInputJoystickHat(js, 0, dpad);
+    }
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformUpdateGamepadGUID(char* guid)
+{
+    if (strcmp(guid + 20, "504944564944") == 0)
+    {
+        char original[33];
+        strncpy(original, guid, sizeof(original) - 1);
+        sprintf(guid, "03000000%.4s0000%.4s000000000000",
+                original, original + 4);
+    }
+}
+
diff --git a/glfw/src/win32_joystick.h b/glfw/src/win32_joystick.h
--- a/glfw/src/win32_joystick.h
+++ b/glfw/src/win32_joystick.h
@@ -1,56 +1,56 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-
-#define _GLFW_PLATFORM_JOYSTICK_STATE         _GLFWjoystickWin32 win32
-#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
-
-#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
-
-// Joystick element (axis, button or slider)
-//
-typedef struct _GLFWjoyobjectWin32
-{
-    int                     offset;
-    int                     type;
-} _GLFWjoyobjectWin32;
-
-// Win32-specific per-joystick data
-//
-typedef struct _GLFWjoystickWin32
-{
-    _GLFWjoyobjectWin32*    objects;
-    int                     objectCount;
-    IDirectInputDevice8W*   device;
-    DWORD                   index;
-    GUID                    guid;
-} _GLFWjoystickWin32;
-
-
-void _glfwInitJoysticksWin32(void);
-void _glfwTerminateJoysticksWin32(void);
-void _glfwDetectJoystickConnectionWin32(void);
-void _glfwDetectJoystickDisconnectionWin32(void);
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+
+#define _GLFW_PLATFORM_JOYSTICK_STATE         _GLFWjoystickWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE struct { int dummyLibraryJoystick; }
+
+#define _GLFW_PLATFORM_MAPPING_NAME "Windows"
+
+// Joystick element (axis, button or slider)
+//
+typedef struct _GLFWjoyobjectWin32
+{
+    int                     offset;
+    int                     type;
+} _GLFWjoyobjectWin32;
+
+// Win32-specific per-joystick data
+//
+typedef struct _GLFWjoystickWin32
+{
+    _GLFWjoyobjectWin32*    objects;
+    int                     objectCount;
+    IDirectInputDevice8W*   device;
+    DWORD                   index;
+    GUID                    guid;
+} _GLFWjoystickWin32;
+
+
+void _glfwInitJoysticksWin32(void);
+void _glfwTerminateJoysticksWin32(void);
+void _glfwDetectJoystickConnectionWin32(void);
+void _glfwDetectJoystickDisconnectionWin32(void);
+
diff --git a/glfw/src/win32_monitor.c b/glfw/src/win32_monitor.c
--- a/glfw/src/win32_monitor.c
+++ b/glfw/src/win32_monitor.c
@@ -1,535 +1,535 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <malloc.h>
-#include <wchar.h>
-
-
-// Callback for EnumDisplayMonitors in createMonitor
-//
-static BOOL CALLBACK monitorCallback(HMONITOR handle,
-                                     HDC dc,
-                                     RECT* rect,
-                                     LPARAM data)
-{
-    MONITORINFOEXW mi;
-    ZeroMemory(&mi, sizeof(mi));
-    mi.cbSize = sizeof(mi);
-
-    if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
-    {
-        _GLFWmonitor* monitor = (_GLFWmonitor*) data;
-        if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
-            monitor->win32.handle = handle;
-    }
-
-    return TRUE;
-}
-
-// Create monitor from an adapter and (optionally) a display
-//
-static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
-                                   DISPLAY_DEVICEW* display)
-{
-    _GLFWmonitor* monitor;
-    int widthMM, heightMM;
-    char* name;
-    HDC dc;
-    DEVMODEW dm;
-    RECT rect;
-
-    if (display)
-        name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
-    else
-        name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
-    if (!name)
-        return NULL;
-
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-    EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
-
-    dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
-
-    if (IsWindows8Point1OrGreater())
-    {
-        widthMM  = GetDeviceCaps(dc, HORZSIZE);
-        heightMM = GetDeviceCaps(dc, VERTSIZE);
-    }
-    else
-    {
-        widthMM  = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
-        heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
-    }
-
-    DeleteDC(dc);
-
-    monitor = _glfwAllocMonitor(name, widthMM, heightMM);
-    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);
-    }
-
-    rect.left   = dm.dmPosition.x;
-    rect.top    = dm.dmPosition.y;
-    rect.right  = dm.dmPosition.x + dm.dmPelsWidth;
-    rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
-
-    EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
-    return monitor;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Poll for changes in the set of connected monitors
-//
-void _glfwPollMonitorsWin32(void)
-{
-    int i, disconnectedCount;
-    _GLFWmonitor** disconnected = NULL;
-    DWORD adapterIndex, displayIndex;
-    DISPLAY_DEVICEW adapter, display;
-    _GLFWmonitor* monitor;
-
-    disconnectedCount = _glfw.monitorCount;
-    if (disconnectedCount)
-    {
-        disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
-        memcpy(disconnected,
-               _glfw.monitors,
-               _glfw.monitorCount * sizeof(_GLFWmonitor*));
-    }
-
-    for (adapterIndex = 0;  ;  adapterIndex++)
-    {
-        int type = _GLFW_INSERT_LAST;
-
-        ZeroMemory(&adapter, sizeof(adapter));
-        adapter.cb = sizeof(adapter);
-
-        if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
-            break;
-
-        if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
-            continue;
-
-        if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
-            type = _GLFW_INSERT_FIRST;
-
-        for (displayIndex = 0;  ;  displayIndex++)
-        {
-            ZeroMemory(&display, sizeof(display));
-            display.cb = sizeof(display);
-
-            if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
-                break;
-
-            if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
-                continue;
-
-            for (i = 0;  i < disconnectedCount;  i++)
-            {
-                if (disconnected[i] &&
-                    wcscmp(disconnected[i]->win32.displayName,
-                           display.DeviceName) == 0)
-                {
-                    disconnected[i] = NULL;
-                    break;
-                }
-            }
-
-            if (i < disconnectedCount)
-                continue;
-
-            monitor = createMonitor(&adapter, &display);
-            if (!monitor)
-            {
-                free(disconnected);
-                return;
-            }
-
-            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
-
-            type = _GLFW_INSERT_LAST;
-        }
-
-        // HACK: If an active adapter does not have any display devices
-        //       (as sometimes happens), add it directly as a monitor
-        if (displayIndex == 0)
-        {
-            for (i = 0;  i < disconnectedCount;  i++)
-            {
-                if (disconnected[i] &&
-                    wcscmp(disconnected[i]->win32.adapterName,
-                           adapter.DeviceName) == 0)
-                {
-                    disconnected[i] = NULL;
-                    break;
-                }
-            }
-
-            if (i < disconnectedCount)
-                continue;
-
-            monitor = createMonitor(&adapter, NULL);
-            if (!monitor)
-            {
-                free(disconnected);
-                return;
-            }
-
-            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
-        }
-    }
-
-    for (i = 0;  i < disconnectedCount;  i++)
-    {
-        if (disconnected[i])
-            _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
-    }
-
-    free(disconnected);
-}
-
-// Change the current video mode
-//
-void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
-{
-    GLFWvidmode current;
-    const GLFWvidmode* best;
-    DEVMODEW dm;
-    LONG result;
-
-    best = _glfwChooseVideoMode(monitor, desired);
-    _glfwPlatformGetVideoMode(monitor, &current);
-    if (_glfwCompareVideoModes(&current, best) == 0)
-        return;
-
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-    dm.dmFields           = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
-                            DM_DISPLAYFREQUENCY;
-    dm.dmPelsWidth        = best->width;
-    dm.dmPelsHeight       = best->height;
-    dm.dmBitsPerPel       = best->redBits + best->greenBits + best->blueBits;
-    dm.dmDisplayFrequency = best->refreshRate;
-
-    if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
-        dm.dmBitsPerPel = 32;
-
-    result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
-                                      &dm,
-                                      NULL,
-                                      CDS_FULLSCREEN,
-                                      NULL);
-    if (result == DISP_CHANGE_SUCCESSFUL)
-        monitor->win32.modeChanged = GLFW_TRUE;
-    else
-    {
-        const char* description = "Unknown error";
-
-        if (result == DISP_CHANGE_BADDUALVIEW)
-            description = "The system uses DualView";
-        else if (result == DISP_CHANGE_BADFLAGS)
-            description = "Invalid flags";
-        else if (result == DISP_CHANGE_BADMODE)
-            description = "Graphics mode not supported";
-        else if (result == DISP_CHANGE_BADPARAM)
-            description = "Invalid parameter";
-        else if (result == DISP_CHANGE_FAILED)
-            description = "Graphics mode failed";
-        else if (result == DISP_CHANGE_NOTUPDATED)
-            description = "Failed to write to registry";
-        else if (result == DISP_CHANGE_RESTART)
-            description = "Computer restart required";
-
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Win32: Failed to set video mode: %s",
-                        description);
-    }
-}
-
-// Restore the previously saved (original) video mode
-//
-void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
-{
-    if (monitor->win32.modeChanged)
-    {
-        ChangeDisplaySettingsExW(monitor->win32.adapterName,
-                                 NULL, NULL, CDS_FULLSCREEN, NULL);
-        monitor->win32.modeChanged = GLFW_FALSE;
-    }
-}
-
-void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
-{
-    UINT xdpi, ydpi;
-
-    if (IsWindows8Point1OrGreater())
-        GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
-    else
-    {
-        const HDC dc = GetDC(NULL);
-        xdpi = GetDeviceCaps(dc, LOGPIXELSX);
-        ydpi = GetDeviceCaps(dc, LOGPIXELSY);
-        ReleaseDC(NULL, dc);
-    }
-
-    if (xscale)
-        *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
-    if (yscale)
-        *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
-{
-}
-
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
-{
-    DEVMODEW dm;
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-
-    EnumDisplaySettingsExW(monitor->win32.adapterName,
-                           ENUM_CURRENT_SETTINGS,
-                           &dm,
-                           EDS_ROTATEDMODE);
-
-    if (xpos)
-        *xpos = dm.dmPosition.x;
-    if (ypos)
-        *ypos = dm.dmPosition.y;
-}
-
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale)
-{
-    _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
-}
-
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
-                                     int* xpos, int* ypos,
-                                     int* width, int* height)
-{
-    MONITORINFO mi = { sizeof(mi) };
-    GetMonitorInfo(monitor->win32.handle, &mi);
-
-    if (xpos)
-        *xpos = mi.rcWork.left;
-    if (ypos)
-        *ypos = mi.rcWork.top;
-    if (width)
-        *width = mi.rcWork.right - mi.rcWork.left;
-    if (height)
-        *height = mi.rcWork.bottom - mi.rcWork.top;
-}
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
-{
-    int modeIndex = 0, size = 0;
-    GLFWvidmode* result = NULL;
-
-    *count = 0;
-
-    for (;;)
-    {
-        int i;
-        GLFWvidmode mode;
-        DEVMODEW dm;
-
-        ZeroMemory(&dm, sizeof(dm));
-        dm.dmSize = sizeof(dm);
-
-        if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
-            break;
-
-        modeIndex++;
-
-        // Skip modes with less than 15 BPP
-        if (dm.dmBitsPerPel < 15)
-            continue;
-
-        mode.width  = dm.dmPelsWidth;
-        mode.height = dm.dmPelsHeight;
-        mode.refreshRate = dm.dmDisplayFrequency;
-        _glfwSplitBPP(dm.dmBitsPerPel,
-                      &mode.redBits,
-                      &mode.greenBits,
-                      &mode.blueBits);
-
-        for (i = 0;  i < *count;  i++)
-        {
-            if (_glfwCompareVideoModes(result + i, &mode) == 0)
-                break;
-        }
-
-        // Skip duplicate modes
-        if (i < *count)
-            continue;
-
-        if (monitor->win32.modesPruned)
-        {
-            // Skip modes not supported by the connected displays
-            if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
-                                         &dm,
-                                         NULL,
-                                         CDS_TEST,
-                                         NULL) != DISP_CHANGE_SUCCESSFUL)
-            {
-                continue;
-            }
-        }
-
-        if (*count == size)
-        {
-            size += 128;
-            result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
-        }
-
-        (*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;
-}
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-    DEVMODEW dm;
-    ZeroMemory(&dm, sizeof(dm));
-    dm.dmSize = sizeof(dm);
-
-    EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
-
-    mode->width  = dm.dmPelsWidth;
-    mode->height = dm.dmPelsHeight;
-    mode->refreshRate = dm.dmDisplayFrequency;
-    _glfwSplitBPP(dm.dmBitsPerPel,
-                  &mode->redBits,
-                  &mode->greenBits,
-                  &mode->blueBits);
-}
-
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
-{
-    HDC dc;
-    WORD values[3][256];
-
-    dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
-    GetDeviceGammaRamp(dc, values);
-    DeleteDC(dc);
-
-    _glfwAllocGammaArrays(ramp, 256);
-
-    memcpy(ramp->red,   values[0], sizeof(values[0]));
-    memcpy(ramp->green, values[1], sizeof(values[1]));
-    memcpy(ramp->blue,  values[2], sizeof(values[2]));
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
-{
-    HDC dc;
-    WORD values[3][256];
-
-    if (ramp->size != 256)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Win32: Gamma ramp size must be 256");
-        return;
-    }
-
-    memcpy(values[0], ramp->red,   sizeof(values[0]));
-    memcpy(values[1], ramp->green, sizeof(values[1]));
-    memcpy(values[2], ramp->blue,  sizeof(values[2]));
-
-    dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
-    SetDeviceGammaRamp(dc, values);
-    DeleteDC(dc);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return monitor->win32.publicAdapterName;
-}
-
-GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return monitor->win32.publicDisplayName;
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <malloc.h>
+#include <wchar.h>
+
+
+// Callback for EnumDisplayMonitors in createMonitor
+//
+static BOOL CALLBACK monitorCallback(HMONITOR handle,
+                                     HDC dc,
+                                     RECT* rect,
+                                     LPARAM data)
+{
+    MONITORINFOEXW mi;
+    ZeroMemory(&mi, sizeof(mi));
+    mi.cbSize = sizeof(mi);
+
+    if (GetMonitorInfoW(handle, (MONITORINFO*) &mi))
+    {
+        _GLFWmonitor* monitor = (_GLFWmonitor*) data;
+        if (wcscmp(mi.szDevice, monitor->win32.adapterName) == 0)
+            monitor->win32.handle = handle;
+    }
+
+    return TRUE;
+}
+
+// Create monitor from an adapter and (optionally) a display
+//
+static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
+                                   DISPLAY_DEVICEW* display)
+{
+    _GLFWmonitor* monitor;
+    int widthMM, heightMM;
+    char* name;
+    HDC dc;
+    DEVMODEW dm;
+    RECT rect;
+
+    if (display)
+        name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
+    else
+        name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
+    if (!name)
+        return NULL;
+
+    ZeroMemory(&dm, sizeof(dm));
+    dm.dmSize = sizeof(dm);
+    EnumDisplaySettingsW(adapter->DeviceName, ENUM_CURRENT_SETTINGS, &dm);
+
+    dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
+
+    if (IsWindows8Point1OrGreater())
+    {
+        widthMM  = GetDeviceCaps(dc, HORZSIZE);
+        heightMM = GetDeviceCaps(dc, VERTSIZE);
+    }
+    else
+    {
+        widthMM  = (int) (dm.dmPelsWidth * 25.4f / GetDeviceCaps(dc, LOGPIXELSX));
+        heightMM = (int) (dm.dmPelsHeight * 25.4f / GetDeviceCaps(dc, LOGPIXELSY));
+    }
+
+    DeleteDC(dc);
+
+    monitor = _glfwAllocMonitor(name, widthMM, heightMM);
+    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);
+    }
+
+    rect.left   = dm.dmPosition.x;
+    rect.top    = dm.dmPosition.y;
+    rect.right  = dm.dmPosition.x + dm.dmPelsWidth;
+    rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
+
+    EnumDisplayMonitors(NULL, &rect, monitorCallback, (LPARAM) monitor);
+    return monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsWin32(void)
+{
+    int i, disconnectedCount;
+    _GLFWmonitor** disconnected = NULL;
+    DWORD adapterIndex, displayIndex;
+    DISPLAY_DEVICEW adapter, display;
+    _GLFWmonitor* monitor;
+
+    disconnectedCount = _glfw.monitorCount;
+    if (disconnectedCount)
+    {
+        disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+        memcpy(disconnected,
+               _glfw.monitors,
+               _glfw.monitorCount * sizeof(_GLFWmonitor*));
+    }
+
+    for (adapterIndex = 0;  ;  adapterIndex++)
+    {
+        int type = _GLFW_INSERT_LAST;
+
+        ZeroMemory(&adapter, sizeof(adapter));
+        adapter.cb = sizeof(adapter);
+
+        if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
+            break;
+
+        if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
+            continue;
+
+        if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+            type = _GLFW_INSERT_FIRST;
+
+        for (displayIndex = 0;  ;  displayIndex++)
+        {
+            ZeroMemory(&display, sizeof(display));
+            display.cb = sizeof(display);
+
+            if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
+                break;
+
+            if (!(display.StateFlags & DISPLAY_DEVICE_ACTIVE))
+                continue;
+
+            for (i = 0;  i < disconnectedCount;  i++)
+            {
+                if (disconnected[i] &&
+                    wcscmp(disconnected[i]->win32.displayName,
+                           display.DeviceName) == 0)
+                {
+                    disconnected[i] = NULL;
+                    break;
+                }
+            }
+
+            if (i < disconnectedCount)
+                continue;
+
+            monitor = createMonitor(&adapter, &display);
+            if (!monitor)
+            {
+                free(disconnected);
+                return;
+            }
+
+            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+
+            type = _GLFW_INSERT_LAST;
+        }
+
+        // HACK: If an active adapter does not have any display devices
+        //       (as sometimes happens), add it directly as a monitor
+        if (displayIndex == 0)
+        {
+            for (i = 0;  i < disconnectedCount;  i++)
+            {
+                if (disconnected[i] &&
+                    wcscmp(disconnected[i]->win32.adapterName,
+                           adapter.DeviceName) == 0)
+                {
+                    disconnected[i] = NULL;
+                    break;
+                }
+            }
+
+            if (i < disconnectedCount)
+                continue;
+
+            monitor = createMonitor(&adapter, NULL);
+            if (!monitor)
+            {
+                free(disconnected);
+                return;
+            }
+
+            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+        }
+    }
+
+    for (i = 0;  i < disconnectedCount;  i++)
+    {
+        if (disconnected[i])
+            _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+    }
+
+    free(disconnected);
+}
+
+// Change the current video mode
+//
+void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+    GLFWvidmode current;
+    const GLFWvidmode* best;
+    DEVMODEW dm;
+    LONG result;
+
+    best = _glfwChooseVideoMode(monitor, desired);
+    _glfwPlatformGetVideoMode(monitor, &current);
+    if (_glfwCompareVideoModes(&current, best) == 0)
+        return;
+
+    ZeroMemory(&dm, sizeof(dm));
+    dm.dmSize = sizeof(dm);
+    dm.dmFields           = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL |
+                            DM_DISPLAYFREQUENCY;
+    dm.dmPelsWidth        = best->width;
+    dm.dmPelsHeight       = best->height;
+    dm.dmBitsPerPel       = best->redBits + best->greenBits + best->blueBits;
+    dm.dmDisplayFrequency = best->refreshRate;
+
+    if (dm.dmBitsPerPel < 15 || dm.dmBitsPerPel >= 24)
+        dm.dmBitsPerPel = 32;
+
+    result = ChangeDisplaySettingsExW(monitor->win32.adapterName,
+                                      &dm,
+                                      NULL,
+                                      CDS_FULLSCREEN,
+                                      NULL);
+    if (result == DISP_CHANGE_SUCCESSFUL)
+        monitor->win32.modeChanged = GLFW_TRUE;
+    else
+    {
+        const char* description = "Unknown error";
+
+        if (result == DISP_CHANGE_BADDUALVIEW)
+            description = "The system uses DualView";
+        else if (result == DISP_CHANGE_BADFLAGS)
+            description = "Invalid flags";
+        else if (result == DISP_CHANGE_BADMODE)
+            description = "Graphics mode not supported";
+        else if (result == DISP_CHANGE_BADPARAM)
+            description = "Invalid parameter";
+        else if (result == DISP_CHANGE_FAILED)
+            description = "Graphics mode failed";
+        else if (result == DISP_CHANGE_NOTUPDATED)
+            description = "Failed to write to registry";
+        else if (result == DISP_CHANGE_RESTART)
+            description = "Computer restart required";
+
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: Failed to set video mode: %s",
+                        description);
+    }
+}
+
+// Restore the previously saved (original) video mode
+//
+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor)
+{
+    if (monitor->win32.modeChanged)
+    {
+        ChangeDisplaySettingsExW(monitor->win32.adapterName,
+                                 NULL, NULL, CDS_FULLSCREEN, NULL);
+        monitor->win32.modeChanged = GLFW_FALSE;
+    }
+}
+
+void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale)
+{
+    UINT xdpi, ydpi;
+
+    if (IsWindows8Point1OrGreater())
+        GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi);
+    else
+    {
+        const HDC dc = GetDC(NULL);
+        xdpi = GetDeviceCaps(dc, LOGPIXELSX);
+        ydpi = GetDeviceCaps(dc, LOGPIXELSY);
+        ReleaseDC(NULL, dc);
+    }
+
+    if (xscale)
+        *xscale = xdpi / (float) USER_DEFAULT_SCREEN_DPI;
+    if (yscale)
+        *yscale = ydpi / (float) USER_DEFAULT_SCREEN_DPI;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+    DEVMODEW dm;
+    ZeroMemory(&dm, sizeof(dm));
+    dm.dmSize = sizeof(dm);
+
+    EnumDisplaySettingsExW(monitor->win32.adapterName,
+                           ENUM_CURRENT_SETTINGS,
+                           &dm,
+                           EDS_ROTATEDMODE);
+
+    if (xpos)
+        *xpos = dm.dmPosition.x;
+    if (ypos)
+        *ypos = dm.dmPosition.y;
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale)
+{
+    _glfwGetMonitorContentScaleWin32(monitor->win32.handle, xscale, yscale);
+}
+
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
+                                     int* xpos, int* ypos,
+                                     int* width, int* height)
+{
+    MONITORINFO mi = { sizeof(mi) };
+    GetMonitorInfo(monitor->win32.handle, &mi);
+
+    if (xpos)
+        *xpos = mi.rcWork.left;
+    if (ypos)
+        *ypos = mi.rcWork.top;
+    if (width)
+        *width = mi.rcWork.right - mi.rcWork.left;
+    if (height)
+        *height = mi.rcWork.bottom - mi.rcWork.top;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+    int modeIndex = 0, size = 0;
+    GLFWvidmode* result = NULL;
+
+    *count = 0;
+
+    for (;;)
+    {
+        int i;
+        GLFWvidmode mode;
+        DEVMODEW dm;
+
+        ZeroMemory(&dm, sizeof(dm));
+        dm.dmSize = sizeof(dm);
+
+        if (!EnumDisplaySettingsW(monitor->win32.adapterName, modeIndex, &dm))
+            break;
+
+        modeIndex++;
+
+        // Skip modes with less than 15 BPP
+        if (dm.dmBitsPerPel < 15)
+            continue;
+
+        mode.width  = dm.dmPelsWidth;
+        mode.height = dm.dmPelsHeight;
+        mode.refreshRate = dm.dmDisplayFrequency;
+        _glfwSplitBPP(dm.dmBitsPerPel,
+                      &mode.redBits,
+                      &mode.greenBits,
+                      &mode.blueBits);
+
+        for (i = 0;  i < *count;  i++)
+        {
+            if (_glfwCompareVideoModes(result + i, &mode) == 0)
+                break;
+        }
+
+        // Skip duplicate modes
+        if (i < *count)
+            continue;
+
+        if (monitor->win32.modesPruned)
+        {
+            // Skip modes not supported by the connected displays
+            if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
+                                         &dm,
+                                         NULL,
+                                         CDS_TEST,
+                                         NULL) != DISP_CHANGE_SUCCESSFUL)
+            {
+                continue;
+            }
+        }
+
+        if (*count == size)
+        {
+            size += 128;
+            result = (GLFWvidmode*) realloc(result, size * sizeof(GLFWvidmode));
+        }
+
+        (*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;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+    DEVMODEW dm;
+    ZeroMemory(&dm, sizeof(dm));
+    dm.dmSize = sizeof(dm);
+
+    EnumDisplaySettingsW(monitor->win32.adapterName, ENUM_CURRENT_SETTINGS, &dm);
+
+    mode->width  = dm.dmPelsWidth;
+    mode->height = dm.dmPelsHeight;
+    mode->refreshRate = dm.dmDisplayFrequency;
+    _glfwSplitBPP(dm.dmBitsPerPel,
+                  &mode->redBits,
+                  &mode->greenBits,
+                  &mode->blueBits);
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+    HDC dc;
+    WORD values[3][256];
+
+    dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
+    GetDeviceGammaRamp(dc, values);
+    DeleteDC(dc);
+
+    _glfwAllocGammaArrays(ramp, 256);
+
+    memcpy(ramp->red,   values[0], sizeof(values[0]));
+    memcpy(ramp->green, values[1], sizeof(values[1]));
+    memcpy(ramp->blue,  values[2], sizeof(values[2]));
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+    HDC dc;
+    WORD values[3][256];
+
+    if (ramp->size != 256)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Win32: Gamma ramp size must be 256");
+        return;
+    }
+
+    memcpy(values[0], ramp->red,   sizeof(values[0]));
+    memcpy(values[1], ramp->green, sizeof(values[1]));
+    memcpy(values[2], ramp->blue,  sizeof(values[2]));
+
+    dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
+    SetDeviceGammaRamp(dc, values);
+    DeleteDC(dc);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return monitor->win32.publicAdapterName;
+}
+
+GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return monitor->win32.publicDisplayName;
+}
+
diff --git a/glfw/src/win32_platform.h b/glfw/src/win32_platform.h
--- a/glfw/src/win32_platform.h
+++ b/glfw/src/win32_platform.h
@@ -1,458 +1,458 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-
-// We don't need all the fancy stuff
-#ifndef NOMINMAX
- #define NOMINMAX
-#endif
-
-#ifndef VC_EXTRALEAN
- #define VC_EXTRALEAN
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
- #define WIN32_LEAN_AND_MEAN
-#endif
-
-// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
-// example to allow applications to correctly declare a GL_ARB_debug_output
-// callback) but windows.h assumes no one will define APIENTRY before it does
-#undef APIENTRY
-
-// GLFW on Windows is Unicode only and does not work in MBCS mode
-#ifndef UNICODE
- #define UNICODE
-#endif
-
-// GLFW requires Windows XP or later
-#if WINVER < 0x0501
- #undef WINVER
- #define WINVER 0x0501
-#endif
-#if _WIN32_WINNT < 0x0501
- #undef _WIN32_WINNT
- #define _WIN32_WINNT 0x0501
-#endif
-
-// GLFW uses DirectInput8 interfaces
-#define DIRECTINPUT_VERSION 0x0800
-
-// GLFW uses OEM cursor resources
-#define OEMRESOURCE
-
-#include <wctype.h>
-#include <windows.h>
-#include <dinput.h>
-#include <xinput.h>
-#include <dbt.h>
-
-// HACK: Define macros that some windows.h variants don't
-#ifndef WM_MOUSEHWHEEL
- #define WM_MOUSEHWHEEL 0x020E
-#endif
-#ifndef WM_DWMCOMPOSITIONCHANGED
- #define WM_DWMCOMPOSITIONCHANGED 0x031E
-#endif
-#ifndef WM_COPYGLOBALDATA
- #define WM_COPYGLOBALDATA 0x0049
-#endif
-#ifndef WM_UNICHAR
- #define WM_UNICHAR 0x0109
-#endif
-#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
-#ifndef _WIN32_WINNT_WINBLUE
- #define _WIN32_WINNT_WINBLUE 0x0602
-#endif
-#ifndef _WIN32_WINNT_WIN8
- #define _WIN32_WINNT_WIN8 0x0602
-#endif
-#ifndef WM_GETDPISCALEDSIZE
- #define WM_GETDPISCALEDSIZE 0x02e4
-#endif
-#ifndef USER_DEFAULT_SCREEN_DPI
- #define USER_DEFAULT_SCREEN_DPI 96
-#endif
-#ifndef OCR_HAND
- #define OCR_HAND 32649
-#endif
-
-#if WINVER < 0x0601
-typedef struct
-{
-    DWORD cbSize;
-    DWORD ExtStatus;
-} CHANGEFILTERSTRUCT;
-#ifndef MSGFLT_ALLOW
- #define MSGFLT_ALLOW 1
-#endif
-#endif /*Windows 7*/
-
-#if WINVER < 0x0600
-#define DWM_BB_ENABLE 0x00000001
-#define DWM_BB_BLURREGION 0x00000002
-typedef struct
-{
-    DWORD dwFlags;
-    BOOL fEnable;
-    HRGN hRgnBlur;
-    BOOL fTransitionOnMaximized;
-} DWM_BLURBEHIND;
-#else
- #include <dwmapi.h>
-#endif /*Windows Vista*/
-
-#ifndef DPI_ENUMS_DECLARED
-typedef enum
-{
-    PROCESS_DPI_UNAWARE = 0,
-    PROCESS_SYSTEM_DPI_AWARE = 1,
-    PROCESS_PER_MONITOR_DPI_AWARE = 2
-} PROCESS_DPI_AWARENESS;
-typedef enum
-{
-    MDT_EFFECTIVE_DPI = 0,
-    MDT_ANGULAR_DPI = 1,
-    MDT_RAW_DPI = 2,
-    MDT_DEFAULT = MDT_EFFECTIVE_DPI
-} MONITOR_DPI_TYPE;
-#endif /*DPI_ENUMS_DECLARED*/
-
-#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
-#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
-#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
-
-// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
-#define IsWindowsXPOrGreater()                                 \
-    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP),   \
-                                        LOBYTE(_WIN32_WINNT_WINXP), 0)
-#define IsWindowsVistaOrGreater()                                     \
-    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA),   \
-                                        LOBYTE(_WIN32_WINNT_VISTA), 0)
-#define IsWindows7OrGreater()                                         \
-    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7),    \
-                                        LOBYTE(_WIN32_WINNT_WIN7), 0)
-#define IsWindows8OrGreater()                                         \
-    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8),    \
-                                        LOBYTE(_WIN32_WINNT_WIN8), 0)
-#define IsWindows8Point1OrGreater()                                   \
-    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
-                                        LOBYTE(_WIN32_WINNT_WINBLUE), 0)
-
-#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
-    _glfwIsWindows10BuildOrGreaterWin32(14393)
-#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
-    _glfwIsWindows10BuildOrGreaterWin32(15063)
-
-// 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 DWORD (WINAPI * PFN_timeGetTime)(void);
-#define timeGetTime _glfw.win32.winmm.GetTime
-
-// xinput.dll function pointer typedefs
-typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
-typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
-#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
-#define XInputGetState _glfw.win32.xinput.GetState
-
-// dinput8.dll function pointer typedefs
-typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
-#define DirectInput8Create _glfw.win32.dinput8.Create
-
-// user32.dll function pointer typedefs
-typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
-typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
-typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
-typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
-typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
-typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
-#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
-#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
-#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
-#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
-#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
-#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
-
-// dwmapi.dll function pointer typedefs
-typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
-typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
-typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
-#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
-#define DwmFlush _glfw.win32.dwmapi.Flush
-#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
-
-// shcore.dll function pointer typedefs
-typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
-typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
-#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
-#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
-
-// ntdll.dll function pointer typedefs
-typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
-#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
-
-typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
-
-typedef struct VkWin32SurfaceCreateInfoKHR
-{
-    VkStructureType                 sType;
-    const void*                     pNext;
-    VkWin32SurfaceCreateFlagsKHR    flags;
-    HINSTANCE                       hinstance;
-    HWND                            hwnd;
-} VkWin32SurfaceCreateInfoKHR;
-
-typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
-typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
-
-#include "win32_joystick.h"
-#include "wgl_context.h"
-#include "egl_context.h"
-#include "osmesa_context.h"
-
-#if !defined(_GLFW_WNDCLASSNAME)
- #define _GLFW_WNDCLASSNAME L"GLFW30"
-#endif
-
-#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_TIMER_STATE  _GLFWtimerWin32   win32
-#define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorWin32 win32
-#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorWin32  win32
-#define _GLFW_PLATFORM_TLS_STATE            _GLFWtlsWin32     win32
-#define _GLFW_PLATFORM_MUTEX_STATE          _GLFWmutexWin32   win32
-
-
-// Win32-specific per-window data
-//
-typedef struct _GLFWwindowWin32
-{
-    HWND                handle;
-    HICON               bigIcon;
-    HICON               smallIcon;
-
-    GLFWbool            cursorTracked;
-    GLFWbool            frameAction;
-    GLFWbool            iconified;
-    GLFWbool            maximized;
-    // Whether to enable framebuffer transparency on DWM
-    GLFWbool            transparent;
-    GLFWbool            scaleToMonitor;
-
-    // The last received cursor position, regardless of source
-    int                 lastCursorPosX, lastCursorPosY;
-
-} _GLFWwindowWin32;
-
-// Win32-specific global data
-//
-typedef struct _GLFWlibraryWin32
-{
-    HWND                helperWindowHandle;
-    HDEVNOTIFY          deviceNotificationHandle;
-    DWORD               foregroundLockTimeout;
-    int                 acquiredMonitorCount;
-    char*               clipboardString;
-    short int           keycodes[512];
-    short int           scancodes[GLFW_KEY_LAST + 1];
-    char                keynames[GLFW_KEY_LAST + 1][5];
-    // Where to place the cursor when re-enabled
-    double              restoreCursorPosX, restoreCursorPosY;
-    // The window whose disabled cursor mode is active
-    _GLFWwindow*        disabledCursorWindow;
-    RAWINPUT*           rawInput;
-    int                 rawInputSize;
-    UINT                mouseTrailSize;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_timeGetTime                 GetTime;
-    } winmm;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_DirectInput8Create          Create;
-        IDirectInput8W*                 api;
-    } dinput8;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_XInputGetCapabilities       GetCapabilities;
-        PFN_XInputGetState              GetState;
-    } xinput;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_SetProcessDPIAware          SetProcessDPIAware_;
-        PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
-        PFN_EnableNonClientDpiScaling   EnableNonClientDpiScaling_;
-        PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
-        PFN_GetDpiForWindow             GetDpiForWindow_;
-        PFN_AdjustWindowRectExForDpi    AdjustWindowRectExForDpi_;
-    } user32;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_DwmIsCompositionEnabled     IsCompositionEnabled;
-        PFN_DwmFlush                    Flush;
-        PFN_DwmEnableBlurBehindWindow   EnableBlurBehindWindow;
-    } dwmapi;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_SetProcessDpiAwareness      SetProcessDpiAwareness_;
-        PFN_GetDpiForMonitor            GetDpiForMonitor_;
-    } shcore;
-
-    struct {
-        HINSTANCE                       instance;
-        PFN_RtlVerifyVersionInfo        RtlVerifyVersionInfo_;
-    } ntdll;
-
-} _GLFWlibraryWin32;
-
-// Win32-specific per-monitor data
-//
-typedef struct _GLFWmonitorWin32
-{
-    HMONITOR            handle;
-    // This size matches the static size of DISPLAY_DEVICE.DeviceName
-    WCHAR               adapterName[32];
-    WCHAR               displayName[32];
-    char                publicAdapterName[32];
-    char                publicDisplayName[32];
-    GLFWbool            modesPruned;
-    GLFWbool            modeChanged;
-
-} _GLFWmonitorWin32;
-
-// Win32-specific per-cursor data
-//
-typedef struct _GLFWcursorWin32
-{
-    HCURSOR             handle;
-
-} _GLFWcursorWin32;
-
-// Win32-specific global timer data
-//
-typedef struct _GLFWtimerWin32
-{
-    GLFWbool            hasPC;
-    uint64_t            frequency;
-
-} _GLFWtimerWin32;
-
-// Win32-specific thread local storage data
-//
-typedef struct _GLFWtlsWin32
-{
-    GLFWbool            allocated;
-    DWORD               index;
-
-} _GLFWtlsWin32;
-
-// Win32-specific mutex data
-//
-typedef struct _GLFWmutexWin32
-{
-    GLFWbool            allocated;
-    CRITICAL_SECTION    section;
-
-} _GLFWmutexWin32;
-
-
-GLFWbool _glfwRegisterWindowClassWin32(void);
-void _glfwUnregisterWindowClassWin32(void);
-
-WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
-char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
-BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
-BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
-void _glfwInputErrorWin32(int error, const char* description);
-void _glfwUpdateKeyNamesWin32(void);
-
-void _glfwInitTimerWin32(void);
-
-void _glfwPollMonitorsWin32(void);
-void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
-void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
-void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+
+// We don't need all the fancy stuff
+#ifndef NOMINMAX
+ #define NOMINMAX
+#endif
+
+#ifndef VC_EXTRALEAN
+ #define VC_EXTRALEAN
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+
+// This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
+// example to allow applications to correctly declare a GL_ARB_debug_output
+// callback) but windows.h assumes no one will define APIENTRY before it does
+#undef APIENTRY
+
+// GLFW on Windows is Unicode only and does not work in MBCS mode
+#ifndef UNICODE
+ #define UNICODE
+#endif
+
+// GLFW requires Windows XP or later
+#if WINVER < 0x0501
+ #undef WINVER
+ #define WINVER 0x0501
+#endif
+#if _WIN32_WINNT < 0x0501
+ #undef _WIN32_WINNT
+ #define _WIN32_WINNT 0x0501
+#endif
+
+// GLFW uses DirectInput8 interfaces
+#define DIRECTINPUT_VERSION 0x0800
+
+// GLFW uses OEM cursor resources
+#define OEMRESOURCE
+
+#include <wctype.h>
+#include <windows.h>
+#include <dinput.h>
+#include <xinput.h>
+#include <dbt.h>
+
+// HACK: Define macros that some windows.h variants don't
+#ifndef WM_MOUSEHWHEEL
+ #define WM_MOUSEHWHEEL 0x020E
+#endif
+#ifndef WM_DWMCOMPOSITIONCHANGED
+ #define WM_DWMCOMPOSITIONCHANGED 0x031E
+#endif
+#ifndef WM_COPYGLOBALDATA
+ #define WM_COPYGLOBALDATA 0x0049
+#endif
+#ifndef WM_UNICHAR
+ #define WM_UNICHAR 0x0109
+#endif
+#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
+#ifndef _WIN32_WINNT_WINBLUE
+ #define _WIN32_WINNT_WINBLUE 0x0602
+#endif
+#ifndef _WIN32_WINNT_WIN8
+ #define _WIN32_WINNT_WIN8 0x0602
+#endif
+#ifndef WM_GETDPISCALEDSIZE
+ #define WM_GETDPISCALEDSIZE 0x02e4
+#endif
+#ifndef USER_DEFAULT_SCREEN_DPI
+ #define USER_DEFAULT_SCREEN_DPI 96
+#endif
+#ifndef OCR_HAND
+ #define OCR_HAND 32649
+#endif
+
+#if WINVER < 0x0601
+typedef struct
+{
+    DWORD cbSize;
+    DWORD ExtStatus;
+} CHANGEFILTERSTRUCT;
+#ifndef MSGFLT_ALLOW
+ #define MSGFLT_ALLOW 1
+#endif
+#endif /*Windows 7*/
+
+#if WINVER < 0x0600
+#define DWM_BB_ENABLE 0x00000001
+#define DWM_BB_BLURREGION 0x00000002
+typedef struct
+{
+    DWORD dwFlags;
+    BOOL fEnable;
+    HRGN hRgnBlur;
+    BOOL fTransitionOnMaximized;
+} DWM_BLURBEHIND;
+#else
+ #include <dwmapi.h>
+#endif /*Windows Vista*/
+
+#ifndef DPI_ENUMS_DECLARED
+typedef enum
+{
+    PROCESS_DPI_UNAWARE = 0,
+    PROCESS_SYSTEM_DPI_AWARE = 1,
+    PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+typedef enum
+{
+    MDT_EFFECTIVE_DPI = 0,
+    MDT_ANGULAR_DPI = 1,
+    MDT_RAW_DPI = 2,
+    MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+#endif /*DPI_ENUMS_DECLARED*/
+
+#ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
+#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
+#endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
+
+// HACK: Define versionhelpers.h functions manually as MinGW lacks the header
+#define IsWindowsXPOrGreater()                                 \
+    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP),   \
+                                        LOBYTE(_WIN32_WINNT_WINXP), 0)
+#define IsWindowsVistaOrGreater()                                     \
+    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA),   \
+                                        LOBYTE(_WIN32_WINNT_VISTA), 0)
+#define IsWindows7OrGreater()                                         \
+    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7),    \
+                                        LOBYTE(_WIN32_WINNT_WIN7), 0)
+#define IsWindows8OrGreater()                                         \
+    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8),    \
+                                        LOBYTE(_WIN32_WINNT_WIN8), 0)
+#define IsWindows8Point1OrGreater()                                   \
+    _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
+                                        LOBYTE(_WIN32_WINNT_WINBLUE), 0)
+
+#define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
+    _glfwIsWindows10BuildOrGreaterWin32(14393)
+#define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
+    _glfwIsWindows10BuildOrGreaterWin32(15063)
+
+// 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 DWORD (WINAPI * PFN_timeGetTime)(void);
+#define timeGetTime _glfw.win32.winmm.GetTime
+
+// xinput.dll function pointer typedefs
+typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
+typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
+#define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
+#define XInputGetState _glfw.win32.xinput.GetState
+
+// dinput8.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
+#define DirectInput8Create _glfw.win32.dinput8.Create
+
+// user32.dll function pointer typedefs
+typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
+typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
+typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
+typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
+typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
+typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
+#define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
+#define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
+#define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
+#define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
+#define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
+#define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
+
+// dwmapi.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
+typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
+typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
+#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
+#define DwmFlush _glfw.win32.dwmapi.Flush
+#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
+
+// shcore.dll function pointer typedefs
+typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
+typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
+#define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
+#define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
+
+// ntdll.dll function pointer typedefs
+typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
+#define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
+
+typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
+
+typedef struct VkWin32SurfaceCreateInfoKHR
+{
+    VkStructureType                 sType;
+    const void*                     pNext;
+    VkWin32SurfaceCreateFlagsKHR    flags;
+    HINSTANCE                       hinstance;
+    HWND                            hwnd;
+} VkWin32SurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
+
+#include "win32_joystick.h"
+#include "wgl_context.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+
+#if !defined(_GLFW_WNDCLASSNAME)
+ #define _GLFW_WNDCLASSNAME L"GLFW30"
+#endif
+
+#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_TIMER_STATE  _GLFWtimerWin32   win32
+#define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorWin32 win32
+#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorWin32  win32
+#define _GLFW_PLATFORM_TLS_STATE            _GLFWtlsWin32     win32
+#define _GLFW_PLATFORM_MUTEX_STATE          _GLFWmutexWin32   win32
+
+
+// Win32-specific per-window data
+//
+typedef struct _GLFWwindowWin32
+{
+    HWND                handle;
+    HICON               bigIcon;
+    HICON               smallIcon;
+
+    GLFWbool            cursorTracked;
+    GLFWbool            frameAction;
+    GLFWbool            iconified;
+    GLFWbool            maximized;
+    // Whether to enable framebuffer transparency on DWM
+    GLFWbool            transparent;
+    GLFWbool            scaleToMonitor;
+
+    // The last received cursor position, regardless of source
+    int                 lastCursorPosX, lastCursorPosY;
+
+} _GLFWwindowWin32;
+
+// Win32-specific global data
+//
+typedef struct _GLFWlibraryWin32
+{
+    HWND                helperWindowHandle;
+    HDEVNOTIFY          deviceNotificationHandle;
+    DWORD               foregroundLockTimeout;
+    int                 acquiredMonitorCount;
+    char*               clipboardString;
+    short int           keycodes[512];
+    short int           scancodes[GLFW_KEY_LAST + 1];
+    char                keynames[GLFW_KEY_LAST + 1][5];
+    // Where to place the cursor when re-enabled
+    double              restoreCursorPosX, restoreCursorPosY;
+    // The window whose disabled cursor mode is active
+    _GLFWwindow*        disabledCursorWindow;
+    RAWINPUT*           rawInput;
+    int                 rawInputSize;
+    UINT                mouseTrailSize;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_timeGetTime                 GetTime;
+    } winmm;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_DirectInput8Create          Create;
+        IDirectInput8W*                 api;
+    } dinput8;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_XInputGetCapabilities       GetCapabilities;
+        PFN_XInputGetState              GetState;
+    } xinput;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_SetProcessDPIAware          SetProcessDPIAware_;
+        PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
+        PFN_EnableNonClientDpiScaling   EnableNonClientDpiScaling_;
+        PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
+        PFN_GetDpiForWindow             GetDpiForWindow_;
+        PFN_AdjustWindowRectExForDpi    AdjustWindowRectExForDpi_;
+    } user32;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_DwmIsCompositionEnabled     IsCompositionEnabled;
+        PFN_DwmFlush                    Flush;
+        PFN_DwmEnableBlurBehindWindow   EnableBlurBehindWindow;
+    } dwmapi;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_SetProcessDpiAwareness      SetProcessDpiAwareness_;
+        PFN_GetDpiForMonitor            GetDpiForMonitor_;
+    } shcore;
+
+    struct {
+        HINSTANCE                       instance;
+        PFN_RtlVerifyVersionInfo        RtlVerifyVersionInfo_;
+    } ntdll;
+
+} _GLFWlibraryWin32;
+
+// Win32-specific per-monitor data
+//
+typedef struct _GLFWmonitorWin32
+{
+    HMONITOR            handle;
+    // This size matches the static size of DISPLAY_DEVICE.DeviceName
+    WCHAR               adapterName[32];
+    WCHAR               displayName[32];
+    char                publicAdapterName[32];
+    char                publicDisplayName[32];
+    GLFWbool            modesPruned;
+    GLFWbool            modeChanged;
+
+} _GLFWmonitorWin32;
+
+// Win32-specific per-cursor data
+//
+typedef struct _GLFWcursorWin32
+{
+    HCURSOR             handle;
+
+} _GLFWcursorWin32;
+
+// Win32-specific global timer data
+//
+typedef struct _GLFWtimerWin32
+{
+    GLFWbool            hasPC;
+    uint64_t            frequency;
+
+} _GLFWtimerWin32;
+
+// Win32-specific thread local storage data
+//
+typedef struct _GLFWtlsWin32
+{
+    GLFWbool            allocated;
+    DWORD               index;
+
+} _GLFWtlsWin32;
+
+// Win32-specific mutex data
+//
+typedef struct _GLFWmutexWin32
+{
+    GLFWbool            allocated;
+    CRITICAL_SECTION    section;
+
+} _GLFWmutexWin32;
+
+
+GLFWbool _glfwRegisterWindowClassWin32(void);
+void _glfwUnregisterWindowClassWin32(void);
+
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
+BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
+BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
+void _glfwInputErrorWin32(int error, const char* description);
+void _glfwUpdateKeyNamesWin32(void);
+
+void _glfwInitTimerWin32(void);
+
+void _glfwPollMonitorsWin32(void);
+void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
+void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
+
diff --git a/glfw/src/win32_thread.c b/glfw/src/win32_thread.c
--- a/glfw/src/win32_thread.c
+++ b/glfw/src/win32_thread.c
@@ -1,99 +1,99 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
-{
-    assert(tls->win32.allocated == GLFW_FALSE);
-
-    tls->win32.index = TlsAlloc();
-    if (tls->win32.index == TLS_OUT_OF_INDEXES)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to allocate TLS index");
-        return GLFW_FALSE;
-    }
-
-    tls->win32.allocated = GLFW_TRUE;
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyTls(_GLFWtls* tls)
-{
-    if (tls->win32.allocated)
-        TlsFree(tls->win32.index);
-    memset(tls, 0, sizeof(_GLFWtls));
-}
-
-void* _glfwPlatformGetTls(_GLFWtls* tls)
-{
-    assert(tls->win32.allocated == GLFW_TRUE);
-    return TlsGetValue(tls->win32.index);
-}
-
-void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
-{
-    assert(tls->win32.allocated == GLFW_TRUE);
-    TlsSetValue(tls->win32.index, value);
-}
-
-GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->win32.allocated == GLFW_FALSE);
-    InitializeCriticalSection(&mutex->win32.section);
-    return mutex->win32.allocated = GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
-{
-    if (mutex->win32.allocated)
-        DeleteCriticalSection(&mutex->win32.section);
-    memset(mutex, 0, sizeof(_GLFWmutex));
-}
-
-void _glfwPlatformLockMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->win32.allocated == GLFW_TRUE);
-    EnterCriticalSection(&mutex->win32.section);
-}
-
-void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
-{
-    assert(mutex->win32.allocated == GLFW_TRUE);
-    LeaveCriticalSection(&mutex->win32.section);
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
+{
+    assert(tls->win32.allocated == GLFW_FALSE);
+
+    tls->win32.index = TlsAlloc();
+    if (tls->win32.index == TLS_OUT_OF_INDEXES)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to allocate TLS index");
+        return GLFW_FALSE;
+    }
+
+    tls->win32.allocated = GLFW_TRUE;
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyTls(_GLFWtls* tls)
+{
+    if (tls->win32.allocated)
+        TlsFree(tls->win32.index);
+    memset(tls, 0, sizeof(_GLFWtls));
+}
+
+void* _glfwPlatformGetTls(_GLFWtls* tls)
+{
+    assert(tls->win32.allocated == GLFW_TRUE);
+    return TlsGetValue(tls->win32.index);
+}
+
+void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
+{
+    assert(tls->win32.allocated == GLFW_TRUE);
+    TlsSetValue(tls->win32.index, value);
+}
+
+GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->win32.allocated == GLFW_FALSE);
+    InitializeCriticalSection(&mutex->win32.section);
+    return mutex->win32.allocated = GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
+{
+    if (mutex->win32.allocated)
+        DeleteCriticalSection(&mutex->win32.section);
+    memset(mutex, 0, sizeof(_GLFWmutex));
+}
+
+void _glfwPlatformLockMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->win32.allocated == GLFW_TRUE);
+    EnterCriticalSection(&mutex->win32.section);
+}
+
+void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
+{
+    assert(mutex->win32.allocated == GLFW_TRUE);
+    LeaveCriticalSection(&mutex->win32.section);
+}
+
diff --git a/glfw/src/win32_time.c b/glfw/src/win32_time.c
--- a/glfw/src/win32_time.c
+++ b/glfw/src/win32_time.c
@@ -1,76 +1,76 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Initialise timer
-//
-void _glfwInitTimerWin32(void)
-{
-    uint64_t frequency;
-
-    if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
-    {
-        _glfw.timer.win32.hasPC = GLFW_TRUE;
-        _glfw.timer.win32.frequency = frequency;
-    }
-    else
-    {
-        _glfw.timer.win32.hasPC = GLFW_FALSE;
-        _glfw.timer.win32.frequency = 1000;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-uint64_t _glfwPlatformGetTimerValue(void)
-{
-    if (_glfw.timer.win32.hasPC)
-    {
-        uint64_t value;
-        QueryPerformanceCounter((LARGE_INTEGER*) &value);
-        return value;
-    }
-    else
-        return (uint64_t) timeGetTime();
-}
-
-uint64_t _glfwPlatformGetTimerFrequency(void)
-{
-    return _glfw.timer.win32.frequency;
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerWin32(void)
+{
+    uint64_t frequency;
+
+    if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
+    {
+        _glfw.timer.win32.hasPC = GLFW_TRUE;
+        _glfw.timer.win32.frequency = frequency;
+    }
+    else
+    {
+        _glfw.timer.win32.hasPC = GLFW_FALSE;
+        _glfw.timer.win32.frequency = 1000;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+    if (_glfw.timer.win32.hasPC)
+    {
+        uint64_t value;
+        QueryPerformanceCounter((LARGE_INTEGER*) &value);
+        return value;
+    }
+    else
+        return (uint64_t) timeGetTime();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+    return _glfw.timer.win32.frequency;
+}
+
diff --git a/glfw/src/win32_window.c b/glfw/src/win32_window.c
--- a/glfw/src/win32_window.c
+++ b/glfw/src/win32_window.c
@@ -1,2249 +1,2244 @@
-//========================================================================
-// GLFW 3.3 Win32 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#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
-    {
-        style |= WS_SYSMENU | WS_MINIMIZEBOX;
-
-        if (window->decorated)
-        {
-            style |= WS_CAPTION;
-
-            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(bi);
-    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)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to create RGBA bitmap");
-        return NULL;
-    }
-
-    mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
-    if (!mask)
-    {
-        _glfwInputErrorWin32(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)
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "Win32: Failed to create icon");
-        }
-        else
-        {
-            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                                 "Win32: Failed to create cursor");
-        }
-    }
-
-    return handle;
-}
-
-// Translate content area size to full window size according to styles and DPI
-//
-static void getFullWindowSize(DWORD style, DWORD exStyle,
-                              int contentWidth, int contentHeight,
-                              int* fullWidth, int* fullHeight,
-                              UINT dpi)
-{
-    RECT rect = { 0, 0, contentWidth, contentHeight };
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
-    else
-        AdjustWindowRectEx(&rect, style, FALSE, exStyle);
-
-    *fullWidth = rect.right - rect.left;
-    *fullHeight = rect.bottom - rect.top;
-}
-
-// Enforce the content area aspect ratio based on which edge is being dragged
-//
-static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
-{
-    int xoff, yoff;
-    UINT dpi = USER_DEFAULT_SCREEN_DPI;
-    const float ratio = (float) window->numer / (float) window->denom;
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        dpi = GetDpiForWindow(window->win32.handle);
-
-    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
-                      0, 0, &xoff, &yoff, dpi);
-
-    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);
-    }
-}
-
-// 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);
-}
-
-// Enables WM_INPUT messages for the mouse for the specified window
-//
-static void enableRawMouseMotion(_GLFWwindow* window)
-{
-    const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
-
-    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to register raw input device");
-    }
-}
-
-// Disables WM_INPUT messages for the mouse
-//
-static void disableRawMouseMotion(_GLFWwindow* window)
-{
-    const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
-
-    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to remove raw input device");
-    }
-}
-
-// Apply disabled cursor mode to a focused window
-//
-static void disableCursor(_GLFWwindow* window)
-{
-    _glfw.win32.disabledCursorWindow = window;
-    _glfwPlatformGetCursorPos(window,
-                              &_glfw.win32.restoreCursorPosX,
-                              &_glfw.win32.restoreCursorPosY);
-    updateCursorImage(window);
-    _glfwCenterCursorInContentArea(window);
-    updateClipRect(window);
-
-    if (window->rawMouseMotion)
-        enableRawMouseMotion(window);
-}
-
-// Exit disabled cursor mode for the specified window
-//
-static void enableCursor(_GLFWwindow* window)
-{
-    if (window->rawMouseMotion)
-        disableRawMouseMotion(window);
-
-    _glfw.win32.disabledCursorWindow = NULL;
-    updateClipRect(NULL);
-    _glfwPlatformSetCursorPos(window,
-                              _glfw.win32.restoreCursorPosX,
-                              _glfw.win32.restoreCursorPosY);
-    updateCursorImage(window);
-}
-
-// Returns whether the cursor is in the content area of the specified window
-//
-static GLFWbool cursorInContentArea(_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);
-}
-
-// Update native window styles to match attributes
-//
-static void updateWindowStyles(const _GLFWwindow* window)
-{
-    RECT rect;
-    DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
-    style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
-    style |= getWindowStyle(window);
-
-    GetClientRect(window->win32.handle, &rect);
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-    {
-        AdjustWindowRectExForDpi(&rect, style, FALSE,
-                                 getWindowExStyle(window),
-                                 GetDpiForWindow(window->win32.handle));
-    }
-    else
-        AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
-
-    ClientToScreen(window->win32.handle, (POINT*) &rect.left);
-    ClientToScreen(window->win32.handle, (POINT*) &rect.right);
-    SetWindowLongW(window->win32.handle, GWL_STYLE, style);
-    SetWindowPos(window->win32.handle, HWND_TOP,
-                 rect.left, rect.top,
-                 rect.right - rect.left, rect.bottom - rect.top,
-                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
-}
-
-// Update window framebuffer transparency
-//
-static void updateFramebufferTransparency(const _GLFWwindow* window)
-{
-    BOOL enabled;
-
-    if (!IsWindowsVistaOrGreater())
-        return;
-
-    if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
-    {
-        HRGN region = CreateRectRgn(0, 0, -1, -1);
-        DWM_BLURBEHIND bb = {0};
-        bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
-        bb.hRgnBlur = region;
-        bb.fEnable = TRUE;
-
-        if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
-        {
-            // Decorated windows don't repaint the transparent background
-            // leaving a trail behind animations
-            // HACK: Making the window layered with a transparency color key
-            //       seems to fix this.  Normally, when specifying
-            //       a transparency color key to be used when composing the
-            //       layered window, all pixels painted by the window in this
-            //       color will be transparent.  That doesn't seem to be the
-            //       case anymore, at least when used with blur behind window
-            //       plus negative region.
-            LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
-            exStyle |= WS_EX_LAYERED;
-            SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
-
-            // Using a color key not equal to black to fix the trailing
-            // issue.  When set to black, something is making the hit test
-            // not resize with the window frame.
-            SetLayeredWindowAttributes(window->win32.handle,
-                                       RGB(255, 0, 255), 255, LWA_COLORKEY);
-        }
-
-        DeleteObject(region);
-    }
-    else
-    {
-        LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
-        exStyle &= ~WS_EX_LAYERED;
-        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
-        RedrawWindow(window->win32.handle, NULL, NULL,
-                     RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
-    }
-}
-
-// Retrieves and translates modifier keys
-//
-static int getKeyMods(void)
-{
-    int mods = 0;
-
-    if (GetKeyState(VK_SHIFT) & 0x8000)
-        mods |= GLFW_MOD_SHIFT;
-    if (GetKeyState(VK_CONTROL) & 0x8000)
-        mods |= GLFW_MOD_CONTROL;
-    if (GetKeyState(VK_MENU) & 0x8000)
-        mods |= GLFW_MOD_ALT;
-    if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
-        mods |= GLFW_MOD_SUPER;
-    if (GetKeyState(VK_CAPITAL) & 1)
-        mods |= GLFW_MOD_CAPS_LOCK;
-    if (GetKeyState(VK_NUMLOCK) & 1)
-        mods |= GLFW_MOD_NUM_LOCK;
-
-    return mods;
-}
-
-// Retrieves and translates modifier keys
-//
-static int getAsyncKeyMods(void)
-{
-    int mods = 0;
-
-    if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
-        mods |= GLFW_MOD_SHIFT;
-    if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
-        mods |= GLFW_MOD_CONTROL;
-    if (GetAsyncKeyState(VK_MENU) & 0x8000)
-        mods |= GLFW_MOD_ALT;
-    if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & 0x8000)
-        mods |= GLFW_MOD_SUPER;
-    if (GetAsyncKeyState(VK_CAPITAL) & 1)
-        mods |= GLFW_MOD_CAPS_LOCK;
-    if (GetAsyncKeyState(VK_NUMLOCK) & 1)
-        mods |= GLFW_MOD_NUM_LOCK;
-
-    return mods;
-}
-
-// Translates a Windows key to the corresponding GLFW key
-//
-static int translateKey(WPARAM wParam, LPARAM lParam)
-{
-    // The Ctrl keys require special handling
-    if (wParam == VK_CONTROL)
-    {
-        MSG next;
-        DWORD time;
-
-        // Right side keys have the extended key bit set
-        if (HIWORD(lParam) & KF_EXTENDED)
-            return GLFW_KEY_RIGHT_CONTROL;
-
-        // HACK: Alt Gr sends Left Ctrl and then Right Alt in close sequence
-        //       We only want the Right Alt message, so if the next message is
-        //       Right Alt we ignore this (synthetic) Left Ctrl message
-        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 &&
-                    (HIWORD(next.lParam) & KF_EXTENDED) &&
-                    next.time == time)
-                {
-                    // Next message is Right Alt down so discard this
-                    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.keycodes[HIWORD(lParam) & 0x1FF];
-}
-
-static void fitToMonitor(_GLFWwindow* window)
-{
-    MONITORINFO mi = { sizeof(mi) };
-    GetMonitorInfo(window->monitor->win32.handle, &mi);
-    SetWindowPos(window->win32.handle, HWND_TOPMOST,
-                 mi.rcMonitor.left,
-                 mi.rcMonitor.top,
-                 mi.rcMonitor.right - mi.rcMonitor.left,
-                 mi.rcMonitor.bottom - mi.rcMonitor.top,
-                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
-}
-
-// Make the specified window and its video mode active on its monitor
-//
-static void acquireMonitor(_GLFWwindow* window)
-{
-    if (!_glfw.win32.acquiredMonitorCount)
-    {
-        SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
-
-        // HACK: When mouse trails are enabled the cursor becomes invisible when
-        //       the OpenGL ICD switches to page flipping
-        if (IsWindowsXPOrGreater())
-        {
-            SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
-            SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
-        }
-    }
-
-    if (!window->monitor->window)
-        _glfw.win32.acquiredMonitorCount++;
-
-    _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
-    _glfwInputMonitorWindow(window->monitor, window);
-}
-
-// Remove the window and restore the original video mode
-//
-static void releaseMonitor(_GLFWwindow* window)
-{
-    if (window->monitor->window != window)
-        return;
-
-    _glfw.win32.acquiredMonitorCount--;
-    if (!_glfw.win32.acquiredMonitorCount)
-    {
-        SetThreadExecutionState(ES_CONTINUOUS);
-
-        // HACK: Restore mouse trail length saved in acquireMonitor
-        if (IsWindowsXPOrGreater())
-            SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
-    }
-
-    _glfwInputMonitorWindow(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
-        // and for a regular window during its initial creation
-
-        switch (uMsg)
-        {
-            case WM_NCCREATE:
-            {
-                if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-                    EnableNonClientDpiScaling(hWnd);
-
-                break;
-            }
-
-            case WM_DISPLAYCHANGE:
-                _glfwPollMonitorsWin32();
-                break;
-
-            case WM_DEVICECHANGE:
-            {
-                if (wParam == DBT_DEVICEARRIVAL)
-                {
-                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
-                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
-                        _glfwDetectJoystickConnectionWin32();
-                }
-                else if (wParam == DBT_DEVICEREMOVECOMPLETE)
-                {
-                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
-                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
-                        _glfwDetectJoystickDisconnectionWin32();
-                }
-
-                break;
-            }
-        }
-
-        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
-    }
-
-    switch (uMsg)
-    {
-        case WM_MOUSEACTIVATE:
-        {
-            // HACK: Postpone cursor disabling when the window was activated by
-            //       clicking a caption button
-            if (HIWORD(lParam) == WM_LBUTTONDOWN)
-            {
-                if (LOWORD(lParam) != HTCLIENT)
-                    window->win32.frameAction = GLFW_TRUE;
-            }
-
-            break;
-        }
-
-        case WM_CAPTURECHANGED:
-        {
-            // HACK: Disable the cursor once the caption button action has been
-            //       completed or cancelled
-            if (lParam == 0 && window->win32.frameAction)
-            {
-                if (window->cursorMode == GLFW_CURSOR_DISABLED)
-                    disableCursor(window);
-
-                window->win32.frameAction = GLFW_FALSE;
-            }
-
-            break;
-        }
-
-        case WM_SETFOCUS:
-        {
-            _glfwInputWindowFocus(window, GLFW_TRUE);
-
-            // HACK: Do not disable cursor while the user is interacting with
-            //       a caption button
-            if (window->win32.frameAction)
-                break;
-
-            if (window->cursorMode == GLFW_CURSOR_DISABLED)
-                disableCursor(window);
-
-            return 0;
-        }
-
-        case WM_KILLFOCUS:
-        {
-            if (window->cursorMode == GLFW_CURSOR_DISABLED)
-                enableCursor(window);
-
-            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_INPUTLANGCHANGE:
-        {
-            _glfwUpdateKeyNamesWin32();
-            break;
-        }
-
-        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 = (HIWORD(lParam) & 0x1ff);
-            const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
-            const int mods = getKeyMods();
-
-            if (key == _GLFW_KEY_INVALID)
-                break;
-
-            if (action == GLFW_RELEASE && wParam == VK_SHIFT)
-            {
-                // HACK: Release both Shift keys on Shift up event, as when both
-                //       are pressed the first release does not emit any event
-                // NOTE: The other half of this is in _glfwPlatformPollEvents
-                _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
-                _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
-            }
-            else if (wParam == VK_SNAPSHOT)
-            {
-                // HACK: 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 i, 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;
-            }
-            else
-                action = GLFW_RELEASE;
-
-            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
-            {
-                if (window->mouseButtons[i] == GLFW_PRESS)
-                    break;
-            }
-
-            if (i > GLFW_MOUSE_BUTTON_LAST)
-                SetCapture(hWnd);
-
-            _glfwInputMouseClick(window, button, action, getKeyMods());
-
-            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
-            {
-                if (window->mouseButtons[i] == GLFW_PRESS)
-                    break;
-            }
-
-            if (i > GLFW_MOUSE_BUTTON_LAST)
-                ReleaseCapture();
-
-            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->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);
-            }
-
-            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;
-                if (window->rawMouseMotion)
-                    break;
-
-                _glfwInputCursorPos(window,
-                                    window->virtualCursorPosX + dx,
-                                    window->virtualCursorPosY + dy);
-            }
-            else
-                _glfwInputCursorPos(window, x, y);
-
-            window->win32.lastCursorPosX = x;
-            window->win32.lastCursorPosY = y;
-
-            return 0;
-        }
-
-        case WM_INPUT:
-        {
-            UINT size = 0;
-            HRAWINPUT ri = (HRAWINPUT) lParam;
-            RAWINPUT* data = NULL;
-            int dx, dy;
-
-            if (_glfw.win32.disabledCursorWindow != window)
-                break;
-            if (!window->rawMouseMotion)
-                break;
-
-            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
-            if (size > (UINT) _glfw.win32.rawInputSize)
-            {
-                free(_glfw.win32.rawInput);
-                _glfw.win32.rawInput = calloc(size, 1);
-                _glfw.win32.rawInputSize = size;
-            }
-
-            size = _glfw.win32.rawInputSize;
-            if (GetRawInputData(ri, RID_INPUT,
-                                _glfw.win32.rawInput, &size,
-                                sizeof(RAWINPUTHEADER)) == (UINT) -1)
-            {
-                _glfwInputError(GLFW_PLATFORM_ERROR,
-                                "Win32: Failed to retrieve raw input data");
-                break;
-            }
-
-            data = _glfw.win32.rawInput;
-            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
-            {
-                dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
-                dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
-            }
-            else
-            {
-                dx = data->data.mouse.lLastX;
-                dy = data->data.mouse.lLastY;
-            }
-
-            _glfwInputCursorPos(window,
-                                window->virtualCursorPosX + dx,
-                                window->virtualCursorPosY + dy);
-
-            window->win32.lastCursorPosX += dx;
-            window->win32.lastCursorPosY += dy;
-            break;
-        }
-
-        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 macOS and X11
-            _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
-            return 0;
-        }
-
-        case WM_ENTERSIZEMOVE:
-        case WM_ENTERMENULOOP:
-        {
-            if (window->win32.frameAction)
-                break;
-
-            // HACK: Enable the cursor while the user is moving or
-            //       resizing the window or using the window menu
-            if (window->cursorMode == GLFW_CURSOR_DISABLED)
-                enableCursor(window);
-
-            break;
-        }
-
-        case WM_EXITSIZEMOVE:
-        case WM_EXITMENULOOP:
-        {
-            if (window->win32.frameAction)
-                break;
-
-            // HACK: Disable the cursor once the user is done moving or
-            //       resizing the window or using the menu
-            if (window->cursorMode == GLFW_CURSOR_DISABLED)
-                disableCursor(window);
-
-            break;
-        }
-
-        case WM_SIZE:
-        {
-            const GLFWbool iconified = wParam == SIZE_MINIMIZED;
-            const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
-                                       (window->win32.maximized &&
-                                        wParam != SIZE_RESTORED);
-
-            if (_glfw.win32.disabledCursorWindow == window)
-                updateClipRect(window);
-
-            if (window->win32.iconified != iconified)
-                _glfwInputWindowIconify(window, iconified);
-
-            if (window->win32.maximized != maximized)
-                _glfwInputWindowMaximize(window, maximized);
-
-            _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
-            _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
-
-            if (window->monitor && window->win32.iconified != iconified)
-            {
-                if (iconified)
-                    releaseMonitor(window);
-                else
-                {
-                    acquireMonitor(window);
-                    fitToMonitor(window);
-                }
-            }
-
-            window->win32.iconified = iconified;
-            window->win32.maximized = maximized;
-            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;
-            UINT dpi = USER_DEFAULT_SCREEN_DPI;
-            MINMAXINFO* mmi = (MINMAXINFO*) lParam;
-
-            if (window->monitor)
-                break;
-
-            if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-                dpi = GetDpiForWindow(window->win32.handle);
-
-            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
-                              0, 0, &xoff, &yoff, dpi);
-
-            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;
-            }
-
-            if (!window->decorated)
-            {
-                MONITORINFO mi;
-                const HMONITOR mh = MonitorFromWindow(window->win32.handle,
-                                                      MONITOR_DEFAULTTONEAREST);
-
-                ZeroMemory(&mi, sizeof(mi));
-                mi.cbSize = sizeof(mi);
-                GetMonitorInfo(mh, &mi);
-
-                mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
-                mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
-                mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
-                mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
-            }
-
-            return 0;
-        }
-
-        case WM_PAINT:
-        {
-            _glfwInputWindowDamage(window);
-            break;
-        }
-
-        case WM_ERASEBKGND:
-        {
-            return TRUE;
-        }
-
-        case WM_NCACTIVATE:
-        case WM_NCPAINT:
-        {
-            // Prevent title bar from being drawn after restoring a minimized
-            // undecorated window
-            if (!window->decorated)
-                return TRUE;
-
-            break;
-        }
-
-        case WM_DWMCOMPOSITIONCHANGED:
-        {
-            if (window->win32.transparent)
-                updateFramebufferTransparency(window);
-            return 0;
-        }
-
-        case WM_GETDPISCALEDSIZE:
-        {
-            if (window->win32.scaleToMonitor)
-                break;
-
-            // Adjust the window size to keep the content area size constant
-            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
-            {
-                RECT source = {0}, target = {0};
-                SIZE* size = (SIZE*) lParam;
-
-                AdjustWindowRectExForDpi(&source, getWindowStyle(window),
-                                         FALSE, getWindowExStyle(window),
-                                         GetDpiForWindow(window->win32.handle));
-                AdjustWindowRectExForDpi(&target, getWindowStyle(window),
-                                         FALSE, getWindowExStyle(window),
-                                         LOWORD(wParam));
-
-                size->cx += (target.right - target.left) -
-                            (source.right - source.left);
-                size->cy += (target.bottom - target.top) -
-                            (source.bottom - source.top);
-                return TRUE;
-            }
-
-            break;
-        }
-
-        case WM_DPICHANGED:
-        {
-            const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
-            const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
-
-            // Only apply the suggested size if the OS is new enough to have
-            // sent a WM_GETDPISCALEDSIZE before this
-            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
-            {
-                RECT* suggested = (RECT*) lParam;
-                SetWindowPos(window->win32.handle, HWND_TOP,
-                             suggested->left,
-                             suggested->top,
-                             suggested->right - suggested->left,
-                             suggested->bottom - suggested->top,
-                             SWP_NOACTIVATE | SWP_NOZORDER);
-            }
-
-            _glfwInputWindowContentScale(window, xscale, yscale);
-            break;
-        }
-
-        case WM_SETCURSOR:
-        {
-            if (LOWORD(lParam) == HTCLIENT)
-            {
-                updateCursorImage(window);
-                return TRUE;
-            }
-
-            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((size_t) 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,
-                              const _GLFWfbconfig* fbconfig)
-{
-    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 picked in _glfwSetVideoModeWin32
-        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
-        _glfwPlatformGetVideoMode(window->monitor, &mode);
-        fullWidth  = mode.width;
-        fullHeight = mode.height;
-    }
-    else
-    {
-        xpos = CW_USEDEFAULT;
-        ypos = CW_USEDEFAULT;
-
-        window->win32.maximized = wndconfig->maximized;
-        if (wndconfig->maximized)
-            style |= WS_MAXIMIZE;
-
-        getFullWindowSize(style, exStyle,
-                          wndconfig->width, wndconfig->height,
-                          &fullWidth, &fullHeight,
-                          USER_DEFAULT_SCREEN_DPI);
-    }
-
-    wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
-    if (!wideTitle)
-        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)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to create window");
-        return GLFW_FALSE;
-    }
-
-    SetPropW(window->win32.handle, L"GLFW", window);
-
-    if (IsWindows7OrGreater())
-    {
-        ChangeWindowMessageFilterEx(window->win32.handle,
-                                    WM_DROPFILES, MSGFLT_ALLOW, NULL);
-        ChangeWindowMessageFilterEx(window->win32.handle,
-                                    WM_COPYDATA, MSGFLT_ALLOW, NULL);
-        ChangeWindowMessageFilterEx(window->win32.handle,
-                                    WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
-    }
-
-    window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
-
-    // Adjust window rect to account for DPI scaling of the window frame and
-    // (if enabled) DPI scaling of the content area
-    // This cannot be done until we know what monitor the window was placed on
-    if (!window->monitor)
-    {
-        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
-        WINDOWPLACEMENT wp = { sizeof(wp) };
-
-        if (wndconfig->scaleToMonitor)
-        {
-            float xscale, yscale;
-            _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
-            rect.right = (int) (rect.right * xscale);
-            rect.bottom = (int) (rect.bottom * yscale);
-        }
-
-        ClientToScreen(window->win32.handle, (POINT*) &rect.left);
-        ClientToScreen(window->win32.handle, (POINT*) &rect.right);
-
-        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        {
-            AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
-                                     GetDpiForWindow(window->win32.handle));
-        }
-        else
-            AdjustWindowRectEx(&rect, style, FALSE, exStyle);
-
-        // Only update the restored window rect as the window may be maximized
-        GetWindowPlacement(window->win32.handle, &wp);
-        wp.rcNormalPosition = rect;
-        wp.showCmd = SW_HIDE;
-        SetWindowPlacement(window->win32.handle, &wp);
-    }
-
-    DragAcceptFiles(window->win32.handle, TRUE);
-
-    if (fbconfig->transparent)
-    {
-        updateFramebufferTransparency(window);
-        window->win32.transparent = GLFW_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))
-    {
-        _glfwInputErrorWin32(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, fbconfig))
-        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 (ctxconfig->source == GLFW_EGL_CONTEXT_API)
-        {
-            if (!_glfwInitEGL())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwInitOSMesa())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-    }
-
-    if (window->monitor)
-    {
-        _glfwPlatformShowWindow(window);
-        _glfwPlatformFocusWindow(window);
-        acquireMonitor(window);
-        fitToMonitor(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)
-        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 };
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-    {
-        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
-                                 FALSE, getWindowExStyle(window),
-                                 GetDpiForWindow(window->win32.handle));
-    }
-    else
-    {
-        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);
-            fitToMonitor(window);
-        }
-    }
-    else
-    {
-        RECT rect = { 0, 0, width, height };
-
-        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        {
-            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
-                                     FALSE, getWindowExStyle(window),
-                                     GetDpiForWindow(window->win32.handle));
-        }
-        else
-        {
-            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);
-
-    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-    {
-        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
-                                 FALSE, getWindowExStyle(window),
-                                 GetDpiForWindow(window->win32.handle));
-    }
-    else
-    {
-        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 _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale)
-{
-    const HANDLE handle = MonitorFromWindow(window->win32.handle,
-                                            MONITOR_DEFAULTTONEAREST);
-    _glfwGetMonitorContentScaleWin32(handle, xscale, yscale);
-}
-
-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_SHOWNA);
-}
-
-void _glfwPlatformHideWindow(_GLFWwindow* window)
-{
-    ShowWindow(window->win32.handle, SW_HIDE);
-}
-
-void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
-{
-    FlashWindow(window->win32.handle, TRUE);
-}
-
-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);
-                fitToMonitor(window);
-            }
-        }
-        else
-        {
-            RECT rect = { xpos, ypos, xpos + width, ypos + height };
-
-            if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-            {
-                AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
-                                         FALSE, getWindowExStyle(window),
-                                         GetDpiForWindow(window->win32.handle));
-            }
-            else
-            {
-                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);
-
-    _glfwInputWindowMonitor(window, monitor);
-
-    if (window->monitor)
-    {
-        MONITORINFO mi = { sizeof(mi) };
-        UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
-
-        if (window->decorated)
-        {
-            DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
-            style &= ~WS_OVERLAPPEDWINDOW;
-            style |= getWindowStyle(window);
-            SetWindowLongW(window->win32.handle, GWL_STYLE, style);
-            flags |= SWP_FRAMECHANGED;
-        }
-
-        acquireMonitor(window);
-
-        GetMonitorInfo(window->monitor->win32.handle, &mi);
-        SetWindowPos(window->win32.handle, HWND_TOPMOST,
-                     mi.rcMonitor.left,
-                     mi.rcMonitor.top,
-                     mi.rcMonitor.right - mi.rcMonitor.left,
-                     mi.rcMonitor.bottom - mi.rcMonitor.top,
-                     flags);
-    }
-    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;
-
-        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
-        {
-            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
-                                     FALSE, getWindowExStyle(window),
-                                     GetDpiForWindow(window->win32.handle));
-        }
-        else
-        {
-            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);
-}
-
-int _glfwPlatformWindowHovered(_GLFWwindow* window)
-{
-    return cursorInContentArea(window);
-}
-
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
-{
-    BOOL enabled;
-
-    if (!window->win32.transparent)
-        return GLFW_FALSE;
-
-    if (!IsWindowsVistaOrGreater())
-        return GLFW_FALSE;
-
-    return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
-}
-
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
-{
-    updateWindowStyles(window);
-}
-
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
-{
-    updateWindowStyles(window);
-}
-
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
-{
-    const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
-    SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
-                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
-}
-
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
-{
-    BYTE alpha;
-    DWORD flags;
-
-    if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
-        GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
-    {
-        if (flags & LWA_ALPHA)
-            return alpha / 255.f;
-    }
-
-    return 1.f;
-}
-
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
-{
-    if (opacity < 1.f)
-    {
-        const BYTE alpha = (BYTE) (255 * opacity);
-        DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
-        style |= WS_EX_LAYERED;
-        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
-        SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
-    }
-    else
-    {
-        DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
-        style &= ~WS_EX_LAYERED;
-        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
-    }
-}
-
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
-{
-    if (_glfw.win32.disabledCursorWindow != window)
-        return;
-
-    if (enabled)
-        enableRawMouseMotion(window);
-    else
-        disableRawMouseMotion(window);
-}
-
-GLFWbool _glfwPlatformRawMouseMotionSupported(void)
-{
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformPollEvents(void)
-{
-    MSG msg;
-    HWND handle;
-    _GLFWwindow* window;
-
-    while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
-    {
-        if (msg.message == WM_QUIT)
-        {
-            // NOTE: While GLFW does not itself post WM_QUIT, other processes
-            //       may post it to this one, for example Task Manager
-            // HACK: Treat WM_QUIT as a close on all windows
-
-            window = _glfw.windowListHead;
-            while (window)
-            {
-                _glfwInputWindowCloseRequest(window);
-                window = window->next;
-            }
-        }
-        else
-        {
-            TranslateMessage(&msg);
-            DispatchMessageW(&msg);
-        }
-    }
-
-    handle = GetActiveWindow();
-    if (handle)
-    {
-        // NOTE: Shift keys on Windows tend to "stick" when both are pressed as
-        //       no key up message is generated by the first key release
-        //       The other half of this is in the handling of WM_KEYUP
-        // HACK: Query actual key state and synthesize release events as needed
-        window = GetPropW(handle, L"GLFW");
-        if (window)
-        {
-            const GLFWbool lshift = (GetAsyncKeyState(VK_LSHIFT) & 0x8000) != 0;
-            const GLFWbool rshift = (GetAsyncKeyState(VK_RSHIFT) & 0x8000) != 0;
-
-            if (!lshift && window->keys[GLFW_KEY_LEFT_SHIFT] == GLFW_PRESS)
-            {
-                const int mods = getAsyncKeyMods();
-                const int scancode = _glfw.win32.scancodes[GLFW_KEY_LEFT_SHIFT];
-                _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, GLFW_RELEASE, mods);
-            }
-            else if (!rshift && window->keys[GLFW_KEY_RIGHT_SHIFT] == GLFW_PRESS)
-            {
-                const int mods = getAsyncKeyMods();
-                const int scancode = _glfw.win32.scancodes[GLFW_KEY_RIGHT_SHIFT];
-                _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, 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)
-{
-    PostMessage(_glfw.win32.helperWindowHandle, 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)
-    {
-        if (_glfwPlatformWindowFocused(window))
-            disableCursor(window);
-    }
-    else if (_glfw.win32.disabledCursorWindow == window)
-        enableCursor(window);
-    else if (cursorInContentArea(window))
-        updateCursorImage(window);
-}
-
-const char* _glfwPlatformGetScancodeName(int scancode)
-{
-    return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
-}
-
-int _glfwPlatformGetKeyScancode(int key)
-{
-    return _glfw.win32.scancodes[key];
-}
-
-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)
-{
-    int id = 0;
-
-    if (shape == GLFW_ARROW_CURSOR)
-        id = OCR_NORMAL;
-    else if (shape == GLFW_IBEAM_CURSOR)
-        id = OCR_IBEAM;
-    else if (shape == GLFW_CROSSHAIR_CURSOR)
-        id = OCR_CROSS;
-    else if (shape == GLFW_HAND_CURSOR)
-        id = OCR_HAND;
-    else if (shape == GLFW_HRESIZE_CURSOR)
-        id = OCR_SIZEWE;
-    else if (shape == GLFW_VRESIZE_CURSOR)
-        id = OCR_SIZENS;
-    else
-        return GLFW_FALSE;
-
-    cursor->win32.handle = LoadImageW(NULL,
-                                      MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0,
-                                      LR_DEFAULTSIZE | LR_SHARED);
-    if (!cursor->win32.handle)
-    {
-        _glfwInputErrorWin32(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 (cursorInContentArea(window))
-        updateCursorImage(window);
-}
-
-void _glfwPlatformSetClipboardString(const char* string)
-{
-    int characterCount;
-    HANDLE object;
-    WCHAR* buffer;
-
-    characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
-    if (!characterCount)
-        return;
-
-    object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
-    if (!object)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to allocate global handle for clipboard");
-        return;
-    }
-
-    buffer = GlobalLock(object);
-    if (!buffer)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to lock global handle");
-        GlobalFree(object);
-        return;
-    }
-
-    MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
-    GlobalUnlock(object);
-
-    if (!OpenClipboard(_glfw.win32.helperWindowHandle))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to open clipboard");
-        GlobalFree(object);
-        return;
-    }
-
-    EmptyClipboard();
-    SetClipboardData(CF_UNICODETEXT, object);
-    CloseClipboard();
-}
-
-const char* _glfwPlatformGetClipboardString(void)
-{
-    HANDLE object;
-    WCHAR* buffer;
-
-    if (!OpenClipboard(_glfw.win32.helperWindowHandle))
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to open clipboard");
-        return NULL;
-    }
-
-    object = GetClipboardData(CF_UNICODETEXT);
-    if (!object)
-    {
-        _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
-                             "Win32: Failed to convert clipboard to string");
-        CloseClipboard();
-        return NULL;
-    }
-
-    buffer = GlobalLock(object);
-    if (!buffer)
-    {
-        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
-                             "Win32: Failed to lock global handle");
-        CloseClipboard();
-        return NULL;
-    }
-
-    free(_glfw.win32.clipboardString);
-    _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
-
-    GlobalUnlock(object);
-    CloseClipboard();
-
-    return _glfw.win32.clipboardString;
-}
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
-{
-    if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
-        return;
-
-    extensions[0] = "VK_KHR_surface";
-    extensions[1] = "VK_KHR_win32_surface";
-}
-
-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 native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return window->win32.handle;
-}
-
+//========================================================================
+// GLFW 3.3 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <windowsx.h>
+#include <shellapi.h>
+
+// 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
+    {
+        style |= WS_SYSMENU | WS_MINIMIZEBOX;
+
+        if (window->decorated)
+        {
+            style |= WS_CAPTION;
+
+            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(bi);
+    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)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to create RGBA bitmap");
+        return NULL;
+    }
+
+    mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
+    if (!mask)
+    {
+        _glfwInputErrorWin32(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)
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "Win32: Failed to create icon");
+        }
+        else
+        {
+            _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                                 "Win32: Failed to create cursor");
+        }
+    }
+
+    return handle;
+}
+
+// Translate content area size to full window size according to styles and DPI
+//
+static void getFullWindowSize(DWORD style, DWORD exStyle,
+                              int contentWidth, int contentHeight,
+                              int* fullWidth, int* fullHeight,
+                              UINT dpi)
+{
+    RECT rect = { 0, 0, contentWidth, contentHeight };
+
+    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+        AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, dpi);
+    else
+        AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+    *fullWidth = rect.right - rect.left;
+    *fullHeight = rect.bottom - rect.top;
+}
+
+// Enforce the content area aspect ratio based on which edge is being dragged
+//
+static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
+{
+    int xoff, yoff;
+    UINT dpi = USER_DEFAULT_SCREEN_DPI;
+    const float ratio = (float) window->numer / (float) window->denom;
+
+    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+        dpi = GetDpiForWindow(window->win32.handle);
+
+    getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+                      0, 0, &xoff, &yoff, dpi);
+
+    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);
+    }
+}
+
+// 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);
+}
+
+// Enables WM_INPUT messages for the mouse for the specified window
+//
+static void enableRawMouseMotion(_GLFWwindow* window)
+{
+    const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
+
+    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to register raw input device");
+    }
+}
+
+// Disables WM_INPUT messages for the mouse
+//
+static void disableRawMouseMotion(_GLFWwindow* window)
+{
+    const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_REMOVE, NULL };
+
+    if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to remove raw input device");
+    }
+}
+
+// Apply disabled cursor mode to a focused window
+//
+static void disableCursor(_GLFWwindow* window)
+{
+    _glfw.win32.disabledCursorWindow = window;
+    _glfwPlatformGetCursorPos(window,
+                              &_glfw.win32.restoreCursorPosX,
+                              &_glfw.win32.restoreCursorPosY);
+    updateCursorImage(window);
+    _glfwCenterCursorInContentArea(window);
+    updateClipRect(window);
+
+    if (window->rawMouseMotion)
+        enableRawMouseMotion(window);
+}
+
+// Exit disabled cursor mode for the specified window
+//
+static void enableCursor(_GLFWwindow* window)
+{
+    if (window->rawMouseMotion)
+        disableRawMouseMotion(window);
+
+    _glfw.win32.disabledCursorWindow = NULL;
+    updateClipRect(NULL);
+    _glfwPlatformSetCursorPos(window,
+                              _glfw.win32.restoreCursorPosX,
+                              _glfw.win32.restoreCursorPosY);
+    updateCursorImage(window);
+}
+
+// Returns whether the cursor is in the content area of the specified window
+//
+static GLFWbool cursorInContentArea(_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);
+}
+
+// Update native window styles to match attributes
+//
+static void updateWindowStyles(const _GLFWwindow* window)
+{
+    RECT rect;
+    DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+    style &= ~(WS_OVERLAPPEDWINDOW | WS_POPUP);
+    style |= getWindowStyle(window);
+
+    GetClientRect(window->win32.handle, &rect);
+
+    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+    {
+        AdjustWindowRectExForDpi(&rect, style, FALSE,
+                                 getWindowExStyle(window),
+                                 GetDpiForWindow(window->win32.handle));
+    }
+    else
+        AdjustWindowRectEx(&rect, style, FALSE, getWindowExStyle(window));
+
+    ClientToScreen(window->win32.handle, (POINT*) &rect.left);
+    ClientToScreen(window->win32.handle, (POINT*) &rect.right);
+    SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+    SetWindowPos(window->win32.handle, HWND_TOP,
+                 rect.left, rect.top,
+                 rect.right - rect.left, rect.bottom - rect.top,
+                 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER);
+}
+
+// Update window framebuffer transparency
+//
+static void updateFramebufferTransparency(const _GLFWwindow* window)
+{
+    BOOL enabled;
+
+    if (!IsWindowsVistaOrGreater())
+        return;
+
+    if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
+    {
+        HRGN region = CreateRectRgn(0, 0, -1, -1);
+        DWM_BLURBEHIND bb = {0};
+        bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+        bb.hRgnBlur = region;
+        bb.fEnable = TRUE;
+
+        if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
+        {
+            // Decorated windows don't repaint the transparent background
+            // leaving a trail behind animations
+            // HACK: Making the window layered with a transparency color key
+            //       seems to fix this.  Normally, when specifying
+            //       a transparency color key to be used when composing the
+            //       layered window, all pixels painted by the window in this
+            //       color will be transparent.  That doesn't seem to be the
+            //       case anymore, at least when used with blur behind window
+            //       plus negative region.
+            LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+            exStyle |= WS_EX_LAYERED;
+            SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
+
+            // Using a color key not equal to black to fix the trailing
+            // issue.  When set to black, something is making the hit test
+            // not resize with the window frame.
+            SetLayeredWindowAttributes(window->win32.handle,
+                                       RGB(255, 0, 255), 255, LWA_COLORKEY);
+        }
+
+        DeleteObject(region);
+    }
+    else
+    {
+        LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+        exStyle &= ~WS_EX_LAYERED;
+        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
+        RedrawWindow(window->win32.handle, NULL, NULL,
+                     RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
+    }
+}
+
+// Retrieves and translates modifier keys
+//
+static int getKeyMods(void)
+{
+    int mods = 0;
+
+    if (GetKeyState(VK_SHIFT) & 0x8000)
+        mods |= GLFW_MOD_SHIFT;
+    if (GetKeyState(VK_CONTROL) & 0x8000)
+        mods |= GLFW_MOD_CONTROL;
+    if (GetKeyState(VK_MENU) & 0x8000)
+        mods |= GLFW_MOD_ALT;
+    if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & 0x8000)
+        mods |= GLFW_MOD_SUPER;
+    if (GetKeyState(VK_CAPITAL) & 1)
+        mods |= GLFW_MOD_CAPS_LOCK;
+    if (GetKeyState(VK_NUMLOCK) & 1)
+        mods |= GLFW_MOD_NUM_LOCK;
+
+    return mods;
+}
+
+static void fitToMonitor(_GLFWwindow* window)
+{
+    MONITORINFO mi = { sizeof(mi) };
+    GetMonitorInfo(window->monitor->win32.handle, &mi);
+    SetWindowPos(window->win32.handle, HWND_TOPMOST,
+                 mi.rcMonitor.left,
+                 mi.rcMonitor.top,
+                 mi.rcMonitor.right - mi.rcMonitor.left,
+                 mi.rcMonitor.bottom - mi.rcMonitor.top,
+                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_GLFWwindow* window)
+{
+    if (!_glfw.win32.acquiredMonitorCount)
+    {
+        SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+
+        // HACK: When mouse trails are enabled the cursor becomes invisible when
+        //       the OpenGL ICD switches to page flipping
+        if (IsWindowsXPOrGreater())
+        {
+            SystemParametersInfo(SPI_GETMOUSETRAILS, 0, &_glfw.win32.mouseTrailSize, 0);
+            SystemParametersInfo(SPI_SETMOUSETRAILS, 0, 0, 0);
+        }
+    }
+
+    if (!window->monitor->window)
+        _glfw.win32.acquiredMonitorCount++;
+
+    _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
+    _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+    if (window->monitor->window != window)
+        return;
+
+    _glfw.win32.acquiredMonitorCount--;
+    if (!_glfw.win32.acquiredMonitorCount)
+    {
+        SetThreadExecutionState(ES_CONTINUOUS);
+
+        // HACK: Restore mouse trail length saved in acquireMonitor
+        if (IsWindowsXPOrGreater())
+            SystemParametersInfo(SPI_SETMOUSETRAILS, _glfw.win32.mouseTrailSize, 0, 0);
+    }
+
+    _glfwInputMonitorWindow(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
+        // and for a regular window during its initial creation
+
+        switch (uMsg)
+        {
+            case WM_NCCREATE:
+            {
+                if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+                    EnableNonClientDpiScaling(hWnd);
+
+                break;
+            }
+
+            case WM_DISPLAYCHANGE:
+                _glfwPollMonitorsWin32();
+                break;
+
+            case WM_DEVICECHANGE:
+            {
+                if (wParam == DBT_DEVICEARRIVAL)
+                {
+                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+                        _glfwDetectJoystickConnectionWin32();
+                }
+                else if (wParam == DBT_DEVICEREMOVECOMPLETE)
+                {
+                    DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+                    if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+                        _glfwDetectJoystickDisconnectionWin32();
+                }
+
+                break;
+            }
+        }
+
+        return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+    }
+
+    switch (uMsg)
+    {
+        case WM_MOUSEACTIVATE:
+        {
+            // HACK: Postpone cursor disabling when the window was activated by
+            //       clicking a caption button
+            if (HIWORD(lParam) == WM_LBUTTONDOWN)
+            {
+                if (LOWORD(lParam) != HTCLIENT)
+                    window->win32.frameAction = GLFW_TRUE;
+            }
+
+            break;
+        }
+
+        case WM_CAPTURECHANGED:
+        {
+            // HACK: Disable the cursor once the caption button action has been
+            //       completed or cancelled
+            if (lParam == 0 && window->win32.frameAction)
+            {
+                if (window->cursorMode == GLFW_CURSOR_DISABLED)
+                    disableCursor(window);
+
+                window->win32.frameAction = GLFW_FALSE;
+            }
+
+            break;
+        }
+
+        case WM_SETFOCUS:
+        {
+            _glfwInputWindowFocus(window, GLFW_TRUE);
+
+            // HACK: Do not disable cursor while the user is interacting with
+            //       a caption button
+            if (window->win32.frameAction)
+                break;
+
+            if (window->cursorMode == GLFW_CURSOR_DISABLED)
+                disableCursor(window);
+
+            return 0;
+        }
+
+        case WM_KILLFOCUS:
+        {
+            if (window->cursorMode == GLFW_CURSOR_DISABLED)
+                enableCursor(window);
+
+            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_INPUTLANGCHANGE:
+        {
+            _glfwUpdateKeyNamesWin32();
+            break;
+        }
+
+        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:
+        {
+            int key, scancode;
+            const int action = (HIWORD(lParam) & KF_UP) ? GLFW_RELEASE : GLFW_PRESS;
+            const int mods = getKeyMods();
+
+            scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
+            if (!scancode)
+            {
+                // NOTE: Some synthetic key messages have a scancode of zero
+                // HACK: Map the virtual key back to a usable scancode
+                scancode = MapVirtualKeyW((UINT) wParam, MAPVK_VK_TO_VSC);
+            }
+
+            key = _glfw.win32.keycodes[scancode];
+
+            // The Ctrl keys require special handling
+            if (wParam == VK_CONTROL)
+            {
+                if (HIWORD(lParam) & KF_EXTENDED)
+                {
+                    // Right side keys have the extended key bit set
+                    key = GLFW_KEY_RIGHT_CONTROL;
+                }
+                else
+                {
+                    // NOTE: Alt Gr sends Left Ctrl followed by Right Alt
+                    // HACK: We only want one event for Alt Gr, so if we detect
+                    //       this sequence we discard this Left Ctrl message now
+                    //       and later report Right Alt normally
+                    MSG next;
+                    const DWORD 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 &&
+                                (HIWORD(next.lParam) & KF_EXTENDED) &&
+                                next.time == time)
+                            {
+                                // Next message is Right Alt down so discard this
+                                break;
+                            }
+                        }
+                    }
+
+                    // This is a regular Left Ctrl message
+                    key = GLFW_KEY_LEFT_CONTROL;
+                }
+            }
+            else if (wParam == VK_PROCESSKEY)
+            {
+                // IME notifies that keys have been filtered by setting the
+                // virtual key-code to VK_PROCESSKEY
+                break;
+            }
+
+            if (action == GLFW_RELEASE && wParam == VK_SHIFT)
+            {
+                // HACK: Release both Shift keys on Shift up event, as when both
+                //       are pressed the first release does not emit any event
+                // NOTE: The other half of this is in _glfwPlatformPollEvents
+                _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
+                _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
+            }
+            else if (wParam == VK_SNAPSHOT)
+            {
+                // HACK: 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 i, 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;
+            }
+            else
+                action = GLFW_RELEASE;
+
+            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
+            {
+                if (window->mouseButtons[i] == GLFW_PRESS)
+                    break;
+            }
+
+            if (i > GLFW_MOUSE_BUTTON_LAST)
+                SetCapture(hWnd);
+
+            _glfwInputMouseClick(window, button, action, getKeyMods());
+
+            for (i = 0;  i <= GLFW_MOUSE_BUTTON_LAST;  i++)
+            {
+                if (window->mouseButtons[i] == GLFW_PRESS)
+                    break;
+            }
+
+            if (i > GLFW_MOUSE_BUTTON_LAST)
+                ReleaseCapture();
+
+            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->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);
+            }
+
+            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;
+                if (window->rawMouseMotion)
+                    break;
+
+                _glfwInputCursorPos(window,
+                                    window->virtualCursorPosX + dx,
+                                    window->virtualCursorPosY + dy);
+            }
+            else
+                _glfwInputCursorPos(window, x, y);
+
+            window->win32.lastCursorPosX = x;
+            window->win32.lastCursorPosY = y;
+
+            return 0;
+        }
+
+        case WM_INPUT:
+        {
+            UINT size = 0;
+            HRAWINPUT ri = (HRAWINPUT) lParam;
+            RAWINPUT* data = NULL;
+            int dx, dy;
+
+            if (_glfw.win32.disabledCursorWindow != window)
+                break;
+            if (!window->rawMouseMotion)
+                break;
+
+            GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
+            if (size > (UINT) _glfw.win32.rawInputSize)
+            {
+                free(_glfw.win32.rawInput);
+                _glfw.win32.rawInput = calloc(size, 1);
+                _glfw.win32.rawInputSize = size;
+            }
+
+            size = _glfw.win32.rawInputSize;
+            if (GetRawInputData(ri, RID_INPUT,
+                                _glfw.win32.rawInput, &size,
+                                sizeof(RAWINPUTHEADER)) == (UINT) -1)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Win32: Failed to retrieve raw input data");
+                break;
+            }
+
+            data = _glfw.win32.rawInput;
+            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
+            {
+                dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
+                dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
+            }
+            else
+            {
+                dx = data->data.mouse.lLastX;
+                dy = data->data.mouse.lLastY;
+            }
+
+            _glfwInputCursorPos(window,
+                                window->virtualCursorPosX + dx,
+                                window->virtualCursorPosY + dy);
+
+            window->win32.lastCursorPosX += dx;
+            window->win32.lastCursorPosY += dy;
+            break;
+        }
+
+        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 macOS and X11
+            _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
+            return 0;
+        }
+
+        case WM_ENTERSIZEMOVE:
+        case WM_ENTERMENULOOP:
+        {
+            if (window->win32.frameAction)
+                break;
+
+            // HACK: Enable the cursor while the user is moving or
+            //       resizing the window or using the window menu
+            if (window->cursorMode == GLFW_CURSOR_DISABLED)
+                enableCursor(window);
+
+            break;
+        }
+
+        case WM_EXITSIZEMOVE:
+        case WM_EXITMENULOOP:
+        {
+            if (window->win32.frameAction)
+                break;
+
+            // HACK: Disable the cursor once the user is done moving or
+            //       resizing the window or using the menu
+            if (window->cursorMode == GLFW_CURSOR_DISABLED)
+                disableCursor(window);
+
+            break;
+        }
+
+        case WM_SIZE:
+        {
+            const GLFWbool iconified = wParam == SIZE_MINIMIZED;
+            const GLFWbool maximized = wParam == SIZE_MAXIMIZED ||
+                                       (window->win32.maximized &&
+                                        wParam != SIZE_RESTORED);
+
+            if (_glfw.win32.disabledCursorWindow == window)
+                updateClipRect(window);
+
+            if (window->win32.iconified != iconified)
+                _glfwInputWindowIconify(window, iconified);
+
+            if (window->win32.maximized != maximized)
+                _glfwInputWindowMaximize(window, maximized);
+
+            _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
+            _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
+
+            if (window->monitor && window->win32.iconified != iconified)
+            {
+                if (iconified)
+                    releaseMonitor(window);
+                else
+                {
+                    acquireMonitor(window);
+                    fitToMonitor(window);
+                }
+            }
+
+            window->win32.iconified = iconified;
+            window->win32.maximized = maximized;
+            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;
+            UINT dpi = USER_DEFAULT_SCREEN_DPI;
+            MINMAXINFO* mmi = (MINMAXINFO*) lParam;
+
+            if (window->monitor)
+                break;
+
+            if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+                dpi = GetDpiForWindow(window->win32.handle);
+
+            getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+                              0, 0, &xoff, &yoff, dpi);
+
+            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;
+            }
+
+            if (!window->decorated)
+            {
+                MONITORINFO mi;
+                const HMONITOR mh = MonitorFromWindow(window->win32.handle,
+                                                      MONITOR_DEFAULTTONEAREST);
+
+                ZeroMemory(&mi, sizeof(mi));
+                mi.cbSize = sizeof(mi);
+                GetMonitorInfo(mh, &mi);
+
+                mmi->ptMaxPosition.x = mi.rcWork.left - mi.rcMonitor.left;
+                mmi->ptMaxPosition.y = mi.rcWork.top - mi.rcMonitor.top;
+                mmi->ptMaxSize.x = mi.rcWork.right - mi.rcWork.left;
+                mmi->ptMaxSize.y = mi.rcWork.bottom - mi.rcWork.top;
+            }
+
+            return 0;
+        }
+
+        case WM_PAINT:
+        {
+            _glfwInputWindowDamage(window);
+            break;
+        }
+
+        case WM_ERASEBKGND:
+        {
+            return TRUE;
+        }
+
+        case WM_NCACTIVATE:
+        case WM_NCPAINT:
+        {
+            // Prevent title bar from being drawn after restoring a minimized
+            // undecorated window
+            if (!window->decorated)
+                return TRUE;
+
+            break;
+        }
+
+        case WM_DWMCOMPOSITIONCHANGED:
+        {
+            if (window->win32.transparent)
+                updateFramebufferTransparency(window);
+            return 0;
+        }
+
+        case WM_GETDPISCALEDSIZE:
+        {
+            if (window->win32.scaleToMonitor)
+                break;
+
+            // Adjust the window size to keep the content area size constant
+            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+            {
+                RECT source = {0}, target = {0};
+                SIZE* size = (SIZE*) lParam;
+
+                AdjustWindowRectExForDpi(&source, getWindowStyle(window),
+                                         FALSE, getWindowExStyle(window),
+                                         GetDpiForWindow(window->win32.handle));
+                AdjustWindowRectExForDpi(&target, getWindowStyle(window),
+                                         FALSE, getWindowExStyle(window),
+                                         LOWORD(wParam));
+
+                size->cx += (target.right - target.left) -
+                            (source.right - source.left);
+                size->cy += (target.bottom - target.top) -
+                            (source.bottom - source.top);
+                return TRUE;
+            }
+
+            break;
+        }
+
+        case WM_DPICHANGED:
+        {
+            const float xscale = HIWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
+            const float yscale = LOWORD(wParam) / (float) USER_DEFAULT_SCREEN_DPI;
+
+            // Only apply the suggested size if the OS is new enough to have
+            // sent a WM_GETDPISCALEDSIZE before this
+            if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32())
+            {
+                RECT* suggested = (RECT*) lParam;
+                SetWindowPos(window->win32.handle, HWND_TOP,
+                             suggested->left,
+                             suggested->top,
+                             suggested->right - suggested->left,
+                             suggested->bottom - suggested->top,
+                             SWP_NOACTIVATE | SWP_NOZORDER);
+            }
+
+            _glfwInputWindowContentScale(window, xscale, yscale);
+            break;
+        }
+
+        case WM_SETCURSOR:
+        {
+            if (LOWORD(lParam) == HTCLIENT)
+            {
+                updateCursorImage(window);
+                return TRUE;
+            }
+
+            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((size_t) 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,
+                              const _GLFWfbconfig* fbconfig)
+{
+    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 picked in _glfwSetVideoModeWin32
+        _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+        _glfwPlatformGetVideoMode(window->monitor, &mode);
+        fullWidth  = mode.width;
+        fullHeight = mode.height;
+    }
+    else
+    {
+        xpos = CW_USEDEFAULT;
+        ypos = CW_USEDEFAULT;
+
+        window->win32.maximized = wndconfig->maximized;
+        if (wndconfig->maximized)
+            style |= WS_MAXIMIZE;
+
+        getFullWindowSize(style, exStyle,
+                          wndconfig->width, wndconfig->height,
+                          &fullWidth, &fullHeight,
+                          USER_DEFAULT_SCREEN_DPI);
+    }
+
+    wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
+    if (!wideTitle)
+        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)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to create window");
+        return GLFW_FALSE;
+    }
+
+    SetPropW(window->win32.handle, L"GLFW", window);
+
+    if (IsWindows7OrGreater())
+    {
+        ChangeWindowMessageFilterEx(window->win32.handle,
+                                    WM_DROPFILES, MSGFLT_ALLOW, NULL);
+        ChangeWindowMessageFilterEx(window->win32.handle,
+                                    WM_COPYDATA, MSGFLT_ALLOW, NULL);
+        ChangeWindowMessageFilterEx(window->win32.handle,
+                                    WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
+    }
+
+    window->win32.scaleToMonitor = wndconfig->scaleToMonitor;
+
+    // Adjust window rect to account for DPI scaling of the window frame and
+    // (if enabled) DPI scaling of the content area
+    // This cannot be done until we know what monitor the window was placed on
+    if (!window->monitor)
+    {
+        RECT rect = { 0, 0, wndconfig->width, wndconfig->height };
+        WINDOWPLACEMENT wp = { sizeof(wp) };
+
+        if (wndconfig->scaleToMonitor)
+        {
+            float xscale, yscale;
+            _glfwPlatformGetWindowContentScale(window, &xscale, &yscale);
+            rect.right = (int) (rect.right * xscale);
+            rect.bottom = (int) (rect.bottom * yscale);
+        }
+
+        ClientToScreen(window->win32.handle, (POINT*) &rect.left);
+        ClientToScreen(window->win32.handle, (POINT*) &rect.right);
+
+        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+        {
+            AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
+                                     GetDpiForWindow(window->win32.handle));
+        }
+        else
+            AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+        // Only update the restored window rect as the window may be maximized
+        GetWindowPlacement(window->win32.handle, &wp);
+        wp.rcNormalPosition = rect;
+        wp.showCmd = SW_HIDE;
+        SetWindowPlacement(window->win32.handle, &wp);
+    }
+
+    DragAcceptFiles(window->win32.handle, TRUE);
+
+    if (fbconfig->transparent)
+    {
+        updateFramebufferTransparency(window);
+        window->win32.transparent = GLFW_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))
+    {
+        _glfwInputErrorWin32(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, fbconfig))
+        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 (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+        {
+            if (!_glfwInitEGL())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwInitOSMesa())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+    }
+
+    if (window->monitor)
+    {
+        _glfwPlatformShowWindow(window);
+        _glfwPlatformFocusWindow(window);
+        acquireMonitor(window);
+        fitToMonitor(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)
+        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 };
+
+    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+    {
+        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+                                 FALSE, getWindowExStyle(window),
+                                 GetDpiForWindow(window->win32.handle));
+    }
+    else
+    {
+        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);
+            fitToMonitor(window);
+        }
+    }
+    else
+    {
+        RECT rect = { 0, 0, width, height };
+
+        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+        {
+            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+                                     FALSE, getWindowExStyle(window),
+                                     GetDpiForWindow(window->win32.handle));
+        }
+        else
+        {
+            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);
+
+    if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+    {
+        AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+                                 FALSE, getWindowExStyle(window),
+                                 GetDpiForWindow(window->win32.handle));
+    }
+    else
+    {
+        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 _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale)
+{
+    const HANDLE handle = MonitorFromWindow(window->win32.handle,
+                                            MONITOR_DEFAULTTONEAREST);
+    _glfwGetMonitorContentScaleWin32(handle, xscale, yscale);
+}
+
+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_SHOWNA);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+    ShowWindow(window->win32.handle, SW_HIDE);
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+    FlashWindow(window->win32.handle, TRUE);
+}
+
+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);
+                fitToMonitor(window);
+            }
+        }
+        else
+        {
+            RECT rect = { xpos, ypos, xpos + width, ypos + height };
+
+            if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+            {
+                AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+                                         FALSE, getWindowExStyle(window),
+                                         GetDpiForWindow(window->win32.handle));
+            }
+            else
+            {
+                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);
+
+    _glfwInputWindowMonitor(window, monitor);
+
+    if (window->monitor)
+    {
+        MONITORINFO mi = { sizeof(mi) };
+        UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
+
+        if (window->decorated)
+        {
+            DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+            style &= ~WS_OVERLAPPEDWINDOW;
+            style |= getWindowStyle(window);
+            SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+            flags |= SWP_FRAMECHANGED;
+        }
+
+        acquireMonitor(window);
+
+        GetMonitorInfo(window->monitor->win32.handle, &mi);
+        SetWindowPos(window->win32.handle, HWND_TOPMOST,
+                     mi.rcMonitor.left,
+                     mi.rcMonitor.top,
+                     mi.rcMonitor.right - mi.rcMonitor.left,
+                     mi.rcMonitor.bottom - mi.rcMonitor.top,
+                     flags);
+    }
+    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;
+
+        if (_glfwIsWindows10AnniversaryUpdateOrGreaterWin32())
+        {
+            AdjustWindowRectExForDpi(&rect, getWindowStyle(window),
+                                     FALSE, getWindowExStyle(window),
+                                     GetDpiForWindow(window->win32.handle));
+        }
+        else
+        {
+            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);
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return cursorInContentArea(window);
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+    BOOL enabled;
+
+    if (!window->win32.transparent)
+        return GLFW_FALSE;
+
+    if (!IsWindowsVistaOrGreater())
+        return GLFW_FALSE;
+
+    return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+    updateWindowStyles(window);
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+    updateWindowStyles(window);
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+    const HWND after = enabled ? HWND_TOPMOST : HWND_NOTOPMOST;
+    SetWindowPos(window->win32.handle, after, 0, 0, 0, 0,
+                 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+    BYTE alpha;
+    DWORD flags;
+
+    if ((GetWindowLongW(window->win32.handle, GWL_EXSTYLE) & WS_EX_LAYERED) &&
+        GetLayeredWindowAttributes(window->win32.handle, NULL, &alpha, &flags))
+    {
+        if (flags & LWA_ALPHA)
+            return alpha / 255.f;
+    }
+
+    return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+    if (opacity < 1.f)
+    {
+        const BYTE alpha = (BYTE) (255 * opacity);
+        DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+        style |= WS_EX_LAYERED;
+        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
+        SetLayeredWindowAttributes(window->win32.handle, 0, alpha, LWA_ALPHA);
+    }
+    else
+    {
+        DWORD style = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
+        style &= ~WS_EX_LAYERED;
+        SetWindowLongW(window->win32.handle, GWL_EXSTYLE, style);
+    }
+}
+
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+{
+    if (_glfw.win32.disabledCursorWindow != window)
+        return;
+
+    if (enabled)
+        enableRawMouseMotion(window);
+    else
+        disableRawMouseMotion(window);
+}
+
+GLFWbool _glfwPlatformRawMouseMotionSupported(void)
+{
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+    MSG msg;
+    HWND handle;
+    _GLFWwindow* window;
+
+    while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+    {
+        if (msg.message == WM_QUIT)
+        {
+            // NOTE: While GLFW does not itself post WM_QUIT, other processes
+            //       may post it to this one, for example Task Manager
+            // HACK: Treat WM_QUIT as a close on all windows
+
+            window = _glfw.windowListHead;
+            while (window)
+            {
+                _glfwInputWindowCloseRequest(window);
+                window = window->next;
+            }
+        }
+        else
+        {
+            TranslateMessage(&msg);
+            DispatchMessageW(&msg);
+        }
+    }
+
+    // HACK: Release modifier keys that the system did not emit KEYUP for
+    // NOTE: Shift keys on Windows tend to "stick" when both are pressed as
+    //       no key up message is generated by the first key release
+    // NOTE: Windows key is not reported as released by the Win+V hotkey
+    //       Other Win hotkeys are handled implicitly by _glfwInputWindowFocus
+    //       because they change the input focus
+    // NOTE: The other half of this is in the WM_*KEY* handler in windowProc
+    handle = GetActiveWindow();
+    if (handle)
+    {
+        window = GetPropW(handle, L"GLFW");
+        if (window)
+        {
+            int i;
+            const int keys[4][2] =
+            {
+                { VK_LSHIFT, GLFW_KEY_LEFT_SHIFT },
+                { VK_RSHIFT, GLFW_KEY_RIGHT_SHIFT },
+                { VK_LWIN, GLFW_KEY_LEFT_SUPER },
+                { VK_RWIN, GLFW_KEY_RIGHT_SUPER }
+            };
+
+            for (i = 0;  i < 4;  i++)
+            {
+                const int vk = keys[i][0];
+                const int key = keys[i][1];
+                const int scancode = _glfw.win32.scancodes[key];
+
+                if ((GetKeyState(vk) & 0x8000))
+                    continue;
+                if (window->keys[key] != GLFW_PRESS)
+                    continue;
+
+                _glfwInputKey(window, key, scancode, GLFW_RELEASE, getKeyMods());
+            }
+        }
+    }
+
+    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)
+{
+    PostMessage(_glfw.win32.helperWindowHandle, 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)
+    {
+        if (_glfwPlatformWindowFocused(window))
+            disableCursor(window);
+    }
+    else if (_glfw.win32.disabledCursorWindow == window)
+        enableCursor(window);
+    else if (cursorInContentArea(window))
+        updateCursorImage(window);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+    if (scancode < 0 || scancode > (KF_EXTENDED | 0xff) ||
+        _glfw.win32.keycodes[scancode] == GLFW_KEY_UNKNOWN)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
+        return NULL;
+    }
+
+    return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]];
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+    return _glfw.win32.scancodes[key];
+}
+
+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)
+{
+    int id = 0;
+
+    if (shape == GLFW_ARROW_CURSOR)
+        id = OCR_NORMAL;
+    else if (shape == GLFW_IBEAM_CURSOR)
+        id = OCR_IBEAM;
+    else if (shape == GLFW_CROSSHAIR_CURSOR)
+        id = OCR_CROSS;
+    else if (shape == GLFW_HAND_CURSOR)
+        id = OCR_HAND;
+    else if (shape == GLFW_HRESIZE_CURSOR)
+        id = OCR_SIZEWE;
+    else if (shape == GLFW_VRESIZE_CURSOR)
+        id = OCR_SIZENS;
+    else
+        return GLFW_FALSE;
+
+    cursor->win32.handle = LoadImageW(NULL,
+                                      MAKEINTRESOURCEW(id), IMAGE_CURSOR, 0, 0,
+                                      LR_DEFAULTSIZE | LR_SHARED);
+    if (!cursor->win32.handle)
+    {
+        _glfwInputErrorWin32(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 (cursorInContentArea(window))
+        updateCursorImage(window);
+}
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+    int characterCount;
+    HANDLE object;
+    WCHAR* buffer;
+
+    characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+    if (!characterCount)
+        return;
+
+    object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
+    if (!object)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to allocate global handle for clipboard");
+        return;
+    }
+
+    buffer = GlobalLock(object);
+    if (!buffer)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to lock global handle");
+        GlobalFree(object);
+        return;
+    }
+
+    MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
+    GlobalUnlock(object);
+
+    if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to open clipboard");
+        GlobalFree(object);
+        return;
+    }
+
+    EmptyClipboard();
+    SetClipboardData(CF_UNICODETEXT, object);
+    CloseClipboard();
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+    HANDLE object;
+    WCHAR* buffer;
+
+    if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to open clipboard");
+        return NULL;
+    }
+
+    object = GetClipboardData(CF_UNICODETEXT);
+    if (!object)
+    {
+        _glfwInputErrorWin32(GLFW_FORMAT_UNAVAILABLE,
+                             "Win32: Failed to convert clipboard to string");
+        CloseClipboard();
+        return NULL;
+    }
+
+    buffer = GlobalLock(object);
+    if (!buffer)
+    {
+        _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+                             "Win32: Failed to lock global handle");
+        CloseClipboard();
+        return NULL;
+    }
+
+    free(_glfw.win32.clipboardString);
+    _glfw.win32.clipboardString = _glfwCreateUTF8FromWideStringWin32(buffer);
+
+    GlobalUnlock(object);
+    CloseClipboard();
+
+    return _glfw.win32.clipboardString;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+    if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
+        return;
+
+    extensions[0] = "VK_KHR_surface";
+    extensions[1] = "VK_KHR_win32_surface";
+}
+
+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 native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return window->win32.handle;
+}
+
diff --git a/glfw/src/window.c b/glfw/src/window.c
--- a/glfw/src/window.c
+++ b/glfw/src/window.c
@@ -1,1101 +1,1101 @@
-//========================================================================
-// GLFW 3.3 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// Please use C89 style variable declarations in this file because VS 2010
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <string.h>
-#include <stdlib.h>
-#include <float.h>
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                         GLFW event API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-// Notifies shared code that a window has lost or received input focus
-//
-void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
-{
-    if (window->callbacks.focus)
-        window->callbacks.focus((GLFWwindow*) window, focused);
-
-    if (!focused)
-    {
-        int key, button;
-
-        for (key = 0;  key <= GLFW_KEY_LAST;  key++)
-        {
-            if (window->keys[key] == GLFW_PRESS)
-            {
-                const int scancode = _glfwPlatformGetKeyScancode(key);
-                _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
-            }
-        }
-
-        for (button = 0;  button <= GLFW_MOUSE_BUTTON_LAST;  button++)
-        {
-            if (window->mouseButtons[button] == GLFW_PRESS)
-                _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
-        }
-    }
-}
-
-// Notifies shared code that a window has moved
-// The position is specified in content area relative screen coordinates
-//
-void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
-{
-    if (window->callbacks.pos)
-        window->callbacks.pos((GLFWwindow*) window, x, y);
-}
-
-// Notifies shared code that a window has been resized
-// The size is specified in screen coordinates
-//
-void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
-{
-    if (window->callbacks.size)
-        window->callbacks.size((GLFWwindow*) window, width, height);
-}
-
-// Notifies shared code that a window has been iconified or restored
-//
-void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
-{
-    if (window->callbacks.iconify)
-        window->callbacks.iconify((GLFWwindow*) window, iconified);
-}
-
-// Notifies shared code that a window has been maximized or restored
-//
-void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
-{
-    if (window->callbacks.maximize)
-        window->callbacks.maximize((GLFWwindow*) window, maximized);
-}
-
-// Notifies shared code that a window framebuffer has been resized
-// The size is specified in pixels
-//
-void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
-{
-    if (window->callbacks.fbsize)
-        window->callbacks.fbsize((GLFWwindow*) window, width, height);
-}
-
-// Notifies shared code that a window content scale has changed
-// The scale is specified as the ratio between the current and default DPI
-//
-void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
-{
-    if (window->callbacks.scale)
-        window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
-}
-
-// Notifies shared code that the window contents needs updating
-//
-void _glfwInputWindowDamage(_GLFWwindow* window)
-{
-    if (window->callbacks.refresh)
-        window->callbacks.refresh((GLFWwindow*) window);
-}
-
-// Notifies shared code that the user wishes to close a window
-//
-void _glfwInputWindowCloseRequest(_GLFWwindow* window)
-{
-    window->shouldClose = GLFW_TRUE;
-
-    if (window->callbacks.close)
-        window->callbacks.close((GLFWwindow*) window);
-}
-
-// Notifies shared code that a window has changed its desired monitor
-//
-void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
-{
-    window->monitor = monitor;
-}
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW public API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
-                                     const char* title,
-                                     GLFWmonitor* monitor,
-                                     GLFWwindow* share)
-{
-    _GLFWfbconfig fbconfig;
-    _GLFWctxconfig ctxconfig;
-    _GLFWwndconfig wndconfig;
-    _GLFWwindow* window;
-
-    assert(title != NULL);
-    assert(width >= 0);
-    assert(height >= 0);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-
-    if (width <= 0 || height <= 0)
-    {
-        _glfwInputError(GLFW_INVALID_VALUE,
-                        "Invalid window size %ix%i",
-                        width, height);
-
-        return NULL;
-    }
-
-    fbconfig  = _glfw.hints.framebuffer;
-    ctxconfig = _glfw.hints.context;
-    wndconfig = _glfw.hints.window;
-
-    wndconfig.width   = width;
-    wndconfig.height  = height;
-    wndconfig.title   = title;
-    ctxconfig.share   = (_GLFWwindow*) share;
-
-    if (!_glfwIsValidContextConfig(&ctxconfig))
-        return NULL;
-
-    window = calloc(1, sizeof(_GLFWwindow));
-    window->next = _glfw.windowListHead;
-    _glfw.windowListHead = window;
-
-    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;
-
-    window->monitor     = (_GLFWmonitor*) monitor;
-    window->resizable   = wndconfig.resizable;
-    window->decorated   = wndconfig.decorated;
-    window->autoIconify = wndconfig.autoIconify;
-    window->floating    = wndconfig.floating;
-    window->focusOnShow = wndconfig.focusOnShow;
-    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;
-
-    // Open the actual window and create its context
-    if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
-    {
-        glfwDestroyWindow((GLFWwindow*) window);
-        return NULL;
-    }
-
-    if (ctxconfig.client != GLFW_NO_API)
-    {
-        if (!_glfwRefreshContextAttribs(window, &ctxconfig))
-        {
-            glfwDestroyWindow((GLFWwindow*) window);
-            return NULL;
-        }
-    }
-
-    if (window->monitor)
-    {
-        if (wndconfig.centerCursor)
-            _glfwCenterCursorInContentArea(window);
-    }
-    else
-    {
-        if (wndconfig.visible)
-        {
-            _glfwPlatformShowWindow(window);
-            if (wndconfig.focused)
-                _glfwPlatformFocusWindow(window);
-        }
-    }
-
-    return (GLFWwindow*) window;
-}
-
-void glfwDefaultWindowHints(void)
-{
-    _GLFW_REQUIRE_INIT();
-
-    // The default is OpenGL with minimum version 1.0
-    memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
-    _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
-    memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
-    _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;
-    _glfw.hints.window.centerCursor = GLFW_TRUE;
-    _glfw.hints.window.focusOnShow  = GLFW_TRUE;
-
-    // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
-    // double buffered
-    memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
-    _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;
-
-    // The default is to use full Retina resolution framebuffers
-    _glfw.hints.window.ns.retina = GLFW_TRUE;
-}
-
-GLFWAPI void glfwWindowHint(int hint, int value)
-{
-    _GLFW_REQUIRE_INIT();
-
-    switch (hint)
-    {
-        case GLFW_RED_BITS:
-            _glfw.hints.framebuffer.redBits = value;
-            return;
-        case GLFW_GREEN_BITS:
-            _glfw.hints.framebuffer.greenBits = value;
-            return;
-        case GLFW_BLUE_BITS:
-            _glfw.hints.framebuffer.blueBits = value;
-            return;
-        case GLFW_ALPHA_BITS:
-            _glfw.hints.framebuffer.alphaBits = value;
-            return;
-        case GLFW_DEPTH_BITS:
-            _glfw.hints.framebuffer.depthBits = value;
-            return;
-        case GLFW_STENCIL_BITS:
-            _glfw.hints.framebuffer.stencilBits = value;
-            return;
-        case GLFW_ACCUM_RED_BITS:
-            _glfw.hints.framebuffer.accumRedBits = value;
-            return;
-        case GLFW_ACCUM_GREEN_BITS:
-            _glfw.hints.framebuffer.accumGreenBits = value;
-            return;
-        case GLFW_ACCUM_BLUE_BITS:
-            _glfw.hints.framebuffer.accumBlueBits = value;
-            return;
-        case GLFW_ACCUM_ALPHA_BITS:
-            _glfw.hints.framebuffer.accumAlphaBits = value;
-            return;
-        case GLFW_AUX_BUFFERS:
-            _glfw.hints.framebuffer.auxBuffers = value;
-            return;
-        case GLFW_STEREO:
-            _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_DOUBLEBUFFER:
-            _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_TRANSPARENT_FRAMEBUFFER:
-            _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_SAMPLES:
-            _glfw.hints.framebuffer.samples = value;
-            return;
-        case GLFW_SRGB_CAPABLE:
-            _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_RESIZABLE:
-            _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_DECORATED:
-            _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_FOCUSED:
-            _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_AUTO_ICONIFY:
-            _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_FLOATING:
-            _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_MAXIMIZED:
-            _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_VISIBLE:
-            _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_COCOA_RETINA_FRAMEBUFFER:
-            _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_COCOA_GRAPHICS_SWITCHING:
-            _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_SCALE_TO_MONITOR:
-            _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_CENTER_CURSOR:
-            _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_FOCUS_ON_SHOW:
-            _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_CLIENT_API:
-            _glfw.hints.context.client = value;
-            return;
-        case GLFW_CONTEXT_CREATION_API:
-            _glfw.hints.context.source = value;
-            return;
-        case GLFW_CONTEXT_VERSION_MAJOR:
-            _glfw.hints.context.major = value;
-            return;
-        case GLFW_CONTEXT_VERSION_MINOR:
-            _glfw.hints.context.minor = value;
-            return;
-        case GLFW_CONTEXT_ROBUSTNESS:
-            _glfw.hints.context.robustness = value;
-            return;
-        case GLFW_OPENGL_FORWARD_COMPAT:
-            _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_OPENGL_DEBUG_CONTEXT:
-            _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_CONTEXT_NO_ERROR:
-            _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
-            return;
-        case GLFW_OPENGL_PROFILE:
-            _glfw.hints.context.profile = value;
-            return;
-        case GLFW_CONTEXT_RELEASE_BEHAVIOR:
-            _glfw.hints.context.release = value;
-            return;
-        case GLFW_REFRESH_RATE:
-            _glfw.hints.refreshRate = value;
-            return;
-    }
-
-    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
-}
-
-GLFWAPI void glfwWindowHintString(int hint, const char* value)
-{
-    assert(value != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    switch (hint)
-    {
-        case GLFW_COCOA_FRAME_NAME:
-            strncpy(_glfw.hints.window.ns.frameName, value,
-                    sizeof(_glfw.hints.window.ns.frameName) - 1);
-            return;
-        case GLFW_X11_CLASS_NAME:
-            strncpy(_glfw.hints.window.x11.className, value,
-                    sizeof(_glfw.hints.window.x11.className) - 1);
-            return;
-        case GLFW_X11_INSTANCE_NAME:
-            strncpy(_glfw.hints.window.x11.instanceName, value,
-                    sizeof(_glfw.hints.window.x11.instanceName) - 1);
-            return;
-    }
-
-    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
-}
-
-GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-
-    _GLFW_REQUIRE_INIT();
-
-    // Allow closing of NULL (to match the behavior of free)
-    if (window == NULL)
-        return;
-
-    // Clear all callbacks to avoid exposing a half torn-down window object
-    memset(&window->callbacks, 0, sizeof(window->callbacks));
-
-    // The window's context must not be current on another thread when the
-    // window is destroyed
-    if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
-        glfwMakeContextCurrent(NULL);
-
-    _glfwPlatformDestroyWindow(window);
-
-    // Unlink window from global linked list
-    {
-        _GLFWwindow** prev = &_glfw.windowListHead;
-
-        while (*prev != window)
-            prev = &((*prev)->next);
-
-        *prev = window->next;
-    }
-
-    free(window);
-}
-
-GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(0);
-    return window->shouldClose;
-}
-
-GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-    window->shouldClose = value;
-}
-
-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;
-    if (ypos)
-        *ypos = 0;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetWindowPos(window, xpos, ypos);
-}
-
-GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window->monitor)
-        return;
-
-    _glfwPlatformSetWindowPos(window, xpos, ypos);
-}
-
-GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    if (width)
-        *width = 0;
-    if (height)
-        *height = 0;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetWindowSize(window, width, height);
-}
-
-GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-    assert(width >= 0);
-    assert(height >= 0);
-
-    _GLFW_REQUIRE_INIT();
-
-    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)
-    {
-        if (minwidth < 0 || minheight < 0)
-        {
-            _glfwInputError(GLFW_INVALID_VALUE,
-                            "Invalid window minimum size %ix%i",
-                            minwidth, minheight);
-            return;
-        }
-    }
-
-    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);
-    assert(numer != 0);
-    assert(denom != 0);
-
-    _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;
-    if (height)
-        *height = 0;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetFramebufferSize(window, width, height);
-}
-
-GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
-                                    int* left, int* top,
-                                    int* right, int* bottom)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    if (left)
-        *left = 0;
-    if (top)
-        *top = 0;
-    if (right)
-        *right = 0;
-    if (bottom)
-        *bottom = 0;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
-}
-
-GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
-                                       float* xscale, float* yscale)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    if (xscale)
-        *xscale = 0.f;
-    if (yscale)
-        *yscale = 0.f;
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformGetWindowContentScale(window, xscale, yscale);
-}
-
-GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(1.f);
-    return _glfwPlatformGetWindowOpacity(window);
-}
-
-GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-    assert(opacity == opacity);
-    assert(opacity >= 0.f);
-    assert(opacity <= 1.f);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (opacity != opacity || opacity < 0.f || opacity > 1.f)
-    {
-        _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
-        return;
-    }
-
-    _glfwPlatformSetWindowOpacity(window, opacity);
-}
-
-GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformIconifyWindow(window);
-}
-
-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();
-
-    if (window->monitor)
-        return;
-
-    _glfwPlatformMaximizeWindow(window);
-}
-
-GLFWAPI void glfwShowWindow(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window->monitor)
-        return;
-
-    _glfwPlatformShowWindow(window);
-
-    if (window->focusOnShow)
-        _glfwPlatformFocusWindow(window);
-}
-
-GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    _glfwPlatformRequestWindowAttention(window);
-}
-
-GLFWAPI void glfwHideWindow(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    if (window->monitor)
-        return;
-
-    _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);
-
-    switch (attrib)
-    {
-        case GLFW_FOCUSED:
-            return _glfwPlatformWindowFocused(window);
-        case GLFW_ICONIFIED:
-            return _glfwPlatformWindowIconified(window);
-        case GLFW_VISIBLE:
-            return _glfwPlatformWindowVisible(window);
-        case GLFW_MAXIMIZED:
-            return _glfwPlatformWindowMaximized(window);
-        case GLFW_HOVERED:
-            return _glfwPlatformWindowHovered(window);
-        case GLFW_FOCUS_ON_SHOW:
-            return window->focusOnShow;
-        case GLFW_TRANSPARENT_FRAMEBUFFER:
-            return _glfwPlatformFramebufferTransparent(window);
-        case GLFW_RESIZABLE:
-            return window->resizable;
-        case GLFW_DECORATED:
-            return window->decorated;
-        case GLFW_FLOATING:
-            return window->floating;
-        case GLFW_AUTO_ICONIFY:
-            return window->autoIconify;
-        case GLFW_CLIENT_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:
-            return window->context.minor;
-        case GLFW_CONTEXT_REVISION:
-            return window->context.revision;
-        case GLFW_CONTEXT_ROBUSTNESS:
-            return window->context.robustness;
-        case GLFW_OPENGL_FORWARD_COMPAT:
-            return window->context.forward;
-        case GLFW_OPENGL_DEBUG_CONTEXT:
-            return window->context.debug;
-        case GLFW_OPENGL_PROFILE:
-            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, "Invalid window attribute 0x%08X", attrib);
-    return 0;
-}
-
-GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT();
-
-    value = value ? GLFW_TRUE : GLFW_FALSE;
-
-    if (attrib == GLFW_AUTO_ICONIFY)
-        window->autoIconify = value;
-    else if (attrib == GLFW_RESIZABLE)
-    {
-        if (window->resizable == value)
-            return;
-
-        window->resizable = value;
-        if (!window->monitor)
-            _glfwPlatformSetWindowResizable(window, value);
-    }
-    else if (attrib == GLFW_DECORATED)
-    {
-        if (window->decorated == value)
-            return;
-
-        window->decorated = value;
-        if (!window->monitor)
-            _glfwPlatformSetWindowDecorated(window, value);
-    }
-    else if (attrib == GLFW_FLOATING)
-    {
-        if (window->floating == value)
-            return;
-
-        window->floating = value;
-        if (!window->monitor)
-            _glfwPlatformSetWindowFloating(window, value);
-    }
-    else if (attrib == GLFW_FOCUS_ON_SHOW)
-        window->focusOnShow = value;
-    else
-        _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
-}
-
-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);
-    assert(width >= 0);
-    assert(height >= 0);
-
-    _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;
-}
-
-GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return window->userPointer;
-}
-
-GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
-                                                  GLFWwindowposfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
-                                                    GLFWwindowsizefun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
-                                                      GLFWwindowclosefun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
-                                                          GLFWwindowrefreshfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
-                                                      GLFWwindowfocusfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
-                                                          GLFWwindowiconifyfun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
-                                                            GLFWwindowmaximizefun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
-                                                              GLFWframebuffersizefun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
-    return cbfun;
-}
-
-GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
-                                                                    GLFWwindowcontentscalefun cbfun)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    assert(window != NULL);
-
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
-    return cbfun;
-}
-
-GLFWAPI void glfwPollEvents(void)
-{
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformPollEvents();
-}
-
-GLFWAPI void glfwWaitEvents(void)
-{
-    _GLFW_REQUIRE_INIT();
-    _glfwPlatformWaitEvents();
-}
-
-GLFWAPI void glfwWaitEventsTimeout(double timeout)
-{
-    _GLFW_REQUIRE_INIT();
-    assert(timeout == timeout);
-    assert(timeout >= 0.0);
-    assert(timeout <= DBL_MAX);
-
-    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_REQUIRE_INIT();
-    _glfwPlatformPostEmptyEvent();
-}
+//========================================================================
+// GLFW 3.3 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                         GLFW event API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+// Notifies shared code that a window has lost or received input focus
+//
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
+{
+    if (window->callbacks.focus)
+        window->callbacks.focus((GLFWwindow*) window, focused);
+
+    if (!focused)
+    {
+        int key, button;
+
+        for (key = 0;  key <= GLFW_KEY_LAST;  key++)
+        {
+            if (window->keys[key] == GLFW_PRESS)
+            {
+                const int scancode = _glfwPlatformGetKeyScancode(key);
+                _glfwInputKey(window, key, scancode, GLFW_RELEASE, 0);
+            }
+        }
+
+        for (button = 0;  button <= GLFW_MOUSE_BUTTON_LAST;  button++)
+        {
+            if (window->mouseButtons[button] == GLFW_PRESS)
+                _glfwInputMouseClick(window, button, GLFW_RELEASE, 0);
+        }
+    }
+}
+
+// Notifies shared code that a window has moved
+// The position is specified in content area relative screen coordinates
+//
+void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
+{
+    if (window->callbacks.pos)
+        window->callbacks.pos((GLFWwindow*) window, x, y);
+}
+
+// Notifies shared code that a window has been resized
+// The size is specified in screen coordinates
+//
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
+{
+    if (window->callbacks.size)
+        window->callbacks.size((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window has been iconified or restored
+//
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
+{
+    if (window->callbacks.iconify)
+        window->callbacks.iconify((GLFWwindow*) window, iconified);
+}
+
+// Notifies shared code that a window has been maximized or restored
+//
+void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized)
+{
+    if (window->callbacks.maximize)
+        window->callbacks.maximize((GLFWwindow*) window, maximized);
+}
+
+// Notifies shared code that a window framebuffer has been resized
+// The size is specified in pixels
+//
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
+{
+    if (window->callbacks.fbsize)
+        window->callbacks.fbsize((GLFWwindow*) window, width, height);
+}
+
+// Notifies shared code that a window content scale has changed
+// The scale is specified as the ratio between the current and default DPI
+//
+void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale)
+{
+    if (window->callbacks.scale)
+        window->callbacks.scale((GLFWwindow*) window, xscale, yscale);
+}
+
+// Notifies shared code that the window contents needs updating
+//
+void _glfwInputWindowDamage(_GLFWwindow* window)
+{
+    if (window->callbacks.refresh)
+        window->callbacks.refresh((GLFWwindow*) window);
+}
+
+// Notifies shared code that the user wishes to close a window
+//
+void _glfwInputWindowCloseRequest(_GLFWwindow* window)
+{
+    window->shouldClose = GLFW_TRUE;
+
+    if (window->callbacks.close)
+        window->callbacks.close((GLFWwindow*) window);
+}
+
+// Notifies shared code that a window has changed its desired monitor
+//
+void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
+{
+    window->monitor = monitor;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW public API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
+                                     const char* title,
+                                     GLFWmonitor* monitor,
+                                     GLFWwindow* share)
+{
+    _GLFWfbconfig fbconfig;
+    _GLFWctxconfig ctxconfig;
+    _GLFWwndconfig wndconfig;
+    _GLFWwindow* window;
+
+    assert(title != NULL);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+    if (width <= 0 || height <= 0)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE,
+                        "Invalid window size %ix%i",
+                        width, height);
+
+        return NULL;
+    }
+
+    fbconfig  = _glfw.hints.framebuffer;
+    ctxconfig = _glfw.hints.context;
+    wndconfig = _glfw.hints.window;
+
+    wndconfig.width   = width;
+    wndconfig.height  = height;
+    wndconfig.title   = title;
+    ctxconfig.share   = (_GLFWwindow*) share;
+
+    if (!_glfwIsValidContextConfig(&ctxconfig))
+        return NULL;
+
+    window = calloc(1, sizeof(_GLFWwindow));
+    window->next = _glfw.windowListHead;
+    _glfw.windowListHead = window;
+
+    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;
+
+    window->monitor     = (_GLFWmonitor*) monitor;
+    window->resizable   = wndconfig.resizable;
+    window->decorated   = wndconfig.decorated;
+    window->autoIconify = wndconfig.autoIconify;
+    window->floating    = wndconfig.floating;
+    window->focusOnShow = wndconfig.focusOnShow;
+    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;
+
+    // Open the actual window and create its context
+    if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
+    {
+        glfwDestroyWindow((GLFWwindow*) window);
+        return NULL;
+    }
+
+    if (ctxconfig.client != GLFW_NO_API)
+    {
+        if (!_glfwRefreshContextAttribs(window, &ctxconfig))
+        {
+            glfwDestroyWindow((GLFWwindow*) window);
+            return NULL;
+        }
+    }
+
+    if (window->monitor)
+    {
+        if (wndconfig.centerCursor)
+            _glfwCenterCursorInContentArea(window);
+    }
+    else
+    {
+        if (wndconfig.visible)
+        {
+            _glfwPlatformShowWindow(window);
+            if (wndconfig.focused)
+                _glfwPlatformFocusWindow(window);
+        }
+    }
+
+    return (GLFWwindow*) window;
+}
+
+void glfwDefaultWindowHints(void)
+{
+    _GLFW_REQUIRE_INIT();
+
+    // The default is OpenGL with minimum version 1.0
+    memset(&_glfw.hints.context, 0, sizeof(_glfw.hints.context));
+    _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
+    memset(&_glfw.hints.window, 0, sizeof(_glfw.hints.window));
+    _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;
+    _glfw.hints.window.centerCursor = GLFW_TRUE;
+    _glfw.hints.window.focusOnShow  = GLFW_TRUE;
+
+    // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
+    // double buffered
+    memset(&_glfw.hints.framebuffer, 0, sizeof(_glfw.hints.framebuffer));
+    _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;
+
+    // The default is to use full Retina resolution framebuffers
+    _glfw.hints.window.ns.retina = GLFW_TRUE;
+}
+
+GLFWAPI void glfwWindowHint(int hint, int value)
+{
+    _GLFW_REQUIRE_INIT();
+
+    switch (hint)
+    {
+        case GLFW_RED_BITS:
+            _glfw.hints.framebuffer.redBits = value;
+            return;
+        case GLFW_GREEN_BITS:
+            _glfw.hints.framebuffer.greenBits = value;
+            return;
+        case GLFW_BLUE_BITS:
+            _glfw.hints.framebuffer.blueBits = value;
+            return;
+        case GLFW_ALPHA_BITS:
+            _glfw.hints.framebuffer.alphaBits = value;
+            return;
+        case GLFW_DEPTH_BITS:
+            _glfw.hints.framebuffer.depthBits = value;
+            return;
+        case GLFW_STENCIL_BITS:
+            _glfw.hints.framebuffer.stencilBits = value;
+            return;
+        case GLFW_ACCUM_RED_BITS:
+            _glfw.hints.framebuffer.accumRedBits = value;
+            return;
+        case GLFW_ACCUM_GREEN_BITS:
+            _glfw.hints.framebuffer.accumGreenBits = value;
+            return;
+        case GLFW_ACCUM_BLUE_BITS:
+            _glfw.hints.framebuffer.accumBlueBits = value;
+            return;
+        case GLFW_ACCUM_ALPHA_BITS:
+            _glfw.hints.framebuffer.accumAlphaBits = value;
+            return;
+        case GLFW_AUX_BUFFERS:
+            _glfw.hints.framebuffer.auxBuffers = value;
+            return;
+        case GLFW_STEREO:
+            _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_DOUBLEBUFFER:
+            _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_TRANSPARENT_FRAMEBUFFER:
+            _glfw.hints.framebuffer.transparent = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_SAMPLES:
+            _glfw.hints.framebuffer.samples = value;
+            return;
+        case GLFW_SRGB_CAPABLE:
+            _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_RESIZABLE:
+            _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_DECORATED:
+            _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FOCUSED:
+            _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_AUTO_ICONIFY:
+            _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FLOATING:
+            _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_MAXIMIZED:
+            _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_VISIBLE:
+            _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_COCOA_RETINA_FRAMEBUFFER:
+            _glfw.hints.window.ns.retina = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_COCOA_GRAPHICS_SWITCHING:
+            _glfw.hints.context.nsgl.offline = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_SCALE_TO_MONITOR:
+            _glfw.hints.window.scaleToMonitor = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CENTER_CURSOR:
+            _glfw.hints.window.centerCursor = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_FOCUS_ON_SHOW:
+            _glfw.hints.window.focusOnShow = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CLIENT_API:
+            _glfw.hints.context.client = value;
+            return;
+        case GLFW_CONTEXT_CREATION_API:
+            _glfw.hints.context.source = value;
+            return;
+        case GLFW_CONTEXT_VERSION_MAJOR:
+            _glfw.hints.context.major = value;
+            return;
+        case GLFW_CONTEXT_VERSION_MINOR:
+            _glfw.hints.context.minor = value;
+            return;
+        case GLFW_CONTEXT_ROBUSTNESS:
+            _glfw.hints.context.robustness = value;
+            return;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_OPENGL_DEBUG_CONTEXT:
+            _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_CONTEXT_NO_ERROR:
+            _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
+            return;
+        case GLFW_OPENGL_PROFILE:
+            _glfw.hints.context.profile = value;
+            return;
+        case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+            _glfw.hints.context.release = value;
+            return;
+        case GLFW_REFRESH_RATE:
+            _glfw.hints.refreshRate = value;
+            return;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint 0x%08X", hint);
+}
+
+GLFWAPI void glfwWindowHintString(int hint, const char* value)
+{
+    assert(value != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    switch (hint)
+    {
+        case GLFW_COCOA_FRAME_NAME:
+            strncpy(_glfw.hints.window.ns.frameName, value,
+                    sizeof(_glfw.hints.window.ns.frameName) - 1);
+            return;
+        case GLFW_X11_CLASS_NAME:
+            strncpy(_glfw.hints.window.x11.className, value,
+                    sizeof(_glfw.hints.window.x11.className) - 1);
+            return;
+        case GLFW_X11_INSTANCE_NAME:
+            strncpy(_glfw.hints.window.x11.instanceName, value,
+                    sizeof(_glfw.hints.window.x11.instanceName) - 1);
+            return;
+    }
+
+    _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint string 0x%08X", hint);
+}
+
+GLFWAPI void glfwDestroyWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+
+    _GLFW_REQUIRE_INIT();
+
+    // Allow closing of NULL (to match the behavior of free)
+    if (window == NULL)
+        return;
+
+    // Clear all callbacks to avoid exposing a half torn-down window object
+    memset(&window->callbacks, 0, sizeof(window->callbacks));
+
+    // The window's context must not be current on another thread when the
+    // window is destroyed
+    if (window == _glfwPlatformGetTls(&_glfw.contextSlot))
+        glfwMakeContextCurrent(NULL);
+
+    _glfwPlatformDestroyWindow(window);
+
+    // Unlink window from global linked list
+    {
+        _GLFWwindow** prev = &_glfw.windowListHead;
+
+        while (*prev != window)
+            prev = &((*prev)->next);
+
+        *prev = window->next;
+    }
+
+    free(window);
+}
+
+GLFWAPI int glfwWindowShouldClose(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(0);
+    return window->shouldClose;
+}
+
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    window->shouldClose = value;
+}
+
+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;
+    if (ypos)
+        *ypos = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwSetWindowPos(GLFWwindow* handle, int xpos, int ypos)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformSetWindowPos(window, xpos, ypos);
+}
+
+GLFWAPI void glfwGetWindowSize(GLFWwindow* handle, int* width, int* height)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (width)
+        *width = 0;
+    if (height)
+        *height = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowSize(window, width, height);
+}
+
+GLFWAPI void glfwSetWindowSize(GLFWwindow* handle, int width, int height)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _GLFW_REQUIRE_INIT();
+
+    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)
+    {
+        if (minwidth < 0 || minheight < 0)
+        {
+            _glfwInputError(GLFW_INVALID_VALUE,
+                            "Invalid window minimum size %ix%i",
+                            minwidth, minheight);
+            return;
+        }
+    }
+
+    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);
+    assert(numer != 0);
+    assert(denom != 0);
+
+    _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;
+    if (height)
+        *height = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetFramebufferSize(window, width, height);
+}
+
+GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* handle,
+                                    int* left, int* top,
+                                    int* right, int* bottom)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (left)
+        *left = 0;
+    if (top)
+        *top = 0;
+    if (right)
+        *right = 0;
+    if (bottom)
+        *bottom = 0;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowFrameSize(window, left, top, right, bottom);
+}
+
+GLFWAPI void glfwGetWindowContentScale(GLFWwindow* handle,
+                                       float* xscale, float* yscale)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    if (xscale)
+        *xscale = 0.f;
+    if (yscale)
+        *yscale = 0.f;
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformGetWindowContentScale(window, xscale, yscale);
+}
+
+GLFWAPI float glfwGetWindowOpacity(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(1.f);
+    return _glfwPlatformGetWindowOpacity(window);
+}
+
+GLFWAPI void glfwSetWindowOpacity(GLFWwindow* handle, float opacity)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+    assert(opacity == opacity);
+    assert(opacity >= 0.f);
+    assert(opacity <= 1.f);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (opacity != opacity || opacity < 0.f || opacity > 1.f)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid window opacity %f", opacity);
+        return;
+    }
+
+    _glfwPlatformSetWindowOpacity(window, opacity);
+}
+
+GLFWAPI void glfwIconifyWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformIconifyWindow(window);
+}
+
+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();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformMaximizeWindow(window);
+}
+
+GLFWAPI void glfwShowWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _glfwPlatformShowWindow(window);
+
+    if (window->focusOnShow)
+        _glfwPlatformFocusWindow(window);
+}
+
+GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    _glfwPlatformRequestWindowAttention(window);
+}
+
+GLFWAPI void glfwHideWindow(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    if (window->monitor)
+        return;
+
+    _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);
+
+    switch (attrib)
+    {
+        case GLFW_FOCUSED:
+            return _glfwPlatformWindowFocused(window);
+        case GLFW_ICONIFIED:
+            return _glfwPlatformWindowIconified(window);
+        case GLFW_VISIBLE:
+            return _glfwPlatformWindowVisible(window);
+        case GLFW_MAXIMIZED:
+            return _glfwPlatformWindowMaximized(window);
+        case GLFW_HOVERED:
+            return _glfwPlatformWindowHovered(window);
+        case GLFW_FOCUS_ON_SHOW:
+            return window->focusOnShow;
+        case GLFW_TRANSPARENT_FRAMEBUFFER:
+            return _glfwPlatformFramebufferTransparent(window);
+        case GLFW_RESIZABLE:
+            return window->resizable;
+        case GLFW_DECORATED:
+            return window->decorated;
+        case GLFW_FLOATING:
+            return window->floating;
+        case GLFW_AUTO_ICONIFY:
+            return window->autoIconify;
+        case GLFW_CLIENT_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:
+            return window->context.minor;
+        case GLFW_CONTEXT_REVISION:
+            return window->context.revision;
+        case GLFW_CONTEXT_ROBUSTNESS:
+            return window->context.robustness;
+        case GLFW_OPENGL_FORWARD_COMPAT:
+            return window->context.forward;
+        case GLFW_OPENGL_DEBUG_CONTEXT:
+            return window->context.debug;
+        case GLFW_OPENGL_PROFILE:
+            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, "Invalid window attribute 0x%08X", attrib);
+    return 0;
+}
+
+GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT();
+
+    value = value ? GLFW_TRUE : GLFW_FALSE;
+
+    if (attrib == GLFW_AUTO_ICONIFY)
+        window->autoIconify = value;
+    else if (attrib == GLFW_RESIZABLE)
+    {
+        if (window->resizable == value)
+            return;
+
+        window->resizable = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowResizable(window, value);
+    }
+    else if (attrib == GLFW_DECORATED)
+    {
+        if (window->decorated == value)
+            return;
+
+        window->decorated = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowDecorated(window, value);
+    }
+    else if (attrib == GLFW_FLOATING)
+    {
+        if (window->floating == value)
+            return;
+
+        window->floating = value;
+        if (!window->monitor)
+            _glfwPlatformSetWindowFloating(window, value);
+    }
+    else if (attrib == GLFW_FOCUS_ON_SHOW)
+        window->focusOnShow = value;
+    else
+        _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib);
+}
+
+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);
+    assert(width >= 0);
+    assert(height >= 0);
+
+    _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;
+}
+
+GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return window->userPointer;
+}
+
+GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* handle,
+                                                  GLFWwindowposfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.pos, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* handle,
+                                                    GLFWwindowsizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.size, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* handle,
+                                                      GLFWwindowclosefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.close, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* handle,
+                                                          GLFWwindowrefreshfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.refresh, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* handle,
+                                                      GLFWwindowfocusfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.focus, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* handle,
+                                                          GLFWwindowiconifyfun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.iconify, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* handle,
+                                                            GLFWwindowmaximizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.maximize, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* handle,
+                                                              GLFWframebuffersizefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.fbsize, cbfun);
+    return cbfun;
+}
+
+GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* handle,
+                                                                    GLFWwindowcontentscalefun cbfun)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    assert(window != NULL);
+
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    _GLFW_SWAP_POINTERS(window->callbacks.scale, cbfun);
+    return cbfun;
+}
+
+GLFWAPI void glfwPollEvents(void)
+{
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformPollEvents();
+}
+
+GLFWAPI void glfwWaitEvents(void)
+{
+    _GLFW_REQUIRE_INIT();
+    _glfwPlatformWaitEvents();
+}
+
+GLFWAPI void glfwWaitEventsTimeout(double timeout)
+{
+    _GLFW_REQUIRE_INIT();
+    assert(timeout == timeout);
+    assert(timeout >= 0.0);
+    assert(timeout <= DBL_MAX);
+
+    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_REQUIRE_INIT();
+    _glfwPlatformPostEmptyEvent();
+}
diff --git a/glfw/src/wl_init.c b/glfw/src/wl_init.c
--- a/glfw/src/wl_init.c
+++ b/glfw/src/wl_init.c
@@ -1,1324 +1,1324 @@
-//========================================================================
-// GLFW 3.3 Wayland - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
-// 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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <limits.h>
-#include <linux/input.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/timerfd.h>
-#include <unistd.h>
-#include <wayland-client.h>
-
-
-static inline int min(int n1, int n2)
-{
-    return n1 < n2 ? n1 : n2;
-}
-
-static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
-                                                    int* which)
-{
-    int focus;
-    _GLFWwindow* window = _glfw.windowListHead;
-    if (!which)
-        which = &focus;
-    while (window)
-    {
-        if (surface == window->wl.decorations.top.surface)
-        {
-            *which = topDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.left.surface)
-        {
-            *which = leftDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.right.surface)
-        {
-            *which = rightDecoration;
-            break;
-        }
-        if (surface == window->wl.decorations.bottom.surface)
-        {
-            *which = bottomDecoration;
-            break;
-        }
-        window = window->next;
-    }
-    return window;
-}
-
-static void pointerHandleEnter(void* data,
-                               struct wl_pointer* pointer,
-                               uint32_t serial,
-                               struct wl_surface* surface,
-                               wl_fixed_t sx,
-                               wl_fixed_t sy)
-{
-    // Happens in the case we just destroyed the surface.
-    if (!surface)
-        return;
-
-    int focus = 0;
-    _GLFWwindow* window = wl_surface_get_user_data(surface);
-    if (!window)
-    {
-        window = findWindowFromDecorationSurface(surface, &focus);
-        if (!window)
-            return;
-    }
-
-    window->wl.decorations.focus = focus;
-    _glfw.wl.serial = serial;
-    _glfw.wl.pointerFocus = window;
-
-    window->wl.hovered = GLFW_TRUE;
-
-    _glfwPlatformSetCursor(window, window->wl.currentCursor);
-    _glfwInputCursorEnter(window, GLFW_TRUE);
-}
-
-static void pointerHandleLeave(void* data,
-                               struct wl_pointer* pointer,
-                               uint32_t serial,
-                               struct wl_surface* surface)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-
-    if (!window)
-        return;
-
-    window->wl.hovered = GLFW_FALSE;
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.pointerFocus = NULL;
-    _glfwInputCursorEnter(window, GLFW_FALSE);
-    _glfw.wl.cursorPreviousName = NULL;
-}
-
-static void setCursor(_GLFWwindow* window, const char* name)
-{
-    struct wl_buffer* buffer;
-    struct wl_cursor* cursor;
-    struct wl_cursor_image* image;
-    struct wl_surface* surface = _glfw.wl.cursorSurface;
-    struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
-    int scale = 1;
-
-    if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
-    {
-        // We only support up to scale=2 for now, since libwayland-cursor
-        // requires us to load a different theme for each size.
-        scale = 2;
-        theme = _glfw.wl.cursorThemeHiDPI;
-    }
-
-    cursor = wl_cursor_theme_get_cursor(theme, name);
-    if (!cursor)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Standard cursor not found");
-        return;
-    }
-    // TODO: handle animated cursors too.
-    image = cursor->images[0];
-
-    if (!image)
-        return;
-
-    buffer = wl_cursor_image_get_buffer(image);
-    if (!buffer)
-        return;
-    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
-                          surface,
-                          image->hotspot_x / scale,
-                          image->hotspot_y / scale);
-    wl_surface_set_buffer_scale(surface, scale);
-    wl_surface_attach(surface, buffer, 0, 0);
-    wl_surface_damage(surface, 0, 0,
-                      image->width, image->height);
-    wl_surface_commit(surface);
-    _glfw.wl.cursorPreviousName = name;
-}
-
-static void pointerHandleMotion(void* data,
-                                struct wl_pointer* pointer,
-                                uint32_t time,
-                                wl_fixed_t sx,
-                                wl_fixed_t sy)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    const char* cursorName = NULL;
-    double x, y;
-
-    if (!window)
-        return;
-
-    if (window->cursorMode == GLFW_CURSOR_DISABLED)
-        return;
-    x = wl_fixed_to_double(sx);
-    y = wl_fixed_to_double(sy);
-
-    switch (window->wl.decorations.focus)
-    {
-        case mainWindow:
-            window->wl.cursorPosX = x;
-            window->wl.cursorPosY = y;
-            _glfwInputCursorPos(window, x, y);
-            _glfw.wl.cursorPreviousName = NULL;
-            return;
-        case topDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "n-resize";
-            else
-                cursorName = "left_ptr";
-            break;
-        case leftDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "nw-resize";
-            else
-                cursorName = "w-resize";
-            break;
-        case rightDecoration:
-            if (y < _GLFW_DECORATION_WIDTH)
-                cursorName = "ne-resize";
-            else
-                cursorName = "e-resize";
-            break;
-        case bottomDecoration:
-            if (x < _GLFW_DECORATION_WIDTH)
-                cursorName = "sw-resize";
-            else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
-                cursorName = "se-resize";
-            else
-                cursorName = "s-resize";
-            break;
-        default:
-            assert(0);
-    }
-    if (_glfw.wl.cursorPreviousName != cursorName)
-        setCursor(window, cursorName);
-}
-
-static void pointerHandleButton(void* data,
-                                struct wl_pointer* pointer,
-                                uint32_t serial,
-                                uint32_t time,
-                                uint32_t button,
-                                uint32_t state)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    int glfwButton;
-
-    // Both xdg-shell and wl_shell use the same values.
-    uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
-
-    if (!window)
-        return;
-    if (button == BTN_LEFT)
-    {
-        switch (window->wl.decorations.focus)
-        {
-            case mainWindow:
-                break;
-            case topDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP;
-                else
-                {
-                    if (window->wl.xdg.toplevel)
-                        xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
-                    else
-                        wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
-                }
-                break;
-            case leftDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_LEFT;
-                break;
-            case rightDecoration:
-                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
-                break;
-            case bottomDecoration:
-                if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
-                else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
-                else
-                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
-                break;
-            default:
-                assert(0);
-        }
-        if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
-        {
-            if (window->wl.xdg.toplevel)
-                xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
-                                    serial, edges);
-            else
-                wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
-                                        serial, edges);
-        }
-    }
-    else if (button == BTN_RIGHT)
-    {
-        if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
-        {
-            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
-                                          _glfw.wl.seat, serial,
-                                          window->wl.cursorPosX,
-                                          window->wl.cursorPosY);
-            return;
-        }
-    }
-
-    // Don’t pass the button to the user if it was related to a decoration.
-    if (window->wl.decorations.focus != mainWindow)
-        return;
-
-    _glfw.wl.serial = serial;
-
-    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
-     * codes. */
-    glfwButton = button - BTN_LEFT;
-
-    _glfwInputMouseClick(window,
-                         glfwButton,
-                         state == WL_POINTER_BUTTON_STATE_PRESSED
-                                ? GLFW_PRESS
-                                : GLFW_RELEASE,
-                         _glfw.wl.xkb.modifiers);
-}
-
-static void pointerHandleAxis(void* data,
-                              struct wl_pointer* pointer,
-                              uint32_t time,
-                              uint32_t axis,
-                              wl_fixed_t value)
-{
-    _GLFWwindow* window = _glfw.wl.pointerFocus;
-    double x = 0.0, y = 0.0;
-    // Wayland scroll events are in pointer motion coordinate space (think two
-    // finger scroll).  The factor 10 is commonly used to convert to "scroll
-    // step means 1.0.
-    const double scrollFactor = 1.0 / 10.0;
-
-    if (!window)
-        return;
-
-    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
-           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
-
-    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
-        x = wl_fixed_to_double(value) * scrollFactor;
-    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
-        y = wl_fixed_to_double(value) * scrollFactor;
-
-    _glfwInputScroll(window, x, y);
-}
-
-static const struct wl_pointer_listener pointerListener = {
-    pointerHandleEnter,
-    pointerHandleLeave,
-    pointerHandleMotion,
-    pointerHandleButton,
-    pointerHandleAxis,
-};
-
-static void keyboardHandleKeymap(void* data,
-                                 struct wl_keyboard* keyboard,
-                                 uint32_t format,
-                                 int fd,
-                                 uint32_t size)
-{
-    struct xkb_keymap* keymap;
-    struct xkb_state* state;
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-    struct xkb_compose_table* composeTable;
-    struct xkb_compose_state* composeState;
-#endif
-
-    char* mapStr;
-    const char* locale;
-
-    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
-    {
-        close(fd);
-        return;
-    }
-
-    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
-    if (mapStr == MAP_FAILED) {
-        close(fd);
-        return;
-    }
-
-    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
-                                        mapStr,
-                                        XKB_KEYMAP_FORMAT_TEXT_V1,
-                                        0);
-    munmap(mapStr, size);
-    close(fd);
-
-    if (!keymap)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to compile keymap");
-        return;
-    }
-
-    state = xkb_state_new(keymap);
-    if (!state)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to create XKB state");
-        xkb_keymap_unref(keymap);
-        return;
-    }
-
-    // Look up the preferred locale, falling back to "C" as default.
-    locale = getenv("LC_ALL");
-    if (!locale)
-        locale = getenv("LC_CTYPE");
-    if (!locale)
-        locale = getenv("LANG");
-    if (!locale)
-        locale = "C";
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-    composeTable =
-        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
-                                          XKB_COMPOSE_COMPILE_NO_FLAGS);
-    if (composeTable)
-    {
-        composeState =
-            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
-        xkb_compose_table_unref(composeTable);
-        if (composeState)
-            _glfw.wl.xkb.composeState = composeState;
-        else
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Failed to create XKB compose state");
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to create XKB compose table");
-    }
-#endif
-
-    xkb_keymap_unref(_glfw.wl.xkb.keymap);
-    xkb_state_unref(_glfw.wl.xkb.state);
-    _glfw.wl.xkb.keymap = keymap;
-    _glfw.wl.xkb.state = state;
-
-    _glfw.wl.xkb.controlMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
-    _glfw.wl.xkb.altMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
-    _glfw.wl.xkb.shiftMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
-    _glfw.wl.xkb.superMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
-    _glfw.wl.xkb.capsLockMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
-    _glfw.wl.xkb.numLockMask =
-        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
-}
-
-static void keyboardHandleEnter(void* data,
-                                struct wl_keyboard* keyboard,
-                                uint32_t serial,
-                                struct wl_surface* surface,
-                                struct wl_array* keys)
-{
-    // Happens in the case we just destroyed the surface.
-    if (!surface)
-        return;
-
-    _GLFWwindow* window = wl_surface_get_user_data(surface);
-    if (!window)
-    {
-        window = findWindowFromDecorationSurface(surface, NULL);
-        if (!window)
-            return;
-    }
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.keyboardFocus = window;
-    _glfwInputWindowFocus(window, GLFW_TRUE);
-}
-
-static void keyboardHandleLeave(void* data,
-                                struct wl_keyboard* keyboard,
-                                uint32_t serial,
-                                struct wl_surface* surface)
-{
-    _GLFWwindow* window = _glfw.wl.keyboardFocus;
-
-    if (!window)
-        return;
-
-    _glfw.wl.serial = serial;
-    _glfw.wl.keyboardFocus = NULL;
-    _glfwInputWindowFocus(window, GLFW_FALSE);
-}
-
-static int toGLFWKeyCode(uint32_t key)
-{
-    if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
-        return _glfw.wl.keycodes[key];
-
-    return GLFW_KEY_UNKNOWN;
-}
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
-{
-    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
-        return sym;
-    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
-            != XKB_COMPOSE_FEED_ACCEPTED)
-        return sym;
-    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
-    {
-        case XKB_COMPOSE_COMPOSED:
-            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
-        case XKB_COMPOSE_COMPOSING:
-        case XKB_COMPOSE_CANCELLED:
-            return XKB_KEY_NoSymbol;
-        case XKB_COMPOSE_NOTHING:
-        default:
-            return sym;
-    }
-}
-#endif
-
-static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
-{
-    uint32_t code, numSyms;
-    long cp;
-    const xkb_keysym_t *syms;
-    xkb_keysym_t sym;
-
-    code = key + 8;
-    numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
-
-    if (numSyms == 1)
-    {
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-        sym = composeSymbol(syms[0]);
-#else
-        sym = syms[0];
-#endif
-        cp = _glfwKeySym2Unicode(sym);
-        if (cp != -1)
-        {
-            const int mods = _glfw.wl.xkb.modifiers;
-            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
-            _glfwInputChar(window, cp, mods, plain);
-        }
-    }
-
-    return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
-}
-
-static void keyboardHandleKey(void* data,
-                              struct wl_keyboard* keyboard,
-                              uint32_t serial,
-                              uint32_t time,
-                              uint32_t key,
-                              uint32_t state)
-{
-    int keyCode;
-    int action;
-    _GLFWwindow* window = _glfw.wl.keyboardFocus;
-    GLFWbool shouldRepeat;
-    struct itimerspec timer = {};
-
-    if (!window)
-        return;
-
-    keyCode = toGLFWKeyCode(key);
-    action = state == WL_KEYBOARD_KEY_STATE_PRESSED
-            ? GLFW_PRESS : GLFW_RELEASE;
-
-    _glfw.wl.serial = serial;
-    _glfwInputKey(window, keyCode, key, action,
-                  _glfw.wl.xkb.modifiers);
-
-    if (action == GLFW_PRESS)
-    {
-        shouldRepeat = inputChar(window, key);
-
-        if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
-        {
-            _glfw.wl.keyboardLastKey = keyCode;
-            _glfw.wl.keyboardLastScancode = key;
-            if (_glfw.wl.keyboardRepeatRate > 1)
-                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
-            else
-                timer.it_interval.tv_sec = 1;
-            timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
-            timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
-        }
-    }
-    timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
-}
-
-static void keyboardHandleModifiers(void* data,
-                                    struct wl_keyboard* keyboard,
-                                    uint32_t serial,
-                                    uint32_t modsDepressed,
-                                    uint32_t modsLatched,
-                                    uint32_t modsLocked,
-                                    uint32_t group)
-{
-    xkb_mod_mask_t mask;
-    unsigned int modifiers = 0;
-
-    _glfw.wl.serial = serial;
-
-    if (!_glfw.wl.xkb.keymap)
-        return;
-
-    xkb_state_update_mask(_glfw.wl.xkb.state,
-                          modsDepressed,
-                          modsLatched,
-                          modsLocked,
-                          0,
-                          0,
-                          group);
-
-    mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
-                                    XKB_STATE_MODS_DEPRESSED |
-                                    XKB_STATE_LAYOUT_DEPRESSED |
-                                    XKB_STATE_MODS_LATCHED |
-                                    XKB_STATE_LAYOUT_LATCHED);
-    if (mask & _glfw.wl.xkb.controlMask)
-        modifiers |= GLFW_MOD_CONTROL;
-    if (mask & _glfw.wl.xkb.altMask)
-        modifiers |= GLFW_MOD_ALT;
-    if (mask & _glfw.wl.xkb.shiftMask)
-        modifiers |= GLFW_MOD_SHIFT;
-    if (mask & _glfw.wl.xkb.superMask)
-        modifiers |= GLFW_MOD_SUPER;
-    if (mask & _glfw.wl.xkb.capsLockMask)
-        modifiers |= GLFW_MOD_CAPS_LOCK;
-    if (mask & _glfw.wl.xkb.numLockMask)
-        modifiers |= GLFW_MOD_NUM_LOCK;
-    _glfw.wl.xkb.modifiers = modifiers;
-}
-
-#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
-static void keyboardHandleRepeatInfo(void* data,
-                                     struct wl_keyboard* keyboard,
-                                     int32_t rate,
-                                     int32_t delay)
-{
-    if (keyboard != _glfw.wl.keyboard)
-        return;
-
-    _glfw.wl.keyboardRepeatRate = rate;
-    _glfw.wl.keyboardRepeatDelay = delay;
-}
-#endif
-
-static const struct wl_keyboard_listener keyboardListener = {
-    keyboardHandleKeymap,
-    keyboardHandleEnter,
-    keyboardHandleLeave,
-    keyboardHandleKey,
-    keyboardHandleModifiers,
-#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
-    keyboardHandleRepeatInfo,
-#endif
-};
-
-static void seatHandleCapabilities(void* data,
-                                   struct wl_seat* seat,
-                                   enum wl_seat_capability caps)
-{
-    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
-    {
-        _glfw.wl.pointer = wl_seat_get_pointer(seat);
-        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
-    }
-    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
-    {
-        wl_pointer_destroy(_glfw.wl.pointer);
-        _glfw.wl.pointer = NULL;
-    }
-
-    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
-    {
-        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
-        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
-    }
-    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
-    {
-        wl_keyboard_destroy(_glfw.wl.keyboard);
-        _glfw.wl.keyboard = NULL;
-    }
-}
-
-static void seatHandleName(void* data,
-                           struct wl_seat* seat,
-                           const char* name)
-{
-}
-
-static const struct wl_seat_listener seatListener = {
-    seatHandleCapabilities,
-    seatHandleName,
-};
-
-static void dataOfferHandleOffer(void* data,
-                                 struct wl_data_offer* dataOffer,
-                                 const char* mimeType)
-{
-}
-
-static const struct wl_data_offer_listener dataOfferListener = {
-    dataOfferHandleOffer,
-};
-
-static void dataDeviceHandleDataOffer(void* data,
-                                      struct wl_data_device* dataDevice,
-                                      struct wl_data_offer* id)
-{
-    if (_glfw.wl.dataOffer)
-        wl_data_offer_destroy(_glfw.wl.dataOffer);
-
-    _glfw.wl.dataOffer = id;
-    wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
-}
-
-static void dataDeviceHandleEnter(void* data,
-                                  struct wl_data_device* dataDevice,
-                                  uint32_t serial,
-                                  struct wl_surface *surface,
-                                  wl_fixed_t x,
-                                  wl_fixed_t y,
-                                  struct wl_data_offer *id)
-{
-}
-
-static void dataDeviceHandleLeave(void* data,
-                                  struct wl_data_device* dataDevice)
-{
-}
-
-static void dataDeviceHandleMotion(void* data,
-                                   struct wl_data_device* dataDevice,
-                                   uint32_t time,
-                                   wl_fixed_t x,
-                                   wl_fixed_t y)
-{
-}
-
-static void dataDeviceHandleDrop(void* data,
-                                 struct wl_data_device* dataDevice)
-{
-}
-
-static void dataDeviceHandleSelection(void* data,
-                                      struct wl_data_device* dataDevice,
-                                      struct wl_data_offer* id)
-{
-}
-
-static const struct wl_data_device_listener dataDeviceListener = {
-    dataDeviceHandleDataOffer,
-    dataDeviceHandleEnter,
-    dataDeviceHandleLeave,
-    dataDeviceHandleMotion,
-    dataDeviceHandleDrop,
-    dataDeviceHandleSelection,
-};
-
-static void wmBaseHandlePing(void* data,
-                             struct xdg_wm_base* wmBase,
-                             uint32_t serial)
-{
-    xdg_wm_base_pong(wmBase, serial);
-}
-
-static const struct xdg_wm_base_listener wmBaseListener = {
-    wmBaseHandlePing
-};
-
-static void registryHandleGlobal(void* data,
-                                 struct wl_registry* registry,
-                                 uint32_t name,
-                                 const char* interface,
-                                 uint32_t version)
-{
-    if (strcmp(interface, "wl_compositor") == 0)
-    {
-        _glfw.wl.compositorVersion = min(3, version);
-        _glfw.wl.compositor =
-            wl_registry_bind(registry, name, &wl_compositor_interface,
-                             _glfw.wl.compositorVersion);
-    }
-    else if (strcmp(interface, "wl_subcompositor") == 0)
-    {
-        _glfw.wl.subcompositor =
-            wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
-    }
-    else if (strcmp(interface, "wl_shm") == 0)
-    {
-        _glfw.wl.shm =
-            wl_registry_bind(registry, name, &wl_shm_interface, 1);
-    }
-    else if (strcmp(interface, "wl_shell") == 0)
-    {
-        _glfw.wl.shell =
-            wl_registry_bind(registry, name, &wl_shell_interface, 1);
-    }
-    else if (strcmp(interface, "wl_output") == 0)
-    {
-        _glfwAddOutputWayland(name, version);
-    }
-    else if (strcmp(interface, "wl_seat") == 0)
-    {
-        if (!_glfw.wl.seat)
-        {
-            _glfw.wl.seatVersion = min(4, version);
-            _glfw.wl.seat =
-                wl_registry_bind(registry, name, &wl_seat_interface,
-                                 _glfw.wl.seatVersion);
-            wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
-        }
-    }
-    else if (strcmp(interface, "wl_data_device_manager") == 0)
-    {
-        if (!_glfw.wl.dataDeviceManager)
-        {
-            _glfw.wl.dataDeviceManager =
-                wl_registry_bind(registry, name,
-                                 &wl_data_device_manager_interface, 1);
-        }
-    }
-    else if (strcmp(interface, "xdg_wm_base") == 0)
-    {
-        _glfw.wl.wmBase =
-            wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
-        xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
-    }
-    else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
-    {
-        _glfw.wl.decorationManager =
-            wl_registry_bind(registry, name,
-                             &zxdg_decoration_manager_v1_interface,
-                             1);
-    }
-    else if (strcmp(interface, "wp_viewporter") == 0)
-    {
-        _glfw.wl.viewporter =
-            wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
-    }
-    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);
-    }
-    else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
-    {
-        _glfw.wl.idleInhibitManager =
-            wl_registry_bind(registry, name,
-                             &zwp_idle_inhibit_manager_v1_interface,
-                             1);
-    }
-}
-
-static void registryHandleGlobalRemove(void *data,
-                                       struct wl_registry *registry,
-                                       uint32_t name)
-{
-    int i;
-    _GLFWmonitor* monitor;
-
-    for (i = 0; i < _glfw.monitorCount; ++i)
-    {
-        monitor = _glfw.monitors[i];
-        if (monitor->wl.name == name)
-        {
-            _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
-            return;
-        }
-    }
-}
-
-
-static const struct wl_registry_listener registryListener = {
-    registryHandleGlobal,
-    registryHandleGlobalRemove
-};
-
-// Create key code translation tables
-//
-static void createKeyTables(void)
-{
-    int scancode;
-
-    memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
-    memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
-
-    _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;
-    _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;
-    _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;
-    _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;
-    _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;
-    _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;
-    _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;
-    _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;
-    _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;
-    _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;
-    _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;
-    _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;
-    _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;
-    _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;
-    _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;
-    _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;
-    _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;
-    _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;
-    _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;
-    _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;
-    _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;
-    _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;
-    _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;
-    _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;
-    _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;
-    _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
-    _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;
-    _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;
-    _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;
-    _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;
-    _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;
-    _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;
-    _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;
-    _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;
-    _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;
-    _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;
-    _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
-    _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;
-    _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;
-    _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;
-    _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;
-    _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;
-    _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;
-    _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;
-    _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;
-    _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;
-    _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;
-    _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;
-    _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;
-    _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;
-    _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;
-    _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
-    _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;
-    _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;
-    _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;
-    _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;
-    _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;
-    _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;
-    _glfw.wl.keycodes[KEY_MENU]       = GLFW_KEY_MENU;
-    _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;
-    _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;
-    _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;
-    _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
-    _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;
-    _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;
-    _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;
-    _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;
-    _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;
-    _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;
-    _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;
-    _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;
-    _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;
-    _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;
-    _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;
-    _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;
-    _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;
-    _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;
-    _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;
-    _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;
-    _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;
-    _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;
-    _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;
-    _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;
-    _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;
-    _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;
-    _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;
-    _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;
-    _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;
-    _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;
-    _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;
-    _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;
-    _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;
-    _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;
-    _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;
-    _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;
-    _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;
-    _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;
-    _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;
-    _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;
-    _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;
-    _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;
-    _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_MULTIPLY;
-    _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;
-    _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;
-    _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;
-    _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;
-    _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;
-    _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;
-    _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;
-    _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;
-    _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;
-    _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;
-    _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;
-    _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;
-    _glfw.wl.keycodes[KEY_KPCOMMA]    = GLFW_KEY_KP_DECIMAL;
-    _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;
-    _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;
-
-    for (scancode = 0;  scancode < 256;  scancode++)
-    {
-        if (_glfw.wl.keycodes[scancode] > 0)
-            _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void)
-{
-    const char *cursorTheme;
-    const char *cursorSizeStr;
-    char *cursorSizeEnd;
-    long cursorSizeLong;
-    int cursorSize;
-
-    _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
-    if (!_glfw.wl.cursor.handle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libwayland-cursor");
-        return GLFW_FALSE;
-    }
-
-    _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
-    _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
-    _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
-    _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
-        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
-
-    _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
-    if (!_glfw.wl.egl.handle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libwayland-egl");
-        return GLFW_FALSE;
-    }
-
-    _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
-    _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
-    _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
-        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
-
-    _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
-    if (!_glfw.wl.xkb.handle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to open libxkbcommon");
-        return GLFW_FALSE;
-    }
-
-    _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
-    _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
-    _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
-    _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
-    _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
-    _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
-    _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
-    _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
-    _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
-    _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
-    _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-    _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
-    _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
-    _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
-    _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
-    _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
-    _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
-    _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
-        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
-#endif
-
-    _glfw.wl.display = wl_display_connect(NULL);
-    if (!_glfw.wl.display)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Failed to connect to display");
-        return GLFW_FALSE;
-    }
-
-    _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
-    wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
-
-    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 GLFW_FALSE;
-    }
-
-    // Sync so we got all registry objects
-    wl_display_roundtrip(_glfw.wl.display);
-
-    // Sync so we got all initial output events
-    wl_display_roundtrip(_glfw.wl.display);
-
-#ifdef __linux__
-    if (!_glfwInitJoysticksLinux())
-        return GLFW_FALSE;
-#endif
-
-    _glfwInitTimerPOSIX();
-
-    _glfw.wl.timerfd = -1;
-    if (_glfw.wl.seatVersion >= 4)
-        _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
-
-    if (_glfw.wl.pointer && _glfw.wl.shm)
-    {
-        cursorTheme = getenv("XCURSOR_THEME");
-        cursorSizeStr = getenv("XCURSOR_SIZE");
-        cursorSize = 32;
-        if (cursorSizeStr)
-        {
-            errno = 0;
-            cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
-            if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
-                cursorSize = (int)cursorSizeLong;
-        }
-        _glfw.wl.cursorTheme =
-            wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
-        if (!_glfw.wl.cursorTheme)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Unable to load default cursor theme");
-            return GLFW_FALSE;
-        }
-        // If this happens to be NULL, we just fallback to the scale=1 version.
-        _glfw.wl.cursorThemeHiDPI =
-            wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
-        _glfw.wl.cursorSurface =
-            wl_compositor_create_surface(_glfw.wl.compositor);
-        _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
-    }
-
-    if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
-    {
-        _glfw.wl.dataDevice =
-            wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
-                                                   _glfw.wl.seat);
-        wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
-        _glfw.wl.clipboardString = malloc(4096);
-        if (!_glfw.wl.clipboardString)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Unable to allocate clipboard memory");
-            return GLFW_FALSE;
-        }
-        _glfw.wl.clipboardSize = 4096;
-    }
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformTerminate(void)
-{
-#ifdef __linux__
-    _glfwTerminateJoysticksLinux();
-#endif
-    _glfwTerminateEGL();
-    if (_glfw.wl.egl.handle)
-    {
-        _glfw_dlclose(_glfw.wl.egl.handle);
-        _glfw.wl.egl.handle = NULL;
-    }
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-    if (_glfw.wl.xkb.composeState)
-        xkb_compose_state_unref(_glfw.wl.xkb.composeState);
-#endif
-    if (_glfw.wl.xkb.keymap)
-        xkb_keymap_unref(_glfw.wl.xkb.keymap);
-    if (_glfw.wl.xkb.state)
-        xkb_state_unref(_glfw.wl.xkb.state);
-    if (_glfw.wl.xkb.context)
-        xkb_context_unref(_glfw.wl.xkb.context);
-    if (_glfw.wl.xkb.handle)
-    {
-        _glfw_dlclose(_glfw.wl.xkb.handle);
-        _glfw.wl.xkb.handle = NULL;
-    }
-
-    if (_glfw.wl.cursorTheme)
-        wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
-    if (_glfw.wl.cursorThemeHiDPI)
-        wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
-    if (_glfw.wl.cursor.handle)
-    {
-        _glfw_dlclose(_glfw.wl.cursor.handle);
-        _glfw.wl.cursor.handle = NULL;
-    }
-
-    if (_glfw.wl.cursorSurface)
-        wl_surface_destroy(_glfw.wl.cursorSurface);
-    if (_glfw.wl.subcompositor)
-        wl_subcompositor_destroy(_glfw.wl.subcompositor);
-    if (_glfw.wl.compositor)
-        wl_compositor_destroy(_glfw.wl.compositor);
-    if (_glfw.wl.shm)
-        wl_shm_destroy(_glfw.wl.shm);
-    if (_glfw.wl.shell)
-        wl_shell_destroy(_glfw.wl.shell);
-    if (_glfw.wl.viewporter)
-        wp_viewporter_destroy(_glfw.wl.viewporter);
-    if (_glfw.wl.decorationManager)
-        zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
-    if (_glfw.wl.wmBase)
-        xdg_wm_base_destroy(_glfw.wl.wmBase);
-    if (_glfw.wl.dataSource)
-        wl_data_source_destroy(_glfw.wl.dataSource);
-    if (_glfw.wl.dataDevice)
-        wl_data_device_destroy(_glfw.wl.dataDevice);
-    if (_glfw.wl.dataOffer)
-        wl_data_offer_destroy(_glfw.wl.dataOffer);
-    if (_glfw.wl.dataDeviceManager)
-        wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
-    if (_glfw.wl.pointer)
-        wl_pointer_destroy(_glfw.wl.pointer);
-    if (_glfw.wl.keyboard)
-        wl_keyboard_destroy(_glfw.wl.keyboard);
-    if (_glfw.wl.seat)
-        wl_seat_destroy(_glfw.wl.seat);
-    if (_glfw.wl.relativePointerManager)
-        zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
-    if (_glfw.wl.pointerConstraints)
-        zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
-    if (_glfw.wl.idleInhibitManager)
-        zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
-    if (_glfw.wl.registry)
-        wl_registry_destroy(_glfw.wl.registry);
-    if (_glfw.wl.display)
-    {
-        wl_display_flush(_glfw.wl.display);
-        wl_display_disconnect(_glfw.wl.display);
-    }
-
-    if (_glfw.wl.timerfd >= 0)
-        close(_glfw.wl.timerfd);
-    if (_glfw.wl.cursorTimerfd >= 0)
-        close(_glfw.wl.cursorTimerfd);
-
-    if (_glfw.wl.clipboardString)
-        free(_glfw.wl.clipboardString);
-    if (_glfw.wl.clipboardSendString)
-        free(_glfw.wl.clipboardSendString);
-}
-
-const char* _glfwPlatformGetVersionString(void)
-{
-    return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
-#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
-        " clock_gettime"
-#else
-        " gettimeofday"
-#endif
-        " evdev"
-#if defined(_GLFW_BUILD_DLL)
-        " shared"
-#endif
-        ;
-}
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
+// 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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+#include <wayland-client.h>
+
+
+static inline int min(int n1, int n2)
+{
+    return n1 < n2 ? n1 : n2;
+}
+
+static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
+                                                    int* which)
+{
+    int focus;
+    _GLFWwindow* window = _glfw.windowListHead;
+    if (!which)
+        which = &focus;
+    while (window)
+    {
+        if (surface == window->wl.decorations.top.surface)
+        {
+            *which = topDecoration;
+            break;
+        }
+        if (surface == window->wl.decorations.left.surface)
+        {
+            *which = leftDecoration;
+            break;
+        }
+        if (surface == window->wl.decorations.right.surface)
+        {
+            *which = rightDecoration;
+            break;
+        }
+        if (surface == window->wl.decorations.bottom.surface)
+        {
+            *which = bottomDecoration;
+            break;
+        }
+        window = window->next;
+    }
+    return window;
+}
+
+static void pointerHandleEnter(void* data,
+                               struct wl_pointer* pointer,
+                               uint32_t serial,
+                               struct wl_surface* surface,
+                               wl_fixed_t sx,
+                               wl_fixed_t sy)
+{
+    // Happens in the case we just destroyed the surface.
+    if (!surface)
+        return;
+
+    int focus = 0;
+    _GLFWwindow* window = wl_surface_get_user_data(surface);
+    if (!window)
+    {
+        window = findWindowFromDecorationSurface(surface, &focus);
+        if (!window)
+            return;
+    }
+
+    window->wl.decorations.focus = focus;
+    _glfw.wl.serial = serial;
+    _glfw.wl.pointerFocus = window;
+
+    window->wl.hovered = GLFW_TRUE;
+
+    _glfwPlatformSetCursor(window, window->wl.currentCursor);
+    _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+static void pointerHandleLeave(void* data,
+                               struct wl_pointer* pointer,
+                               uint32_t serial,
+                               struct wl_surface* surface)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+
+    if (!window)
+        return;
+
+    window->wl.hovered = GLFW_FALSE;
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.pointerFocus = NULL;
+    _glfwInputCursorEnter(window, GLFW_FALSE);
+    _glfw.wl.cursorPreviousName = NULL;
+}
+
+static void setCursor(_GLFWwindow* window, const char* name)
+{
+    struct wl_buffer* buffer;
+    struct wl_cursor* cursor;
+    struct wl_cursor_image* image;
+    struct wl_surface* surface = _glfw.wl.cursorSurface;
+    struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
+    int scale = 1;
+
+    if (window->wl.scale > 1 && _glfw.wl.cursorThemeHiDPI)
+    {
+        // We only support up to scale=2 for now, since libwayland-cursor
+        // requires us to load a different theme for each size.
+        scale = 2;
+        theme = _glfw.wl.cursorThemeHiDPI;
+    }
+
+    cursor = wl_cursor_theme_get_cursor(theme, name);
+    if (!cursor)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Standard cursor not found");
+        return;
+    }
+    // TODO: handle animated cursors too.
+    image = cursor->images[0];
+
+    if (!image)
+        return;
+
+    buffer = wl_cursor_image_get_buffer(image);
+    if (!buffer)
+        return;
+    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
+                          surface,
+                          image->hotspot_x / scale,
+                          image->hotspot_y / scale);
+    wl_surface_set_buffer_scale(surface, scale);
+    wl_surface_attach(surface, buffer, 0, 0);
+    wl_surface_damage(surface, 0, 0,
+                      image->width, image->height);
+    wl_surface_commit(surface);
+    _glfw.wl.cursorPreviousName = name;
+}
+
+static void pointerHandleMotion(void* data,
+                                struct wl_pointer* pointer,
+                                uint32_t time,
+                                wl_fixed_t sx,
+                                wl_fixed_t sy)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    const char* cursorName = NULL;
+    double x, y;
+
+    if (!window)
+        return;
+
+    if (window->cursorMode == GLFW_CURSOR_DISABLED)
+        return;
+    x = wl_fixed_to_double(sx);
+    y = wl_fixed_to_double(sy);
+
+    switch (window->wl.decorations.focus)
+    {
+        case mainWindow:
+            window->wl.cursorPosX = x;
+            window->wl.cursorPosY = y;
+            _glfwInputCursorPos(window, x, y);
+            _glfw.wl.cursorPreviousName = NULL;
+            return;
+        case topDecoration:
+            if (y < _GLFW_DECORATION_WIDTH)
+                cursorName = "n-resize";
+            else
+                cursorName = "left_ptr";
+            break;
+        case leftDecoration:
+            if (y < _GLFW_DECORATION_WIDTH)
+                cursorName = "nw-resize";
+            else
+                cursorName = "w-resize";
+            break;
+        case rightDecoration:
+            if (y < _GLFW_DECORATION_WIDTH)
+                cursorName = "ne-resize";
+            else
+                cursorName = "e-resize";
+            break;
+        case bottomDecoration:
+            if (x < _GLFW_DECORATION_WIDTH)
+                cursorName = "sw-resize";
+            else if (x > window->wl.width + _GLFW_DECORATION_WIDTH)
+                cursorName = "se-resize";
+            else
+                cursorName = "s-resize";
+            break;
+        default:
+            assert(0);
+    }
+    if (_glfw.wl.cursorPreviousName != cursorName)
+        setCursor(window, cursorName);
+}
+
+static void pointerHandleButton(void* data,
+                                struct wl_pointer* pointer,
+                                uint32_t serial,
+                                uint32_t time,
+                                uint32_t button,
+                                uint32_t state)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    int glfwButton;
+
+    // Both xdg-shell and wl_shell use the same values.
+    uint32_t edges = WL_SHELL_SURFACE_RESIZE_NONE;
+
+    if (!window)
+        return;
+    if (button == BTN_LEFT)
+    {
+        switch (window->wl.decorations.focus)
+        {
+            case mainWindow:
+                break;
+            case topDecoration:
+                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+                    edges = WL_SHELL_SURFACE_RESIZE_TOP;
+                else
+                {
+                    if (window->wl.xdg.toplevel)
+                        xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
+                    else
+                        wl_shell_surface_move(window->wl.shellSurface, _glfw.wl.seat, serial);
+                }
+                break;
+            case leftDecoration:
+                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+                    edges = WL_SHELL_SURFACE_RESIZE_TOP_LEFT;
+                else
+                    edges = WL_SHELL_SURFACE_RESIZE_LEFT;
+                break;
+            case rightDecoration:
+                if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
+                    edges = WL_SHELL_SURFACE_RESIZE_TOP_RIGHT;
+                else
+                    edges = WL_SHELL_SURFACE_RESIZE_RIGHT;
+                break;
+            case bottomDecoration:
+                if (window->wl.cursorPosX < _GLFW_DECORATION_WIDTH)
+                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT;
+                else if (window->wl.cursorPosX > window->wl.width + _GLFW_DECORATION_WIDTH)
+                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT;
+                else
+                    edges = WL_SHELL_SURFACE_RESIZE_BOTTOM;
+                break;
+            default:
+                assert(0);
+        }
+        if (edges != WL_SHELL_SURFACE_RESIZE_NONE)
+        {
+            if (window->wl.xdg.toplevel)
+                xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
+                                    serial, edges);
+            else
+                wl_shell_surface_resize(window->wl.shellSurface, _glfw.wl.seat,
+                                        serial, edges);
+        }
+    }
+    else if (button == BTN_RIGHT)
+    {
+        if (window->wl.decorations.focus != mainWindow && window->wl.xdg.toplevel)
+        {
+            xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
+                                          _glfw.wl.seat, serial,
+                                          window->wl.cursorPosX,
+                                          window->wl.cursorPosY);
+            return;
+        }
+    }
+
+    // Don’t pass the button to the user if it was related to a decoration.
+    if (window->wl.decorations.focus != mainWindow)
+        return;
+
+    _glfw.wl.serial = serial;
+
+    /* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
+     * codes. */
+    glfwButton = button - BTN_LEFT;
+
+    _glfwInputMouseClick(window,
+                         glfwButton,
+                         state == WL_POINTER_BUTTON_STATE_PRESSED
+                                ? GLFW_PRESS
+                                : GLFW_RELEASE,
+                         _glfw.wl.xkb.modifiers);
+}
+
+static void pointerHandleAxis(void* data,
+                              struct wl_pointer* pointer,
+                              uint32_t time,
+                              uint32_t axis,
+                              wl_fixed_t value)
+{
+    _GLFWwindow* window = _glfw.wl.pointerFocus;
+    double x = 0.0, y = 0.0;
+    // Wayland scroll events are in pointer motion coordinate space (think two
+    // finger scroll).  The factor 10 is commonly used to convert to "scroll
+    // step means 1.0.
+    const double scrollFactor = 1.0 / 10.0;
+
+    if (!window)
+        return;
+
+    assert(axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL ||
+           axis == WL_POINTER_AXIS_VERTICAL_SCROLL);
+
+    if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
+        x = wl_fixed_to_double(value) * scrollFactor;
+    else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
+        y = wl_fixed_to_double(value) * scrollFactor;
+
+    _glfwInputScroll(window, x, y);
+}
+
+static const struct wl_pointer_listener pointerListener = {
+    pointerHandleEnter,
+    pointerHandleLeave,
+    pointerHandleMotion,
+    pointerHandleButton,
+    pointerHandleAxis,
+};
+
+static void keyboardHandleKeymap(void* data,
+                                 struct wl_keyboard* keyboard,
+                                 uint32_t format,
+                                 int fd,
+                                 uint32_t size)
+{
+    struct xkb_keymap* keymap;
+    struct xkb_state* state;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+    struct xkb_compose_table* composeTable;
+    struct xkb_compose_state* composeState;
+#endif
+
+    char* mapStr;
+    const char* locale;
+
+    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
+    {
+        close(fd);
+        return;
+    }
+
+    mapStr = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+    if (mapStr == MAP_FAILED) {
+        close(fd);
+        return;
+    }
+
+    keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
+                                        mapStr,
+                                        XKB_KEYMAP_FORMAT_TEXT_V1,
+                                        0);
+    munmap(mapStr, size);
+    close(fd);
+
+    if (!keymap)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to compile keymap");
+        return;
+    }
+
+    state = xkb_state_new(keymap);
+    if (!state)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create XKB state");
+        xkb_keymap_unref(keymap);
+        return;
+    }
+
+    // Look up the preferred locale, falling back to "C" as default.
+    locale = getenv("LC_ALL");
+    if (!locale)
+        locale = getenv("LC_CTYPE");
+    if (!locale)
+        locale = getenv("LANG");
+    if (!locale)
+        locale = "C";
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+    composeTable =
+        xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
+                                          XKB_COMPOSE_COMPILE_NO_FLAGS);
+    if (composeTable)
+    {
+        composeState =
+            xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
+        xkb_compose_table_unref(composeTable);
+        if (composeState)
+            _glfw.wl.xkb.composeState = composeState;
+        else
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Failed to create XKB compose state");
+    }
+    else
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to create XKB compose table");
+    }
+#endif
+
+    xkb_keymap_unref(_glfw.wl.xkb.keymap);
+    xkb_state_unref(_glfw.wl.xkb.state);
+    _glfw.wl.xkb.keymap = keymap;
+    _glfw.wl.xkb.state = state;
+
+    _glfw.wl.xkb.controlMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
+    _glfw.wl.xkb.altMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
+    _glfw.wl.xkb.shiftMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
+    _glfw.wl.xkb.superMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
+    _glfw.wl.xkb.capsLockMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
+    _glfw.wl.xkb.numLockMask =
+        1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
+}
+
+static void keyboardHandleEnter(void* data,
+                                struct wl_keyboard* keyboard,
+                                uint32_t serial,
+                                struct wl_surface* surface,
+                                struct wl_array* keys)
+{
+    // Happens in the case we just destroyed the surface.
+    if (!surface)
+        return;
+
+    _GLFWwindow* window = wl_surface_get_user_data(surface);
+    if (!window)
+    {
+        window = findWindowFromDecorationSurface(surface, NULL);
+        if (!window)
+            return;
+    }
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.keyboardFocus = window;
+    _glfwInputWindowFocus(window, GLFW_TRUE);
+}
+
+static void keyboardHandleLeave(void* data,
+                                struct wl_keyboard* keyboard,
+                                uint32_t serial,
+                                struct wl_surface* surface)
+{
+    _GLFWwindow* window = _glfw.wl.keyboardFocus;
+
+    if (!window)
+        return;
+
+    _glfw.wl.serial = serial;
+    _glfw.wl.keyboardFocus = NULL;
+    _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+static int toGLFWKeyCode(uint32_t key)
+{
+    if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
+        return _glfw.wl.keycodes[key];
+
+    return GLFW_KEY_UNKNOWN;
+}
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
+{
+    if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
+        return sym;
+    if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym)
+            != XKB_COMPOSE_FEED_ACCEPTED)
+        return sym;
+    switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState))
+    {
+        case XKB_COMPOSE_COMPOSED:
+            return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState);
+        case XKB_COMPOSE_COMPOSING:
+        case XKB_COMPOSE_CANCELLED:
+            return XKB_KEY_NoSymbol;
+        case XKB_COMPOSE_NOTHING:
+        default:
+            return sym;
+    }
+}
+#endif
+
+static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
+{
+    uint32_t code, numSyms;
+    long cp;
+    const xkb_keysym_t *syms;
+    xkb_keysym_t sym;
+
+    code = key + 8;
+    numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
+
+    if (numSyms == 1)
+    {
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+        sym = composeSymbol(syms[0]);
+#else
+        sym = syms[0];
+#endif
+        cp = _glfwKeySym2Unicode(sym);
+        if (cp != -1)
+        {
+            const int mods = _glfw.wl.xkb.modifiers;
+            const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+            _glfwInputChar(window, cp, mods, plain);
+        }
+    }
+
+    return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
+}
+
+static void keyboardHandleKey(void* data,
+                              struct wl_keyboard* keyboard,
+                              uint32_t serial,
+                              uint32_t time,
+                              uint32_t key,
+                              uint32_t state)
+{
+    int keyCode;
+    int action;
+    _GLFWwindow* window = _glfw.wl.keyboardFocus;
+    GLFWbool shouldRepeat;
+    struct itimerspec timer = {};
+
+    if (!window)
+        return;
+
+    keyCode = toGLFWKeyCode(key);
+    action = state == WL_KEYBOARD_KEY_STATE_PRESSED
+            ? GLFW_PRESS : GLFW_RELEASE;
+
+    _glfw.wl.serial = serial;
+    _glfwInputKey(window, keyCode, key, action,
+                  _glfw.wl.xkb.modifiers);
+
+    if (action == GLFW_PRESS)
+    {
+        shouldRepeat = inputChar(window, key);
+
+        if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
+        {
+            _glfw.wl.keyboardLastKey = keyCode;
+            _glfw.wl.keyboardLastScancode = key;
+            if (_glfw.wl.keyboardRepeatRate > 1)
+                timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate;
+            else
+                timer.it_interval.tv_sec = 1;
+            timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
+            timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
+        }
+    }
+    timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
+}
+
+static void keyboardHandleModifiers(void* data,
+                                    struct wl_keyboard* keyboard,
+                                    uint32_t serial,
+                                    uint32_t modsDepressed,
+                                    uint32_t modsLatched,
+                                    uint32_t modsLocked,
+                                    uint32_t group)
+{
+    xkb_mod_mask_t mask;
+    unsigned int modifiers = 0;
+
+    _glfw.wl.serial = serial;
+
+    if (!_glfw.wl.xkb.keymap)
+        return;
+
+    xkb_state_update_mask(_glfw.wl.xkb.state,
+                          modsDepressed,
+                          modsLatched,
+                          modsLocked,
+                          0,
+                          0,
+                          group);
+
+    mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
+                                    XKB_STATE_MODS_DEPRESSED |
+                                    XKB_STATE_LAYOUT_DEPRESSED |
+                                    XKB_STATE_MODS_LATCHED |
+                                    XKB_STATE_LAYOUT_LATCHED);
+    if (mask & _glfw.wl.xkb.controlMask)
+        modifiers |= GLFW_MOD_CONTROL;
+    if (mask & _glfw.wl.xkb.altMask)
+        modifiers |= GLFW_MOD_ALT;
+    if (mask & _glfw.wl.xkb.shiftMask)
+        modifiers |= GLFW_MOD_SHIFT;
+    if (mask & _glfw.wl.xkb.superMask)
+        modifiers |= GLFW_MOD_SUPER;
+    if (mask & _glfw.wl.xkb.capsLockMask)
+        modifiers |= GLFW_MOD_CAPS_LOCK;
+    if (mask & _glfw.wl.xkb.numLockMask)
+        modifiers |= GLFW_MOD_NUM_LOCK;
+    _glfw.wl.xkb.modifiers = modifiers;
+}
+
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+static void keyboardHandleRepeatInfo(void* data,
+                                     struct wl_keyboard* keyboard,
+                                     int32_t rate,
+                                     int32_t delay)
+{
+    if (keyboard != _glfw.wl.keyboard)
+        return;
+
+    _glfw.wl.keyboardRepeatRate = rate;
+    _glfw.wl.keyboardRepeatDelay = delay;
+}
+#endif
+
+static const struct wl_keyboard_listener keyboardListener = {
+    keyboardHandleKeymap,
+    keyboardHandleEnter,
+    keyboardHandleLeave,
+    keyboardHandleKey,
+    keyboardHandleModifiers,
+#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
+    keyboardHandleRepeatInfo,
+#endif
+};
+
+static void seatHandleCapabilities(void* data,
+                                   struct wl_seat* seat,
+                                   enum wl_seat_capability caps)
+{
+    if ((caps & WL_SEAT_CAPABILITY_POINTER) && !_glfw.wl.pointer)
+    {
+        _glfw.wl.pointer = wl_seat_get_pointer(seat);
+        wl_pointer_add_listener(_glfw.wl.pointer, &pointerListener, NULL);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && _glfw.wl.pointer)
+    {
+        wl_pointer_destroy(_glfw.wl.pointer);
+        _glfw.wl.pointer = NULL;
+    }
+
+    if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !_glfw.wl.keyboard)
+    {
+        _glfw.wl.keyboard = wl_seat_get_keyboard(seat);
+        wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
+    }
+    else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
+    {
+        wl_keyboard_destroy(_glfw.wl.keyboard);
+        _glfw.wl.keyboard = NULL;
+    }
+}
+
+static void seatHandleName(void* data,
+                           struct wl_seat* seat,
+                           const char* name)
+{
+}
+
+static const struct wl_seat_listener seatListener = {
+    seatHandleCapabilities,
+    seatHandleName,
+};
+
+static void dataOfferHandleOffer(void* data,
+                                 struct wl_data_offer* dataOffer,
+                                 const char* mimeType)
+{
+}
+
+static const struct wl_data_offer_listener dataOfferListener = {
+    dataOfferHandleOffer,
+};
+
+static void dataDeviceHandleDataOffer(void* data,
+                                      struct wl_data_device* dataDevice,
+                                      struct wl_data_offer* id)
+{
+    if (_glfw.wl.dataOffer)
+        wl_data_offer_destroy(_glfw.wl.dataOffer);
+
+    _glfw.wl.dataOffer = id;
+    wl_data_offer_add_listener(_glfw.wl.dataOffer, &dataOfferListener, NULL);
+}
+
+static void dataDeviceHandleEnter(void* data,
+                                  struct wl_data_device* dataDevice,
+                                  uint32_t serial,
+                                  struct wl_surface *surface,
+                                  wl_fixed_t x,
+                                  wl_fixed_t y,
+                                  struct wl_data_offer *id)
+{
+}
+
+static void dataDeviceHandleLeave(void* data,
+                                  struct wl_data_device* dataDevice)
+{
+}
+
+static void dataDeviceHandleMotion(void* data,
+                                   struct wl_data_device* dataDevice,
+                                   uint32_t time,
+                                   wl_fixed_t x,
+                                   wl_fixed_t y)
+{
+}
+
+static void dataDeviceHandleDrop(void* data,
+                                 struct wl_data_device* dataDevice)
+{
+}
+
+static void dataDeviceHandleSelection(void* data,
+                                      struct wl_data_device* dataDevice,
+                                      struct wl_data_offer* id)
+{
+}
+
+static const struct wl_data_device_listener dataDeviceListener = {
+    dataDeviceHandleDataOffer,
+    dataDeviceHandleEnter,
+    dataDeviceHandleLeave,
+    dataDeviceHandleMotion,
+    dataDeviceHandleDrop,
+    dataDeviceHandleSelection,
+};
+
+static void wmBaseHandlePing(void* data,
+                             struct xdg_wm_base* wmBase,
+                             uint32_t serial)
+{
+    xdg_wm_base_pong(wmBase, serial);
+}
+
+static const struct xdg_wm_base_listener wmBaseListener = {
+    wmBaseHandlePing
+};
+
+static void registryHandleGlobal(void* data,
+                                 struct wl_registry* registry,
+                                 uint32_t name,
+                                 const char* interface,
+                                 uint32_t version)
+{
+    if (strcmp(interface, "wl_compositor") == 0)
+    {
+        _glfw.wl.compositorVersion = min(3, version);
+        _glfw.wl.compositor =
+            wl_registry_bind(registry, name, &wl_compositor_interface,
+                             _glfw.wl.compositorVersion);
+    }
+    else if (strcmp(interface, "wl_subcompositor") == 0)
+    {
+        _glfw.wl.subcompositor =
+            wl_registry_bind(registry, name, &wl_subcompositor_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shm") == 0)
+    {
+        _glfw.wl.shm =
+            wl_registry_bind(registry, name, &wl_shm_interface, 1);
+    }
+    else if (strcmp(interface, "wl_shell") == 0)
+    {
+        _glfw.wl.shell =
+            wl_registry_bind(registry, name, &wl_shell_interface, 1);
+    }
+    else if (strcmp(interface, "wl_output") == 0)
+    {
+        _glfwAddOutputWayland(name, version);
+    }
+    else if (strcmp(interface, "wl_seat") == 0)
+    {
+        if (!_glfw.wl.seat)
+        {
+            _glfw.wl.seatVersion = min(4, version);
+            _glfw.wl.seat =
+                wl_registry_bind(registry, name, &wl_seat_interface,
+                                 _glfw.wl.seatVersion);
+            wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
+        }
+    }
+    else if (strcmp(interface, "wl_data_device_manager") == 0)
+    {
+        if (!_glfw.wl.dataDeviceManager)
+        {
+            _glfw.wl.dataDeviceManager =
+                wl_registry_bind(registry, name,
+                                 &wl_data_device_manager_interface, 1);
+        }
+    }
+    else if (strcmp(interface, "xdg_wm_base") == 0)
+    {
+        _glfw.wl.wmBase =
+            wl_registry_bind(registry, name, &xdg_wm_base_interface, 1);
+        xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL);
+    }
+    else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0)
+    {
+        _glfw.wl.decorationManager =
+            wl_registry_bind(registry, name,
+                             &zxdg_decoration_manager_v1_interface,
+                             1);
+    }
+    else if (strcmp(interface, "wp_viewporter") == 0)
+    {
+        _glfw.wl.viewporter =
+            wl_registry_bind(registry, name, &wp_viewporter_interface, 1);
+    }
+    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);
+    }
+    else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
+    {
+        _glfw.wl.idleInhibitManager =
+            wl_registry_bind(registry, name,
+                             &zwp_idle_inhibit_manager_v1_interface,
+                             1);
+    }
+}
+
+static void registryHandleGlobalRemove(void *data,
+                                       struct wl_registry *registry,
+                                       uint32_t name)
+{
+    int i;
+    _GLFWmonitor* monitor;
+
+    for (i = 0; i < _glfw.monitorCount; ++i)
+    {
+        monitor = _glfw.monitors[i];
+        if (monitor->wl.name == name)
+        {
+            _glfwInputMonitor(monitor, GLFW_DISCONNECTED, 0);
+            return;
+        }
+    }
+}
+
+
+static const struct wl_registry_listener registryListener = {
+    registryHandleGlobal,
+    registryHandleGlobalRemove
+};
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+    int scancode;
+
+    memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
+    memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
+
+    _glfw.wl.keycodes[KEY_GRAVE]      = GLFW_KEY_GRAVE_ACCENT;
+    _glfw.wl.keycodes[KEY_1]          = GLFW_KEY_1;
+    _glfw.wl.keycodes[KEY_2]          = GLFW_KEY_2;
+    _glfw.wl.keycodes[KEY_3]          = GLFW_KEY_3;
+    _glfw.wl.keycodes[KEY_4]          = GLFW_KEY_4;
+    _glfw.wl.keycodes[KEY_5]          = GLFW_KEY_5;
+    _glfw.wl.keycodes[KEY_6]          = GLFW_KEY_6;
+    _glfw.wl.keycodes[KEY_7]          = GLFW_KEY_7;
+    _glfw.wl.keycodes[KEY_8]          = GLFW_KEY_8;
+    _glfw.wl.keycodes[KEY_9]          = GLFW_KEY_9;
+    _glfw.wl.keycodes[KEY_0]          = GLFW_KEY_0;
+    _glfw.wl.keycodes[KEY_SPACE]      = GLFW_KEY_SPACE;
+    _glfw.wl.keycodes[KEY_MINUS]      = GLFW_KEY_MINUS;
+    _glfw.wl.keycodes[KEY_EQUAL]      = GLFW_KEY_EQUAL;
+    _glfw.wl.keycodes[KEY_Q]          = GLFW_KEY_Q;
+    _glfw.wl.keycodes[KEY_W]          = GLFW_KEY_W;
+    _glfw.wl.keycodes[KEY_E]          = GLFW_KEY_E;
+    _glfw.wl.keycodes[KEY_R]          = GLFW_KEY_R;
+    _glfw.wl.keycodes[KEY_T]          = GLFW_KEY_T;
+    _glfw.wl.keycodes[KEY_Y]          = GLFW_KEY_Y;
+    _glfw.wl.keycodes[KEY_U]          = GLFW_KEY_U;
+    _glfw.wl.keycodes[KEY_I]          = GLFW_KEY_I;
+    _glfw.wl.keycodes[KEY_O]          = GLFW_KEY_O;
+    _glfw.wl.keycodes[KEY_P]          = GLFW_KEY_P;
+    _glfw.wl.keycodes[KEY_LEFTBRACE]  = GLFW_KEY_LEFT_BRACKET;
+    _glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
+    _glfw.wl.keycodes[KEY_A]          = GLFW_KEY_A;
+    _glfw.wl.keycodes[KEY_S]          = GLFW_KEY_S;
+    _glfw.wl.keycodes[KEY_D]          = GLFW_KEY_D;
+    _glfw.wl.keycodes[KEY_F]          = GLFW_KEY_F;
+    _glfw.wl.keycodes[KEY_G]          = GLFW_KEY_G;
+    _glfw.wl.keycodes[KEY_H]          = GLFW_KEY_H;
+    _glfw.wl.keycodes[KEY_J]          = GLFW_KEY_J;
+    _glfw.wl.keycodes[KEY_K]          = GLFW_KEY_K;
+    _glfw.wl.keycodes[KEY_L]          = GLFW_KEY_L;
+    _glfw.wl.keycodes[KEY_SEMICOLON]  = GLFW_KEY_SEMICOLON;
+    _glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
+    _glfw.wl.keycodes[KEY_Z]          = GLFW_KEY_Z;
+    _glfw.wl.keycodes[KEY_X]          = GLFW_KEY_X;
+    _glfw.wl.keycodes[KEY_C]          = GLFW_KEY_C;
+    _glfw.wl.keycodes[KEY_V]          = GLFW_KEY_V;
+    _glfw.wl.keycodes[KEY_B]          = GLFW_KEY_B;
+    _glfw.wl.keycodes[KEY_N]          = GLFW_KEY_N;
+    _glfw.wl.keycodes[KEY_M]          = GLFW_KEY_M;
+    _glfw.wl.keycodes[KEY_COMMA]      = GLFW_KEY_COMMA;
+    _glfw.wl.keycodes[KEY_DOT]        = GLFW_KEY_PERIOD;
+    _glfw.wl.keycodes[KEY_SLASH]      = GLFW_KEY_SLASH;
+    _glfw.wl.keycodes[KEY_BACKSLASH]  = GLFW_KEY_BACKSLASH;
+    _glfw.wl.keycodes[KEY_ESC]        = GLFW_KEY_ESCAPE;
+    _glfw.wl.keycodes[KEY_TAB]        = GLFW_KEY_TAB;
+    _glfw.wl.keycodes[KEY_LEFTSHIFT]  = GLFW_KEY_LEFT_SHIFT;
+    _glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
+    _glfw.wl.keycodes[KEY_LEFTCTRL]   = GLFW_KEY_LEFT_CONTROL;
+    _glfw.wl.keycodes[KEY_RIGHTCTRL]  = GLFW_KEY_RIGHT_CONTROL;
+    _glfw.wl.keycodes[KEY_LEFTALT]    = GLFW_KEY_LEFT_ALT;
+    _glfw.wl.keycodes[KEY_RIGHTALT]   = GLFW_KEY_RIGHT_ALT;
+    _glfw.wl.keycodes[KEY_LEFTMETA]   = GLFW_KEY_LEFT_SUPER;
+    _glfw.wl.keycodes[KEY_RIGHTMETA]  = GLFW_KEY_RIGHT_SUPER;
+    _glfw.wl.keycodes[KEY_MENU]       = GLFW_KEY_MENU;
+    _glfw.wl.keycodes[KEY_NUMLOCK]    = GLFW_KEY_NUM_LOCK;
+    _glfw.wl.keycodes[KEY_CAPSLOCK]   = GLFW_KEY_CAPS_LOCK;
+    _glfw.wl.keycodes[KEY_PRINT]      = GLFW_KEY_PRINT_SCREEN;
+    _glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
+    _glfw.wl.keycodes[KEY_PAUSE]      = GLFW_KEY_PAUSE;
+    _glfw.wl.keycodes[KEY_DELETE]     = GLFW_KEY_DELETE;
+    _glfw.wl.keycodes[KEY_BACKSPACE]  = GLFW_KEY_BACKSPACE;
+    _glfw.wl.keycodes[KEY_ENTER]      = GLFW_KEY_ENTER;
+    _glfw.wl.keycodes[KEY_HOME]       = GLFW_KEY_HOME;
+    _glfw.wl.keycodes[KEY_END]        = GLFW_KEY_END;
+    _glfw.wl.keycodes[KEY_PAGEUP]     = GLFW_KEY_PAGE_UP;
+    _glfw.wl.keycodes[KEY_PAGEDOWN]   = GLFW_KEY_PAGE_DOWN;
+    _glfw.wl.keycodes[KEY_INSERT]     = GLFW_KEY_INSERT;
+    _glfw.wl.keycodes[KEY_LEFT]       = GLFW_KEY_LEFT;
+    _glfw.wl.keycodes[KEY_RIGHT]      = GLFW_KEY_RIGHT;
+    _glfw.wl.keycodes[KEY_DOWN]       = GLFW_KEY_DOWN;
+    _glfw.wl.keycodes[KEY_UP]         = GLFW_KEY_UP;
+    _glfw.wl.keycodes[KEY_F1]         = GLFW_KEY_F1;
+    _glfw.wl.keycodes[KEY_F2]         = GLFW_KEY_F2;
+    _glfw.wl.keycodes[KEY_F3]         = GLFW_KEY_F3;
+    _glfw.wl.keycodes[KEY_F4]         = GLFW_KEY_F4;
+    _glfw.wl.keycodes[KEY_F5]         = GLFW_KEY_F5;
+    _glfw.wl.keycodes[KEY_F6]         = GLFW_KEY_F6;
+    _glfw.wl.keycodes[KEY_F7]         = GLFW_KEY_F7;
+    _glfw.wl.keycodes[KEY_F8]         = GLFW_KEY_F8;
+    _glfw.wl.keycodes[KEY_F9]         = GLFW_KEY_F9;
+    _glfw.wl.keycodes[KEY_F10]        = GLFW_KEY_F10;
+    _glfw.wl.keycodes[KEY_F11]        = GLFW_KEY_F11;
+    _glfw.wl.keycodes[KEY_F12]        = GLFW_KEY_F12;
+    _glfw.wl.keycodes[KEY_F13]        = GLFW_KEY_F13;
+    _glfw.wl.keycodes[KEY_F14]        = GLFW_KEY_F14;
+    _glfw.wl.keycodes[KEY_F15]        = GLFW_KEY_F15;
+    _glfw.wl.keycodes[KEY_F16]        = GLFW_KEY_F16;
+    _glfw.wl.keycodes[KEY_F17]        = GLFW_KEY_F17;
+    _glfw.wl.keycodes[KEY_F18]        = GLFW_KEY_F18;
+    _glfw.wl.keycodes[KEY_F19]        = GLFW_KEY_F19;
+    _glfw.wl.keycodes[KEY_F20]        = GLFW_KEY_F20;
+    _glfw.wl.keycodes[KEY_F21]        = GLFW_KEY_F21;
+    _glfw.wl.keycodes[KEY_F22]        = GLFW_KEY_F22;
+    _glfw.wl.keycodes[KEY_F23]        = GLFW_KEY_F23;
+    _glfw.wl.keycodes[KEY_F24]        = GLFW_KEY_F24;
+    _glfw.wl.keycodes[KEY_KPSLASH]    = GLFW_KEY_KP_DIVIDE;
+    _glfw.wl.keycodes[KEY_KPDOT]      = GLFW_KEY_KP_MULTIPLY;
+    _glfw.wl.keycodes[KEY_KPMINUS]    = GLFW_KEY_KP_SUBTRACT;
+    _glfw.wl.keycodes[KEY_KPPLUS]     = GLFW_KEY_KP_ADD;
+    _glfw.wl.keycodes[KEY_KP0]        = GLFW_KEY_KP_0;
+    _glfw.wl.keycodes[KEY_KP1]        = GLFW_KEY_KP_1;
+    _glfw.wl.keycodes[KEY_KP2]        = GLFW_KEY_KP_2;
+    _glfw.wl.keycodes[KEY_KP3]        = GLFW_KEY_KP_3;
+    _glfw.wl.keycodes[KEY_KP4]        = GLFW_KEY_KP_4;
+    _glfw.wl.keycodes[KEY_KP5]        = GLFW_KEY_KP_5;
+    _glfw.wl.keycodes[KEY_KP6]        = GLFW_KEY_KP_6;
+    _glfw.wl.keycodes[KEY_KP7]        = GLFW_KEY_KP_7;
+    _glfw.wl.keycodes[KEY_KP8]        = GLFW_KEY_KP_8;
+    _glfw.wl.keycodes[KEY_KP9]        = GLFW_KEY_KP_9;
+    _glfw.wl.keycodes[KEY_KPCOMMA]    = GLFW_KEY_KP_DECIMAL;
+    _glfw.wl.keycodes[KEY_KPEQUAL]    = GLFW_KEY_KP_EQUAL;
+    _glfw.wl.keycodes[KEY_KPENTER]    = GLFW_KEY_KP_ENTER;
+
+    for (scancode = 0;  scancode < 256;  scancode++)
+    {
+        if (_glfw.wl.keycodes[scancode] > 0)
+            _glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+    const char *cursorTheme;
+    const char *cursorSizeStr;
+    char *cursorSizeEnd;
+    long cursorSizeLong;
+    int cursorSize;
+
+    _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
+    if (!_glfw.wl.cursor.handle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to open libwayland-cursor");
+        return GLFW_FALSE;
+    }
+
+    _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load)
+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load");
+    _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy)
+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
+    _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
+    _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
+        _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
+
+    _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
+    if (!_glfw.wl.egl.handle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to open libwayland-egl");
+        return GLFW_FALSE;
+    }
+
+    _glfw.wl.egl.window_create = (PFN_wl_egl_window_create)
+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create");
+    _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy)
+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
+    _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
+        _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
+
+    _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
+    if (!_glfw.wl.xkb.handle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to open libxkbcommon");
+        return GLFW_FALSE;
+    }
+
+    _glfw.wl.xkb.context_new = (PFN_xkb_context_new)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
+    _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
+    _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
+    _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
+    _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
+    _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
+    _glfw.wl.xkb.state_new = (PFN_xkb_state_new)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
+    _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
+    _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
+    _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
+    _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+    _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
+    _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
+    _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
+    _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
+    _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
+    _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
+    _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
+        _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
+#endif
+
+    _glfw.wl.display = wl_display_connect(NULL);
+    if (!_glfw.wl.display)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Failed to connect to display");
+        return GLFW_FALSE;
+    }
+
+    _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
+    wl_registry_add_listener(_glfw.wl.registry, &registryListener, NULL);
+
+    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 GLFW_FALSE;
+    }
+
+    // Sync so we got all registry objects
+    wl_display_roundtrip(_glfw.wl.display);
+
+    // Sync so we got all initial output events
+    wl_display_roundtrip(_glfw.wl.display);
+
+#ifdef __linux__
+    if (!_glfwInitJoysticksLinux())
+        return GLFW_FALSE;
+#endif
+
+    _glfwInitTimerPOSIX();
+
+    _glfw.wl.timerfd = -1;
+    if (_glfw.wl.seatVersion >= 4)
+        _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+
+    if (_glfw.wl.pointer && _glfw.wl.shm)
+    {
+        cursorTheme = getenv("XCURSOR_THEME");
+        cursorSizeStr = getenv("XCURSOR_SIZE");
+        cursorSize = 32;
+        if (cursorSizeStr)
+        {
+            errno = 0;
+            cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
+            if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
+                cursorSize = (int)cursorSizeLong;
+        }
+        _glfw.wl.cursorTheme =
+            wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
+        if (!_glfw.wl.cursorTheme)
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Unable to load default cursor theme");
+            return GLFW_FALSE;
+        }
+        // If this happens to be NULL, we just fallback to the scale=1 version.
+        _glfw.wl.cursorThemeHiDPI =
+            wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
+        _glfw.wl.cursorSurface =
+            wl_compositor_create_surface(_glfw.wl.compositor);
+        _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+    }
+
+    if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
+    {
+        _glfw.wl.dataDevice =
+            wl_data_device_manager_get_data_device(_glfw.wl.dataDeviceManager,
+                                                   _glfw.wl.seat);
+        wl_data_device_add_listener(_glfw.wl.dataDevice, &dataDeviceListener, NULL);
+        _glfw.wl.clipboardString = malloc(4096);
+        if (!_glfw.wl.clipboardString)
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Unable to allocate clipboard memory");
+            return GLFW_FALSE;
+        }
+        _glfw.wl.clipboardSize = 4096;
+    }
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+#ifdef __linux__
+    _glfwTerminateJoysticksLinux();
+#endif
+    _glfwTerminateEGL();
+    if (_glfw.wl.egl.handle)
+    {
+        _glfw_dlclose(_glfw.wl.egl.handle);
+        _glfw.wl.egl.handle = NULL;
+    }
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+    if (_glfw.wl.xkb.composeState)
+        xkb_compose_state_unref(_glfw.wl.xkb.composeState);
+#endif
+    if (_glfw.wl.xkb.keymap)
+        xkb_keymap_unref(_glfw.wl.xkb.keymap);
+    if (_glfw.wl.xkb.state)
+        xkb_state_unref(_glfw.wl.xkb.state);
+    if (_glfw.wl.xkb.context)
+        xkb_context_unref(_glfw.wl.xkb.context);
+    if (_glfw.wl.xkb.handle)
+    {
+        _glfw_dlclose(_glfw.wl.xkb.handle);
+        _glfw.wl.xkb.handle = NULL;
+    }
+
+    if (_glfw.wl.cursorTheme)
+        wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
+    if (_glfw.wl.cursorThemeHiDPI)
+        wl_cursor_theme_destroy(_glfw.wl.cursorThemeHiDPI);
+    if (_glfw.wl.cursor.handle)
+    {
+        _glfw_dlclose(_glfw.wl.cursor.handle);
+        _glfw.wl.cursor.handle = NULL;
+    }
+
+    if (_glfw.wl.cursorSurface)
+        wl_surface_destroy(_glfw.wl.cursorSurface);
+    if (_glfw.wl.subcompositor)
+        wl_subcompositor_destroy(_glfw.wl.subcompositor);
+    if (_glfw.wl.compositor)
+        wl_compositor_destroy(_glfw.wl.compositor);
+    if (_glfw.wl.shm)
+        wl_shm_destroy(_glfw.wl.shm);
+    if (_glfw.wl.shell)
+        wl_shell_destroy(_glfw.wl.shell);
+    if (_glfw.wl.viewporter)
+        wp_viewporter_destroy(_glfw.wl.viewporter);
+    if (_glfw.wl.decorationManager)
+        zxdg_decoration_manager_v1_destroy(_glfw.wl.decorationManager);
+    if (_glfw.wl.wmBase)
+        xdg_wm_base_destroy(_glfw.wl.wmBase);
+    if (_glfw.wl.dataSource)
+        wl_data_source_destroy(_glfw.wl.dataSource);
+    if (_glfw.wl.dataDevice)
+        wl_data_device_destroy(_glfw.wl.dataDevice);
+    if (_glfw.wl.dataOffer)
+        wl_data_offer_destroy(_glfw.wl.dataOffer);
+    if (_glfw.wl.dataDeviceManager)
+        wl_data_device_manager_destroy(_glfw.wl.dataDeviceManager);
+    if (_glfw.wl.pointer)
+        wl_pointer_destroy(_glfw.wl.pointer);
+    if (_glfw.wl.keyboard)
+        wl_keyboard_destroy(_glfw.wl.keyboard);
+    if (_glfw.wl.seat)
+        wl_seat_destroy(_glfw.wl.seat);
+    if (_glfw.wl.relativePointerManager)
+        zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
+    if (_glfw.wl.pointerConstraints)
+        zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
+    if (_glfw.wl.idleInhibitManager)
+        zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
+    if (_glfw.wl.registry)
+        wl_registry_destroy(_glfw.wl.registry);
+    if (_glfw.wl.display)
+    {
+        wl_display_flush(_glfw.wl.display);
+        wl_display_disconnect(_glfw.wl.display);
+    }
+
+    if (_glfw.wl.timerfd >= 0)
+        close(_glfw.wl.timerfd);
+    if (_glfw.wl.cursorTimerfd >= 0)
+        close(_glfw.wl.cursorTimerfd);
+
+    if (_glfw.wl.clipboardString)
+        free(_glfw.wl.clipboardString);
+    if (_glfw.wl.clipboardSendString)
+        free(_glfw.wl.clipboardSendString);
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+    return _GLFW_VERSION_NUMBER " Wayland EGL OSMesa"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+        " clock_gettime"
+#else
+        " gettimeofday"
+#endif
+        " evdev"
+#if defined(_GLFW_BUILD_DLL)
+        " shared"
+#endif
+        ;
+}
diff --git a/glfw/src/wl_monitor.c b/glfw/src/wl_monitor.c
--- a/glfw/src/wl_monitor.c
+++ b/glfw/src/wl_monitor.c
@@ -1,225 +1,225 @@
-//========================================================================
-// GLFW 3.3 Wayland - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
-// 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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-
-
-static void outputHandleGeometry(void* data,
-                                 struct wl_output* output,
-                                 int32_t x,
-                                 int32_t y,
-                                 int32_t physicalWidth,
-                                 int32_t physicalHeight,
-                                 int32_t subpixel,
-                                 const char* make,
-                                 const char* model,
-                                 int32_t transform)
-{
-    struct _GLFWmonitor *monitor = data;
-    char name[1024];
-
-    monitor->wl.x = x;
-    monitor->wl.y = y;
-    monitor->widthMM = physicalWidth;
-    monitor->heightMM = physicalHeight;
-
-    snprintf(name, sizeof(name), "%s %s", make, model);
-    monitor->name = _glfw_strdup(name);
-}
-
-static void outputHandleMode(void* data,
-                             struct wl_output* output,
-                             uint32_t flags,
-                             int32_t width,
-                             int32_t height,
-                             int32_t refresh)
-{
-    struct _GLFWmonitor *monitor = data;
-    GLFWvidmode mode;
-
-    mode.width = width;
-    mode.height = height;
-    mode.redBits = 8;
-    mode.greenBits = 8;
-    mode.blueBits = 8;
-    mode.refreshRate = (int) round(refresh / 1000.0);
-
-    monitor->modeCount++;
-    monitor->modes =
-        realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
-    monitor->modes[monitor->modeCount - 1] = mode;
-
-    if (flags & WL_OUTPUT_MODE_CURRENT)
-        monitor->wl.currentMode = monitor->modeCount - 1;
-}
-
-static void outputHandleDone(void* data, struct wl_output* output)
-{
-    struct _GLFWmonitor *monitor = data;
-
-    _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
-}
-
-static void outputHandleScale(void* data,
-                              struct wl_output* output,
-                              int32_t factor)
-{
-    struct _GLFWmonitor *monitor = data;
-
-    monitor->wl.scale = factor;
-}
-
-static const struct wl_output_listener outputListener = {
-    outputHandleGeometry,
-    outputHandleMode,
-    outputHandleDone,
-    outputHandleScale,
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwAddOutputWayland(uint32_t name, uint32_t version)
-{
-    _GLFWmonitor *monitor;
-    struct wl_output *output;
-
-    if (version < 2)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unsupported output interface version");
-        return;
-    }
-
-    // The actual name of this output will be set in the geometry handler.
-    monitor = _glfwAllocMonitor(NULL, 0, 0);
-
-    output = wl_registry_bind(_glfw.wl.registry,
-                              name,
-                              &wl_output_interface,
-                              2);
-    if (!output)
-    {
-        _glfwFreeMonitor(monitor);
-        return;
-    }
-
-    monitor->wl.scale = 1;
-    monitor->wl.output = output;
-    monitor->wl.name = name;
-
-    wl_output_add_listener(output, &outputListener, monitor);
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
-{
-    if (monitor->wl.output)
-        wl_output_destroy(monitor->wl.output);
-}
-
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
-{
-    if (xpos)
-        *xpos = monitor->wl.x;
-    if (ypos)
-        *ypos = monitor->wl.y;
-}
-
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = (float) monitor->wl.scale;
-    if (yscale)
-        *yscale = (float) monitor->wl.scale;
-}
-
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
-                                     int* xpos, int* ypos,
-                                     int* width, int* height)
-{
-    if (xpos)
-        *xpos = monitor->wl.x;
-    if (ypos)
-        *ypos = monitor->wl.y;
-    if (width)
-        *width = monitor->modes[monitor->wl.currentMode].width;
-    if (height)
-        *height = monitor->modes[monitor->wl.currentMode].height;
-}
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
-{
-    *found = monitor->modeCount;
-    return monitor->modes;
-}
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-    *mode = monitor->modes[monitor->wl.currentMode];
-}
-
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
-{
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Gamma ramp access is not available");
-    return GLFW_FALSE;
-}
-
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
-                               const GLFWgammaramp* ramp)
-{
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Gamma ramp access is not available");
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        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 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
+// 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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <math.h>
+
+
+static void outputHandleGeometry(void* data,
+                                 struct wl_output* output,
+                                 int32_t x,
+                                 int32_t y,
+                                 int32_t physicalWidth,
+                                 int32_t physicalHeight,
+                                 int32_t subpixel,
+                                 const char* make,
+                                 const char* model,
+                                 int32_t transform)
+{
+    struct _GLFWmonitor *monitor = data;
+    char name[1024];
+
+    monitor->wl.x = x;
+    monitor->wl.y = y;
+    monitor->widthMM = physicalWidth;
+    monitor->heightMM = physicalHeight;
+
+    snprintf(name, sizeof(name), "%s %s", make, model);
+    monitor->name = _glfw_strdup(name);
+}
+
+static void outputHandleMode(void* data,
+                             struct wl_output* output,
+                             uint32_t flags,
+                             int32_t width,
+                             int32_t height,
+                             int32_t refresh)
+{
+    struct _GLFWmonitor *monitor = data;
+    GLFWvidmode mode;
+
+    mode.width = width;
+    mode.height = height;
+    mode.redBits = 8;
+    mode.greenBits = 8;
+    mode.blueBits = 8;
+    mode.refreshRate = (int) round(refresh / 1000.0);
+
+    monitor->modeCount++;
+    monitor->modes =
+        realloc(monitor->modes, monitor->modeCount * sizeof(GLFWvidmode));
+    monitor->modes[monitor->modeCount - 1] = mode;
+
+    if (flags & WL_OUTPUT_MODE_CURRENT)
+        monitor->wl.currentMode = monitor->modeCount - 1;
+}
+
+static void outputHandleDone(void* data, struct wl_output* output)
+{
+    struct _GLFWmonitor *monitor = data;
+
+    _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
+}
+
+static void outputHandleScale(void* data,
+                              struct wl_output* output,
+                              int32_t factor)
+{
+    struct _GLFWmonitor *monitor = data;
+
+    monitor->wl.scale = factor;
+}
+
+static const struct wl_output_listener outputListener = {
+    outputHandleGeometry,
+    outputHandleMode,
+    outputHandleDone,
+    outputHandleScale,
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version)
+{
+    _GLFWmonitor *monitor;
+    struct wl_output *output;
+
+    if (version < 2)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Unsupported output interface version");
+        return;
+    }
+
+    // The actual name of this output will be set in the geometry handler.
+    monitor = _glfwAllocMonitor(NULL, 0, 0);
+
+    output = wl_registry_bind(_glfw.wl.registry,
+                              name,
+                              &wl_output_interface,
+                              2);
+    if (!output)
+    {
+        _glfwFreeMonitor(monitor);
+        return;
+    }
+
+    monitor->wl.scale = 1;
+    monitor->wl.output = output;
+    monitor->wl.name = name;
+
+    wl_output_add_listener(output, &outputListener, monitor);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+    if (monitor->wl.output)
+        wl_output_destroy(monitor->wl.output);
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+    if (xpos)
+        *xpos = monitor->wl.x;
+    if (ypos)
+        *ypos = monitor->wl.y;
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = (float) monitor->wl.scale;
+    if (yscale)
+        *yscale = (float) monitor->wl.scale;
+}
+
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
+                                     int* xpos, int* ypos,
+                                     int* width, int* height)
+{
+    if (xpos)
+        *xpos = monitor->wl.x;
+    if (ypos)
+        *ypos = monitor->wl.y;
+    if (width)
+        *width = monitor->modes[monitor->wl.currentMode].width;
+    if (height)
+        *height = monitor->modes[monitor->wl.currentMode].height;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+    *found = monitor->modeCount;
+    return monitor->modes;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+    *mode = monitor->modes[monitor->wl.currentMode];
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Gamma ramp access is not available");
+    return GLFW_FALSE;
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor,
+                               const GLFWgammaramp* ramp)
+{
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Gamma ramp access is not available");
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return monitor->wl.output;
+}
+
diff --git a/glfw/src/wl_platform.h b/glfw/src/wl_platform.h
--- a/glfw/src/wl_platform.h
+++ b/glfw/src/wl_platform.h
@@ -1,359 +1,359 @@
-//========================================================================
-// GLFW 3.3 Wayland - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
-// 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 <wayland-client.h>
-#include <xkbcommon/xkbcommon.h>
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-#include <xkbcommon/xkbcommon-compose.h>
-#endif
-#include <dlfcn.h>
-
-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_thread.h"
-#include "posix_time.h"
-#ifdef __linux__
-#include "linux_joystick.h"
-#else
-#include "null_joystick.h"
-#endif
-#include "xkb_unicode.h"
-#include "egl_context.h"
-#include "osmesa_context.h"
-
-#include "wayland-xdg-shell-client-protocol.h"
-#include "wayland-xdg-decoration-client-protocol.h"
-#include "wayland-viewporter-client-protocol.h"
-#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
-#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
-#include "wayland-idle-inhibit-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         struct { int dummyContext; }
-#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
-
-struct wl_cursor_image {
-    uint32_t width;
-    uint32_t height;
-    uint32_t hotspot_x;
-    uint32_t hotspot_y;
-    uint32_t delay;
-};
-struct wl_cursor {
-    unsigned int image_count;
-    struct wl_cursor_image** images;
-    char* name;
-};
-typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
-typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
-typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
-typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
-#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
-#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
-#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
-#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
-
-typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
-typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
-typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
-#define wl_egl_window_create _glfw.wl.egl.window_create
-#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
-#define wl_egl_window_resize _glfw.wl.egl.window_resize
-
-typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
-typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
-typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
-typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
-typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
-typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
-typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
-typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
-typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
-typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
-typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
-#define xkb_context_new _glfw.wl.xkb.context_new
-#define xkb_context_unref _glfw.wl.xkb.context_unref
-#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
-#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
-#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
-#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
-#define xkb_state_new _glfw.wl.xkb.state_new
-#define xkb_state_unref _glfw.wl.xkb.state_unref
-#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
-#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
-#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
-typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
-typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
-typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
-typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
-typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
-typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
-#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
-#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
-#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
-#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
-#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
-#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
-#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
-#endif
-
-#define _GLFW_DECORATION_WIDTH 4
-#define _GLFW_DECORATION_TOP 24
-#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
-#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
-
-typedef enum _GLFWdecorationSideWayland
-{
-    mainWindow,
-    topDecoration,
-    leftDecoration,
-    rightDecoration,
-    bottomDecoration,
-
-} _GLFWdecorationSideWayland;
-
-typedef struct _GLFWdecorationWayland
-{
-    struct wl_surface*          surface;
-    struct wl_subsurface*       subsurface;
-    struct wp_viewport*         viewport;
-
-} _GLFWdecorationWayland;
-
-// Wayland-specific per-window data
-//
-typedef struct _GLFWwindowWayland
-{
-    int                         width, height;
-    GLFWbool                    visible;
-    GLFWbool                    maximized;
-    GLFWbool                    hovered;
-    GLFWbool                    transparent;
-    struct wl_surface*          surface;
-    struct wl_egl_window*       native;
-    struct wl_shell_surface*    shellSurface;
-    struct wl_callback*         callback;
-
-    struct {
-        struct xdg_surface*     surface;
-        struct xdg_toplevel*    toplevel;
-        struct zxdg_toplevel_decoration_v1* decoration;
-    } xdg;
-
-    _GLFWcursor*                currentCursor;
-    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;
-
-    struct zwp_idle_inhibitor_v1*          idleInhibitor;
-
-    GLFWbool                    wasFullscreen;
-
-    struct {
-        GLFWbool                           serverSide;
-        struct wl_buffer*                  buffer;
-        _GLFWdecorationWayland             top, left, right, bottom;
-        int                                focus;
-    } decorations;
-
-} _GLFWwindowWayland;
-
-// Wayland-specific global data
-//
-typedef struct _GLFWlibraryWayland
-{
-    struct wl_display*          display;
-    struct wl_registry*         registry;
-    struct wl_compositor*       compositor;
-    struct wl_subcompositor*    subcompositor;
-    struct wl_shell*            shell;
-    struct wl_shm*              shm;
-    struct wl_seat*             seat;
-    struct wl_pointer*          pointer;
-    struct wl_keyboard*         keyboard;
-    struct wl_data_device_manager*          dataDeviceManager;
-    struct wl_data_device*      dataDevice;
-    struct wl_data_offer*       dataOffer;
-    struct wl_data_source*      dataSource;
-    struct xdg_wm_base*         wmBase;
-    struct zxdg_decoration_manager_v1*      decorationManager;
-    struct wp_viewporter*       viewporter;
-    struct zwp_relative_pointer_manager_v1* relativePointerManager;
-    struct zwp_pointer_constraints_v1*      pointerConstraints;
-    struct zwp_idle_inhibit_manager_v1*     idleInhibitManager;
-
-    int                         compositorVersion;
-    int                         seatVersion;
-
-    struct wl_cursor_theme*     cursorTheme;
-    struct wl_cursor_theme*     cursorThemeHiDPI;
-    struct wl_surface*          cursorSurface;
-    const char*                 cursorPreviousName;
-    int                         cursorTimerfd;
-    uint32_t                    serial;
-
-    int32_t                     keyboardRepeatRate;
-    int32_t                     keyboardRepeatDelay;
-    int                         keyboardLastKey;
-    int                         keyboardLastScancode;
-    char*                       clipboardString;
-    size_t                      clipboardSize;
-    char*                       clipboardSendString;
-    size_t                      clipboardSendSize;
-    int                         timerfd;
-    short int                   keycodes[256];
-    short int                   scancodes[GLFW_KEY_LAST + 1];
-
-    struct {
-        void*                   handle;
-        struct xkb_context*     context;
-        struct xkb_keymap*      keymap;
-        struct xkb_state*       state;
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-        struct xkb_compose_state* composeState;
-#endif
-
-        xkb_mod_mask_t          controlMask;
-        xkb_mod_mask_t          altMask;
-        xkb_mod_mask_t          shiftMask;
-        xkb_mod_mask_t          superMask;
-        xkb_mod_mask_t          capsLockMask;
-        xkb_mod_mask_t          numLockMask;
-        unsigned int            modifiers;
-
-        PFN_xkb_context_new context_new;
-        PFN_xkb_context_unref context_unref;
-        PFN_xkb_keymap_new_from_string keymap_new_from_string;
-        PFN_xkb_keymap_unref keymap_unref;
-        PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
-        PFN_xkb_keymap_key_repeats keymap_key_repeats;
-        PFN_xkb_state_new state_new;
-        PFN_xkb_state_unref state_unref;
-        PFN_xkb_state_key_get_syms state_key_get_syms;
-        PFN_xkb_state_update_mask state_update_mask;
-        PFN_xkb_state_serialize_mods state_serialize_mods;
-
-#ifdef HAVE_XKBCOMMON_COMPOSE_H
-        PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
-        PFN_xkb_compose_table_unref compose_table_unref;
-        PFN_xkb_compose_state_new compose_state_new;
-        PFN_xkb_compose_state_unref compose_state_unref;
-        PFN_xkb_compose_state_feed compose_state_feed;
-        PFN_xkb_compose_state_get_status compose_state_get_status;
-        PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
-#endif
-    } xkb;
-
-    _GLFWwindow*                pointerFocus;
-    _GLFWwindow*                keyboardFocus;
-
-    struct {
-        void*                   handle;
-
-        PFN_wl_cursor_theme_load theme_load;
-        PFN_wl_cursor_theme_destroy theme_destroy;
-        PFN_wl_cursor_theme_get_cursor theme_get_cursor;
-        PFN_wl_cursor_image_get_buffer image_get_buffer;
-    } cursor;
-
-    struct {
-        void*                   handle;
-
-        PFN_wl_egl_window_create window_create;
-        PFN_wl_egl_window_destroy window_destroy;
-        PFN_wl_egl_window_resize window_resize;
-    } egl;
-
-} _GLFWlibraryWayland;
-
-// Wayland-specific per-monitor data
-//
-typedef struct _GLFWmonitorWayland
-{
-    struct wl_output*           output;
-    uint32_t                    name;
-    int                         currentMode;
-
-    int                         x;
-    int                         y;
-    int                         scale;
-
-} _GLFWmonitorWayland;
-
-// Wayland-specific per-cursor data
-//
-typedef struct _GLFWcursorWayland
-{
-    struct wl_cursor*           cursor;
-    struct wl_cursor*           cursorHiDPI;
-    struct wl_buffer*           buffer;
-    int                         width, height;
-    int                         xhot, yhot;
-    int                         currentImage;
-} _GLFWcursorWayland;
-
-
-void _glfwAddOutputWayland(uint32_t name, uint32_t version);
-
+//========================================================================
+// GLFW 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
+// 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 <wayland-client.h>
+#include <xkbcommon/xkbcommon.h>
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+#include <xkbcommon/xkbcommon-compose.h>
+#endif
+#include <dlfcn.h>
+
+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_thread.h"
+#include "posix_time.h"
+#ifdef __linux__
+#include "linux_joystick.h"
+#else
+#include "null_joystick.h"
+#endif
+#include "xkb_unicode.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+
+#include "wayland-xdg-shell-client-protocol.h"
+#include "wayland-xdg-decoration-client-protocol.h"
+#include "wayland-viewporter-client-protocol.h"
+#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
+#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
+#include "wayland-idle-inhibit-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         struct { int dummyContext; }
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE struct { int dummyLibraryContext; }
+
+struct wl_cursor_image {
+    uint32_t width;
+    uint32_t height;
+    uint32_t hotspot_x;
+    uint32_t hotspot_y;
+    uint32_t delay;
+};
+struct wl_cursor {
+    unsigned int image_count;
+    struct wl_cursor_image** images;
+    char* name;
+};
+typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*);
+typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*);
+typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*);
+typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*);
+#define wl_cursor_theme_load _glfw.wl.cursor.theme_load
+#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy
+#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor
+#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer
+
+typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int);
+typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*);
+typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int);
+#define wl_egl_window_create _glfw.wl.egl.window_create
+#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
+#define wl_egl_window_resize _glfw.wl.egl.window_resize
+
+typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
+typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
+typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
+typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
+typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
+typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
+typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
+typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
+typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
+typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
+typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
+#define xkb_context_new _glfw.wl.xkb.context_new
+#define xkb_context_unref _glfw.wl.xkb.context_unref
+#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
+#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
+#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
+#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
+#define xkb_state_new _glfw.wl.xkb.state_new
+#define xkb_state_unref _glfw.wl.xkb.state_unref
+#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
+#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
+#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
+typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
+typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
+typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
+typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
+typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
+typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
+#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
+#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
+#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
+#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
+#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
+#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
+#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
+#endif
+
+#define _GLFW_DECORATION_WIDTH 4
+#define _GLFW_DECORATION_TOP 24
+#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
+#define _GLFW_DECORATION_HORIZONTAL (2 * _GLFW_DECORATION_WIDTH)
+
+typedef enum _GLFWdecorationSideWayland
+{
+    mainWindow,
+    topDecoration,
+    leftDecoration,
+    rightDecoration,
+    bottomDecoration,
+
+} _GLFWdecorationSideWayland;
+
+typedef struct _GLFWdecorationWayland
+{
+    struct wl_surface*          surface;
+    struct wl_subsurface*       subsurface;
+    struct wp_viewport*         viewport;
+
+} _GLFWdecorationWayland;
+
+// Wayland-specific per-window data
+//
+typedef struct _GLFWwindowWayland
+{
+    int                         width, height;
+    GLFWbool                    visible;
+    GLFWbool                    maximized;
+    GLFWbool                    hovered;
+    GLFWbool                    transparent;
+    struct wl_surface*          surface;
+    struct wl_egl_window*       native;
+    struct wl_shell_surface*    shellSurface;
+    struct wl_callback*         callback;
+
+    struct {
+        struct xdg_surface*     surface;
+        struct xdg_toplevel*    toplevel;
+        struct zxdg_toplevel_decoration_v1* decoration;
+    } xdg;
+
+    _GLFWcursor*                currentCursor;
+    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;
+
+    struct zwp_idle_inhibitor_v1*          idleInhibitor;
+
+    GLFWbool                    wasFullscreen;
+
+    struct {
+        GLFWbool                           serverSide;
+        struct wl_buffer*                  buffer;
+        _GLFWdecorationWayland             top, left, right, bottom;
+        int                                focus;
+    } decorations;
+
+} _GLFWwindowWayland;
+
+// Wayland-specific global data
+//
+typedef struct _GLFWlibraryWayland
+{
+    struct wl_display*          display;
+    struct wl_registry*         registry;
+    struct wl_compositor*       compositor;
+    struct wl_subcompositor*    subcompositor;
+    struct wl_shell*            shell;
+    struct wl_shm*              shm;
+    struct wl_seat*             seat;
+    struct wl_pointer*          pointer;
+    struct wl_keyboard*         keyboard;
+    struct wl_data_device_manager*          dataDeviceManager;
+    struct wl_data_device*      dataDevice;
+    struct wl_data_offer*       dataOffer;
+    struct wl_data_source*      dataSource;
+    struct xdg_wm_base*         wmBase;
+    struct zxdg_decoration_manager_v1*      decorationManager;
+    struct wp_viewporter*       viewporter;
+    struct zwp_relative_pointer_manager_v1* relativePointerManager;
+    struct zwp_pointer_constraints_v1*      pointerConstraints;
+    struct zwp_idle_inhibit_manager_v1*     idleInhibitManager;
+
+    int                         compositorVersion;
+    int                         seatVersion;
+
+    struct wl_cursor_theme*     cursorTheme;
+    struct wl_cursor_theme*     cursorThemeHiDPI;
+    struct wl_surface*          cursorSurface;
+    const char*                 cursorPreviousName;
+    int                         cursorTimerfd;
+    uint32_t                    serial;
+
+    int32_t                     keyboardRepeatRate;
+    int32_t                     keyboardRepeatDelay;
+    int                         keyboardLastKey;
+    int                         keyboardLastScancode;
+    char*                       clipboardString;
+    size_t                      clipboardSize;
+    char*                       clipboardSendString;
+    size_t                      clipboardSendSize;
+    int                         timerfd;
+    short int                   keycodes[256];
+    short int                   scancodes[GLFW_KEY_LAST + 1];
+
+    struct {
+        void*                   handle;
+        struct xkb_context*     context;
+        struct xkb_keymap*      keymap;
+        struct xkb_state*       state;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+        struct xkb_compose_state* composeState;
+#endif
+
+        xkb_mod_mask_t          controlMask;
+        xkb_mod_mask_t          altMask;
+        xkb_mod_mask_t          shiftMask;
+        xkb_mod_mask_t          superMask;
+        xkb_mod_mask_t          capsLockMask;
+        xkb_mod_mask_t          numLockMask;
+        unsigned int            modifiers;
+
+        PFN_xkb_context_new context_new;
+        PFN_xkb_context_unref context_unref;
+        PFN_xkb_keymap_new_from_string keymap_new_from_string;
+        PFN_xkb_keymap_unref keymap_unref;
+        PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
+        PFN_xkb_keymap_key_repeats keymap_key_repeats;
+        PFN_xkb_state_new state_new;
+        PFN_xkb_state_unref state_unref;
+        PFN_xkb_state_key_get_syms state_key_get_syms;
+        PFN_xkb_state_update_mask state_update_mask;
+        PFN_xkb_state_serialize_mods state_serialize_mods;
+
+#ifdef HAVE_XKBCOMMON_COMPOSE_H
+        PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
+        PFN_xkb_compose_table_unref compose_table_unref;
+        PFN_xkb_compose_state_new compose_state_new;
+        PFN_xkb_compose_state_unref compose_state_unref;
+        PFN_xkb_compose_state_feed compose_state_feed;
+        PFN_xkb_compose_state_get_status compose_state_get_status;
+        PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
+#endif
+    } xkb;
+
+    _GLFWwindow*                pointerFocus;
+    _GLFWwindow*                keyboardFocus;
+
+    struct {
+        void*                   handle;
+
+        PFN_wl_cursor_theme_load theme_load;
+        PFN_wl_cursor_theme_destroy theme_destroy;
+        PFN_wl_cursor_theme_get_cursor theme_get_cursor;
+        PFN_wl_cursor_image_get_buffer image_get_buffer;
+    } cursor;
+
+    struct {
+        void*                   handle;
+
+        PFN_wl_egl_window_create window_create;
+        PFN_wl_egl_window_destroy window_destroy;
+        PFN_wl_egl_window_resize window_resize;
+    } egl;
+
+} _GLFWlibraryWayland;
+
+// Wayland-specific per-monitor data
+//
+typedef struct _GLFWmonitorWayland
+{
+    struct wl_output*           output;
+    uint32_t                    name;
+    int                         currentMode;
+
+    int                         x;
+    int                         y;
+    int                         scale;
+
+} _GLFWmonitorWayland;
+
+// Wayland-specific per-cursor data
+//
+typedef struct _GLFWcursorWayland
+{
+    struct wl_cursor*           cursor;
+    struct wl_cursor*           cursorHiDPI;
+    struct wl_buffer*           buffer;
+    int                         width, height;
+    int                         xhot, yhot;
+    int                         currentImage;
+} _GLFWcursorWayland;
+
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version);
+
diff --git a/glfw/src/wl_window.c b/glfw/src/wl_window.c
--- a/glfw/src/wl_window.c
+++ b/glfw/src/wl_window.c
@@ -1,1894 +1,1894 @@
-//========================================================================
-// GLFW 3.3 Wayland - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
-// 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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#define _GNU_SOURCE
-
-#include "internal.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/timerfd.h>
-#include <poll.h>
-
-
-static void shellSurfaceHandlePing(void* data,
-                                   struct wl_shell_surface* shellSurface,
-                                   uint32_t serial)
-{
-    wl_shell_surface_pong(shellSurface, serial);
-}
-
-static void shellSurfaceHandleConfigure(void* data,
-                                        struct wl_shell_surface* shellSurface,
-                                        uint32_t edges,
-                                        int32_t width,
-                                        int32_t height)
-{
-    _GLFWwindow* window = data;
-    float aspectRatio;
-    float targetRatio;
-
-    if (!window->monitor)
-    {
-        if (_glfw.wl.viewporter && window->decorated)
-        {
-            width -= _GLFW_DECORATION_HORIZONTAL;
-            height -= _GLFW_DECORATION_VERTICAL;
-        }
-        if (width < 1)
-            width = 1;
-        if (height < 1)
-            height = 1;
-
-        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);
-}
-
-static void shellSurfaceHandlePopupDone(void* data,
-                                        struct wl_shell_surface* shellSurface)
-{
-}
-
-static const struct wl_shell_surface_listener shellSurfaceListener = {
-    shellSurfaceHandlePing,
-    shellSurfaceHandleConfigure,
-    shellSurfaceHandlePopupDone
-};
-
-static int createTmpfileCloexec(char* tmpname)
-{
-    int fd;
-
-    fd = mkostemp(tmpname, O_CLOEXEC);
-    if (fd >= 0)
-        unlink(tmpname);
-
-    return fd;
-}
-
-/*
- * Create a new, unique, anonymous file of the given size, and
- * return the file descriptor for it. The file descriptor is set
- * CLOEXEC. The file is immediately suitable for mmap()'ing
- * the given size at offset zero.
- *
- * The file should not have a permanent backing store like a disk,
- * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
- *
- * The file name is deleted from the file system.
- *
- * The file is suitable for buffer sharing between processes by
- * transmitting the file descriptor over Unix sockets using the
- * SCM_RIGHTS methods.
- *
- * posix_fallocate() is used to guarantee that disk space is available
- * for the file at the given size. If disk space is insufficient, errno
- * is set to ENOSPC. If posix_fallocate() is not supported, program may
- * receive SIGBUS on accessing mmap()'ed file contents instead.
- */
-static int createAnonymousFile(off_t size)
-{
-    static const char template[] = "/glfw-shared-XXXXXX";
-    const char* path;
-    char* name;
-    int fd;
-    int ret;
-
-#ifdef HAVE_MEMFD_CREATE
-    fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
-    if (fd >= 0)
-    {
-        // We can add this seal before calling posix_fallocate(), as the file
-        // is currently zero-sized anyway.
-        //
-        // There is also no need to check for the return value, we couldn’t do
-        // anything with it anyway.
-        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
-    }
-    else
-#elif defined(SHM_ANON)
-    fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);
-    if (fd < 0)
-#endif
-    {
-        path = getenv("XDG_RUNTIME_DIR");
-        if (!path)
-        {
-            errno = ENOENT;
-            return -1;
-        }
-
-        name = calloc(strlen(path) + sizeof(template), 1);
-        strcpy(name, path);
-        strcat(name, template);
-
-        fd = createTmpfileCloexec(name);
-        free(name);
-        if (fd < 0)
-            return -1;
-    }
-
-#if defined(SHM_ANON)
-    // posix_fallocate does not work on SHM descriptors
-    ret = ftruncate(fd, size);
-#else
-    ret = posix_fallocate(fd, 0, size);
-#endif
-    if (ret != 0)
-    {
-        close(fd);
-        errno = ret;
-        return -1;
-    }
-    return fd;
-}
-
-static struct wl_buffer* createShmBuffer(const GLFWimage* image)
-{
-    struct wl_shm_pool* pool;
-    struct wl_buffer* buffer;
-    int stride = image->width * 4;
-    int length = image->width * image->height * 4;
-    void* data;
-    int fd, i;
-
-    fd = createAnonymousFile(length);
-    if (fd < 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Creating a buffer file for %d B failed: %m",
-                        length);
-        return NULL;
-    }
-
-    data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-    if (data == MAP_FAILED)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: mmap failed: %m");
-        close(fd);
-        return NULL;
-    }
-
-    pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
-
-    close(fd);
-    unsigned char* source = (unsigned char*) image->pixels;
-    unsigned char* target = data;
-    for (i = 0;  i < image->width * image->height;  i++, source += 4)
-    {
-        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;
-    }
-
-    buffer =
-        wl_shm_pool_create_buffer(pool, 0,
-                                  image->width,
-                                  image->height,
-                                  stride, WL_SHM_FORMAT_ARGB8888);
-    munmap(data, length);
-    wl_shm_pool_destroy(pool);
-
-    return buffer;
-}
-
-static void createDecoration(_GLFWdecorationWayland* decoration,
-                             struct wl_surface* parent,
-                             struct wl_buffer* buffer, GLFWbool opaque,
-                             int x, int y,
-                             int width, int height)
-{
-    struct wl_region* region;
-
-    decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
-    decoration->subsurface =
-        wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
-                                        decoration->surface, parent);
-    wl_subsurface_set_position(decoration->subsurface, x, y);
-    decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,
-                                                      decoration->surface);
-    wp_viewport_set_destination(decoration->viewport, width, height);
-    wl_surface_attach(decoration->surface, buffer, 0, 0);
-
-    if (opaque)
-    {
-        region = wl_compositor_create_region(_glfw.wl.compositor);
-        wl_region_add(region, 0, 0, width, height);
-        wl_surface_set_opaque_region(decoration->surface, region);
-        wl_surface_commit(decoration->surface);
-        wl_region_destroy(region);
-    }
-    else
-        wl_surface_commit(decoration->surface);
-}
-
-static void createDecorations(_GLFWwindow* window)
-{
-    unsigned char data[] = { 224, 224, 224, 255 };
-    const GLFWimage image = { 1, 1, data };
-    GLFWbool opaque = (data[3] == 255);
-
-    if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
-        return;
-
-    if (!window->wl.decorations.buffer)
-        window->wl.decorations.buffer = createShmBuffer(&image);
-    if (!window->wl.decorations.buffer)
-        return;
-
-    createDecoration(&window->wl.decorations.top, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     0, -_GLFW_DECORATION_TOP,
-                     window->wl.width, _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.left, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP,
-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.right, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     window->wl.width, -_GLFW_DECORATION_TOP,
-                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    createDecoration(&window->wl.decorations.bottom, window->wl.surface,
-                     window->wl.decorations.buffer, opaque,
-                     -_GLFW_DECORATION_WIDTH, window->wl.height,
-                     window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
-}
-
-static void destroyDecoration(_GLFWdecorationWayland* decoration)
-{
-    if (decoration->surface)
-        wl_surface_destroy(decoration->surface);
-    if (decoration->subsurface)
-        wl_subsurface_destroy(decoration->subsurface);
-    if (decoration->viewport)
-        wp_viewport_destroy(decoration->viewport);
-    decoration->surface = NULL;
-    decoration->subsurface = NULL;
-    decoration->viewport = NULL;
-}
-
-static void destroyDecorations(_GLFWwindow* window)
-{
-    destroyDecoration(&window->wl.decorations.top);
-    destroyDecoration(&window->wl.decorations.left);
-    destroyDecoration(&window->wl.decorations.right);
-    destroyDecoration(&window->wl.decorations.bottom);
-}
-
-static void xdgDecorationHandleConfigure(void* data,
-                                         struct zxdg_toplevel_decoration_v1* decoration,
-                                         uint32_t mode)
-{
-    _GLFWwindow* window = data;
-
-    window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
-
-    if (!window->wl.decorations.serverSide)
-        createDecorations(window);
-}
-
-static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
-    xdgDecorationHandleConfigure,
-};
-
-// 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 void resizeWindow(_GLFWwindow* window)
-{
-    int scale = window->wl.scale;
-    int scaledWidth = window->wl.width * scale;
-    int scaledHeight = window->wl.height * scale;
-    wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
-    if (!window->wl.transparent)
-        setOpaqueRegion(window);
-    _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
-    _glfwInputWindowContentScale(window, scale, scale);
-
-    if (!window->wl.decorations.top.surface)
-        return;
-
-    // Top decoration.
-    wp_viewport_set_destination(window->wl.decorations.top.viewport,
-                                window->wl.width, _GLFW_DECORATION_TOP);
-    wl_surface_commit(window->wl.decorations.top.surface);
-
-    // Left decoration.
-    wp_viewport_set_destination(window->wl.decorations.left.viewport,
-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    wl_surface_commit(window->wl.decorations.left.surface);
-
-    // Right decoration.
-    wl_subsurface_set_position(window->wl.decorations.right.subsurface,
-                               window->wl.width, -_GLFW_DECORATION_TOP);
-    wp_viewport_set_destination(window->wl.decorations.right.viewport,
-                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
-    wl_surface_commit(window->wl.decorations.right.surface);
-
-    // Bottom decoration.
-    wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
-                               -_GLFW_DECORATION_WIDTH, window->wl.height);
-    wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
-                                window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
-    wl_surface_commit(window->wl.decorations.bottom.surface);
-}
-
-static void checkScaleChange(_GLFWwindow* window)
-{
-    int scale = 1;
-    int i;
-    int monitorScale;
-
-    // Check if we will be able to set the buffer scale or not.
-    if (_glfw.wl.compositorVersion < 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;
-        wl_surface_set_buffer_scale(window->wl.surface, scale);
-        resizeWindow(window);
-    }
-}
-
-static void surfaceHandleEnter(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 surfaceHandleLeave(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 = {
-    surfaceHandleEnter,
-    surfaceHandleLeave
-};
-
-static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
-{
-    if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
-    {
-        window->wl.idleInhibitor =
-            zwp_idle_inhibit_manager_v1_create_inhibitor(
-                _glfw.wl.idleInhibitManager, window->wl.surface);
-        if (!window->wl.idleInhibitor)
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Idle inhibitor creation failed");
-    }
-    else if (!enable && window->wl.idleInhibitor)
-    {
-        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
-        window->wl.idleInhibitor = NULL;
-    }
-}
-
-static GLFWbool createSurface(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig)
-{
-    window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
-    if (!window->wl.surface)
-        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 GLFW_FALSE;
-
-    window->wl.width = wndconfig->width;
-    window->wl.height = wndconfig->height;
-    window->wl.scale = 1;
-
-    if (!window->wl.transparent)
-        setOpaqueRegion(window);
-
-    return GLFW_TRUE;
-}
-
-static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
-                          int refreshRate)
-{
-    if (window->wl.xdg.toplevel)
-    {
-        xdg_toplevel_set_fullscreen(
-            window->wl.xdg.toplevel,
-            monitor->wl.output);
-    }
-    else if (window->wl.shellSurface)
-    {
-        wl_shell_surface_set_fullscreen(
-            window->wl.shellSurface,
-            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
-            refreshRate * 1000, // Convert Hz to mHz.
-            monitor->wl.output);
-    }
-    setIdleInhibitor(window, GLFW_TRUE);
-    if (!window->wl.decorations.serverSide)
-        destroyDecorations(window);
-}
-
-static GLFWbool createShellSurface(_GLFWwindow* window)
-{
-    if (!_glfw.wl.shell)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: wl_shell protocol not available");
-        return GLFW_FALSE;
-    }
-
-    window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
-                                                         window->wl.surface);
-    if (!window->wl.shellSurface)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Shell surface creation failed");
-        return GLFW_FALSE;
-    }
-
-    wl_shell_surface_add_listener(window->wl.shellSurface,
-                                  &shellSurfaceListener,
-                                  window);
-
-    if (window->wl.title)
-        wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);
-
-    if (window->monitor)
-    {
-        setFullscreen(window, window->monitor, 0);
-    }
-    else if (window->wl.maximized)
-    {
-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
-        setIdleInhibitor(window, GLFW_FALSE);
-        createDecorations(window);
-    }
-    else
-    {
-        wl_shell_surface_set_toplevel(window->wl.shellSurface);
-        setIdleInhibitor(window, GLFW_FALSE);
-        createDecorations(window);
-    }
-
-    wl_surface_commit(window->wl.surface);
-
-    return GLFW_TRUE;
-}
-
-static void xdgToplevelHandleConfigure(void* data,
-                                       struct xdg_toplevel* toplevel,
-                                       int32_t width,
-                                       int32_t height,
-                                       struct wl_array* states)
-{
-    _GLFWwindow* window = data;
-    float aspectRatio;
-    float targetRatio;
-    uint32_t* state;
-    GLFWbool maximized = GLFW_FALSE;
-    GLFWbool fullscreen = GLFW_FALSE;
-    GLFWbool activated = GLFW_FALSE;
-
-    wl_array_for_each(state, states)
-    {
-        switch (*state)
-        {
-            case XDG_TOPLEVEL_STATE_MAXIMIZED:
-                maximized = GLFW_TRUE;
-                break;
-            case XDG_TOPLEVEL_STATE_FULLSCREEN:
-                fullscreen = GLFW_TRUE;
-                break;
-            case XDG_TOPLEVEL_STATE_RESIZING:
-                break;
-            case XDG_TOPLEVEL_STATE_ACTIVATED:
-                activated = GLFW_TRUE;
-                break;
-        }
-    }
-
-    if (width != 0 && height != 0)
-    {
-        if (!maximized && !fullscreen)
-        {
-            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;
-            }
-        }
-
-        _glfwInputWindowSize(window, width, height);
-        _glfwPlatformSetWindowSize(window, width, height);
-        _glfwInputWindowDamage(window);
-    }
-
-    if (window->wl.wasFullscreen && window->autoIconify)
-    {
-        if (!activated || !fullscreen)
-        {
-            _glfwPlatformIconifyWindow(window);
-            window->wl.wasFullscreen = GLFW_FALSE;
-        }
-    }
-    if (fullscreen && activated)
-        window->wl.wasFullscreen = GLFW_TRUE;
-    _glfwInputWindowFocus(window, activated);
-}
-
-static void xdgToplevelHandleClose(void* data,
-                                   struct xdg_toplevel* toplevel)
-{
-    _GLFWwindow* window = data;
-    _glfwInputWindowCloseRequest(window);
-}
-
-static const struct xdg_toplevel_listener xdgToplevelListener = {
-    xdgToplevelHandleConfigure,
-    xdgToplevelHandleClose
-};
-
-static void xdgSurfaceHandleConfigure(void* data,
-                                      struct xdg_surface* surface,
-                                      uint32_t serial)
-{
-    xdg_surface_ack_configure(surface, serial);
-}
-
-static const struct xdg_surface_listener xdgSurfaceListener = {
-    xdgSurfaceHandleConfigure
-};
-
-static void setXdgDecorations(_GLFWwindow* window)
-{
-    if (_glfw.wl.decorationManager)
-    {
-        window->wl.xdg.decoration =
-            zxdg_decoration_manager_v1_get_toplevel_decoration(
-                _glfw.wl.decorationManager, window->wl.xdg.toplevel);
-        zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
-                                                 &xdgDecorationListener,
-                                                 window);
-        zxdg_toplevel_decoration_v1_set_mode(
-            window->wl.xdg.decoration,
-            ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
-    }
-    else
-    {
-        window->wl.decorations.serverSide = GLFW_FALSE;
-        createDecorations(window);
-    }
-}
-
-static GLFWbool createXdgSurface(_GLFWwindow* window)
-{
-    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
-                                                         window->wl.surface);
-    if (!window->wl.xdg.surface)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: xdg-surface creation failed");
-        return GLFW_FALSE;
-    }
-
-    xdg_surface_add_listener(window->wl.xdg.surface,
-                             &xdgSurfaceListener,
-                             window);
-
-    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
-    if (!window->wl.xdg.toplevel)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: xdg-toplevel creation failed");
-        return GLFW_FALSE;
-    }
-
-    xdg_toplevel_add_listener(window->wl.xdg.toplevel,
-                              &xdgToplevelListener,
-                              window);
-
-    if (window->wl.title)
-        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
-
-    if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
-        xdg_toplevel_set_min_size(window->wl.xdg.toplevel,
-                                  window->minwidth, window->minheight);
-    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
-        xdg_toplevel_set_max_size(window->wl.xdg.toplevel,
-                                  window->maxwidth, window->maxheight);
-
-    if (window->monitor)
-    {
-        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
-                                    window->monitor->wl.output);
-        setIdleInhibitor(window, GLFW_TRUE);
-    }
-    else if (window->wl.maximized)
-    {
-        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
-        setIdleInhibitor(window, GLFW_FALSE);
-        setXdgDecorations(window);
-    }
-    else
-    {
-        setIdleInhibitor(window, GLFW_FALSE);
-        setXdgDecorations(window);
-    }
-
-    wl_surface_commit(window->wl.surface);
-    wl_display_roundtrip(_glfw.wl.display);
-
-    return GLFW_TRUE;
-}
-
-static void setCursorImage(_GLFWwindow* window,
-                           _GLFWcursorWayland* cursorWayland)
-{
-    struct itimerspec timer = {};
-    struct wl_cursor* wlCursor = cursorWayland->cursor;
-    struct wl_cursor_image* image;
-    struct wl_buffer* buffer;
-    struct wl_surface* surface = _glfw.wl.cursorSurface;
-    int scale = 1;
-
-    if (!wlCursor)
-        buffer = cursorWayland->buffer;
-    else
-    {
-        if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
-        {
-            wlCursor = cursorWayland->cursorHiDPI;
-            scale = 2;
-        }
-
-        image = wlCursor->images[cursorWayland->currentImage];
-        buffer = wl_cursor_image_get_buffer(image);
-        if (!buffer)
-            return;
-
-        timer.it_value.tv_sec = image->delay / 1000;
-        timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;
-        timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);
-
-        cursorWayland->width = image->width;
-        cursorWayland->height = image->height;
-        cursorWayland->xhot = image->hotspot_x;
-        cursorWayland->yhot = image->hotspot_y;
-    }
-
-    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
-                          surface,
-                          cursorWayland->xhot / scale,
-                          cursorWayland->yhot / scale);
-    wl_surface_set_buffer_scale(surface, scale);
-    wl_surface_attach(surface, buffer, 0, 0);
-    wl_surface_damage(surface, 0, 0,
-                      cursorWayland->width, cursorWayland->height);
-    wl_surface_commit(surface);
-}
-
-static void incrementCursorImage(_GLFWwindow* window)
-{
-    _GLFWcursor* cursor;
-
-    if (!window || window->wl.decorations.focus != mainWindow)
-        return;
-
-    cursor = window->wl.currentCursor;
-    if (cursor && cursor->wl.cursor)
-    {
-        cursor->wl.currentImage += 1;
-        cursor->wl.currentImage %= cursor->wl.cursor->image_count;
-        setCursorImage(window, &cursor->wl);
-    }
-}
-
-static void handleEvents(int timeout)
-{
-    struct wl_display* display = _glfw.wl.display;
-    struct pollfd fds[] = {
-        { wl_display_get_fd(display), POLLIN },
-        { _glfw.wl.timerfd, POLLIN },
-        { _glfw.wl.cursorTimerfd, POLLIN },
-    };
-    ssize_t read_ret;
-    uint64_t repeats, i;
-
-    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, 3, timeout) > 0)
-    {
-        if (fds[0].revents & POLLIN)
-        {
-            wl_display_read_events(display);
-            wl_display_dispatch_pending(display);
-        }
-        else
-        {
-            wl_display_cancel_read(display);
-        }
-
-        if (fds[1].revents & POLLIN)
-        {
-            read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
-            if (read_ret != 8)
-                return;
-
-            for (i = 0; i < repeats; ++i)
-                _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
-                              _glfw.wl.keyboardLastScancode, GLFW_REPEAT,
-                              _glfw.wl.xkb.modifiers);
-        }
-
-        if (fds[2].revents & POLLIN)
-        {
-            read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
-            if (read_ret != 8)
-                return;
-
-            incrementCursorImage(_glfw.wl.pointerFocus);
-        }
-    }
-    else
-    {
-        wl_display_cancel_read(display);
-    }
-}
-
-// 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 "hand2";
-        case GLFW_HRESIZE_CURSOR:
-            return "sb_h_double_arrow";
-        case GLFW_VRESIZE_CURSOR:
-            return "sb_v_double_arrow";
-    }
-    return NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformCreateWindow(_GLFWwindow* window,
-                              const _GLFWwndconfig* wndconfig,
-                              const _GLFWctxconfig* ctxconfig,
-                              const _GLFWfbconfig* fbconfig)
-{
-    window->wl.transparent = fbconfig->transparent;
-
-    if (!createSurface(window, wndconfig))
-        return GLFW_FALSE;
-
-    if (ctxconfig->client != GLFW_NO_API)
-    {
-        if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
-            ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
-        {
-            if (!_glfwInitEGL())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwInitOSMesa())
-                return GLFW_FALSE;
-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-    }
-
-    if (wndconfig->title)
-        window->wl.title = _glfw_strdup(wndconfig->title);
-
-    if (wndconfig->visible)
-    {
-        if (_glfw.wl.wmBase)
-        {
-            if (!createXdgSurface(window))
-                return GLFW_FALSE;
-        }
-        else
-        {
-            if (!createShellSurface(window))
-                return GLFW_FALSE;
-        }
-
-        window->wl.visible = GLFW_TRUE;
-    }
-    else
-    {
-        window->wl.xdg.surface = NULL;
-        window->wl.xdg.toplevel = NULL;
-        window->wl.shellSurface = NULL;
-        window->wl.visible = GLFW_FALSE;
-    }
-
-    window->wl.currentCursor = NULL;
-
-    window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
-    window->wl.monitorsCount = 0;
-    window->wl.monitorsSize = 1;
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyWindow(_GLFWwindow* window)
-{
-    if (window == _glfw.wl.pointerFocus)
-    {
-        _glfw.wl.pointerFocus = NULL;
-        _glfwInputCursorEnter(window, GLFW_FALSE);
-    }
-    if (window == _glfw.wl.keyboardFocus)
-    {
-        _glfw.wl.keyboardFocus = NULL;
-        _glfwInputWindowFocus(window, GLFW_FALSE);
-    }
-
-    if (window->wl.idleInhibitor)
-        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
-
-    if (window->context.destroy)
-        window->context.destroy(window);
-
-    destroyDecorations(window);
-    if (window->wl.xdg.decoration)
-        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
-
-    if (window->wl.decorations.buffer)
-        wl_buffer_destroy(window->wl.decorations.buffer);
-
-    if (window->wl.native)
-        wl_egl_window_destroy(window->wl.native);
-
-    if (window->wl.shellSurface)
-        wl_shell_surface_destroy(window->wl.shellSurface);
-
-    if (window->wl.xdg.toplevel)
-        xdg_toplevel_destroy(window->wl.xdg.toplevel);
-
-    if (window->wl.xdg.surface)
-        xdg_surface_destroy(window->wl.xdg.surface);
-
-    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)
-{
-    if (window->wl.title)
-        free(window->wl.title);
-    window->wl.title = _glfw_strdup(title);
-    if (window->wl.xdg.toplevel)
-        xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
-    else if (window->wl.shellSurface)
-        wl_shell_surface_set_title(window->wl.shellSurface, 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
-    // as (0, 0)
-
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window position retrieval not supported");
-}
-
-void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
-{
-    // A Wayland client can not set its position, so just warn
-
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window position setting not supported");
-}
-
-void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
-{
-    if (width)
-        *width = window->wl.width;
-    if (height)
-        *height = window->wl.height;
-}
-
-void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
-{
-    window->wl.width = width;
-    window->wl.height = height;
-    resizeWindow(window);
-}
-
-void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
-                                      int minwidth, int minheight,
-                                      int maxwidth, int maxheight)
-{
-    if (_glfw.wl.wmBase)
-    {
-        if (window->wl.xdg.toplevel)
-        {
-            if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
-                minwidth = minheight = 0;
-            if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
-                maxwidth = maxheight = 0;
-            xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
-            xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
-            wl_surface_commit(window->wl.surface);
-        }
-    }
-    else
-    {
-        // 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)
-{
-    if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
-    {
-        if (top)
-            *top = _GLFW_DECORATION_TOP;
-        if (left)
-            *left = _GLFW_DECORATION_WIDTH;
-        if (right)
-            *right = _GLFW_DECORATION_WIDTH;
-        if (bottom)
-            *bottom = _GLFW_DECORATION_WIDTH;
-    }
-}
-
-void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = (float) window->wl.scale;
-    if (yscale)
-        *yscale = (float) window->wl.scale;
-}
-
-void _glfwPlatformIconifyWindow(_GLFWwindow* window)
-{
-    if (_glfw.wl.wmBase)
-    {
-        if (window->wl.xdg.toplevel)
-            xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Iconify window not supported on wl_shell");
-    }
-}
-
-void _glfwPlatformRestoreWindow(_GLFWwindow* window)
-{
-    if (window->wl.xdg.toplevel)
-    {
-        if (window->monitor)
-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
-        if (window->wl.maximized)
-            xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
-        // There is no way to unset minimized, or even to know if we are
-        // minimized, so there is nothing to do here.
-    }
-    else if (window->wl.shellSurface)
-    {
-        if (window->monitor || window->wl.maximized)
-            wl_shell_surface_set_toplevel(window->wl.shellSurface);
-    }
-    _glfwInputWindowMonitor(window, NULL);
-    window->wl.maximized = GLFW_FALSE;
-}
-
-void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
-{
-    if (window->wl.xdg.toplevel)
-    {
-        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
-    }
-    else if (window->wl.shellSurface)
-    {
-        // Let the compositor select the best output.
-        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
-    }
-    window->wl.maximized = GLFW_TRUE;
-}
-
-void _glfwPlatformShowWindow(_GLFWwindow* window)
-{
-    if (!window->wl.visible)
-    {
-        if (_glfw.wl.wmBase)
-            createXdgSurface(window);
-        else if (!window->wl.shellSurface)
-            createShellSurface(window);
-        window->wl.visible = GLFW_TRUE;
-    }
-}
-
-void _glfwPlatformHideWindow(_GLFWwindow* window)
-{
-    if (window->wl.xdg.toplevel)
-    {
-        xdg_toplevel_destroy(window->wl.xdg.toplevel);
-        xdg_surface_destroy(window->wl.xdg.surface);
-        window->wl.xdg.toplevel = NULL;
-        window->wl.xdg.surface = NULL;
-    }
-    else if (window->wl.shellSurface)
-    {
-        wl_shell_surface_destroy(window->wl.shellSurface);
-        window->wl.shellSurface = NULL;
-    }
-    window->wl.visible = GLFW_FALSE;
-}
-
-void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
-{
-    // TODO
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window attention request not implemented yet");
-}
-
-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)
-    {
-        setFullscreen(window, monitor, refreshRate);
-    }
-    else
-    {
-        if (window->wl.xdg.toplevel)
-            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
-        else if (window->wl.shellSurface)
-            wl_shell_surface_set_toplevel(window->wl.shellSurface);
-        setIdleInhibitor(window, GLFW_FALSE);
-        if (!_glfw.wl.decorationManager)
-            createDecorations(window);
-    }
-    _glfwInputWindowMonitor(window, monitor);
-}
-
-int _glfwPlatformWindowFocused(_GLFWwindow* window)
-{
-    return _glfw.wl.keyboardFocus == window;
-}
-
-int _glfwPlatformWindowIconified(_GLFWwindow* window)
-{
-    // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
-    // any way to request whether a surface is iconified.
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformWindowVisible(_GLFWwindow* window)
-{
-    return window->wl.visible;
-}
-
-int _glfwPlatformWindowMaximized(_GLFWwindow* window)
-{
-    return window->wl.maximized;
-}
-
-int _glfwPlatformWindowHovered(_GLFWwindow* window)
-{
-    return window->wl.hovered;
-}
-
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
-{
-    return window->wl.transparent;
-}
-
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
-{
-    // TODO
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window attribute setting not implemented yet");
-}
-
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
-{
-    if (!window->monitor)
-    {
-        if (enabled)
-            createDecorations(window);
-        else
-            destroyDecorations(window);
-    }
-}
-
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
-{
-    // TODO
-    _glfwInputError(GLFW_PLATFORM_ERROR,
-                    "Wayland: Window attribute setting not implemented yet");
-}
-
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
-{
-    return 1.f;
-}
-
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
-{
-}
-
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
-{
-    // This is handled in relativePointerHandleRelativeMotion
-}
-
-GLFWbool _glfwPlatformRawMouseMotionSupported(void)
-{
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformPollEvents(void)
-{
-    handleEvents(0);
-}
-
-void _glfwPlatformWaitEvents(void)
-{
-    handleEvents(-1);
-}
-
-void _glfwPlatformWaitEventsTimeout(double timeout)
-{
-    handleEvents((int) (timeout * 1e3));
-}
-
-void _glfwPlatformPostEmptyEvent(void)
-{
-    wl_display_sync(_glfw.wl.display);
-}
-
-void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
-{
-    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)
-{
-    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 _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
-{
-    _glfwPlatformSetCursor(window, window->wl.currentCursor);
-}
-
-const char* _glfwPlatformGetScancodeName(int scancode)
-{
-    // TODO
-    return NULL;
-}
-
-int _glfwPlatformGetKeyScancode(int key)
-{
-    return _glfw.wl.scancodes[key];
-}
-
-int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
-                              const GLFWimage* image,
-                              int xhot, int yhot)
-{
-    cursor->wl.buffer = createShmBuffer(image);
-    if (!cursor->wl.buffer)
-        return GLFW_FALSE;
-
-    cursor->wl.width = image->width;
-    cursor->wl.height = image->height;
-    cursor->wl.xhot = xhot;
-    cursor->wl.yhot = yhot;
-    return GLFW_TRUE;
-}
-
-int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
-{
-    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.cursor = standardCursor;
-    cursor->wl.currentImage = 0;
-
-    if (_glfw.wl.cursorThemeHiDPI)
-    {
-        standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
-                                                    translateCursorShape(shape));
-        cursor->wl.cursorHiDPI = standardCursor;
-    }
-
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
-{
-    // If it's a standard cursor we don't need to do anything here
-    if (cursor->wl.cursor)
-        return;
-
-    if (cursor->wl.buffer)
-        wl_buffer_destroy(cursor->wl.buffer);
-}
-
-static void relativePointerHandleRelativeMotion(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;
-    double xpos = window->virtualCursorPosX;
-    double ypos = window->virtualCursorPosY;
-
-    if (window->cursorMode != GLFW_CURSOR_DISABLED)
-        return;
-
-    if (window->rawMouseMotion)
-    {
-        xpos += wl_fixed_to_double(dxUnaccel);
-        ypos += wl_fixed_to_double(dyUnaccel);
-    }
-    else
-    {
-        xpos += wl_fixed_to_double(dx);
-        ypos += wl_fixed_to_double(dy);
-    }
-
-    _glfwInputCursorPos(window, xpos, ypos);
-}
-
-static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
-    relativePointerHandleRelativeMotion
-};
-
-static void lockedPointerHandleLocked(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 lockedPointerHandleUnlocked(void* data,
-                                        struct zwp_locked_pointer_v1* lockedPointer)
-{
-}
-
-static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
-    lockedPointerHandleLocked,
-    lockedPointerHandleUnlocked
-};
-
-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.serial,
-                          NULL, 0, 0);
-}
-
-static GLFWbool isPointerLocked(_GLFWwindow* window)
-{
-    return window->wl.pointerLock.lockedPointer != NULL;
-}
-
-void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
-{
-    struct wl_cursor* defaultCursor;
-    struct wl_cursor* defaultCursorHiDPI = NULL;
-
-    if (!_glfw.wl.pointer)
-        return;
-
-    window->wl.currentCursor = cursor;
-
-    // If we're not in the correct window just save the cursor
-    // the next time the pointer enters the window the cursor will change
-    if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
-        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)
-            setCursorImage(window, &cursor->wl);
-        else
-        {
-            defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
-                                                       "left_ptr");
-            if (!defaultCursor)
-            {
-                _glfwInputError(GLFW_PLATFORM_ERROR,
-                                "Wayland: Standard cursor not found");
-                return;
-            }
-            if (_glfw.wl.cursorThemeHiDPI)
-                defaultCursorHiDPI =
-                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
-                                               "left_ptr");
-            _GLFWcursorWayland cursorWayland = {
-                defaultCursor,
-                defaultCursorHiDPI,
-                NULL,
-                0, 0,
-                0, 0,
-                0
-            };
-            setCursorImage(window, &cursorWayland);
-        }
-    }
-    else if (window->cursorMode == GLFW_CURSOR_DISABLED)
-    {
-        if (!isPointerLocked(window))
-            lockPointer(window);
-    }
-    else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
-    {
-        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
-    }
-}
-
-static void dataSourceHandleTarget(void* data,
-                                   struct wl_data_source* dataSource,
-                                   const char* mimeType)
-{
-    if (_glfw.wl.dataSource != dataSource)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unknown clipboard data source");
-        return;
-    }
-}
-
-static void dataSourceHandleSend(void* data,
-                                 struct wl_data_source* dataSource,
-                                 const char* mimeType,
-                                 int fd)
-{
-    const char* string = _glfw.wl.clipboardSendString;
-    size_t len = _glfw.wl.clipboardSendSize;
-    int ret;
-
-    if (_glfw.wl.dataSource != dataSource)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unknown clipboard data source");
-        return;
-    }
-
-    if (!string)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Copy requested from an invalid string");
-        return;
-    }
-
-    if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Wrong MIME type asked from clipboard");
-        close(fd);
-        return;
-    }
-
-    while (len > 0)
-    {
-        ret = write(fd, string, len);
-        if (ret == -1 && errno == EINTR)
-            continue;
-        if (ret == -1)
-        {
-            // TODO: also report errno maybe.
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Error while writing the clipboard");
-            close(fd);
-            return;
-        }
-        len -= ret;
-    }
-    close(fd);
-}
-
-static void dataSourceHandleCancelled(void* data,
-                                      struct wl_data_source* dataSource)
-{
-    wl_data_source_destroy(dataSource);
-
-    if (_glfw.wl.dataSource != dataSource)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Unknown clipboard data source");
-        return;
-    }
-
-    _glfw.wl.dataSource = NULL;
-}
-
-static const struct wl_data_source_listener dataSourceListener = {
-    dataSourceHandleTarget,
-    dataSourceHandleSend,
-    dataSourceHandleCancelled,
-};
-
-void _glfwPlatformSetClipboardString(const char* string)
-{
-    if (_glfw.wl.dataSource)
-    {
-        wl_data_source_destroy(_glfw.wl.dataSource);
-        _glfw.wl.dataSource = NULL;
-    }
-
-    if (_glfw.wl.clipboardSendString)
-    {
-        free(_glfw.wl.clipboardSendString);
-        _glfw.wl.clipboardSendString = NULL;
-    }
-
-    _glfw.wl.clipboardSendString = strdup(string);
-    if (!_glfw.wl.clipboardSendString)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to allocate clipboard string");
-        return;
-    }
-    _glfw.wl.clipboardSendSize = strlen(string);
-    _glfw.wl.dataSource =
-        wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
-    if (!_glfw.wl.dataSource)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to create clipboard source");
-        free(_glfw.wl.clipboardSendString);
-        return;
-    }
-    wl_data_source_add_listener(_glfw.wl.dataSource,
-                                &dataSourceListener,
-                                NULL);
-    wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
-    wl_data_device_set_selection(_glfw.wl.dataDevice,
-                                 _glfw.wl.dataSource,
-                                 _glfw.wl.serial);
-}
-
-static GLFWbool growClipboardString(void)
-{
-    char* clipboard = _glfw.wl.clipboardString;
-
-    clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
-    if (!clipboard)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to grow clipboard string");
-        return GLFW_FALSE;
-    }
-    _glfw.wl.clipboardString = clipboard;
-    _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
-    return GLFW_TRUE;
-}
-
-const char* _glfwPlatformGetClipboardString(void)
-{
-    int fds[2];
-    int ret;
-    size_t len = 0;
-
-    if (!_glfw.wl.dataOffer)
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "No clipboard data has been sent yet");
-        return NULL;
-    }
-
-    ret = pipe2(fds, O_CLOEXEC);
-    if (ret < 0)
-    {
-        // TODO: also report errno maybe?
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "Wayland: Impossible to create clipboard pipe fds");
-        return NULL;
-    }
-
-    wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);
-    close(fds[1]);
-
-    // XXX: this is a huge hack, this function shouldn’t be synchronous!
-    handleEvents(-1);
-
-    while (1)
-    {
-        // Grow the clipboard if we need to paste something bigger, there is no
-        // shrink operation yet.
-        if (len + 4096 > _glfw.wl.clipboardSize)
-        {
-            if (!growClipboardString())
-            {
-                close(fds[0]);
-                return NULL;
-            }
-        }
-
-        // Then read from the fd to the clipboard, handling all known errors.
-        ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);
-        if (ret == 0)
-            break;
-        if (ret == -1 && errno == EINTR)
-            continue;
-        if (ret == -1)
-        {
-            // TODO: also report errno maybe.
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "Wayland: Impossible to read from clipboard fd");
-            close(fds[0]);
-            return NULL;
-        }
-        len += ret;
-    }
-    close(fds[0]);
-    if (len + 1 > _glfw.wl.clipboardSize)
-    {
-        if (!growClipboardString())
-            return NULL;
-    }
-    _glfw.wl.clipboardString[len] = '\0';
-    return _glfw.wl.clipboardString;
-}
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
-{
-    if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface)
-        return;
-
-    extensions[0] = "VK_KHR_surface";
-    extensions[1] = "VK_KHR_wayland_surface";
-}
-
-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 3.3 Wayland - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.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
+// 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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#define _GNU_SOURCE
+
+#include "internal.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/timerfd.h>
+#include <poll.h>
+
+
+static void shellSurfaceHandlePing(void* data,
+                                   struct wl_shell_surface* shellSurface,
+                                   uint32_t serial)
+{
+    wl_shell_surface_pong(shellSurface, serial);
+}
+
+static void shellSurfaceHandleConfigure(void* data,
+                                        struct wl_shell_surface* shellSurface,
+                                        uint32_t edges,
+                                        int32_t width,
+                                        int32_t height)
+{
+    _GLFWwindow* window = data;
+    float aspectRatio;
+    float targetRatio;
+
+    if (!window->monitor)
+    {
+        if (_glfw.wl.viewporter && window->decorated)
+        {
+            width -= _GLFW_DECORATION_HORIZONTAL;
+            height -= _GLFW_DECORATION_VERTICAL;
+        }
+        if (width < 1)
+            width = 1;
+        if (height < 1)
+            height = 1;
+
+        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);
+}
+
+static void shellSurfaceHandlePopupDone(void* data,
+                                        struct wl_shell_surface* shellSurface)
+{
+}
+
+static const struct wl_shell_surface_listener shellSurfaceListener = {
+    shellSurfaceHandlePing,
+    shellSurfaceHandleConfigure,
+    shellSurfaceHandlePopupDone
+};
+
+static int createTmpfileCloexec(char* tmpname)
+{
+    int fd;
+
+    fd = mkostemp(tmpname, O_CLOEXEC);
+    if (fd >= 0)
+        unlink(tmpname);
+
+    return fd;
+}
+
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * CLOEXEC. The file is immediately suitable for mmap()'ing
+ * the given size at offset zero.
+ *
+ * The file should not have a permanent backing store like a disk,
+ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
+ *
+ * The file name is deleted from the file system.
+ *
+ * The file is suitable for buffer sharing between processes by
+ * transmitting the file descriptor over Unix sockets using the
+ * SCM_RIGHTS methods.
+ *
+ * posix_fallocate() is used to guarantee that disk space is available
+ * for the file at the given size. If disk space is insufficient, errno
+ * is set to ENOSPC. If posix_fallocate() is not supported, program may
+ * receive SIGBUS on accessing mmap()'ed file contents instead.
+ */
+static int createAnonymousFile(off_t size)
+{
+    static const char template[] = "/glfw-shared-XXXXXX";
+    const char* path;
+    char* name;
+    int fd;
+    int ret;
+
+#ifdef HAVE_MEMFD_CREATE
+    fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+    if (fd >= 0)
+    {
+        // We can add this seal before calling posix_fallocate(), as the file
+        // is currently zero-sized anyway.
+        //
+        // There is also no need to check for the return value, we couldn’t do
+        // anything with it anyway.
+        fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
+    }
+    else
+#elif defined(SHM_ANON)
+    fd = shm_open(SHM_ANON, O_RDWR | O_CLOEXEC, 0600);
+    if (fd < 0)
+#endif
+    {
+        path = getenv("XDG_RUNTIME_DIR");
+        if (!path)
+        {
+            errno = ENOENT;
+            return -1;
+        }
+
+        name = calloc(strlen(path) + sizeof(template), 1);
+        strcpy(name, path);
+        strcat(name, template);
+
+        fd = createTmpfileCloexec(name);
+        free(name);
+        if (fd < 0)
+            return -1;
+    }
+
+#if defined(SHM_ANON)
+    // posix_fallocate does not work on SHM descriptors
+    ret = ftruncate(fd, size);
+#else
+    ret = posix_fallocate(fd, 0, size);
+#endif
+    if (ret != 0)
+    {
+        close(fd);
+        errno = ret;
+        return -1;
+    }
+    return fd;
+}
+
+static struct wl_buffer* createShmBuffer(const GLFWimage* image)
+{
+    struct wl_shm_pool* pool;
+    struct wl_buffer* buffer;
+    int stride = image->width * 4;
+    int length = image->width * image->height * 4;
+    void* data;
+    int fd, i;
+
+    fd = createAnonymousFile(length);
+    if (fd < 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Creating a buffer file for %d B failed: %m",
+                        length);
+        return NULL;
+    }
+
+    data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if (data == MAP_FAILED)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: mmap failed: %m");
+        close(fd);
+        return NULL;
+    }
+
+    pool = wl_shm_create_pool(_glfw.wl.shm, fd, length);
+
+    close(fd);
+    unsigned char* source = (unsigned char*) image->pixels;
+    unsigned char* target = data;
+    for (i = 0;  i < image->width * image->height;  i++, source += 4)
+    {
+        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;
+    }
+
+    buffer =
+        wl_shm_pool_create_buffer(pool, 0,
+                                  image->width,
+                                  image->height,
+                                  stride, WL_SHM_FORMAT_ARGB8888);
+    munmap(data, length);
+    wl_shm_pool_destroy(pool);
+
+    return buffer;
+}
+
+static void createDecoration(_GLFWdecorationWayland* decoration,
+                             struct wl_surface* parent,
+                             struct wl_buffer* buffer, GLFWbool opaque,
+                             int x, int y,
+                             int width, int height)
+{
+    struct wl_region* region;
+
+    decoration->surface = wl_compositor_create_surface(_glfw.wl.compositor);
+    decoration->subsurface =
+        wl_subcompositor_get_subsurface(_glfw.wl.subcompositor,
+                                        decoration->surface, parent);
+    wl_subsurface_set_position(decoration->subsurface, x, y);
+    decoration->viewport = wp_viewporter_get_viewport(_glfw.wl.viewporter,
+                                                      decoration->surface);
+    wp_viewport_set_destination(decoration->viewport, width, height);
+    wl_surface_attach(decoration->surface, buffer, 0, 0);
+
+    if (opaque)
+    {
+        region = wl_compositor_create_region(_glfw.wl.compositor);
+        wl_region_add(region, 0, 0, width, height);
+        wl_surface_set_opaque_region(decoration->surface, region);
+        wl_surface_commit(decoration->surface);
+        wl_region_destroy(region);
+    }
+    else
+        wl_surface_commit(decoration->surface);
+}
+
+static void createDecorations(_GLFWwindow* window)
+{
+    unsigned char data[] = { 224, 224, 224, 255 };
+    const GLFWimage image = { 1, 1, data };
+    GLFWbool opaque = (data[3] == 255);
+
+    if (!_glfw.wl.viewporter || !window->decorated || window->wl.decorations.serverSide)
+        return;
+
+    if (!window->wl.decorations.buffer)
+        window->wl.decorations.buffer = createShmBuffer(&image);
+    if (!window->wl.decorations.buffer)
+        return;
+
+    createDecoration(&window->wl.decorations.top, window->wl.surface,
+                     window->wl.decorations.buffer, opaque,
+                     0, -_GLFW_DECORATION_TOP,
+                     window->wl.width, _GLFW_DECORATION_TOP);
+    createDecoration(&window->wl.decorations.left, window->wl.surface,
+                     window->wl.decorations.buffer, opaque,
+                     -_GLFW_DECORATION_WIDTH, -_GLFW_DECORATION_TOP,
+                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+    createDecoration(&window->wl.decorations.right, window->wl.surface,
+                     window->wl.decorations.buffer, opaque,
+                     window->wl.width, -_GLFW_DECORATION_TOP,
+                     _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+    createDecoration(&window->wl.decorations.bottom, window->wl.surface,
+                     window->wl.decorations.buffer, opaque,
+                     -_GLFW_DECORATION_WIDTH, window->wl.height,
+                     window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+}
+
+static void destroyDecoration(_GLFWdecorationWayland* decoration)
+{
+    if (decoration->surface)
+        wl_surface_destroy(decoration->surface);
+    if (decoration->subsurface)
+        wl_subsurface_destroy(decoration->subsurface);
+    if (decoration->viewport)
+        wp_viewport_destroy(decoration->viewport);
+    decoration->surface = NULL;
+    decoration->subsurface = NULL;
+    decoration->viewport = NULL;
+}
+
+static void destroyDecorations(_GLFWwindow* window)
+{
+    destroyDecoration(&window->wl.decorations.top);
+    destroyDecoration(&window->wl.decorations.left);
+    destroyDecoration(&window->wl.decorations.right);
+    destroyDecoration(&window->wl.decorations.bottom);
+}
+
+static void xdgDecorationHandleConfigure(void* data,
+                                         struct zxdg_toplevel_decoration_v1* decoration,
+                                         uint32_t mode)
+{
+    _GLFWwindow* window = data;
+
+    window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+
+    if (!window->wl.decorations.serverSide)
+        createDecorations(window);
+}
+
+static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener = {
+    xdgDecorationHandleConfigure,
+};
+
+// 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 void resizeWindow(_GLFWwindow* window)
+{
+    int scale = window->wl.scale;
+    int scaledWidth = window->wl.width * scale;
+    int scaledHeight = window->wl.height * scale;
+    wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
+    if (!window->wl.transparent)
+        setOpaqueRegion(window);
+    _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
+    _glfwInputWindowContentScale(window, scale, scale);
+
+    if (!window->wl.decorations.top.surface)
+        return;
+
+    // Top decoration.
+    wp_viewport_set_destination(window->wl.decorations.top.viewport,
+                                window->wl.width, _GLFW_DECORATION_TOP);
+    wl_surface_commit(window->wl.decorations.top.surface);
+
+    // Left decoration.
+    wp_viewport_set_destination(window->wl.decorations.left.viewport,
+                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+    wl_surface_commit(window->wl.decorations.left.surface);
+
+    // Right decoration.
+    wl_subsurface_set_position(window->wl.decorations.right.subsurface,
+                               window->wl.width, -_GLFW_DECORATION_TOP);
+    wp_viewport_set_destination(window->wl.decorations.right.viewport,
+                                _GLFW_DECORATION_WIDTH, window->wl.height + _GLFW_DECORATION_TOP);
+    wl_surface_commit(window->wl.decorations.right.surface);
+
+    // Bottom decoration.
+    wl_subsurface_set_position(window->wl.decorations.bottom.subsurface,
+                               -_GLFW_DECORATION_WIDTH, window->wl.height);
+    wp_viewport_set_destination(window->wl.decorations.bottom.viewport,
+                                window->wl.width + _GLFW_DECORATION_HORIZONTAL, _GLFW_DECORATION_WIDTH);
+    wl_surface_commit(window->wl.decorations.bottom.surface);
+}
+
+static void checkScaleChange(_GLFWwindow* window)
+{
+    int scale = 1;
+    int i;
+    int monitorScale;
+
+    // Check if we will be able to set the buffer scale or not.
+    if (_glfw.wl.compositorVersion < 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;
+        wl_surface_set_buffer_scale(window->wl.surface, scale);
+        resizeWindow(window);
+    }
+}
+
+static void surfaceHandleEnter(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 surfaceHandleLeave(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 = {
+    surfaceHandleEnter,
+    surfaceHandleLeave
+};
+
+static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
+{
+    if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
+    {
+        window->wl.idleInhibitor =
+            zwp_idle_inhibit_manager_v1_create_inhibitor(
+                _glfw.wl.idleInhibitManager, window->wl.surface);
+        if (!window->wl.idleInhibitor)
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Idle inhibitor creation failed");
+    }
+    else if (!enable && window->wl.idleInhibitor)
+    {
+        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+        window->wl.idleInhibitor = NULL;
+    }
+}
+
+static GLFWbool createSurface(_GLFWwindow* window,
+                              const _GLFWwndconfig* wndconfig)
+{
+    window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
+    if (!window->wl.surface)
+        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 GLFW_FALSE;
+
+    window->wl.width = wndconfig->width;
+    window->wl.height = wndconfig->height;
+    window->wl.scale = 1;
+
+    if (!window->wl.transparent)
+        setOpaqueRegion(window);
+
+    return GLFW_TRUE;
+}
+
+static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor,
+                          int refreshRate)
+{
+    if (window->wl.xdg.toplevel)
+    {
+        xdg_toplevel_set_fullscreen(
+            window->wl.xdg.toplevel,
+            monitor->wl.output);
+    }
+    else if (window->wl.shellSurface)
+    {
+        wl_shell_surface_set_fullscreen(
+            window->wl.shellSurface,
+            WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+            refreshRate * 1000, // Convert Hz to mHz.
+            monitor->wl.output);
+    }
+    setIdleInhibitor(window, GLFW_TRUE);
+    if (!window->wl.decorations.serverSide)
+        destroyDecorations(window);
+}
+
+static GLFWbool createShellSurface(_GLFWwindow* window)
+{
+    if (!_glfw.wl.shell)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: wl_shell protocol not available");
+        return GLFW_FALSE;
+    }
+
+    window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell,
+                                                         window->wl.surface);
+    if (!window->wl.shellSurface)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Shell surface creation failed");
+        return GLFW_FALSE;
+    }
+
+    wl_shell_surface_add_listener(window->wl.shellSurface,
+                                  &shellSurfaceListener,
+                                  window);
+
+    if (window->wl.title)
+        wl_shell_surface_set_title(window->wl.shellSurface, window->wl.title);
+
+    if (window->monitor)
+    {
+        setFullscreen(window, window->monitor, 0);
+    }
+    else if (window->wl.maximized)
+    {
+        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
+        setIdleInhibitor(window, GLFW_FALSE);
+        createDecorations(window);
+    }
+    else
+    {
+        wl_shell_surface_set_toplevel(window->wl.shellSurface);
+        setIdleInhibitor(window, GLFW_FALSE);
+        createDecorations(window);
+    }
+
+    wl_surface_commit(window->wl.surface);
+
+    return GLFW_TRUE;
+}
+
+static void xdgToplevelHandleConfigure(void* data,
+                                       struct xdg_toplevel* toplevel,
+                                       int32_t width,
+                                       int32_t height,
+                                       struct wl_array* states)
+{
+    _GLFWwindow* window = data;
+    float aspectRatio;
+    float targetRatio;
+    uint32_t* state;
+    GLFWbool maximized = GLFW_FALSE;
+    GLFWbool fullscreen = GLFW_FALSE;
+    GLFWbool activated = GLFW_FALSE;
+
+    wl_array_for_each(state, states)
+    {
+        switch (*state)
+        {
+            case XDG_TOPLEVEL_STATE_MAXIMIZED:
+                maximized = GLFW_TRUE;
+                break;
+            case XDG_TOPLEVEL_STATE_FULLSCREEN:
+                fullscreen = GLFW_TRUE;
+                break;
+            case XDG_TOPLEVEL_STATE_RESIZING:
+                break;
+            case XDG_TOPLEVEL_STATE_ACTIVATED:
+                activated = GLFW_TRUE;
+                break;
+        }
+    }
+
+    if (width != 0 && height != 0)
+    {
+        if (!maximized && !fullscreen)
+        {
+            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;
+            }
+        }
+
+        _glfwInputWindowSize(window, width, height);
+        _glfwPlatformSetWindowSize(window, width, height);
+        _glfwInputWindowDamage(window);
+    }
+
+    if (window->wl.wasFullscreen && window->autoIconify)
+    {
+        if (!activated || !fullscreen)
+        {
+            _glfwPlatformIconifyWindow(window);
+            window->wl.wasFullscreen = GLFW_FALSE;
+        }
+    }
+    if (fullscreen && activated)
+        window->wl.wasFullscreen = GLFW_TRUE;
+    _glfwInputWindowFocus(window, activated);
+}
+
+static void xdgToplevelHandleClose(void* data,
+                                   struct xdg_toplevel* toplevel)
+{
+    _GLFWwindow* window = data;
+    _glfwInputWindowCloseRequest(window);
+}
+
+static const struct xdg_toplevel_listener xdgToplevelListener = {
+    xdgToplevelHandleConfigure,
+    xdgToplevelHandleClose
+};
+
+static void xdgSurfaceHandleConfigure(void* data,
+                                      struct xdg_surface* surface,
+                                      uint32_t serial)
+{
+    xdg_surface_ack_configure(surface, serial);
+}
+
+static const struct xdg_surface_listener xdgSurfaceListener = {
+    xdgSurfaceHandleConfigure
+};
+
+static void setXdgDecorations(_GLFWwindow* window)
+{
+    if (_glfw.wl.decorationManager)
+    {
+        window->wl.xdg.decoration =
+            zxdg_decoration_manager_v1_get_toplevel_decoration(
+                _glfw.wl.decorationManager, window->wl.xdg.toplevel);
+        zxdg_toplevel_decoration_v1_add_listener(window->wl.xdg.decoration,
+                                                 &xdgDecorationListener,
+                                                 window);
+        zxdg_toplevel_decoration_v1_set_mode(
+            window->wl.xdg.decoration,
+            ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
+    }
+    else
+    {
+        window->wl.decorations.serverSide = GLFW_FALSE;
+        createDecorations(window);
+    }
+}
+
+static GLFWbool createXdgSurface(_GLFWwindow* window)
+{
+    window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
+                                                         window->wl.surface);
+    if (!window->wl.xdg.surface)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: xdg-surface creation failed");
+        return GLFW_FALSE;
+    }
+
+    xdg_surface_add_listener(window->wl.xdg.surface,
+                             &xdgSurfaceListener,
+                             window);
+
+    window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface);
+    if (!window->wl.xdg.toplevel)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: xdg-toplevel creation failed");
+        return GLFW_FALSE;
+    }
+
+    xdg_toplevel_add_listener(window->wl.xdg.toplevel,
+                              &xdgToplevelListener,
+                              window);
+
+    if (window->wl.title)
+        xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title);
+
+    if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE)
+        xdg_toplevel_set_min_size(window->wl.xdg.toplevel,
+                                  window->minwidth, window->minheight);
+    if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE)
+        xdg_toplevel_set_max_size(window->wl.xdg.toplevel,
+                                  window->maxwidth, window->maxheight);
+
+    if (window->monitor)
+    {
+        xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
+                                    window->monitor->wl.output);
+        setIdleInhibitor(window, GLFW_TRUE);
+    }
+    else if (window->wl.maximized)
+    {
+        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
+        setIdleInhibitor(window, GLFW_FALSE);
+        setXdgDecorations(window);
+    }
+    else
+    {
+        setIdleInhibitor(window, GLFW_FALSE);
+        setXdgDecorations(window);
+    }
+
+    wl_surface_commit(window->wl.surface);
+    wl_display_roundtrip(_glfw.wl.display);
+
+    return GLFW_TRUE;
+}
+
+static void setCursorImage(_GLFWwindow* window,
+                           _GLFWcursorWayland* cursorWayland)
+{
+    struct itimerspec timer = {};
+    struct wl_cursor* wlCursor = cursorWayland->cursor;
+    struct wl_cursor_image* image;
+    struct wl_buffer* buffer;
+    struct wl_surface* surface = _glfw.wl.cursorSurface;
+    int scale = 1;
+
+    if (!wlCursor)
+        buffer = cursorWayland->buffer;
+    else
+    {
+        if (window->wl.scale > 1 && cursorWayland->cursorHiDPI)
+        {
+            wlCursor = cursorWayland->cursorHiDPI;
+            scale = 2;
+        }
+
+        image = wlCursor->images[cursorWayland->currentImage];
+        buffer = wl_cursor_image_get_buffer(image);
+        if (!buffer)
+            return;
+
+        timer.it_value.tv_sec = image->delay / 1000;
+        timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;
+        timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);
+
+        cursorWayland->width = image->width;
+        cursorWayland->height = image->height;
+        cursorWayland->xhot = image->hotspot_x;
+        cursorWayland->yhot = image->hotspot_y;
+    }
+
+    wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial,
+                          surface,
+                          cursorWayland->xhot / scale,
+                          cursorWayland->yhot / scale);
+    wl_surface_set_buffer_scale(surface, scale);
+    wl_surface_attach(surface, buffer, 0, 0);
+    wl_surface_damage(surface, 0, 0,
+                      cursorWayland->width, cursorWayland->height);
+    wl_surface_commit(surface);
+}
+
+static void incrementCursorImage(_GLFWwindow* window)
+{
+    _GLFWcursor* cursor;
+
+    if (!window || window->wl.decorations.focus != mainWindow)
+        return;
+
+    cursor = window->wl.currentCursor;
+    if (cursor && cursor->wl.cursor)
+    {
+        cursor->wl.currentImage += 1;
+        cursor->wl.currentImage %= cursor->wl.cursor->image_count;
+        setCursorImage(window, &cursor->wl);
+    }
+}
+
+static void handleEvents(int timeout)
+{
+    struct wl_display* display = _glfw.wl.display;
+    struct pollfd fds[] = {
+        { wl_display_get_fd(display), POLLIN },
+        { _glfw.wl.timerfd, POLLIN },
+        { _glfw.wl.cursorTimerfd, POLLIN },
+    };
+    ssize_t read_ret;
+    uint64_t repeats, i;
+
+    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, 3, timeout) > 0)
+    {
+        if (fds[0].revents & POLLIN)
+        {
+            wl_display_read_events(display);
+            wl_display_dispatch_pending(display);
+        }
+        else
+        {
+            wl_display_cancel_read(display);
+        }
+
+        if (fds[1].revents & POLLIN)
+        {
+            read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
+            if (read_ret != 8)
+                return;
+
+            for (i = 0; i < repeats; ++i)
+                _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
+                              _glfw.wl.keyboardLastScancode, GLFW_REPEAT,
+                              _glfw.wl.xkb.modifiers);
+        }
+
+        if (fds[2].revents & POLLIN)
+        {
+            read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats));
+            if (read_ret != 8)
+                return;
+
+            incrementCursorImage(_glfw.wl.pointerFocus);
+        }
+    }
+    else
+    {
+        wl_display_cancel_read(display);
+    }
+}
+
+// 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 "hand2";
+        case GLFW_HRESIZE_CURSOR:
+            return "sb_h_double_arrow";
+        case GLFW_VRESIZE_CURSOR:
+            return "sb_v_double_arrow";
+    }
+    return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+                              const _GLFWwndconfig* wndconfig,
+                              const _GLFWctxconfig* ctxconfig,
+                              const _GLFWfbconfig* fbconfig)
+{
+    window->wl.transparent = fbconfig->transparent;
+
+    if (!createSurface(window, wndconfig))
+        return GLFW_FALSE;
+
+    if (ctxconfig->client != GLFW_NO_API)
+    {
+        if (ctxconfig->source == GLFW_EGL_CONTEXT_API ||
+            ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+        {
+            if (!_glfwInitEGL())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwInitOSMesa())
+                return GLFW_FALSE;
+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+    }
+
+    if (wndconfig->title)
+        window->wl.title = _glfw_strdup(wndconfig->title);
+
+    if (wndconfig->visible)
+    {
+        if (_glfw.wl.wmBase)
+        {
+            if (!createXdgSurface(window))
+                return GLFW_FALSE;
+        }
+        else
+        {
+            if (!createShellSurface(window))
+                return GLFW_FALSE;
+        }
+
+        window->wl.visible = GLFW_TRUE;
+    }
+    else
+    {
+        window->wl.xdg.surface = NULL;
+        window->wl.xdg.toplevel = NULL;
+        window->wl.shellSurface = NULL;
+        window->wl.visible = GLFW_FALSE;
+    }
+
+    window->wl.currentCursor = NULL;
+
+    window->wl.monitors = calloc(1, sizeof(_GLFWmonitor*));
+    window->wl.monitorsCount = 0;
+    window->wl.monitorsSize = 1;
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+    if (window == _glfw.wl.pointerFocus)
+    {
+        _glfw.wl.pointerFocus = NULL;
+        _glfwInputCursorEnter(window, GLFW_FALSE);
+    }
+    if (window == _glfw.wl.keyboardFocus)
+    {
+        _glfw.wl.keyboardFocus = NULL;
+        _glfwInputWindowFocus(window, GLFW_FALSE);
+    }
+
+    if (window->wl.idleInhibitor)
+        zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+
+    if (window->context.destroy)
+        window->context.destroy(window);
+
+    destroyDecorations(window);
+    if (window->wl.xdg.decoration)
+        zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
+
+    if (window->wl.decorations.buffer)
+        wl_buffer_destroy(window->wl.decorations.buffer);
+
+    if (window->wl.native)
+        wl_egl_window_destroy(window->wl.native);
+
+    if (window->wl.shellSurface)
+        wl_shell_surface_destroy(window->wl.shellSurface);
+
+    if (window->wl.xdg.toplevel)
+        xdg_toplevel_destroy(window->wl.xdg.toplevel);
+
+    if (window->wl.xdg.surface)
+        xdg_surface_destroy(window->wl.xdg.surface);
+
+    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)
+{
+    if (window->wl.title)
+        free(window->wl.title);
+    window->wl.title = _glfw_strdup(title);
+    if (window->wl.xdg.toplevel)
+        xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
+    else if (window->wl.shellSurface)
+        wl_shell_surface_set_title(window->wl.shellSurface, 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
+    // as (0, 0)
+
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Window position retrieval not supported");
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+    // A Wayland client can not set its position, so just warn
+
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Window position setting not supported");
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+    if (width)
+        *width = window->wl.width;
+    if (height)
+        *height = window->wl.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+    window->wl.width = width;
+    window->wl.height = height;
+    resizeWindow(window);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+                                      int minwidth, int minheight,
+                                      int maxwidth, int maxheight)
+{
+    if (_glfw.wl.wmBase)
+    {
+        if (window->wl.xdg.toplevel)
+        {
+            if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+                minwidth = minheight = 0;
+            if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+                maxwidth = maxheight = 0;
+            xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight);
+            xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight);
+            wl_surface_commit(window->wl.surface);
+        }
+    }
+    else
+    {
+        // 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)
+{
+    if (window->decorated && !window->monitor && !window->wl.decorations.serverSide)
+    {
+        if (top)
+            *top = _GLFW_DECORATION_TOP;
+        if (left)
+            *left = _GLFW_DECORATION_WIDTH;
+        if (right)
+            *right = _GLFW_DECORATION_WIDTH;
+        if (bottom)
+            *bottom = _GLFW_DECORATION_WIDTH;
+    }
+}
+
+void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = (float) window->wl.scale;
+    if (yscale)
+        *yscale = (float) window->wl.scale;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+    if (_glfw.wl.wmBase)
+    {
+        if (window->wl.xdg.toplevel)
+            xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
+    }
+    else
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Iconify window not supported on wl_shell");
+    }
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+    if (window->wl.xdg.toplevel)
+    {
+        if (window->monitor)
+            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
+        if (window->wl.maximized)
+            xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
+        // There is no way to unset minimized, or even to know if we are
+        // minimized, so there is nothing to do here.
+    }
+    else if (window->wl.shellSurface)
+    {
+        if (window->monitor || window->wl.maximized)
+            wl_shell_surface_set_toplevel(window->wl.shellSurface);
+    }
+    _glfwInputWindowMonitor(window, NULL);
+    window->wl.maximized = GLFW_FALSE;
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+    if (window->wl.xdg.toplevel)
+    {
+        xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
+    }
+    else if (window->wl.shellSurface)
+    {
+        // Let the compositor select the best output.
+        wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
+    }
+    window->wl.maximized = GLFW_TRUE;
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+    if (!window->wl.visible)
+    {
+        if (_glfw.wl.wmBase)
+            createXdgSurface(window);
+        else if (!window->wl.shellSurface)
+            createShellSurface(window);
+        window->wl.visible = GLFW_TRUE;
+    }
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+    if (window->wl.xdg.toplevel)
+    {
+        xdg_toplevel_destroy(window->wl.xdg.toplevel);
+        xdg_surface_destroy(window->wl.xdg.surface);
+        window->wl.xdg.toplevel = NULL;
+        window->wl.xdg.surface = NULL;
+    }
+    else if (window->wl.shellSurface)
+    {
+        wl_shell_surface_destroy(window->wl.shellSurface);
+        window->wl.shellSurface = NULL;
+    }
+    window->wl.visible = GLFW_FALSE;
+}
+
+void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+    // TODO
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Window attention request not implemented yet");
+}
+
+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)
+    {
+        setFullscreen(window, monitor, refreshRate);
+    }
+    else
+    {
+        if (window->wl.xdg.toplevel)
+            xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
+        else if (window->wl.shellSurface)
+            wl_shell_surface_set_toplevel(window->wl.shellSurface);
+        setIdleInhibitor(window, GLFW_FALSE);
+        if (!_glfw.wl.decorationManager)
+            createDecorations(window);
+    }
+    _glfwInputWindowMonitor(window, monitor);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+    return _glfw.wl.keyboardFocus == window;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+    // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give
+    // any way to request whether a surface is iconified.
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+    return window->wl.visible;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+    return window->wl.maximized;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    return window->wl.hovered;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+    return window->wl.transparent;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+    // TODO
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Window attribute setting not implemented yet");
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+    if (!window->monitor)
+    {
+        if (enabled)
+            createDecorations(window);
+        else
+            destroyDecorations(window);
+    }
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+    // TODO
+    _glfwInputError(GLFW_PLATFORM_ERROR,
+                    "Wayland: Window attribute setting not implemented yet");
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+    return 1.f;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+}
+
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+{
+    // This is handled in relativePointerHandleRelativeMotion
+}
+
+GLFWbool _glfwPlatformRawMouseMotionSupported(void)
+{
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+    handleEvents(0);
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+    handleEvents(-1);
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+    handleEvents((int) (timeout * 1e3));
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+    wl_display_sync(_glfw.wl.display);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+    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)
+{
+    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 _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+    _glfwPlatformSetCursor(window, window->wl.currentCursor);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+    // TODO
+    return NULL;
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+    return _glfw.wl.scancodes[key];
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+                              const GLFWimage* image,
+                              int xhot, int yhot)
+{
+    cursor->wl.buffer = createShmBuffer(image);
+    if (!cursor->wl.buffer)
+        return GLFW_FALSE;
+
+    cursor->wl.width = image->width;
+    cursor->wl.height = image->height;
+    cursor->wl.xhot = xhot;
+    cursor->wl.yhot = yhot;
+    return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+    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.cursor = standardCursor;
+    cursor->wl.currentImage = 0;
+
+    if (_glfw.wl.cursorThemeHiDPI)
+    {
+        standardCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
+                                                    translateCursorShape(shape));
+        cursor->wl.cursorHiDPI = standardCursor;
+    }
+
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+    // If it's a standard cursor we don't need to do anything here
+    if (cursor->wl.cursor)
+        return;
+
+    if (cursor->wl.buffer)
+        wl_buffer_destroy(cursor->wl.buffer);
+}
+
+static void relativePointerHandleRelativeMotion(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;
+    double xpos = window->virtualCursorPosX;
+    double ypos = window->virtualCursorPosY;
+
+    if (window->cursorMode != GLFW_CURSOR_DISABLED)
+        return;
+
+    if (window->rawMouseMotion)
+    {
+        xpos += wl_fixed_to_double(dxUnaccel);
+        ypos += wl_fixed_to_double(dyUnaccel);
+    }
+    else
+    {
+        xpos += wl_fixed_to_double(dx);
+        ypos += wl_fixed_to_double(dy);
+    }
+
+    _glfwInputCursorPos(window, xpos, ypos);
+}
+
+static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
+    relativePointerHandleRelativeMotion
+};
+
+static void lockedPointerHandleLocked(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 lockedPointerHandleUnlocked(void* data,
+                                        struct zwp_locked_pointer_v1* lockedPointer)
+{
+}
+
+static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
+    lockedPointerHandleLocked,
+    lockedPointerHandleUnlocked
+};
+
+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.serial,
+                          NULL, 0, 0);
+}
+
+static GLFWbool isPointerLocked(_GLFWwindow* window)
+{
+    return window->wl.pointerLock.lockedPointer != NULL;
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+    struct wl_cursor* defaultCursor;
+    struct wl_cursor* defaultCursorHiDPI = NULL;
+
+    if (!_glfw.wl.pointer)
+        return;
+
+    window->wl.currentCursor = cursor;
+
+    // If we're not in the correct window just save the cursor
+    // the next time the pointer enters the window the cursor will change
+    if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
+        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)
+            setCursorImage(window, &cursor->wl);
+        else
+        {
+            defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
+                                                       "left_ptr");
+            if (!defaultCursor)
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "Wayland: Standard cursor not found");
+                return;
+            }
+            if (_glfw.wl.cursorThemeHiDPI)
+                defaultCursorHiDPI =
+                    wl_cursor_theme_get_cursor(_glfw.wl.cursorThemeHiDPI,
+                                               "left_ptr");
+            _GLFWcursorWayland cursorWayland = {
+                defaultCursor,
+                defaultCursorHiDPI,
+                NULL,
+                0, 0,
+                0, 0,
+                0
+            };
+            setCursorImage(window, &cursorWayland);
+        }
+    }
+    else if (window->cursorMode == GLFW_CURSOR_DISABLED)
+    {
+        if (!isPointerLocked(window))
+            lockPointer(window);
+    }
+    else if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+    {
+        wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.serial, NULL, 0, 0);
+    }
+}
+
+static void dataSourceHandleTarget(void* data,
+                                   struct wl_data_source* dataSource,
+                                   const char* mimeType)
+{
+    if (_glfw.wl.dataSource != dataSource)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Unknown clipboard data source");
+        return;
+    }
+}
+
+static void dataSourceHandleSend(void* data,
+                                 struct wl_data_source* dataSource,
+                                 const char* mimeType,
+                                 int fd)
+{
+    const char* string = _glfw.wl.clipboardSendString;
+    size_t len = _glfw.wl.clipboardSendSize;
+    int ret;
+
+    if (_glfw.wl.dataSource != dataSource)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Unknown clipboard data source");
+        return;
+    }
+
+    if (!string)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Copy requested from an invalid string");
+        return;
+    }
+
+    if (strcmp(mimeType, "text/plain;charset=utf-8") != 0)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Wrong MIME type asked from clipboard");
+        close(fd);
+        return;
+    }
+
+    while (len > 0)
+    {
+        ret = write(fd, string, len);
+        if (ret == -1 && errno == EINTR)
+            continue;
+        if (ret == -1)
+        {
+            // TODO: also report errno maybe.
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Error while writing the clipboard");
+            close(fd);
+            return;
+        }
+        len -= ret;
+    }
+    close(fd);
+}
+
+static void dataSourceHandleCancelled(void* data,
+                                      struct wl_data_source* dataSource)
+{
+    wl_data_source_destroy(dataSource);
+
+    if (_glfw.wl.dataSource != dataSource)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Unknown clipboard data source");
+        return;
+    }
+
+    _glfw.wl.dataSource = NULL;
+}
+
+static const struct wl_data_source_listener dataSourceListener = {
+    dataSourceHandleTarget,
+    dataSourceHandleSend,
+    dataSourceHandleCancelled,
+};
+
+void _glfwPlatformSetClipboardString(const char* string)
+{
+    if (_glfw.wl.dataSource)
+    {
+        wl_data_source_destroy(_glfw.wl.dataSource);
+        _glfw.wl.dataSource = NULL;
+    }
+
+    if (_glfw.wl.clipboardSendString)
+    {
+        free(_glfw.wl.clipboardSendString);
+        _glfw.wl.clipboardSendString = NULL;
+    }
+
+    _glfw.wl.clipboardSendString = strdup(string);
+    if (!_glfw.wl.clipboardSendString)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Impossible to allocate clipboard string");
+        return;
+    }
+    _glfw.wl.clipboardSendSize = strlen(string);
+    _glfw.wl.dataSource =
+        wl_data_device_manager_create_data_source(_glfw.wl.dataDeviceManager);
+    if (!_glfw.wl.dataSource)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Impossible to create clipboard source");
+        free(_glfw.wl.clipboardSendString);
+        return;
+    }
+    wl_data_source_add_listener(_glfw.wl.dataSource,
+                                &dataSourceListener,
+                                NULL);
+    wl_data_source_offer(_glfw.wl.dataSource, "text/plain;charset=utf-8");
+    wl_data_device_set_selection(_glfw.wl.dataDevice,
+                                 _glfw.wl.dataSource,
+                                 _glfw.wl.serial);
+}
+
+static GLFWbool growClipboardString(void)
+{
+    char* clipboard = _glfw.wl.clipboardString;
+
+    clipboard = realloc(clipboard, _glfw.wl.clipboardSize * 2);
+    if (!clipboard)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Impossible to grow clipboard string");
+        return GLFW_FALSE;
+    }
+    _glfw.wl.clipboardString = clipboard;
+    _glfw.wl.clipboardSize = _glfw.wl.clipboardSize * 2;
+    return GLFW_TRUE;
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+    int fds[2];
+    int ret;
+    size_t len = 0;
+
+    if (!_glfw.wl.dataOffer)
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "No clipboard data has been sent yet");
+        return NULL;
+    }
+
+    ret = pipe2(fds, O_CLOEXEC);
+    if (ret < 0)
+    {
+        // TODO: also report errno maybe?
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "Wayland: Impossible to create clipboard pipe fds");
+        return NULL;
+    }
+
+    wl_data_offer_receive(_glfw.wl.dataOffer, "text/plain;charset=utf-8", fds[1]);
+    close(fds[1]);
+
+    // XXX: this is a huge hack, this function shouldn’t be synchronous!
+    handleEvents(-1);
+
+    while (1)
+    {
+        // Grow the clipboard if we need to paste something bigger, there is no
+        // shrink operation yet.
+        if (len + 4096 > _glfw.wl.clipboardSize)
+        {
+            if (!growClipboardString())
+            {
+                close(fds[0]);
+                return NULL;
+            }
+        }
+
+        // Then read from the fd to the clipboard, handling all known errors.
+        ret = read(fds[0], _glfw.wl.clipboardString + len, 4096);
+        if (ret == 0)
+            break;
+        if (ret == -1 && errno == EINTR)
+            continue;
+        if (ret == -1)
+        {
+            // TODO: also report errno maybe.
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "Wayland: Impossible to read from clipboard fd");
+            close(fds[0]);
+            return NULL;
+        }
+        len += ret;
+    }
+    close(fds[0]);
+    if (len + 1 > _glfw.wl.clipboardSize)
+    {
+        if (!growClipboardString())
+            return NULL;
+    }
+    _glfw.wl.clipboardString[len] = '\0';
+    return _glfw.wl.clipboardString;
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+    if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface)
+        return;
+
+    extensions[0] = "VK_KHR_surface";
+    extensions[1] = "VK_KHR_wayland_surface";
+}
+
+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;
+}
+
diff --git a/glfw/src/x11_init.c b/glfw/src/x11_init.c
--- a/glfw/src/x11_init.c
+++ b/glfw/src/x11_init.c
@@ -1,1106 +1,1106 @@
-//========================================================================
-// GLFW 3.3 X11 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <X11/Xresource.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <stdio.h>
-#include <locale.h>
-
-
-// Translate an X11 key code to a GLFW key code.
-//
-static int translateKeyCode(int scancode)
-{
-    int keySym;
-
-    // Valid key code range is  [8,255], according to the Xlib manual
-    if (scancode < 8 || scancode > 255)
-        return GLFW_KEY_UNKNOWN;
-
-    if (_glfw.x11.xkb.available)
-    {
-        // Try secondary keysym, for numeric keypad keys
-        // Note: This way we always force "NumLock = ON", which is intentional
-        // since the returned key code should correspond to a physical
-        // location.
-        keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
-        switch (keySym)
-        {
-            case XK_KP_0:           return GLFW_KEY_KP_0;
-            case XK_KP_1:           return GLFW_KEY_KP_1;
-            case XK_KP_2:           return GLFW_KEY_KP_2;
-            case XK_KP_3:           return GLFW_KEY_KP_3;
-            case XK_KP_4:           return GLFW_KEY_KP_4;
-            case XK_KP_5:           return GLFW_KEY_KP_5;
-            case XK_KP_6:           return GLFW_KEY_KP_6;
-            case XK_KP_7:           return GLFW_KEY_KP_7;
-            case XK_KP_8:           return GLFW_KEY_KP_8;
-            case XK_KP_9:           return GLFW_KEY_KP_9;
-            case XK_KP_Separator:
-            case XK_KP_Decimal:     return GLFW_KEY_KP_DECIMAL;
-            case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
-            case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
-            default:                break;
-        }
-
-        // 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, _glfw.x11.xkb.group, 0);
-    }
-    else
-    {
-        int dummy;
-        KeySym* keySyms;
-
-        keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
-        keySym = keySyms[0];
-        XFree(keySyms);
-    }
-
-    switch (keySym)
-    {
-        case XK_Escape:         return GLFW_KEY_ESCAPE;
-        case XK_Tab:            return GLFW_KEY_TAB;
-        case XK_Shift_L:        return GLFW_KEY_LEFT_SHIFT;
-        case XK_Shift_R:        return GLFW_KEY_RIGHT_SHIFT;
-        case XK_Control_L:      return GLFW_KEY_LEFT_CONTROL;
-        case XK_Control_R:      return GLFW_KEY_RIGHT_CONTROL;
-        case XK_Meta_L:
-        case XK_Alt_L:          return GLFW_KEY_LEFT_ALT;
-        case XK_Mode_switch: // Mapped to Alt_R on many keyboards
-        case XK_ISO_Level3_Shift: // AltGr on at least some machines
-        case XK_Meta_R:
-        case XK_Alt_R:          return GLFW_KEY_RIGHT_ALT;
-        case XK_Super_L:        return GLFW_KEY_LEFT_SUPER;
-        case XK_Super_R:        return GLFW_KEY_RIGHT_SUPER;
-        case XK_Menu:           return GLFW_KEY_MENU;
-        case XK_Num_Lock:       return GLFW_KEY_NUM_LOCK;
-        case XK_Caps_Lock:      return GLFW_KEY_CAPS_LOCK;
-        case XK_Print:          return GLFW_KEY_PRINT_SCREEN;
-        case XK_Scroll_Lock:    return GLFW_KEY_SCROLL_LOCK;
-        case XK_Pause:          return GLFW_KEY_PAUSE;
-        case XK_Delete:         return GLFW_KEY_DELETE;
-        case XK_BackSpace:      return GLFW_KEY_BACKSPACE;
-        case XK_Return:         return GLFW_KEY_ENTER;
-        case XK_Home:           return GLFW_KEY_HOME;
-        case XK_End:            return GLFW_KEY_END;
-        case XK_Page_Up:        return GLFW_KEY_PAGE_UP;
-        case XK_Page_Down:      return GLFW_KEY_PAGE_DOWN;
-        case XK_Insert:         return GLFW_KEY_INSERT;
-        case XK_Left:           return GLFW_KEY_LEFT;
-        case XK_Right:          return GLFW_KEY_RIGHT;
-        case XK_Down:           return GLFW_KEY_DOWN;
-        case XK_Up:             return GLFW_KEY_UP;
-        case XK_F1:             return GLFW_KEY_F1;
-        case XK_F2:             return GLFW_KEY_F2;
-        case XK_F3:             return GLFW_KEY_F3;
-        case XK_F4:             return GLFW_KEY_F4;
-        case XK_F5:             return GLFW_KEY_F5;
-        case XK_F6:             return GLFW_KEY_F6;
-        case XK_F7:             return GLFW_KEY_F7;
-        case XK_F8:             return GLFW_KEY_F8;
-        case XK_F9:             return GLFW_KEY_F9;
-        case XK_F10:            return GLFW_KEY_F10;
-        case XK_F11:            return GLFW_KEY_F11;
-        case XK_F12:            return GLFW_KEY_F12;
-        case XK_F13:            return GLFW_KEY_F13;
-        case XK_F14:            return GLFW_KEY_F14;
-        case XK_F15:            return GLFW_KEY_F15;
-        case XK_F16:            return GLFW_KEY_F16;
-        case XK_F17:            return GLFW_KEY_F17;
-        case XK_F18:            return GLFW_KEY_F18;
-        case XK_F19:            return GLFW_KEY_F19;
-        case XK_F20:            return GLFW_KEY_F20;
-        case XK_F21:            return GLFW_KEY_F21;
-        case XK_F22:            return GLFW_KEY_F22;
-        case XK_F23:            return GLFW_KEY_F23;
-        case XK_F24:            return GLFW_KEY_F24;
-        case XK_F25:            return GLFW_KEY_F25;
-
-        // Numeric keypad
-        case XK_KP_Divide:      return GLFW_KEY_KP_DIVIDE;
-        case XK_KP_Multiply:    return GLFW_KEY_KP_MULTIPLY;
-        case XK_KP_Subtract:    return GLFW_KEY_KP_SUBTRACT;
-        case XK_KP_Add:         return GLFW_KEY_KP_ADD;
-
-        // These should have been detected in secondary keysym test above!
-        case XK_KP_Insert:      return GLFW_KEY_KP_0;
-        case XK_KP_End:         return GLFW_KEY_KP_1;
-        case XK_KP_Down:        return GLFW_KEY_KP_2;
-        case XK_KP_Page_Down:   return GLFW_KEY_KP_3;
-        case XK_KP_Left:        return GLFW_KEY_KP_4;
-        case XK_KP_Right:       return GLFW_KEY_KP_6;
-        case XK_KP_Home:        return GLFW_KEY_KP_7;
-        case XK_KP_Up:          return GLFW_KEY_KP_8;
-        case XK_KP_Page_Up:     return GLFW_KEY_KP_9;
-        case XK_KP_Delete:      return GLFW_KEY_KP_DECIMAL;
-        case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
-        case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
-
-        // Last resort: Check for printable keys (should not happen if the XKB
-        // extension is available). This will give a layout dependent mapping
-        // (which is wrong, and we may miss some keys, especially on non-US
-        // keyboards), but it's better than nothing...
-        case XK_a:              return GLFW_KEY_A;
-        case XK_b:              return GLFW_KEY_B;
-        case XK_c:              return GLFW_KEY_C;
-        case XK_d:              return GLFW_KEY_D;
-        case XK_e:              return GLFW_KEY_E;
-        case XK_f:              return GLFW_KEY_F;
-        case XK_g:              return GLFW_KEY_G;
-        case XK_h:              return GLFW_KEY_H;
-        case XK_i:              return GLFW_KEY_I;
-        case XK_j:              return GLFW_KEY_J;
-        case XK_k:              return GLFW_KEY_K;
-        case XK_l:              return GLFW_KEY_L;
-        case XK_m:              return GLFW_KEY_M;
-        case XK_n:              return GLFW_KEY_N;
-        case XK_o:              return GLFW_KEY_O;
-        case XK_p:              return GLFW_KEY_P;
-        case XK_q:              return GLFW_KEY_Q;
-        case XK_r:              return GLFW_KEY_R;
-        case XK_s:              return GLFW_KEY_S;
-        case XK_t:              return GLFW_KEY_T;
-        case XK_u:              return GLFW_KEY_U;
-        case XK_v:              return GLFW_KEY_V;
-        case XK_w:              return GLFW_KEY_W;
-        case XK_x:              return GLFW_KEY_X;
-        case XK_y:              return GLFW_KEY_Y;
-        case XK_z:              return GLFW_KEY_Z;
-        case XK_1:              return GLFW_KEY_1;
-        case XK_2:              return GLFW_KEY_2;
-        case XK_3:              return GLFW_KEY_3;
-        case XK_4:              return GLFW_KEY_4;
-        case XK_5:              return GLFW_KEY_5;
-        case XK_6:              return GLFW_KEY_6;
-        case XK_7:              return GLFW_KEY_7;
-        case XK_8:              return GLFW_KEY_8;
-        case XK_9:              return GLFW_KEY_9;
-        case XK_0:              return GLFW_KEY_0;
-        case XK_space:          return GLFW_KEY_SPACE;
-        case XK_minus:          return GLFW_KEY_MINUS;
-        case XK_equal:          return GLFW_KEY_EQUAL;
-        case XK_bracketleft:    return GLFW_KEY_LEFT_BRACKET;
-        case XK_bracketright:   return GLFW_KEY_RIGHT_BRACKET;
-        case XK_backslash:      return GLFW_KEY_BACKSLASH;
-        case XK_semicolon:      return GLFW_KEY_SEMICOLON;
-        case XK_apostrophe:     return GLFW_KEY_APOSTROPHE;
-        case XK_grave:          return GLFW_KEY_GRAVE_ACCENT;
-        case XK_comma:          return GLFW_KEY_COMMA;
-        case XK_period:         return GLFW_KEY_PERIOD;
-        case XK_slash:          return GLFW_KEY_SLASH;
-        case XK_less:           return GLFW_KEY_WORLD_1; // At least in some layouts...
-        default:                break;
-    }
-
-    // No matching translation was found
-    return GLFW_KEY_UNKNOWN;
-}
-
-// Create key code translation tables
-//
-static void createKeyTables(void)
-{
-    int scancode, key;
-
-    memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
-    memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
-
-    if (_glfw.x11.xkb.available)
-    {
-        // Use XKB to determine physical key locations independently of the
-        // current keyboard layout
-
-        char name[XkbKeyNameLength + 1];
-        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 = desc->min_key_code;  scancode <= desc->max_key_code;  scancode++)
-        {
-            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
-            // keys (function keys) are mapped using traditional KeySym
-            // translations.
-            if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
-            else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
-            else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
-            else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
-            else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
-            else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
-            else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
-            else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
-            else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
-            else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
-            else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
-            else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
-            else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
-            else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
-            else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
-            else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
-            else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
-            else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
-            else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
-            else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
-            else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
-            else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
-            else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
-            else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
-            else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
-            else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
-            else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
-            else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
-            else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
-            else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
-            else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
-            else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
-            else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
-            else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
-            else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
-            else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
-            else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
-            else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
-            else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
-            else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
-            else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
-            else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
-            else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
-            else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
-            else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
-            else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
-            else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
-            else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
-            else key = GLFW_KEY_UNKNOWN;
-
-            if ((scancode >= 0) && (scancode < 256))
-                _glfw.x11.keycodes[scancode] = key;
-        }
-
-        XkbFreeNames(desc, XkbKeyNamesMask, True);
-        XkbFreeKeyboard(desc, 0, True);
-    }
-
-    for (scancode = 0;  scancode < 256;  scancode++)
-    {
-        // Translate the un-translated key codes using traditional X11 KeySym
-        // lookups
-        if (_glfw.x11.keycodes[scancode] < 0)
-            _glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
-
-        // Store the reverse translation for faster key name lookup
-        if (_glfw.x11.keycodes[scancode] > 0)
-            _glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
-    }
-}
-
-// Check whether the IM has a usable style
-//
-static GLFWbool hasUsableInputMethodStyle(void)
-{
-    GLFWbool found = GLFW_FALSE;
-    XIMStyles* styles = NULL;
-
-    if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)
-        return GLFW_FALSE;
-
-    for (unsigned int i = 0;  i < styles->count_styles;  i++)
-    {
-        if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing))
-        {
-            found = GLFW_TRUE;
-            break;
-        }
-    }
-
-    XFree(styles);
-    return found;
-}
-
-// Check whether the specified atom is supported
-//
-static Atom getSupportedAtom(Atom* supportedAtoms,
-                             unsigned long atomCount,
-                             const char* atomName)
-{
-    const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
-
-    for (unsigned int i = 0;  i < atomCount;  i++)
-    {
-        if (supportedAtoms[i] == atom)
-            return atom;
-    }
-
-    return None;
-}
-
-// Check whether the running window manager is EWMH-compliant
-//
-static void detectEWMH(void)
-{
-    // First we read the _NET_SUPPORTING_WM_CHECK property on the root window
-
-    Window* windowFromRoot = NULL;
-    if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
-                                   _glfw.x11.NET_SUPPORTING_WM_CHECK,
-                                   XA_WINDOW,
-                                   (unsigned char**) &windowFromRoot))
-    {
-        return;
-    }
-
-    _glfwGrabErrorHandlerX11();
-
-    // If it exists, it should be the XID of a top-level window
-    // Then we look for the same property on that window
-
-    Window* windowFromChild = NULL;
-    if (!_glfwGetWindowPropertyX11(*windowFromRoot,
-                                   _glfw.x11.NET_SUPPORTING_WM_CHECK,
-                                   XA_WINDOW,
-                                   (unsigned char**) &windowFromChild))
-    {
-        XFree(windowFromRoot);
-        return;
-    }
-
-    _glfwReleaseErrorHandlerX11();
-
-    // If the property exists, it should contain the XID of the window
-
-    if (*windowFromRoot != *windowFromChild)
-    {
-        XFree(windowFromRoot);
-        XFree(windowFromChild);
-        return;
-    }
-
-    XFree(windowFromRoot);
-    XFree(windowFromChild);
-
-    // We are now fairly sure that an EWMH-compliant WM is currently running
-    // We can now start querying the WM about what features it supports by
-    // looking in the _NET_SUPPORTED property on the root window
-    // It should contain a list of supported EWMH protocol and state atoms
-
-    Atom* supportedAtoms = NULL;
-    const unsigned long atomCount =
-        _glfwGetWindowPropertyX11(_glfw.x11.root,
-                                  _glfw.x11.NET_SUPPORTED,
-                                  XA_ATOM,
-                                  (unsigned char**) &supportedAtoms);
-
-    // See which of the atoms we support that are supported by the WM
-
-    _glfw.x11.NET_WM_STATE =
-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
-    _glfw.x11.NET_WM_STATE_ABOVE =
-        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_STATE_DEMANDS_ATTENTION =
-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
-    _glfw.x11.NET_WM_FULLSCREEN_MONITORS =
-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
-    _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_WORKAREA =
-        getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
-    _glfw.x11.NET_CURRENT_DESKTOP =
-        getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
-    _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");
-
-    if (supportedAtoms)
-        XFree(supportedAtoms);
-}
-
-// Look for and initialize supported X11 extensions
-//
-static GLFWbool initExtensions(void)
-{
-    _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
-    if (_glfw.x11.vidmode.handle)
-    {
-        _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
-            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
-        _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
-            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
-        _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
-            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
-        _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
-            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
-
-        _glfw.x11.vidmode.available =
-            XF86VidModeQueryExtension(_glfw.x11.display,
-                                      &_glfw.x11.vidmode.eventBase,
-                                      &_glfw.x11.vidmode.errorBase);
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
-#else
-    _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
-#endif
-    if (_glfw.x11.xi.handle)
-    {
-        _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
-            _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
-        _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
-            _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
-
-        if (XQueryExtension(_glfw.x11.display,
-                            "XInputExtension",
-                            &_glfw.x11.xi.majorOpcode,
-                            &_glfw.x11.xi.eventBase,
-                            &_glfw.x11.xi.errorBase))
-        {
-            _glfw.x11.xi.major = 2;
-            _glfw.x11.xi.minor = 0;
-
-            if (XIQueryVersion(_glfw.x11.display,
-                               &_glfw.x11.xi.major,
-                               &_glfw.x11.xi.minor) == Success)
-            {
-                _glfw.x11.xi.available = GLFW_TRUE;
-            }
-        }
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
-#else
-    _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
-#endif
-    if (_glfw.x11.randr.handle)
-    {
-        _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
-        _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
-        _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
-        _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
-        _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
-        _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
-        _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
-        _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
-        _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
-        _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
-        _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
-        _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
-        _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
-        _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
-        _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
-        _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
-        _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
-        _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
-            _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
-
-        if (XRRQueryExtension(_glfw.x11.display,
-                              &_glfw.x11.randr.eventBase,
-                              &_glfw.x11.randr.errorBase))
-        {
-            if (XRRQueryVersion(_glfw.x11.display,
-                                &_glfw.x11.randr.major,
-                                &_glfw.x11.randr.minor))
-            {
-                // 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;
-            }
-            else
-            {
-                _glfwInputError(GLFW_PLATFORM_ERROR,
-                                "X11: Failed to query RandR version");
-            }
-        }
-    }
-
-    if (_glfw.x11.randr.available)
-    {
-        XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
-                                                              _glfw.x11.root);
-
-        if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
-        {
-            // This is likely an older Nvidia driver with broken gamma support
-            // Flag it as useless and fall back to xf86vm gamma, if available
-            _glfw.x11.randr.gammaBroken = GLFW_TRUE;
-        }
-
-        if (!sr->ncrtc)
-        {
-            // A system without CRTCs is likely a system with broken RandR
-            // Disable the RandR monitor path and fall back to core functions
-            _glfw.x11.randr.monitorBroken = GLFW_TRUE;
-        }
-
-        XRRFreeScreenResources(sr);
-    }
-
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
-                       RROutputChangeNotifyMask);
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
-#else
-    _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
-#endif
-    if (_glfw.x11.xcursor.handle)
-    {
-        _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
-            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
-        _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
-            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
-        _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
-            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
-#else
-    _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
-#endif
-    if (_glfw.x11.xinerama.handle)
-    {
-        _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
-            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
-        _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
-            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
-        _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
-            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
-
-        if (XineramaQueryExtension(_glfw.x11.display,
-                                   &_glfw.x11.xinerama.major,
-                                   &_glfw.x11.xinerama.minor))
-        {
-            if (XineramaIsActive(_glfw.x11.display))
-                _glfw.x11.xinerama.available = GLFW_TRUE;
-        }
-    }
-
-    _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.major,
-                          &_glfw.x11.xkb.minor);
-
-    if (_glfw.x11.xkb.available)
-    {
-        Bool supported;
-
-        if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported))
-        {
-            if (supported)
-                _glfw.x11.xkb.detectable = GLFW_TRUE;
-        }
-
-        _glfw.x11.xkb.group = 0;
-        XkbStateRec state;
-        if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success)
-        {
-            XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
-            _glfw.x11.xkb.group = (unsigned int)state.group;
-        }
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
-#else
-    _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
-#endif
-    if (_glfw.x11.x11xcb.handle)
-    {
-        _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
-            _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
-    }
-
-#if defined(__CYGWIN__)
-    _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
-#else
-    _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
-#endif
-    if (_glfw.x11.xrender.handle)
-    {
-        _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
-            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
-        _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
-            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
-        _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
-            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
-
-        if (XRenderQueryExtension(_glfw.x11.display,
-                                  &_glfw.x11.xrender.errorBase,
-                                  &_glfw.x11.xrender.eventBase))
-        {
-            if (XRenderQueryVersion(_glfw.x11.display,
-                                    &_glfw.x11.xrender.major,
-                                    &_glfw.x11.xrender.minor))
-            {
-                _glfw.x11.xrender.available = GLFW_TRUE;
-            }
-        }
-    }
-
-    // Update the key code LUT
-    // FIXME: We should listen to XkbMapNotify events to track changes to
-    // the keyboard mapping.
-    createKeyTables();
-
-    // String format atoms
-    _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
-    _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
-    _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
-
-    // Custom selection property atom
-    _glfw.x11.GLFW_SELECTION =
-        XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
-
-    // ICCCM standard clipboard atoms
-    _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
-    _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
-    _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
-    _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
-    _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
-
-    // 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);
-
-    // 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.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
-    _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
-    _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
-    _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
-
-    // 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_SUPPORTED =
-        XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
-    _glfw.x11.NET_SUPPORTING_WM_CHECK =
-        XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", 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.NET_WM_WINDOW_OPACITY =
-        XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False);
-    _glfw.x11.MOTIF_WM_HINTS =
-        XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
-
-    // The compositing manager selection name contains the screen number
-    {
-        char name[32];
-        snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
-        _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
-    }
-
-    // Detect whether an EWMH-conformant window manager is running
-    detectEWMH();
-
-    return GLFW_TRUE;
-}
-
-// Retrieve system content scale via folklore heuristics
-//
-static void getSystemContentScale(float* xscale, float* yscale)
-{
-    // Start by assuming the default X11 DPI
-    // NOTE: Some desktop environments (KDE) may remove the Xft.dpi field when it
-    //       would be set to 96, so assume that is the case if we cannot find it
-    float xdpi = 96.f, ydpi = 96.f;
-
-    // NOTE: Basing the scale on Xft.dpi where available should provide the most
-    //       consistent user experience (matches Qt, Gtk, etc), although not
-    //       always the most accurate one
-    char* rms = XResourceManagerString(_glfw.x11.display);
-    if (rms)
-    {
-        XrmDatabase db = XrmGetStringDatabase(rms);
-        if (db)
-        {
-            XrmValue value;
-            char* type = NULL;
-
-            if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
-            {
-                if (type && strcmp(type, "String") == 0)
-                    xdpi = ydpi = atof(value.addr);
-            }
-
-            XrmDestroyDatabase(db);
-        }
-    }
-
-    *xscale = xdpi / 96.f;
-    *yscale = ydpi / 96.f;
-}
-
-// Create a blank cursor for hidden and disabled cursor modes
-//
-static Cursor createHiddenCursor(void)
-{
-    unsigned char pixels[16 * 16 * 4] = { 0 };
-    GLFWimage image = { 16, 16, pixels };
-    return _glfwCreateCursorX11(&image, 0, 0);
-}
-
-// Create a helper window for IPC
-//
-static Window createHelperWindow(void)
-{
-    XSetWindowAttributes wa;
-    wa.event_mask = PropertyChangeMask;
-
-    return XCreateWindow(_glfw.x11.display, _glfw.x11.root,
-                         0, 0, 1, 1, 0, 0,
-                         InputOnly,
-                         DefaultVisual(_glfw.x11.display, _glfw.x11.screen),
-                         CWEventMask, &wa);
-}
-
-// X error handler
-//
-static int errorHandler(Display *display, XErrorEvent* event)
-{
-    _glfw.x11.errorCode = event->error_code;
-    return 0;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Sets the X error handler callback
-//
-void _glfwGrabErrorHandlerX11(void)
-{
-    _glfw.x11.errorCode = Success;
-    XSetErrorHandler(errorHandler);
-}
-
-// Clears the X error handler callback
-//
-void _glfwReleaseErrorHandlerX11(void)
-{
-    // Synchronize to make sure all commands are processed
-    XSync(_glfw.x11.display, False);
-    XSetErrorHandler(NULL);
-}
-
-// Reports the specified error, appending information about the last X error
-//
-void _glfwInputErrorX11(int error, const char* message)
-{
-    char buffer[_GLFW_MESSAGE_SIZE];
-    XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
-                  buffer, sizeof(buffer));
-
-    _glfwInputError(error, "%s: %s", message, buffer);
-}
-
-// Creates a native cursor object from the specified image and hotspot
-//
-Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
-{
-    int i;
-    Cursor cursor;
-
-    if (!_glfw.x11.xcursor.handle)
-        return None;
-
-    XcursorImage* native = XcursorImageCreate(image->width, image->height);
-    if (native == NULL)
-        return None;
-
-    native->xhot = xhot;
-    native->yhot = yhot;
-
-    unsigned char* source = (unsigned char*) image->pixels;
-    XcursorPixel* target = native->pixels;
-
-    for (i = 0;  i < image->width * image->height;  i++, target++, source += 4)
-    {
-        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);
-    XcursorImageDestroy(native);
-
-    return cursor;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-int _glfwPlatformInit(void)
-{
-#if !defined(X_HAVE_UTF8_STRING)
-    // HACK: If the current locale is "C" and the Xlib UTF-8 functions are
-    //       unavailable, apply the environment's locale in the hope that it's
-    //       both available and not "C"
-    //       This is done because the "C" locale breaks wide character input,
-    //       which is what we fall back on when UTF-8 support is missing
-    if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
-        setlocale(LC_CTYPE, "");
-#endif
-
-    XInitThreads();
-    XrmInitialize();
-
-    _glfw.x11.display = XOpenDisplay(NULL);
-    if (!_glfw.x11.display)
-    {
-        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);
-    _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
-    _glfw.x11.context = XUniqueContext();
-
-    getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
-
-    if (!initExtensions())
-        return GLFW_FALSE;
-
-    _glfw.x11.helperWindowHandle = createHelperWindow();
-    _glfw.x11.hiddenCursorHandle = createHiddenCursor();
-
-    if (XSupportsLocale())
-    {
-        XSetLocaleModifiers("");
-
-        _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
-        if (_glfw.x11.im)
-        {
-            if (!hasUsableInputMethodStyle())
-            {
-                XCloseIM(_glfw.x11.im);
-                _glfw.x11.im = NULL;
-            }
-        }
-    }
-
-#if defined(__linux__)
-    if (!_glfwInitJoysticksLinux())
-        return GLFW_FALSE;
-#endif
-
-    _glfwInitTimerPOSIX();
-
-    _glfwPollMonitorsX11();
-    return GLFW_TRUE;
-}
-
-void _glfwPlatformTerminate(void)
-{
-    if (_glfw.x11.helperWindowHandle)
-    {
-        if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
-            _glfw.x11.helperWindowHandle)
-        {
-            _glfwPushSelectionToManagerX11();
-        }
-
-        XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle);
-        _glfw.x11.helperWindowHandle = None;
-    }
-
-    if (_glfw.x11.hiddenCursorHandle)
-    {
-        XFreeCursor(_glfw.x11.display, _glfw.x11.hiddenCursorHandle);
-        _glfw.x11.hiddenCursorHandle = (Cursor) 0;
-    }
-
-    free(_glfw.x11.primarySelectionString);
-    free(_glfw.x11.clipboardString);
-
-    if (_glfw.x11.im)
-    {
-        XCloseIM(_glfw.x11.im);
-        _glfw.x11.im = NULL;
-    }
-
-    if (_glfw.x11.display)
-    {
-        XCloseDisplay(_glfw.x11.display);
-        _glfw.x11.display = NULL;
-    }
-
-    if (_glfw.x11.x11xcb.handle)
-    {
-        _glfw_dlclose(_glfw.x11.x11xcb.handle);
-        _glfw.x11.x11xcb.handle = NULL;
-    }
-
-    if (_glfw.x11.xcursor.handle)
-    {
-        _glfw_dlclose(_glfw.x11.xcursor.handle);
-        _glfw.x11.xcursor.handle = NULL;
-    }
-
-    if (_glfw.x11.randr.handle)
-    {
-        _glfw_dlclose(_glfw.x11.randr.handle);
-        _glfw.x11.randr.handle = NULL;
-    }
-
-    if (_glfw.x11.xinerama.handle)
-    {
-        _glfw_dlclose(_glfw.x11.xinerama.handle);
-        _glfw.x11.xinerama.handle = NULL;
-    }
-
-    if (_glfw.x11.xrender.handle)
-    {
-        _glfw_dlclose(_glfw.x11.xrender.handle);
-        _glfw.x11.xrender.handle = NULL;
-    }
-
-    if (_glfw.x11.vidmode.handle)
-    {
-        _glfw_dlclose(_glfw.x11.vidmode.handle);
-        _glfw.x11.vidmode.handle = NULL;
-    }
-
-    if (_glfw.x11.xi.handle)
-    {
-        _glfw_dlclose(_glfw.x11.xi.handle);
-        _glfw.x11.xi.handle = NULL;
-    }
-
-    // NOTE: These need to be unloaded after XCloseDisplay, as they register
-    //       cleanup callbacks that get called by that function
-    _glfwTerminateEGL();
-    _glfwTerminateGLX();
-
-#if defined(__linux__)
-    _glfwTerminateJoysticksLinux();
-#endif
-}
-
-const char* _glfwPlatformGetVersionString(void)
-{
-    return _GLFW_VERSION_NUMBER " X11 GLX EGL OSMesa"
-#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
-        " clock_gettime"
-#else
-        " gettimeofday"
-#endif
-#if defined(__linux__)
-        " evdev"
-#endif
-#if defined(_GLFW_BUILD_DLL)
-        " shared"
-#endif
-        ;
-}
-
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <X11/Xresource.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <locale.h>
+
+
+// Translate an X11 key code to a GLFW key code.
+//
+static int translateKeyCode(int scancode)
+{
+    int keySym;
+
+    // Valid key code range is  [8,255], according to the Xlib manual
+    if (scancode < 8 || scancode > 255)
+        return GLFW_KEY_UNKNOWN;
+
+    if (_glfw.x11.xkb.available)
+    {
+        // Try secondary keysym, for numeric keypad keys
+        // Note: This way we always force "NumLock = ON", which is intentional
+        // since the returned key code should correspond to a physical
+        // location.
+        keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
+        switch (keySym)
+        {
+            case XK_KP_0:           return GLFW_KEY_KP_0;
+            case XK_KP_1:           return GLFW_KEY_KP_1;
+            case XK_KP_2:           return GLFW_KEY_KP_2;
+            case XK_KP_3:           return GLFW_KEY_KP_3;
+            case XK_KP_4:           return GLFW_KEY_KP_4;
+            case XK_KP_5:           return GLFW_KEY_KP_5;
+            case XK_KP_6:           return GLFW_KEY_KP_6;
+            case XK_KP_7:           return GLFW_KEY_KP_7;
+            case XK_KP_8:           return GLFW_KEY_KP_8;
+            case XK_KP_9:           return GLFW_KEY_KP_9;
+            case XK_KP_Separator:
+            case XK_KP_Decimal:     return GLFW_KEY_KP_DECIMAL;
+            case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
+            case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
+            default:                break;
+        }
+
+        // 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, _glfw.x11.xkb.group, 0);
+    }
+    else
+    {
+        int dummy;
+        KeySym* keySyms;
+
+        keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
+        keySym = keySyms[0];
+        XFree(keySyms);
+    }
+
+    switch (keySym)
+    {
+        case XK_Escape:         return GLFW_KEY_ESCAPE;
+        case XK_Tab:            return GLFW_KEY_TAB;
+        case XK_Shift_L:        return GLFW_KEY_LEFT_SHIFT;
+        case XK_Shift_R:        return GLFW_KEY_RIGHT_SHIFT;
+        case XK_Control_L:      return GLFW_KEY_LEFT_CONTROL;
+        case XK_Control_R:      return GLFW_KEY_RIGHT_CONTROL;
+        case XK_Meta_L:
+        case XK_Alt_L:          return GLFW_KEY_LEFT_ALT;
+        case XK_Mode_switch: // Mapped to Alt_R on many keyboards
+        case XK_ISO_Level3_Shift: // AltGr on at least some machines
+        case XK_Meta_R:
+        case XK_Alt_R:          return GLFW_KEY_RIGHT_ALT;
+        case XK_Super_L:        return GLFW_KEY_LEFT_SUPER;
+        case XK_Super_R:        return GLFW_KEY_RIGHT_SUPER;
+        case XK_Menu:           return GLFW_KEY_MENU;
+        case XK_Num_Lock:       return GLFW_KEY_NUM_LOCK;
+        case XK_Caps_Lock:      return GLFW_KEY_CAPS_LOCK;
+        case XK_Print:          return GLFW_KEY_PRINT_SCREEN;
+        case XK_Scroll_Lock:    return GLFW_KEY_SCROLL_LOCK;
+        case XK_Pause:          return GLFW_KEY_PAUSE;
+        case XK_Delete:         return GLFW_KEY_DELETE;
+        case XK_BackSpace:      return GLFW_KEY_BACKSPACE;
+        case XK_Return:         return GLFW_KEY_ENTER;
+        case XK_Home:           return GLFW_KEY_HOME;
+        case XK_End:            return GLFW_KEY_END;
+        case XK_Page_Up:        return GLFW_KEY_PAGE_UP;
+        case XK_Page_Down:      return GLFW_KEY_PAGE_DOWN;
+        case XK_Insert:         return GLFW_KEY_INSERT;
+        case XK_Left:           return GLFW_KEY_LEFT;
+        case XK_Right:          return GLFW_KEY_RIGHT;
+        case XK_Down:           return GLFW_KEY_DOWN;
+        case XK_Up:             return GLFW_KEY_UP;
+        case XK_F1:             return GLFW_KEY_F1;
+        case XK_F2:             return GLFW_KEY_F2;
+        case XK_F3:             return GLFW_KEY_F3;
+        case XK_F4:             return GLFW_KEY_F4;
+        case XK_F5:             return GLFW_KEY_F5;
+        case XK_F6:             return GLFW_KEY_F6;
+        case XK_F7:             return GLFW_KEY_F7;
+        case XK_F8:             return GLFW_KEY_F8;
+        case XK_F9:             return GLFW_KEY_F9;
+        case XK_F10:            return GLFW_KEY_F10;
+        case XK_F11:            return GLFW_KEY_F11;
+        case XK_F12:            return GLFW_KEY_F12;
+        case XK_F13:            return GLFW_KEY_F13;
+        case XK_F14:            return GLFW_KEY_F14;
+        case XK_F15:            return GLFW_KEY_F15;
+        case XK_F16:            return GLFW_KEY_F16;
+        case XK_F17:            return GLFW_KEY_F17;
+        case XK_F18:            return GLFW_KEY_F18;
+        case XK_F19:            return GLFW_KEY_F19;
+        case XK_F20:            return GLFW_KEY_F20;
+        case XK_F21:            return GLFW_KEY_F21;
+        case XK_F22:            return GLFW_KEY_F22;
+        case XK_F23:            return GLFW_KEY_F23;
+        case XK_F24:            return GLFW_KEY_F24;
+        case XK_F25:            return GLFW_KEY_F25;
+
+        // Numeric keypad
+        case XK_KP_Divide:      return GLFW_KEY_KP_DIVIDE;
+        case XK_KP_Multiply:    return GLFW_KEY_KP_MULTIPLY;
+        case XK_KP_Subtract:    return GLFW_KEY_KP_SUBTRACT;
+        case XK_KP_Add:         return GLFW_KEY_KP_ADD;
+
+        // These should have been detected in secondary keysym test above!
+        case XK_KP_Insert:      return GLFW_KEY_KP_0;
+        case XK_KP_End:         return GLFW_KEY_KP_1;
+        case XK_KP_Down:        return GLFW_KEY_KP_2;
+        case XK_KP_Page_Down:   return GLFW_KEY_KP_3;
+        case XK_KP_Left:        return GLFW_KEY_KP_4;
+        case XK_KP_Right:       return GLFW_KEY_KP_6;
+        case XK_KP_Home:        return GLFW_KEY_KP_7;
+        case XK_KP_Up:          return GLFW_KEY_KP_8;
+        case XK_KP_Page_Up:     return GLFW_KEY_KP_9;
+        case XK_KP_Delete:      return GLFW_KEY_KP_DECIMAL;
+        case XK_KP_Equal:       return GLFW_KEY_KP_EQUAL;
+        case XK_KP_Enter:       return GLFW_KEY_KP_ENTER;
+
+        // Last resort: Check for printable keys (should not happen if the XKB
+        // extension is available). This will give a layout dependent mapping
+        // (which is wrong, and we may miss some keys, especially on non-US
+        // keyboards), but it's better than nothing...
+        case XK_a:              return GLFW_KEY_A;
+        case XK_b:              return GLFW_KEY_B;
+        case XK_c:              return GLFW_KEY_C;
+        case XK_d:              return GLFW_KEY_D;
+        case XK_e:              return GLFW_KEY_E;
+        case XK_f:              return GLFW_KEY_F;
+        case XK_g:              return GLFW_KEY_G;
+        case XK_h:              return GLFW_KEY_H;
+        case XK_i:              return GLFW_KEY_I;
+        case XK_j:              return GLFW_KEY_J;
+        case XK_k:              return GLFW_KEY_K;
+        case XK_l:              return GLFW_KEY_L;
+        case XK_m:              return GLFW_KEY_M;
+        case XK_n:              return GLFW_KEY_N;
+        case XK_o:              return GLFW_KEY_O;
+        case XK_p:              return GLFW_KEY_P;
+        case XK_q:              return GLFW_KEY_Q;
+        case XK_r:              return GLFW_KEY_R;
+        case XK_s:              return GLFW_KEY_S;
+        case XK_t:              return GLFW_KEY_T;
+        case XK_u:              return GLFW_KEY_U;
+        case XK_v:              return GLFW_KEY_V;
+        case XK_w:              return GLFW_KEY_W;
+        case XK_x:              return GLFW_KEY_X;
+        case XK_y:              return GLFW_KEY_Y;
+        case XK_z:              return GLFW_KEY_Z;
+        case XK_1:              return GLFW_KEY_1;
+        case XK_2:              return GLFW_KEY_2;
+        case XK_3:              return GLFW_KEY_3;
+        case XK_4:              return GLFW_KEY_4;
+        case XK_5:              return GLFW_KEY_5;
+        case XK_6:              return GLFW_KEY_6;
+        case XK_7:              return GLFW_KEY_7;
+        case XK_8:              return GLFW_KEY_8;
+        case XK_9:              return GLFW_KEY_9;
+        case XK_0:              return GLFW_KEY_0;
+        case XK_space:          return GLFW_KEY_SPACE;
+        case XK_minus:          return GLFW_KEY_MINUS;
+        case XK_equal:          return GLFW_KEY_EQUAL;
+        case XK_bracketleft:    return GLFW_KEY_LEFT_BRACKET;
+        case XK_bracketright:   return GLFW_KEY_RIGHT_BRACKET;
+        case XK_backslash:      return GLFW_KEY_BACKSLASH;
+        case XK_semicolon:      return GLFW_KEY_SEMICOLON;
+        case XK_apostrophe:     return GLFW_KEY_APOSTROPHE;
+        case XK_grave:          return GLFW_KEY_GRAVE_ACCENT;
+        case XK_comma:          return GLFW_KEY_COMMA;
+        case XK_period:         return GLFW_KEY_PERIOD;
+        case XK_slash:          return GLFW_KEY_SLASH;
+        case XK_less:           return GLFW_KEY_WORLD_1; // At least in some layouts...
+        default:                break;
+    }
+
+    // No matching translation was found
+    return GLFW_KEY_UNKNOWN;
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+    int scancode, key;
+
+    memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes));
+    memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes));
+
+    if (_glfw.x11.xkb.available)
+    {
+        // Use XKB to determine physical key locations independently of the
+        // current keyboard layout
+
+        char name[XkbKeyNameLength + 1];
+        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 = desc->min_key_code;  scancode <= desc->max_key_code;  scancode++)
+        {
+            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
+            // keys (function keys) are mapped using traditional KeySym
+            // translations.
+            if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT;
+            else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1;
+            else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2;
+            else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3;
+            else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4;
+            else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5;
+            else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6;
+            else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7;
+            else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8;
+            else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9;
+            else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0;
+            else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS;
+            else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL;
+            else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q;
+            else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W;
+            else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E;
+            else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R;
+            else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T;
+            else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y;
+            else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U;
+            else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I;
+            else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O;
+            else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P;
+            else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET;
+            else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET;
+            else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A;
+            else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S;
+            else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D;
+            else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F;
+            else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G;
+            else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H;
+            else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J;
+            else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K;
+            else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L;
+            else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON;
+            else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE;
+            else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z;
+            else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X;
+            else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C;
+            else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V;
+            else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B;
+            else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N;
+            else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M;
+            else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA;
+            else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD;
+            else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH;
+            else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH;
+            else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1;
+            else key = GLFW_KEY_UNKNOWN;
+
+            if ((scancode >= 0) && (scancode < 256))
+                _glfw.x11.keycodes[scancode] = key;
+        }
+
+        XkbFreeNames(desc, XkbKeyNamesMask, True);
+        XkbFreeKeyboard(desc, 0, True);
+    }
+
+    for (scancode = 0;  scancode < 256;  scancode++)
+    {
+        // Translate the un-translated key codes using traditional X11 KeySym
+        // lookups
+        if (_glfw.x11.keycodes[scancode] < 0)
+            _glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
+
+        // Store the reverse translation for faster key name lookup
+        if (_glfw.x11.keycodes[scancode] > 0)
+            _glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;
+    }
+}
+
+// Check whether the IM has a usable style
+//
+static GLFWbool hasUsableInputMethodStyle(void)
+{
+    GLFWbool found = GLFW_FALSE;
+    XIMStyles* styles = NULL;
+
+    if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)
+        return GLFW_FALSE;
+
+    for (unsigned int i = 0;  i < styles->count_styles;  i++)
+    {
+        if (styles->supported_styles[i] == (XIMPreeditNothing | XIMStatusNothing))
+        {
+            found = GLFW_TRUE;
+            break;
+        }
+    }
+
+    XFree(styles);
+    return found;
+}
+
+// Check whether the specified atom is supported
+//
+static Atom getSupportedAtom(Atom* supportedAtoms,
+                             unsigned long atomCount,
+                             const char* atomName)
+{
+    const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
+
+    for (unsigned int i = 0;  i < atomCount;  i++)
+    {
+        if (supportedAtoms[i] == atom)
+            return atom;
+    }
+
+    return None;
+}
+
+// Check whether the running window manager is EWMH-compliant
+//
+static void detectEWMH(void)
+{
+    // First we read the _NET_SUPPORTING_WM_CHECK property on the root window
+
+    Window* windowFromRoot = NULL;
+    if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
+                                   _glfw.x11.NET_SUPPORTING_WM_CHECK,
+                                   XA_WINDOW,
+                                   (unsigned char**) &windowFromRoot))
+    {
+        return;
+    }
+
+    _glfwGrabErrorHandlerX11();
+
+    // If it exists, it should be the XID of a top-level window
+    // Then we look for the same property on that window
+
+    Window* windowFromChild = NULL;
+    if (!_glfwGetWindowPropertyX11(*windowFromRoot,
+                                   _glfw.x11.NET_SUPPORTING_WM_CHECK,
+                                   XA_WINDOW,
+                                   (unsigned char**) &windowFromChild))
+    {
+        XFree(windowFromRoot);
+        return;
+    }
+
+    _glfwReleaseErrorHandlerX11();
+
+    // If the property exists, it should contain the XID of the window
+
+    if (*windowFromRoot != *windowFromChild)
+    {
+        XFree(windowFromRoot);
+        XFree(windowFromChild);
+        return;
+    }
+
+    XFree(windowFromRoot);
+    XFree(windowFromChild);
+
+    // We are now fairly sure that an EWMH-compliant WM is currently running
+    // We can now start querying the WM about what features it supports by
+    // looking in the _NET_SUPPORTED property on the root window
+    // It should contain a list of supported EWMH protocol and state atoms
+
+    Atom* supportedAtoms = NULL;
+    const unsigned long atomCount =
+        _glfwGetWindowPropertyX11(_glfw.x11.root,
+                                  _glfw.x11.NET_SUPPORTED,
+                                  XA_ATOM,
+                                  (unsigned char**) &supportedAtoms);
+
+    // See which of the atoms we support that are supported by the WM
+
+    _glfw.x11.NET_WM_STATE =
+        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
+    _glfw.x11.NET_WM_STATE_ABOVE =
+        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_STATE_DEMANDS_ATTENTION =
+        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION");
+    _glfw.x11.NET_WM_FULLSCREEN_MONITORS =
+        getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS");
+    _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_WORKAREA =
+        getSupportedAtom(supportedAtoms, atomCount, "_NET_WORKAREA");
+    _glfw.x11.NET_CURRENT_DESKTOP =
+        getSupportedAtom(supportedAtoms, atomCount, "_NET_CURRENT_DESKTOP");
+    _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");
+
+    if (supportedAtoms)
+        XFree(supportedAtoms);
+}
+
+// Look for and initialize supported X11 extensions
+//
+static GLFWbool initExtensions(void)
+{
+    _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
+    if (_glfw.x11.vidmode.handle)
+    {
+        _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension)
+            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
+        _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp)
+            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
+        _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
+            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
+        _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
+            _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
+
+        _glfw.x11.vidmode.available =
+            XF86VidModeQueryExtension(_glfw.x11.display,
+                                      &_glfw.x11.vidmode.eventBase,
+                                      &_glfw.x11.vidmode.errorBase);
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.xi.handle = _glfw_dlopen("libXi-6.so");
+#else
+    _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6");
+#endif
+    if (_glfw.x11.xi.handle)
+    {
+        _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion)
+            _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion");
+        _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
+            _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
+
+        if (XQueryExtension(_glfw.x11.display,
+                            "XInputExtension",
+                            &_glfw.x11.xi.majorOpcode,
+                            &_glfw.x11.xi.eventBase,
+                            &_glfw.x11.xi.errorBase))
+        {
+            _glfw.x11.xi.major = 2;
+            _glfw.x11.xi.minor = 0;
+
+            if (XIQueryVersion(_glfw.x11.display,
+                               &_glfw.x11.xi.major,
+                               &_glfw.x11.xi.minor) == Success)
+            {
+                _glfw.x11.xi.available = GLFW_TRUE;
+            }
+        }
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.randr.handle = _glfw_dlopen("libXrandr-2.so");
+#else
+    _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2");
+#endif
+    if (_glfw.x11.randr.handle)
+    {
+        _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma");
+        _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
+        _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo");
+        _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma");
+        _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo");
+        _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources");
+        _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma");
+        _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
+        _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo");
+        _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
+        _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
+        _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
+        _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
+        _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
+        _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
+        _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
+        _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
+        _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
+            _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
+
+        if (XRRQueryExtension(_glfw.x11.display,
+                              &_glfw.x11.randr.eventBase,
+                              &_glfw.x11.randr.errorBase))
+        {
+            if (XRRQueryVersion(_glfw.x11.display,
+                                &_glfw.x11.randr.major,
+                                &_glfw.x11.randr.minor))
+            {
+                // 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;
+            }
+            else
+            {
+                _glfwInputError(GLFW_PLATFORM_ERROR,
+                                "X11: Failed to query RandR version");
+            }
+        }
+    }
+
+    if (_glfw.x11.randr.available)
+    {
+        XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
+                                                              _glfw.x11.root);
+
+        if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
+        {
+            // This is likely an older Nvidia driver with broken gamma support
+            // Flag it as useless and fall back to xf86vm gamma, if available
+            _glfw.x11.randr.gammaBroken = GLFW_TRUE;
+        }
+
+        if (!sr->ncrtc)
+        {
+            // A system without CRTCs is likely a system with broken RandR
+            // Disable the RandR monitor path and fall back to core functions
+            _glfw.x11.randr.monitorBroken = GLFW_TRUE;
+        }
+
+        XRRFreeScreenResources(sr);
+    }
+
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
+                       RROutputChangeNotifyMask);
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor-1.so");
+#else
+    _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1");
+#endif
+    if (_glfw.x11.xcursor.handle)
+    {
+        _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate)
+            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate");
+        _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy)
+            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
+        _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
+            _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama-1.so");
+#else
+    _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1");
+#endif
+    if (_glfw.x11.xinerama.handle)
+    {
+        _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive)
+            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive");
+        _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension)
+            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
+        _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
+            _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
+
+        if (XineramaQueryExtension(_glfw.x11.display,
+                                   &_glfw.x11.xinerama.major,
+                                   &_glfw.x11.xinerama.minor))
+        {
+            if (XineramaIsActive(_glfw.x11.display))
+                _glfw.x11.xinerama.available = GLFW_TRUE;
+        }
+    }
+
+    _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.major,
+                          &_glfw.x11.xkb.minor);
+
+    if (_glfw.x11.xkb.available)
+    {
+        Bool supported;
+
+        if (XkbSetDetectableAutoRepeat(_glfw.x11.display, True, &supported))
+        {
+            if (supported)
+                _glfw.x11.xkb.detectable = GLFW_TRUE;
+        }
+
+        _glfw.x11.xkb.group = 0;
+        XkbStateRec state;
+        if (XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state) == Success)
+        {
+            XkbSelectEventDetails(_glfw.x11.display, XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask, XkbGroupStateMask);
+            _glfw.x11.xkb.group = (unsigned int)state.group;
+        }
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb-1.so");
+#else
+    _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1");
+#endif
+    if (_glfw.x11.x11xcb.handle)
+    {
+        _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection)
+            _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
+    }
+
+#if defined(__CYGWIN__)
+    _glfw.x11.xrender.handle = _glfw_dlopen("libXrender-1.so");
+#else
+    _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1");
+#endif
+    if (_glfw.x11.xrender.handle)
+    {
+        _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension)
+            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension");
+        _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion)
+            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
+        _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
+            _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
+
+        if (XRenderQueryExtension(_glfw.x11.display,
+                                  &_glfw.x11.xrender.errorBase,
+                                  &_glfw.x11.xrender.eventBase))
+        {
+            if (XRenderQueryVersion(_glfw.x11.display,
+                                    &_glfw.x11.xrender.major,
+                                    &_glfw.x11.xrender.minor))
+            {
+                _glfw.x11.xrender.available = GLFW_TRUE;
+            }
+        }
+    }
+
+    // Update the key code LUT
+    // FIXME: We should listen to XkbMapNotify events to track changes to
+    // the keyboard mapping.
+    createKeyTables();
+
+    // String format atoms
+    _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
+    _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
+    _glfw.x11.ATOM_PAIR = XInternAtom(_glfw.x11.display, "ATOM_PAIR", False);
+
+    // Custom selection property atom
+    _glfw.x11.GLFW_SELECTION =
+        XInternAtom(_glfw.x11.display, "GLFW_SELECTION", False);
+
+    // ICCCM standard clipboard atoms
+    _glfw.x11.TARGETS = XInternAtom(_glfw.x11.display, "TARGETS", False);
+    _glfw.x11.MULTIPLE = XInternAtom(_glfw.x11.display, "MULTIPLE", False);
+    _glfw.x11.PRIMARY = XInternAtom(_glfw.x11.display, "PRIMARY", False);
+    _glfw.x11.INCR = XInternAtom(_glfw.x11.display, "INCR", False);
+    _glfw.x11.CLIPBOARD = XInternAtom(_glfw.x11.display, "CLIPBOARD", False);
+
+    // 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);
+
+    // 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.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
+    _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
+    _glfw.x11.XdndTypeList = XInternAtom(_glfw.x11.display, "XdndTypeList", False);
+    _glfw.x11.text_uri_list = XInternAtom(_glfw.x11.display, "text/uri-list", False);
+
+    // 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_SUPPORTED =
+        XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
+    _glfw.x11.NET_SUPPORTING_WM_CHECK =
+        XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", 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.NET_WM_WINDOW_OPACITY =
+        XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False);
+    _glfw.x11.MOTIF_WM_HINTS =
+        XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
+
+    // The compositing manager selection name contains the screen number
+    {
+        char name[32];
+        snprintf(name, sizeof(name), "_NET_WM_CM_S%u", _glfw.x11.screen);
+        _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
+    }
+
+    // Detect whether an EWMH-conformant window manager is running
+    detectEWMH();
+
+    return GLFW_TRUE;
+}
+
+// Retrieve system content scale via folklore heuristics
+//
+static void getSystemContentScale(float* xscale, float* yscale)
+{
+    // Start by assuming the default X11 DPI
+    // NOTE: Some desktop environments (KDE) may remove the Xft.dpi field when it
+    //       would be set to 96, so assume that is the case if we cannot find it
+    float xdpi = 96.f, ydpi = 96.f;
+
+    // NOTE: Basing the scale on Xft.dpi where available should provide the most
+    //       consistent user experience (matches Qt, Gtk, etc), although not
+    //       always the most accurate one
+    char* rms = XResourceManagerString(_glfw.x11.display);
+    if (rms)
+    {
+        XrmDatabase db = XrmGetStringDatabase(rms);
+        if (db)
+        {
+            XrmValue value;
+            char* type = NULL;
+
+            if (XrmGetResource(db, "Xft.dpi", "Xft.Dpi", &type, &value))
+            {
+                if (type && strcmp(type, "String") == 0)
+                    xdpi = ydpi = atof(value.addr);
+            }
+
+            XrmDestroyDatabase(db);
+        }
+    }
+
+    *xscale = xdpi / 96.f;
+    *yscale = ydpi / 96.f;
+}
+
+// Create a blank cursor for hidden and disabled cursor modes
+//
+static Cursor createHiddenCursor(void)
+{
+    unsigned char pixels[16 * 16 * 4] = { 0 };
+    GLFWimage image = { 16, 16, pixels };
+    return _glfwCreateCursorX11(&image, 0, 0);
+}
+
+// Create a helper window for IPC
+//
+static Window createHelperWindow(void)
+{
+    XSetWindowAttributes wa;
+    wa.event_mask = PropertyChangeMask;
+
+    return XCreateWindow(_glfw.x11.display, _glfw.x11.root,
+                         0, 0, 1, 1, 0, 0,
+                         InputOnly,
+                         DefaultVisual(_glfw.x11.display, _glfw.x11.screen),
+                         CWEventMask, &wa);
+}
+
+// X error handler
+//
+static int errorHandler(Display *display, XErrorEvent* event)
+{
+    _glfw.x11.errorCode = event->error_code;
+    return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Sets the X error handler callback
+//
+void _glfwGrabErrorHandlerX11(void)
+{
+    _glfw.x11.errorCode = Success;
+    XSetErrorHandler(errorHandler);
+}
+
+// Clears the X error handler callback
+//
+void _glfwReleaseErrorHandlerX11(void)
+{
+    // Synchronize to make sure all commands are processed
+    XSync(_glfw.x11.display, False);
+    XSetErrorHandler(NULL);
+}
+
+// Reports the specified error, appending information about the last X error
+//
+void _glfwInputErrorX11(int error, const char* message)
+{
+    char buffer[_GLFW_MESSAGE_SIZE];
+    XGetErrorText(_glfw.x11.display, _glfw.x11.errorCode,
+                  buffer, sizeof(buffer));
+
+    _glfwInputError(error, "%s: %s", message, buffer);
+}
+
+// Creates a native cursor object from the specified image and hotspot
+//
+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
+{
+    int i;
+    Cursor cursor;
+
+    if (!_glfw.x11.xcursor.handle)
+        return None;
+
+    XcursorImage* native = XcursorImageCreate(image->width, image->height);
+    if (native == NULL)
+        return None;
+
+    native->xhot = xhot;
+    native->yhot = yhot;
+
+    unsigned char* source = (unsigned char*) image->pixels;
+    XcursorPixel* target = native->pixels;
+
+    for (i = 0;  i < image->width * image->height;  i++, target++, source += 4)
+    {
+        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);
+    XcursorImageDestroy(native);
+
+    return cursor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+#if !defined(X_HAVE_UTF8_STRING)
+    // HACK: If the current locale is "C" and the Xlib UTF-8 functions are
+    //       unavailable, apply the environment's locale in the hope that it's
+    //       both available and not "C"
+    //       This is done because the "C" locale breaks wide character input,
+    //       which is what we fall back on when UTF-8 support is missing
+    if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
+        setlocale(LC_CTYPE, "");
+#endif
+
+    XInitThreads();
+    XrmInitialize();
+
+    _glfw.x11.display = XOpenDisplay(NULL);
+    if (!_glfw.x11.display)
+    {
+        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);
+    _glfw.x11.root = RootWindow(_glfw.x11.display, _glfw.x11.screen);
+    _glfw.x11.context = XUniqueContext();
+
+    getSystemContentScale(&_glfw.x11.contentScaleX, &_glfw.x11.contentScaleY);
+
+    if (!initExtensions())
+        return GLFW_FALSE;
+
+    _glfw.x11.helperWindowHandle = createHelperWindow();
+    _glfw.x11.hiddenCursorHandle = createHiddenCursor();
+
+    if (XSupportsLocale())
+    {
+        XSetLocaleModifiers("");
+
+        _glfw.x11.im = XOpenIM(_glfw.x11.display, 0, NULL, NULL);
+        if (_glfw.x11.im)
+        {
+            if (!hasUsableInputMethodStyle())
+            {
+                XCloseIM(_glfw.x11.im);
+                _glfw.x11.im = NULL;
+            }
+        }
+    }
+
+#if defined(__linux__)
+    if (!_glfwInitJoysticksLinux())
+        return GLFW_FALSE;
+#endif
+
+    _glfwInitTimerPOSIX();
+
+    _glfwPollMonitorsX11();
+    return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+    if (_glfw.x11.helperWindowHandle)
+    {
+        if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
+            _glfw.x11.helperWindowHandle)
+        {
+            _glfwPushSelectionToManagerX11();
+        }
+
+        XDestroyWindow(_glfw.x11.display, _glfw.x11.helperWindowHandle);
+        _glfw.x11.helperWindowHandle = None;
+    }
+
+    if (_glfw.x11.hiddenCursorHandle)
+    {
+        XFreeCursor(_glfw.x11.display, _glfw.x11.hiddenCursorHandle);
+        _glfw.x11.hiddenCursorHandle = (Cursor) 0;
+    }
+
+    free(_glfw.x11.primarySelectionString);
+    free(_glfw.x11.clipboardString);
+
+    if (_glfw.x11.im)
+    {
+        XCloseIM(_glfw.x11.im);
+        _glfw.x11.im = NULL;
+    }
+
+    if (_glfw.x11.display)
+    {
+        XCloseDisplay(_glfw.x11.display);
+        _glfw.x11.display = NULL;
+    }
+
+    if (_glfw.x11.x11xcb.handle)
+    {
+        _glfw_dlclose(_glfw.x11.x11xcb.handle);
+        _glfw.x11.x11xcb.handle = NULL;
+    }
+
+    if (_glfw.x11.xcursor.handle)
+    {
+        _glfw_dlclose(_glfw.x11.xcursor.handle);
+        _glfw.x11.xcursor.handle = NULL;
+    }
+
+    if (_glfw.x11.randr.handle)
+    {
+        _glfw_dlclose(_glfw.x11.randr.handle);
+        _glfw.x11.randr.handle = NULL;
+    }
+
+    if (_glfw.x11.xinerama.handle)
+    {
+        _glfw_dlclose(_glfw.x11.xinerama.handle);
+        _glfw.x11.xinerama.handle = NULL;
+    }
+
+    if (_glfw.x11.xrender.handle)
+    {
+        _glfw_dlclose(_glfw.x11.xrender.handle);
+        _glfw.x11.xrender.handle = NULL;
+    }
+
+    if (_glfw.x11.vidmode.handle)
+    {
+        _glfw_dlclose(_glfw.x11.vidmode.handle);
+        _glfw.x11.vidmode.handle = NULL;
+    }
+
+    if (_glfw.x11.xi.handle)
+    {
+        _glfw_dlclose(_glfw.x11.xi.handle);
+        _glfw.x11.xi.handle = NULL;
+    }
+
+    // NOTE: These need to be unloaded after XCloseDisplay, as they register
+    //       cleanup callbacks that get called by that function
+    _glfwTerminateEGL();
+    _glfwTerminateGLX();
+
+#if defined(__linux__)
+    _glfwTerminateJoysticksLinux();
+#endif
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+    return _GLFW_VERSION_NUMBER " X11 GLX EGL OSMesa"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+        " clock_gettime"
+#else
+        " gettimeofday"
+#endif
+#if defined(__linux__)
+        " evdev"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+        " shared"
+#endif
+        ;
+}
+
diff --git a/glfw/src/x11_monitor.c b/glfw/src/x11_monitor.c
--- a/glfw/src/x11_monitor.c
+++ b/glfw/src/x11_monitor.c
@@ -1,604 +1,614 @@
-//========================================================================
-// GLFW 3.3 X11 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-
-// Check whether the display mode should be included in enumeration
-//
-static GLFWbool modeIsGood(const XRRModeInfo* mi)
-{
-    return (mi->modeFlags & RR_Interlace) == 0;
-}
-
-// Calculates the refresh rate, in Hz, from the specified RandR mode info
-//
-static int calculateRefreshRate(const XRRModeInfo* mi)
-{
-    if (mi->hTotal && mi->vTotal)
-        return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
-    else
-        return 0;
-}
-
-// Returns the mode info for a RandR mode XID
-//
-static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
-{
-    for (int i = 0;  i < sr->nmode;  i++)
-    {
-        if (sr->modes[i].id == id)
-            return sr->modes + i;
-    }
-
-    return NULL;
-}
-
-// Convert RandR mode info to GLFW video mode
-//
-static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
-                                       const XRRCrtcInfo* ci)
-{
-    GLFWvidmode mode;
-
-    if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
-    {
-        mode.width  = mi->height;
-        mode.height = mi->width;
-    }
-    else
-    {
-        mode.width  = mi->width;
-        mode.height = mi->height;
-    }
-
-    mode.refreshRate = calculateRefreshRate(mi);
-
-    _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
-                  &mode.redBits, &mode.greenBits, &mode.blueBits);
-
-    return mode;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Poll for changes in the set of connected monitors
-//
-void _glfwPollMonitorsX11(void)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        int disconnectedCount, screenCount = 0;
-        _GLFWmonitor** disconnected = NULL;
-        XineramaScreenInfo* screens = NULL;
-        XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
-                                                              _glfw.x11.root);
-        RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
-                                               _glfw.x11.root);
-
-        if (_glfw.x11.xinerama.available)
-            screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
-
-        disconnectedCount = _glfw.monitorCount;
-        if (disconnectedCount)
-        {
-            disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
-            memcpy(disconnected,
-                   _glfw.monitors,
-                   _glfw.monitorCount * sizeof(_GLFWmonitor*));
-        }
-
-        for (int i = 0;  i < sr->noutput;  i++)
-        {
-            int j, type, widthMM, heightMM;
-
-            XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
-            if (oi->connection != RR_Connected || oi->crtc == None)
-            {
-                XRRFreeOutputInfo(oi);
-                continue;
-            }
-
-            for (j = 0;  j < disconnectedCount;  j++)
-            {
-                if (disconnected[j] &&
-                    disconnected[j]->x11.output == sr->outputs[i])
-                {
-                    disconnected[j] = NULL;
-                    break;
-                }
-            }
-
-            if (j < disconnectedCount)
-            {
-                XRRFreeOutputInfo(oi);
-                continue;
-            }
-
-            XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
-            if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
-            {
-                widthMM  = oi->mm_height;
-                heightMM = oi->mm_width;
-            }
-            else
-            {
-                widthMM  = oi->mm_width;
-                heightMM = oi->mm_height;
-            }
-
-            if (widthMM <= 0 || heightMM <= 0)
-            {
-                // HACK: If RandR does not provide a physical size, assume the
-                //       X11 default 96 DPI and calcuate from the CRTC viewport
-                // NOTE: These members are affected by rotation, unlike the mode
-                //       info and output info members
-                widthMM  = (int) (ci->width * 25.4f / 96.f);
-                heightMM = (int) (ci->height * 25.4f / 96.f);
-            }
-
-            _GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
-            monitor->x11.output = sr->outputs[i];
-            monitor->x11.crtc   = oi->crtc;
-
-            for (j = 0;  j < screenCount;  j++)
-            {
-                if (screens[j].x_org == ci->x &&
-                    screens[j].y_org == ci->y &&
-                    screens[j].width == ci->width &&
-                    screens[j].height == ci->height)
-                {
-                    monitor->x11.index = j;
-                    break;
-                }
-            }
-
-            if (monitor->x11.output == primary)
-                type = _GLFW_INSERT_FIRST;
-            else
-                type = _GLFW_INSERT_LAST;
-
-            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
-
-            XRRFreeOutputInfo(oi);
-            XRRFreeCrtcInfo(ci);
-        }
-
-        XRRFreeScreenResources(sr);
-
-        if (screens)
-            XFree(screens);
-
-        for (int i = 0;  i < disconnectedCount;  i++)
-        {
-            if (disconnected[i])
-                _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
-        }
-
-        free(disconnected);
-    }
-    else
-    {
-        const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
-        const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
-
-        _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
-                          GLFW_CONNECTED,
-                          _GLFW_INSERT_FIRST);
-    }
-}
-
-// Set the current video mode for the specified monitor
-//
-void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        GLFWvidmode current;
-        RRMode native = None;
-
-        const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
-        _glfwPlatformGetVideoMode(monitor, &current);
-        if (_glfwCompareVideoModes(&current, best) == 0)
-            return;
-
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-        XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
-
-        for (int i = 0;  i < oi->nmode;  i++)
-        {
-            const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
-            if (!modeIsGood(mi))
-                continue;
-
-            const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
-            if (_glfwCompareVideoModes(best, &mode) == 0)
-            {
-                native = mi->id;
-                break;
-            }
-        }
-
-        if (native)
-        {
-            if (monitor->x11.oldMode == None)
-                monitor->x11.oldMode = ci->mode;
-
-            XRRSetCrtcConfig(_glfw.x11.display,
-                             sr, monitor->x11.crtc,
-                             CurrentTime,
-                             ci->x, ci->y,
-                             native,
-                             ci->rotation,
-                             ci->outputs,
-                             ci->noutput);
-        }
-
-        XRRFreeOutputInfo(oi);
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-    }
-}
-
-// Restore the saved (original) video mode for the specified monitor
-//
-void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        if (monitor->x11.oldMode == None)
-            return;
-
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-
-        XRRSetCrtcConfig(_glfw.x11.display,
-                         sr, monitor->x11.crtc,
-                         CurrentTime,
-                         ci->x, ci->y,
-                         monitor->x11.oldMode,
-                         ci->rotation,
-                         ci->outputs,
-                         ci->noutput);
-
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-
-        monitor->x11.oldMode = None;
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW platform API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
-{
-}
-
-void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-
-        if (xpos)
-            *xpos = ci->x;
-        if (ypos)
-            *ypos = ci->y;
-
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-    }
-}
-
-void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
-                                         float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = _glfw.x11.contentScaleX;
-    if (yscale)
-        *yscale = _glfw.x11.contentScaleY;
-}
-
-void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
-{
-    int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
-
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-
-        areaX = ci->x;
-        areaY = ci->y;
-
-        const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
-
-        if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
-        {
-            areaWidth  = mi->height;
-            areaHeight = mi->width;
-        }
-        else
-        {
-            areaWidth  = mi->width;
-            areaHeight = mi->height;
-        }
-
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-    }
-    else
-    {
-        areaWidth  = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
-        areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
-    }
-
-    if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
-    {
-        Atom* extents = NULL;
-        Atom* desktop = NULL;
-        const unsigned long extentCount =
-            _glfwGetWindowPropertyX11(_glfw.x11.root,
-                                      _glfw.x11.NET_WORKAREA,
-                                      XA_CARDINAL,
-                                      (unsigned char**) &extents);
-
-        if (_glfwGetWindowPropertyX11(_glfw.x11.root,
-                                      _glfw.x11.NET_CURRENT_DESKTOP,
-                                      XA_CARDINAL,
-                                      (unsigned char**) &desktop) > 0)
-        {
-            if (extentCount >= 4 && *desktop < extentCount / 4)
-            {
-                const int globalX = extents[*desktop * 4 + 0];
-                const int globalY = extents[*desktop * 4 + 1];
-                const int globalWidth  = extents[*desktop * 4 + 2];
-                const int globalHeight = extents[*desktop * 4 + 3];
-
-                if (areaX < globalX)
-                {
-                    areaWidth -= globalX - areaX;
-                    areaX = globalX;
-                }
-
-                if (areaY < globalY)
-                {
-                    areaHeight -= globalY - areaY;
-                    areaY = globalY;
-                }
-
-                if (areaX + areaWidth > globalX + globalWidth)
-                    areaWidth = globalX - areaX + globalWidth;
-                if (areaY + areaHeight > globalY + globalHeight)
-                    areaHeight = globalY - areaY + globalHeight;
-            }
-        }
-
-        if (extents)
-            XFree(extents);
-        if (desktop)
-            XFree(desktop);
-    }
-
-    if (xpos)
-        *xpos = areaX;
-    if (ypos)
-        *ypos = areaY;
-    if (width)
-        *width = areaWidth;
-    if (height)
-        *height = areaHeight;
-}
-
-GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
-{
-    GLFWvidmode* result;
-
-    *count = 0;
-
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-        XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
-
-        result = calloc(oi->nmode, sizeof(GLFWvidmode));
-
-        for (int i = 0;  i < oi->nmode;  i++)
-        {
-            const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
-            if (!modeIsGood(mi))
-                continue;
-
-            const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
-            int j;
-
-            for (j = 0;  j < *count;  j++)
-            {
-                if (_glfwCompareVideoModes(result + j, &mode) == 0)
-                    break;
-            }
-
-            // Skip duplicate modes
-            if (j < *count)
-                continue;
-
-            (*count)++;
-            result[*count - 1] = mode;
-        }
-
-        XRRFreeOutputInfo(oi);
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-    }
-    else
-    {
-        *count = 1;
-        result = calloc(1, sizeof(GLFWvidmode));
-        _glfwPlatformGetVideoMode(monitor, result);
-    }
-
-    return result;
-}
-
-void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
-    {
-        XRRScreenResources* sr =
-            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
-        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
-
-        *mode = vidmodeFromModeInfo(getModeInfo(sr, ci->mode), ci);
-
-        XRRFreeCrtcInfo(ci);
-        XRRFreeScreenResources(sr);
-    }
-    else
-    {
-        mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
-        mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
-        mode->refreshRate = 0;
-
-        _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
-                      &mode->redBits, &mode->greenBits, &mode->blueBits);
-    }
-}
-
-GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
-    {
-        const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
-                                                monitor->x11.crtc);
-        XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
-                                              monitor->x11.crtc);
-
-        _glfwAllocGammaArrays(ramp, size);
-
-        memcpy(ramp->red,   gamma->red,   size * sizeof(unsigned short));
-        memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
-        memcpy(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));
-
-        XRRFreeGamma(gamma);
-        return GLFW_TRUE;
-    }
-    else if (_glfw.x11.vidmode.available)
-    {
-        int size;
-        XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
-
-        _glfwAllocGammaArrays(ramp, size);
-
-        XF86VidModeGetGammaRamp(_glfw.x11.display,
-                                _glfw.x11.screen,
-                                ramp->size, ramp->red, ramp->green, ramp->blue);
-        return GLFW_TRUE;
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "X11: Gamma ramp access not supported by server");
-        return GLFW_FALSE;
-    }
-}
-
-void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
-{
-    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
-    {
-        if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
-        {
-            _glfwInputError(GLFW_PLATFORM_ERROR,
-                            "X11: Gamma ramp size must match current ramp size");
-            return;
-        }
-
-        XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
-
-        memcpy(gamma->red,   ramp->red,   ramp->size * sizeof(unsigned short));
-        memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
-        memcpy(gamma->blue,  ramp->blue,  ramp->size * sizeof(unsigned short));
-
-        XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
-        XRRFreeGamma(gamma);
-    }
-    else if (_glfw.x11.vidmode.available)
-    {
-        XF86VidModeSetGammaRamp(_glfw.x11.display,
-                                _glfw.x11.screen,
-                                ramp->size,
-                                (unsigned short*) ramp->red,
-                                (unsigned short*) ramp->green,
-                                (unsigned short*) ramp->blue);
-    }
-    else
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "X11: Gamma ramp access not supported by server");
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                        GLFW native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(None);
-    return monitor->x11.crtc;
-}
-
-GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
-{
-    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(None);
-    return monitor->x11.output;
-}
-
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+
+// Check whether the display mode should be included in enumeration
+//
+static GLFWbool modeIsGood(const XRRModeInfo* mi)
+{
+    return (mi->modeFlags & RR_Interlace) == 0;
+}
+
+// Calculates the refresh rate, in Hz, from the specified RandR mode info
+//
+static int calculateRefreshRate(const XRRModeInfo* mi)
+{
+    if (mi->hTotal && mi->vTotal)
+        return (int) round((double) mi->dotClock / ((double) mi->hTotal * (double) mi->vTotal));
+    else
+        return 0;
+}
+
+// Returns the mode info for a RandR mode XID
+//
+static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
+{
+    for (int i = 0;  i < sr->nmode;  i++)
+    {
+        if (sr->modes[i].id == id)
+            return sr->modes + i;
+    }
+
+    return NULL;
+}
+
+// Convert RandR mode info to GLFW video mode
+//
+static GLFWvidmode vidmodeFromModeInfo(const XRRModeInfo* mi,
+                                       const XRRCrtcInfo* ci)
+{
+    GLFWvidmode mode;
+
+    if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
+    {
+        mode.width  = mi->height;
+        mode.height = mi->width;
+    }
+    else
+    {
+        mode.width  = mi->width;
+        mode.height = mi->height;
+    }
+
+    mode.refreshRate = calculateRefreshRate(mi);
+
+    _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
+                  &mode.redBits, &mode.greenBits, &mode.blueBits);
+
+    return mode;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Poll for changes in the set of connected monitors
+//
+void _glfwPollMonitorsX11(void)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        int disconnectedCount, screenCount = 0;
+        _GLFWmonitor** disconnected = NULL;
+        XineramaScreenInfo* screens = NULL;
+        XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
+                                                              _glfw.x11.root);
+        RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
+                                               _glfw.x11.root);
+
+        if (_glfw.x11.xinerama.available)
+            screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
+
+        disconnectedCount = _glfw.monitorCount;
+        if (disconnectedCount)
+        {
+            disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
+            memcpy(disconnected,
+                   _glfw.monitors,
+                   _glfw.monitorCount * sizeof(_GLFWmonitor*));
+        }
+
+        for (int i = 0;  i < sr->noutput;  i++)
+        {
+            int j, type, widthMM, heightMM;
+
+            XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
+            if (oi->connection != RR_Connected || oi->crtc == None)
+            {
+                XRRFreeOutputInfo(oi);
+                continue;
+            }
+
+            for (j = 0;  j < disconnectedCount;  j++)
+            {
+                if (disconnected[j] &&
+                    disconnected[j]->x11.output == sr->outputs[i])
+                {
+                    disconnected[j] = NULL;
+                    break;
+                }
+            }
+
+            if (j < disconnectedCount)
+            {
+                XRRFreeOutputInfo(oi);
+                continue;
+            }
+
+            XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
+            if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
+            {
+                widthMM  = oi->mm_height;
+                heightMM = oi->mm_width;
+            }
+            else
+            {
+                widthMM  = oi->mm_width;
+                heightMM = oi->mm_height;
+            }
+
+            if (widthMM <= 0 || heightMM <= 0)
+            {
+                // HACK: If RandR does not provide a physical size, assume the
+                //       X11 default 96 DPI and calcuate from the CRTC viewport
+                // NOTE: These members are affected by rotation, unlike the mode
+                //       info and output info members
+                widthMM  = (int) (ci->width * 25.4f / 96.f);
+                heightMM = (int) (ci->height * 25.4f / 96.f);
+            }
+
+            _GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
+            monitor->x11.output = sr->outputs[i];
+            monitor->x11.crtc   = oi->crtc;
+
+            for (j = 0;  j < screenCount;  j++)
+            {
+                if (screens[j].x_org == ci->x &&
+                    screens[j].y_org == ci->y &&
+                    screens[j].width == ci->width &&
+                    screens[j].height == ci->height)
+                {
+                    monitor->x11.index = j;
+                    break;
+                }
+            }
+
+            if (monitor->x11.output == primary)
+                type = _GLFW_INSERT_FIRST;
+            else
+                type = _GLFW_INSERT_LAST;
+
+            _glfwInputMonitor(monitor, GLFW_CONNECTED, type);
+
+            XRRFreeOutputInfo(oi);
+            XRRFreeCrtcInfo(ci);
+        }
+
+        XRRFreeScreenResources(sr);
+
+        if (screens)
+            XFree(screens);
+
+        for (int i = 0;  i < disconnectedCount;  i++)
+        {
+            if (disconnected[i])
+                _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
+        }
+
+        free(disconnected);
+    }
+    else
+    {
+        const int widthMM = DisplayWidthMM(_glfw.x11.display, _glfw.x11.screen);
+        const int heightMM = DisplayHeightMM(_glfw.x11.display, _glfw.x11.screen);
+
+        _glfwInputMonitor(_glfwAllocMonitor("Display", widthMM, heightMM),
+                          GLFW_CONNECTED,
+                          _GLFW_INSERT_FIRST);
+    }
+}
+
+// Set the current video mode for the specified monitor
+//
+void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        GLFWvidmode current;
+        RRMode native = None;
+
+        const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
+        _glfwPlatformGetVideoMode(monitor, &current);
+        if (_glfwCompareVideoModes(&current, best) == 0)
+            return;
+
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+        XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+        for (int i = 0;  i < oi->nmode;  i++)
+        {
+            const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
+            if (!modeIsGood(mi))
+                continue;
+
+            const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
+            if (_glfwCompareVideoModes(best, &mode) == 0)
+            {
+                native = mi->id;
+                break;
+            }
+        }
+
+        if (native)
+        {
+            if (monitor->x11.oldMode == None)
+                monitor->x11.oldMode = ci->mode;
+
+            XRRSetCrtcConfig(_glfw.x11.display,
+                             sr, monitor->x11.crtc,
+                             CurrentTime,
+                             ci->x, ci->y,
+                             native,
+                             ci->rotation,
+                             ci->outputs,
+                             ci->noutput);
+        }
+
+        XRRFreeOutputInfo(oi);
+        XRRFreeCrtcInfo(ci);
+        XRRFreeScreenResources(sr);
+    }
+}
+
+// Restore the saved (original) video mode for the specified monitor
+//
+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        if (monitor->x11.oldMode == None)
+            return;
+
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+        XRRSetCrtcConfig(_glfw.x11.display,
+                         sr, monitor->x11.crtc,
+                         CurrentTime,
+                         ci->x, ci->y,
+                         monitor->x11.oldMode,
+                         ci->rotation,
+                         ci->outputs,
+                         ci->noutput);
+
+        XRRFreeCrtcInfo(ci);
+        XRRFreeScreenResources(sr);
+
+        monitor->x11.oldMode = None;
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW platform API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor)
+{
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+        if (ci)
+        {
+            if (xpos)
+                *xpos = ci->x;
+            if (ypos)
+                *ypos = ci->y;
+
+            XRRFreeCrtcInfo(ci);
+        }
+
+        XRRFreeScreenResources(sr);
+    }
+}
+
+void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
+                                         float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = _glfw.x11.contentScaleX;
+    if (yscale)
+        *yscale = _glfw.x11.contentScaleY;
+}
+
+void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
+{
+    int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
+
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+        areaX = ci->x;
+        areaY = ci->y;
+
+        const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
+
+        if (ci->rotation == RR_Rotate_90 || ci->rotation == RR_Rotate_270)
+        {
+            areaWidth  = mi->height;
+            areaHeight = mi->width;
+        }
+        else
+        {
+            areaWidth  = mi->width;
+            areaHeight = mi->height;
+        }
+
+        XRRFreeCrtcInfo(ci);
+        XRRFreeScreenResources(sr);
+    }
+    else
+    {
+        areaWidth  = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
+        areaHeight = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
+    }
+
+    if (_glfw.x11.NET_WORKAREA && _glfw.x11.NET_CURRENT_DESKTOP)
+    {
+        Atom* extents = NULL;
+        Atom* desktop = NULL;
+        const unsigned long extentCount =
+            _glfwGetWindowPropertyX11(_glfw.x11.root,
+                                      _glfw.x11.NET_WORKAREA,
+                                      XA_CARDINAL,
+                                      (unsigned char**) &extents);
+
+        if (_glfwGetWindowPropertyX11(_glfw.x11.root,
+                                      _glfw.x11.NET_CURRENT_DESKTOP,
+                                      XA_CARDINAL,
+                                      (unsigned char**) &desktop) > 0)
+        {
+            if (extentCount >= 4 && *desktop < extentCount / 4)
+            {
+                const int globalX = extents[*desktop * 4 + 0];
+                const int globalY = extents[*desktop * 4 + 1];
+                const int globalWidth  = extents[*desktop * 4 + 2];
+                const int globalHeight = extents[*desktop * 4 + 3];
+
+                if (areaX < globalX)
+                {
+                    areaWidth -= globalX - areaX;
+                    areaX = globalX;
+                }
+
+                if (areaY < globalY)
+                {
+                    areaHeight -= globalY - areaY;
+                    areaY = globalY;
+                }
+
+                if (areaX + areaWidth > globalX + globalWidth)
+                    areaWidth = globalX - areaX + globalWidth;
+                if (areaY + areaHeight > globalY + globalHeight)
+                    areaHeight = globalY - areaY + globalHeight;
+            }
+        }
+
+        if (extents)
+            XFree(extents);
+        if (desktop)
+            XFree(desktop);
+    }
+
+    if (xpos)
+        *xpos = areaX;
+    if (ypos)
+        *ypos = areaY;
+    if (width)
+        *width = areaWidth;
+    if (height)
+        *height = areaHeight;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+    GLFWvidmode* result;
+
+    *count = 0;
+
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+        XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+        result = calloc(oi->nmode, sizeof(GLFWvidmode));
+
+        for (int i = 0;  i < oi->nmode;  i++)
+        {
+            const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
+            if (!modeIsGood(mi))
+                continue;
+
+            const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
+            int j;
+
+            for (j = 0;  j < *count;  j++)
+            {
+                if (_glfwCompareVideoModes(result + j, &mode) == 0)
+                    break;
+            }
+
+            // Skip duplicate modes
+            if (j < *count)
+                continue;
+
+            (*count)++;
+            result[*count - 1] = mode;
+        }
+
+        XRRFreeOutputInfo(oi);
+        XRRFreeCrtcInfo(ci);
+        XRRFreeScreenResources(sr);
+    }
+    else
+    {
+        *count = 1;
+        result = calloc(1, sizeof(GLFWvidmode));
+        _glfwPlatformGetVideoMode(monitor, result);
+    }
+
+    return result;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+    {
+        XRRScreenResources* sr =
+            XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+        XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+        if (ci)
+        {
+            const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
+            if (mi)  // mi can be NULL if the monitor has been disconnected
+                *mode = vidmodeFromModeInfo(mi, ci);
+
+            XRRFreeCrtcInfo(ci);
+        }
+
+        XRRFreeScreenResources(sr);
+    }
+    else
+    {
+        mode->width = DisplayWidth(_glfw.x11.display, _glfw.x11.screen);
+        mode->height = DisplayHeight(_glfw.x11.display, _glfw.x11.screen);
+        mode->refreshRate = 0;
+
+        _glfwSplitBPP(DefaultDepth(_glfw.x11.display, _glfw.x11.screen),
+                      &mode->redBits, &mode->greenBits, &mode->blueBits);
+    }
+}
+
+GLFWbool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
+    {
+        const size_t size = XRRGetCrtcGammaSize(_glfw.x11.display,
+                                                monitor->x11.crtc);
+        XRRCrtcGamma* gamma = XRRGetCrtcGamma(_glfw.x11.display,
+                                              monitor->x11.crtc);
+
+        _glfwAllocGammaArrays(ramp, size);
+
+        memcpy(ramp->red,   gamma->red,   size * sizeof(unsigned short));
+        memcpy(ramp->green, gamma->green, size * sizeof(unsigned short));
+        memcpy(ramp->blue,  gamma->blue,  size * sizeof(unsigned short));
+
+        XRRFreeGamma(gamma);
+        return GLFW_TRUE;
+    }
+    else if (_glfw.x11.vidmode.available)
+    {
+        int size;
+        XF86VidModeGetGammaRampSize(_glfw.x11.display, _glfw.x11.screen, &size);
+
+        _glfwAllocGammaArrays(ramp, size);
+
+        XF86VidModeGetGammaRamp(_glfw.x11.display,
+                                _glfw.x11.screen,
+                                ramp->size, ramp->red, ramp->green, ramp->blue);
+        return GLFW_TRUE;
+    }
+    else
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "X11: Gamma ramp access not supported by server");
+        return GLFW_FALSE;
+    }
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+    if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
+    {
+        if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
+        {
+            _glfwInputError(GLFW_PLATFORM_ERROR,
+                            "X11: Gamma ramp size must match current ramp size");
+            return;
+        }
+
+        XRRCrtcGamma* gamma = XRRAllocGamma(ramp->size);
+
+        memcpy(gamma->red,   ramp->red,   ramp->size * sizeof(unsigned short));
+        memcpy(gamma->green, ramp->green, ramp->size * sizeof(unsigned short));
+        memcpy(gamma->blue,  ramp->blue,  ramp->size * sizeof(unsigned short));
+
+        XRRSetCrtcGamma(_glfw.x11.display, monitor->x11.crtc, gamma);
+        XRRFreeGamma(gamma);
+    }
+    else if (_glfw.x11.vidmode.available)
+    {
+        XF86VidModeSetGammaRamp(_glfw.x11.display,
+                                _glfw.x11.screen,
+                                ramp->size,
+                                (unsigned short*) ramp->red,
+                                (unsigned short*) ramp->green,
+                                (unsigned short*) ramp->blue);
+    }
+    else
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "X11: Gamma ramp access not supported by server");
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                        GLFW native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(None);
+    return monitor->x11.crtc;
+}
+
+GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* handle)
+{
+    _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(None);
+    return monitor->x11.output;
+}
+
diff --git a/glfw/src/x11_platform.h b/glfw/src/x11_platform.h
--- a/glfw/src/x11_platform.h
+++ b/glfw/src/x11_platform.h
@@ -1,450 +1,450 @@
-//========================================================================
-// GLFW 3.3 X11 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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 <unistd.h>
-#include <signal.h>
-#include <stdint.h>
-#include <dlfcn.h>
-
-#include <X11/Xlib.h>
-#include <X11/keysym.h>
-#include <X11/Xatom.h>
-#include <X11/Xcursor/Xcursor.h>
-
-// The XRandR extension provides mode setting and gamma control
-#include <X11/extensions/Xrandr.h>
-
-// The Xkb extension provides improved keyboard support
-#include <X11/XKBlib.h>
-
-// The Xinerama extension provides legacy monitor indices
-#include <X11/extensions/Xinerama.h>
-
-// The XInput extension provides raw mouse motion input
-#include <X11/extensions/XInput2.h>
-
-typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
-typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
-typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
-typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
-typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
-typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
-typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
-typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
-typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
-typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
-typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
-typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
-typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
-typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
-typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
-typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
-typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
-#define XRRAllocGamma _glfw.x11.randr.AllocGamma
-#define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
-#define XRRFreeGamma _glfw.x11.randr.FreeGamma
-#define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
-#define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
-#define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
-#define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
-#define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
-#define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
-#define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
-#define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
-#define XRRQueryExtension _glfw.x11.randr.QueryExtension
-#define XRRQueryVersion _glfw.x11.randr.QueryVersion
-#define XRRSelectInput _glfw.x11.randr.SelectInput
-#define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
-#define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
-#define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
-
-typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
-typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
-typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
-#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
-#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
-#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
-
-typedef Bool (* PFN_XineramaIsActive)(Display*);
-typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
-typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
-#define XineramaIsActive _glfw.x11.xinerama.IsActive
-#define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
-#define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
-
-typedef XID xcb_window_t;
-typedef XID xcb_visualid_t;
-typedef struct xcb_connection_t xcb_connection_t;
-typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
-#define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
-
-typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
-typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
-typedef Bool (* PFN_XF86VidModeSetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
-typedef Bool (* PFN_XF86VidModeGetGammaRampSize)(Display*,int,int*);
-#define XF86VidModeQueryExtension _glfw.x11.vidmode.QueryExtension
-#define XF86VidModeGetGammaRamp _glfw.x11.vidmode.GetGammaRamp
-#define XF86VidModeSetGammaRamp _glfw.x11.vidmode.SetGammaRamp
-#define XF86VidModeGetGammaRampSize _glfw.x11.vidmode.GetGammaRampSize
-
-typedef Status (* PFN_XIQueryVersion)(Display*,int*,int*);
-typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
-#define XIQueryVersion _glfw.x11.xi.QueryVersion
-#define XISelectEvents _glfw.x11.xi.SelectEvents
-
-typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
-typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
-typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
-#define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
-#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
-#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
-
-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_thread.h"
-#include "posix_time.h"
-#include "xkb_unicode.h"
-#include "glx_context.h"
-#include "egl_context.h"
-#include "osmesa_context.h"
-#if defined(__linux__)
-#include "linux_joystick.h"
-#else
-#include "null_joystick.h"
-#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  ((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
-#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorX11  x11
-
-
-// X11-specific per-window data
-//
-typedef struct _GLFWwindowX11
-{
-    Colormap        colormap;
-    Window          handle;
-    Window          parent;
-    XIC             ic;
-
-    GLFWbool        overrideRedirect;
-    GLFWbool        iconified;
-    GLFWbool        maximized;
-
-    // Whether the visual supports framebuffer transparency
-    GLFWbool        transparent;
-
-    // Cached position and size used to filter out duplicate events
-    int             width, height;
-    int             xpos, ypos;
-
-    // The last received cursor position, regardless of source
-    int             lastCursorPosX, lastCursorPosY;
-    // The last position the cursor was warped to by GLFW
-    int             warpCursorPosX, warpCursorPosY;
-
-    // The time of the last KeyPress event
-    Time            lastKeyTime;
-
-} _GLFWwindowX11;
-
-// X11-specific global data
-//
-typedef struct _GLFWlibraryX11
-{
-    Display*        display;
-    int             screen;
-    Window          root;
-
-    // System content scale
-    float           contentScaleX, contentScaleY;
-    // Helper window for IPC
-    Window          helperWindowHandle;
-    // Invisible cursor for hidden cursor mode
-    Cursor          hiddenCursorHandle;
-    // Context for mapping window XIDs to _GLFWwindow pointers
-    XContext        context;
-    // XIM input method
-    XIM             im;
-    // Most recent error code received by X error handler
-    int             errorCode;
-    // Primary selection string (while the primary selection is owned)
-    char*           primarySelectionString;
-    // Clipboard string (while the selection is owned)
-    char*           clipboardString;
-    // Key name string
-    char            keynames[GLFW_KEY_LAST + 1][5];
-    // X11 keycode to GLFW key LUT
-    short int       keycodes[256];
-    // GLFW key to X11 keycode LUT
-    short int       scancodes[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            NET_SUPPORTED;
-    Atom            NET_SUPPORTING_WM_CHECK;
-    Atom            WM_PROTOCOLS;
-    Atom            WM_STATE;
-    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_STATE_DEMANDS_ATTENTION;
-    Atom            NET_WM_BYPASS_COMPOSITOR;
-    Atom            NET_WM_FULLSCREEN_MONITORS;
-    Atom            NET_WM_WINDOW_OPACITY;
-    Atom            NET_WM_CM_Sx;
-    Atom            NET_WORKAREA;
-    Atom            NET_CURRENT_DESKTOP;
-    Atom            NET_ACTIVE_WINDOW;
-    Atom            NET_FRAME_EXTENTS;
-    Atom            NET_REQUEST_FRAME_EXTENTS;
-    Atom            MOTIF_WM_HINTS;
-
-    // Xdnd (drag and drop) atoms
-    Atom            XdndAware;
-    Atom            XdndEnter;
-    Atom            XdndPosition;
-    Atom            XdndStatus;
-    Atom            XdndActionCopy;
-    Atom            XdndDrop;
-    Atom            XdndFinished;
-    Atom            XdndSelection;
-    Atom            XdndTypeList;
-    Atom            text_uri_list;
-
-    // Selection (clipboard) atoms
-    Atom            TARGETS;
-    Atom            MULTIPLE;
-    Atom            INCR;
-    Atom            CLIPBOARD;
-    Atom            PRIMARY;
-    Atom            CLIPBOARD_MANAGER;
-    Atom            SAVE_TARGETS;
-    Atom            NULL_;
-    Atom            UTF8_STRING;
-    Atom            COMPOUND_STRING;
-    Atom            ATOM_PAIR;
-    Atom            GLFW_SELECTION;
-
-    struct {
-        GLFWbool    available;
-        void*       handle;
-        int         eventBase;
-        int         errorBase;
-        int         major;
-        int         minor;
-        GLFWbool    gammaBroken;
-        GLFWbool    monitorBroken;
-        PFN_XRRAllocGamma AllocGamma;
-        PFN_XRRFreeCrtcInfo FreeCrtcInfo;
-        PFN_XRRFreeGamma FreeGamma;
-        PFN_XRRFreeOutputInfo FreeOutputInfo;
-        PFN_XRRFreeScreenResources FreeScreenResources;
-        PFN_XRRGetCrtcGamma GetCrtcGamma;
-        PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
-        PFN_XRRGetCrtcInfo GetCrtcInfo;
-        PFN_XRRGetOutputInfo GetOutputInfo;
-        PFN_XRRGetOutputPrimary GetOutputPrimary;
-        PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
-        PFN_XRRQueryExtension QueryExtension;
-        PFN_XRRQueryVersion QueryVersion;
-        PFN_XRRSelectInput SelectInput;
-        PFN_XRRSetCrtcConfig SetCrtcConfig;
-        PFN_XRRSetCrtcGamma SetCrtcGamma;
-        PFN_XRRUpdateConfiguration UpdateConfiguration;
-    } randr;
-
-    struct {
-        GLFWbool     available;
-        GLFWbool     detectable;
-        int          majorOpcode;
-        int          eventBase;
-        int          errorBase;
-        int          major;
-        int          minor;
-        unsigned int group;
-    } xkb;
-
-    struct {
-        int         count;
-        int         timeout;
-        int         interval;
-        int         blanking;
-        int         exposure;
-    } saver;
-
-    struct {
-        int         version;
-        Window      source;
-        Atom        format;
-    } xdnd;
-
-    struct {
-        void*       handle;
-        PFN_XcursorImageCreate ImageCreate;
-        PFN_XcursorImageDestroy ImageDestroy;
-        PFN_XcursorImageLoadCursor ImageLoadCursor;
-    } xcursor;
-
-    struct {
-        GLFWbool    available;
-        void*       handle;
-        int         major;
-        int         minor;
-        PFN_XineramaIsActive IsActive;
-        PFN_XineramaQueryExtension QueryExtension;
-        PFN_XineramaQueryScreens QueryScreens;
-    } xinerama;
-
-    struct {
-        void*       handle;
-        PFN_XGetXCBConnection GetXCBConnection;
-    } x11xcb;
-
-    struct {
-        GLFWbool    available;
-        void*       handle;
-        int         eventBase;
-        int         errorBase;
-        PFN_XF86VidModeQueryExtension QueryExtension;
-        PFN_XF86VidModeGetGammaRamp GetGammaRamp;
-        PFN_XF86VidModeSetGammaRamp SetGammaRamp;
-        PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
-    } vidmode;
-
-    struct {
-        GLFWbool    available;
-        void*       handle;
-        int         majorOpcode;
-        int         eventBase;
-        int         errorBase;
-        int         major;
-        int         minor;
-        PFN_XIQueryVersion QueryVersion;
-        PFN_XISelectEvents SelectEvents;
-    } xi;
-
-    struct {
-        GLFWbool    available;
-        void*       handle;
-        int         major;
-        int         minor;
-        int         eventBase;
-        int         errorBase;
-        PFN_XRenderQueryExtension QueryExtension;
-        PFN_XRenderQueryVersion QueryVersion;
-        PFN_XRenderFindVisualFormat FindVisualFormat;
-    } xrender;
-
-} _GLFWlibraryX11;
-
-// X11-specific per-monitor data
-//
-typedef struct _GLFWmonitorX11
-{
-    RROutput        output;
-    RRCrtc          crtc;
-    RRMode          oldMode;
-
-    // Index of corresponding Xinerama screen,
-    // for EWMH full screen window placement
-    int             index;
-
-} _GLFWmonitorX11;
-
-// X11-specific per-cursor data
-//
-typedef struct _GLFWcursorX11
-{
-    Cursor handle;
-
-} _GLFWcursorX11;
-
-
-void _glfwPollMonitorsX11(void);
-void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
-void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
-
-Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
-
-unsigned long _glfwGetWindowPropertyX11(Window window,
-                                        Atom property,
-                                        Atom type,
-                                        unsigned char** value);
-GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
-
-void _glfwGrabErrorHandlerX11(void);
-void _glfwReleaseErrorHandlerX11(void);
-void _glfwInputErrorX11(int error, const char* message);
-
-void _glfwPushSelectionToManagerX11(void);
-
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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 <unistd.h>
+#include <signal.h>
+#include <stdint.h>
+#include <dlfcn.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/Xatom.h>
+#include <X11/Xcursor/Xcursor.h>
+
+// The XRandR extension provides mode setting and gamma control
+#include <X11/extensions/Xrandr.h>
+
+// The Xkb extension provides improved keyboard support
+#include <X11/XKBlib.h>
+
+// The Xinerama extension provides legacy monitor indices
+#include <X11/extensions/Xinerama.h>
+
+// The XInput extension provides raw mouse motion input
+#include <X11/extensions/XInput2.h>
+
+typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int);
+typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*);
+typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*);
+typedef void (* PFN_XRRFreeOutputInfo)(XRROutputInfo*);
+typedef void (* PFN_XRRFreeScreenResources)(XRRScreenResources*);
+typedef XRRCrtcGamma* (* PFN_XRRGetCrtcGamma)(Display*,RRCrtc);
+typedef int (* PFN_XRRGetCrtcGammaSize)(Display*,RRCrtc);
+typedef XRRCrtcInfo* (* PFN_XRRGetCrtcInfo) (Display*,XRRScreenResources*,RRCrtc);
+typedef XRROutputInfo* (* PFN_XRRGetOutputInfo)(Display*,XRRScreenResources*,RROutput);
+typedef RROutput (* PFN_XRRGetOutputPrimary)(Display*,Window);
+typedef XRRScreenResources* (* PFN_XRRGetScreenResourcesCurrent)(Display*,Window);
+typedef Bool (* PFN_XRRQueryExtension)(Display*,int*,int*);
+typedef Status (* PFN_XRRQueryVersion)(Display*,int*,int*);
+typedef void (* PFN_XRRSelectInput)(Display*,Window,int);
+typedef Status (* PFN_XRRSetCrtcConfig)(Display*,XRRScreenResources*,RRCrtc,Time,int,int,RRMode,Rotation,RROutput*,int);
+typedef void (* PFN_XRRSetCrtcGamma)(Display*,RRCrtc,XRRCrtcGamma*);
+typedef int (* PFN_XRRUpdateConfiguration)(XEvent*);
+#define XRRAllocGamma _glfw.x11.randr.AllocGamma
+#define XRRFreeCrtcInfo _glfw.x11.randr.FreeCrtcInfo
+#define XRRFreeGamma _glfw.x11.randr.FreeGamma
+#define XRRFreeOutputInfo _glfw.x11.randr.FreeOutputInfo
+#define XRRFreeScreenResources _glfw.x11.randr.FreeScreenResources
+#define XRRGetCrtcGamma _glfw.x11.randr.GetCrtcGamma
+#define XRRGetCrtcGammaSize _glfw.x11.randr.GetCrtcGammaSize
+#define XRRGetCrtcInfo _glfw.x11.randr.GetCrtcInfo
+#define XRRGetOutputInfo _glfw.x11.randr.GetOutputInfo
+#define XRRGetOutputPrimary _glfw.x11.randr.GetOutputPrimary
+#define XRRGetScreenResourcesCurrent _glfw.x11.randr.GetScreenResourcesCurrent
+#define XRRQueryExtension _glfw.x11.randr.QueryExtension
+#define XRRQueryVersion _glfw.x11.randr.QueryVersion
+#define XRRSelectInput _glfw.x11.randr.SelectInput
+#define XRRSetCrtcConfig _glfw.x11.randr.SetCrtcConfig
+#define XRRSetCrtcGamma _glfw.x11.randr.SetCrtcGamma
+#define XRRUpdateConfiguration _glfw.x11.randr.UpdateConfiguration
+
+typedef XcursorImage* (* PFN_XcursorImageCreate)(int,int);
+typedef void (* PFN_XcursorImageDestroy)(XcursorImage*);
+typedef Cursor (* PFN_XcursorImageLoadCursor)(Display*,const XcursorImage*);
+#define XcursorImageCreate _glfw.x11.xcursor.ImageCreate
+#define XcursorImageDestroy _glfw.x11.xcursor.ImageDestroy
+#define XcursorImageLoadCursor _glfw.x11.xcursor.ImageLoadCursor
+
+typedef Bool (* PFN_XineramaIsActive)(Display*);
+typedef Bool (* PFN_XineramaQueryExtension)(Display*,int*,int*);
+typedef XineramaScreenInfo* (* PFN_XineramaQueryScreens)(Display*,int*);
+#define XineramaIsActive _glfw.x11.xinerama.IsActive
+#define XineramaQueryExtension _glfw.x11.xinerama.QueryExtension
+#define XineramaQueryScreens _glfw.x11.xinerama.QueryScreens
+
+typedef XID xcb_window_t;
+typedef XID xcb_visualid_t;
+typedef struct xcb_connection_t xcb_connection_t;
+typedef xcb_connection_t* (* PFN_XGetXCBConnection)(Display*);
+#define XGetXCBConnection _glfw.x11.x11xcb.GetXCBConnection
+
+typedef Bool (* PFN_XF86VidModeQueryExtension)(Display*,int*,int*);
+typedef Bool (* PFN_XF86VidModeGetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
+typedef Bool (* PFN_XF86VidModeSetGammaRamp)(Display*,int,int,unsigned short*,unsigned short*,unsigned short*);
+typedef Bool (* PFN_XF86VidModeGetGammaRampSize)(Display*,int,int*);
+#define XF86VidModeQueryExtension _glfw.x11.vidmode.QueryExtension
+#define XF86VidModeGetGammaRamp _glfw.x11.vidmode.GetGammaRamp
+#define XF86VidModeSetGammaRamp _glfw.x11.vidmode.SetGammaRamp
+#define XF86VidModeGetGammaRampSize _glfw.x11.vidmode.GetGammaRampSize
+
+typedef Status (* PFN_XIQueryVersion)(Display*,int*,int*);
+typedef int (* PFN_XISelectEvents)(Display*,Window,XIEventMask*,int);
+#define XIQueryVersion _glfw.x11.xi.QueryVersion
+#define XISelectEvents _glfw.x11.xi.SelectEvents
+
+typedef Bool (* PFN_XRenderQueryExtension)(Display*,int*,int*);
+typedef Status (* PFN_XRenderQueryVersion)(Display*dpy,int*,int*);
+typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const*);
+#define XRenderQueryExtension _glfw.x11.xrender.QueryExtension
+#define XRenderQueryVersion _glfw.x11.xrender.QueryVersion
+#define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat
+
+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_thread.h"
+#include "posix_time.h"
+#include "xkb_unicode.h"
+#include "glx_context.h"
+#include "egl_context.h"
+#include "osmesa_context.h"
+#if defined(__linux__)
+#include "linux_joystick.h"
+#else
+#include "null_joystick.h"
+#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  ((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
+#define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorX11  x11
+
+
+// X11-specific per-window data
+//
+typedef struct _GLFWwindowX11
+{
+    Colormap        colormap;
+    Window          handle;
+    Window          parent;
+    XIC             ic;
+
+    GLFWbool        overrideRedirect;
+    GLFWbool        iconified;
+    GLFWbool        maximized;
+
+    // Whether the visual supports framebuffer transparency
+    GLFWbool        transparent;
+
+    // Cached position and size used to filter out duplicate events
+    int             width, height;
+    int             xpos, ypos;
+
+    // The last received cursor position, regardless of source
+    int             lastCursorPosX, lastCursorPosY;
+    // The last position the cursor was warped to by GLFW
+    int             warpCursorPosX, warpCursorPosY;
+
+    // The time of the last KeyPress event
+    Time            lastKeyTime;
+
+} _GLFWwindowX11;
+
+// X11-specific global data
+//
+typedef struct _GLFWlibraryX11
+{
+    Display*        display;
+    int             screen;
+    Window          root;
+
+    // System content scale
+    float           contentScaleX, contentScaleY;
+    // Helper window for IPC
+    Window          helperWindowHandle;
+    // Invisible cursor for hidden cursor mode
+    Cursor          hiddenCursorHandle;
+    // Context for mapping window XIDs to _GLFWwindow pointers
+    XContext        context;
+    // XIM input method
+    XIM             im;
+    // Most recent error code received by X error handler
+    int             errorCode;
+    // Primary selection string (while the primary selection is owned)
+    char*           primarySelectionString;
+    // Clipboard string (while the selection is owned)
+    char*           clipboardString;
+    // Key name string
+    char            keynames[GLFW_KEY_LAST + 1][5];
+    // X11 keycode to GLFW key LUT
+    short int       keycodes[256];
+    // GLFW key to X11 keycode LUT
+    short int       scancodes[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            NET_SUPPORTED;
+    Atom            NET_SUPPORTING_WM_CHECK;
+    Atom            WM_PROTOCOLS;
+    Atom            WM_STATE;
+    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_STATE_DEMANDS_ATTENTION;
+    Atom            NET_WM_BYPASS_COMPOSITOR;
+    Atom            NET_WM_FULLSCREEN_MONITORS;
+    Atom            NET_WM_WINDOW_OPACITY;
+    Atom            NET_WM_CM_Sx;
+    Atom            NET_WORKAREA;
+    Atom            NET_CURRENT_DESKTOP;
+    Atom            NET_ACTIVE_WINDOW;
+    Atom            NET_FRAME_EXTENTS;
+    Atom            NET_REQUEST_FRAME_EXTENTS;
+    Atom            MOTIF_WM_HINTS;
+
+    // Xdnd (drag and drop) atoms
+    Atom            XdndAware;
+    Atom            XdndEnter;
+    Atom            XdndPosition;
+    Atom            XdndStatus;
+    Atom            XdndActionCopy;
+    Atom            XdndDrop;
+    Atom            XdndFinished;
+    Atom            XdndSelection;
+    Atom            XdndTypeList;
+    Atom            text_uri_list;
+
+    // Selection (clipboard) atoms
+    Atom            TARGETS;
+    Atom            MULTIPLE;
+    Atom            INCR;
+    Atom            CLIPBOARD;
+    Atom            PRIMARY;
+    Atom            CLIPBOARD_MANAGER;
+    Atom            SAVE_TARGETS;
+    Atom            NULL_;
+    Atom            UTF8_STRING;
+    Atom            COMPOUND_STRING;
+    Atom            ATOM_PAIR;
+    Atom            GLFW_SELECTION;
+
+    struct {
+        GLFWbool    available;
+        void*       handle;
+        int         eventBase;
+        int         errorBase;
+        int         major;
+        int         minor;
+        GLFWbool    gammaBroken;
+        GLFWbool    monitorBroken;
+        PFN_XRRAllocGamma AllocGamma;
+        PFN_XRRFreeCrtcInfo FreeCrtcInfo;
+        PFN_XRRFreeGamma FreeGamma;
+        PFN_XRRFreeOutputInfo FreeOutputInfo;
+        PFN_XRRFreeScreenResources FreeScreenResources;
+        PFN_XRRGetCrtcGamma GetCrtcGamma;
+        PFN_XRRGetCrtcGammaSize GetCrtcGammaSize;
+        PFN_XRRGetCrtcInfo GetCrtcInfo;
+        PFN_XRRGetOutputInfo GetOutputInfo;
+        PFN_XRRGetOutputPrimary GetOutputPrimary;
+        PFN_XRRGetScreenResourcesCurrent GetScreenResourcesCurrent;
+        PFN_XRRQueryExtension QueryExtension;
+        PFN_XRRQueryVersion QueryVersion;
+        PFN_XRRSelectInput SelectInput;
+        PFN_XRRSetCrtcConfig SetCrtcConfig;
+        PFN_XRRSetCrtcGamma SetCrtcGamma;
+        PFN_XRRUpdateConfiguration UpdateConfiguration;
+    } randr;
+
+    struct {
+        GLFWbool     available;
+        GLFWbool     detectable;
+        int          majorOpcode;
+        int          eventBase;
+        int          errorBase;
+        int          major;
+        int          minor;
+        unsigned int group;
+    } xkb;
+
+    struct {
+        int         count;
+        int         timeout;
+        int         interval;
+        int         blanking;
+        int         exposure;
+    } saver;
+
+    struct {
+        int         version;
+        Window      source;
+        Atom        format;
+    } xdnd;
+
+    struct {
+        void*       handle;
+        PFN_XcursorImageCreate ImageCreate;
+        PFN_XcursorImageDestroy ImageDestroy;
+        PFN_XcursorImageLoadCursor ImageLoadCursor;
+    } xcursor;
+
+    struct {
+        GLFWbool    available;
+        void*       handle;
+        int         major;
+        int         minor;
+        PFN_XineramaIsActive IsActive;
+        PFN_XineramaQueryExtension QueryExtension;
+        PFN_XineramaQueryScreens QueryScreens;
+    } xinerama;
+
+    struct {
+        void*       handle;
+        PFN_XGetXCBConnection GetXCBConnection;
+    } x11xcb;
+
+    struct {
+        GLFWbool    available;
+        void*       handle;
+        int         eventBase;
+        int         errorBase;
+        PFN_XF86VidModeQueryExtension QueryExtension;
+        PFN_XF86VidModeGetGammaRamp GetGammaRamp;
+        PFN_XF86VidModeSetGammaRamp SetGammaRamp;
+        PFN_XF86VidModeGetGammaRampSize GetGammaRampSize;
+    } vidmode;
+
+    struct {
+        GLFWbool    available;
+        void*       handle;
+        int         majorOpcode;
+        int         eventBase;
+        int         errorBase;
+        int         major;
+        int         minor;
+        PFN_XIQueryVersion QueryVersion;
+        PFN_XISelectEvents SelectEvents;
+    } xi;
+
+    struct {
+        GLFWbool    available;
+        void*       handle;
+        int         major;
+        int         minor;
+        int         eventBase;
+        int         errorBase;
+        PFN_XRenderQueryExtension QueryExtension;
+        PFN_XRenderQueryVersion QueryVersion;
+        PFN_XRenderFindVisualFormat FindVisualFormat;
+    } xrender;
+
+} _GLFWlibraryX11;
+
+// X11-specific per-monitor data
+//
+typedef struct _GLFWmonitorX11
+{
+    RROutput        output;
+    RRCrtc          crtc;
+    RRMode          oldMode;
+
+    // Index of corresponding Xinerama screen,
+    // for EWMH full screen window placement
+    int             index;
+
+} _GLFWmonitorX11;
+
+// X11-specific per-cursor data
+//
+typedef struct _GLFWcursorX11
+{
+    Cursor handle;
+
+} _GLFWcursorX11;
+
+
+void _glfwPollMonitorsX11(void);
+void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);
+
+Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot);
+
+unsigned long _glfwGetWindowPropertyX11(Window window,
+                                        Atom property,
+                                        Atom type,
+                                        unsigned char** value);
+GLFWbool _glfwIsVisualTransparentX11(Visual* visual);
+
+void _glfwGrabErrorHandlerX11(void);
+void _glfwReleaseErrorHandlerX11(void);
+void _glfwInputErrorX11(int error, const char* message);
+
+void _glfwPushSelectionToManagerX11(void);
+
diff --git a/glfw/src/x11_window.c b/glfw/src/x11_window.c
--- a/glfw/src/x11_window.c
+++ b/glfw/src/x11_window.c
@@ -1,3164 +1,3166 @@
-//========================================================================
-// GLFW 3.3 X11 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2019 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#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
-
-// Motif WM hints flags
-#define MWM_HINTS_DECORATIONS   2
-#define MWM_DECOR_ALL           1
-
-#define _GLFW_XDND_VERSION 5
-
-
-// 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;
-
-#if defined(__linux__)
-    if (_glfw.linjs.inotify > fd)
-        count = _glfw.linjs.inotify + 1;
-#endif
-    for (;;)
-    {
-        FD_ZERO(&fds);
-        FD_SET(fd, &fds);
-#if defined(__linux__)
-        if (_glfw.linjs.inotify > 0)
-            FD_SET(_glfw.linjs.inotify, &fds);
-#endif
-
-        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;
-    }
-
-    if (state)
-        XFree(state);
-
-    return result;
-}
-
-// Returns whether the event is a selection event
-//
-static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
-{
-    if (event->xany.window != _glfw.x11.helperWindowHandle)
-        return False;
-
-    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;
-}
-
-// Returns whether it is a property event for the specified selection transfer
-//
-static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
-{
-    XEvent* notification = (XEvent*) pointer;
-    return event->type == PropertyNotify &&
-           event->xproperty.state == PropertyNewValue &&
-           event->xproperty.window == notification->xselection.requestor &&
-           event->xproperty.atom == notification->xselection.property;
-}
-
-// 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;
-    if (state & LockMask)
-        mods |= GLFW_MOD_CAPS_LOCK;
-    if (state & Mod2Mask)
-        mods |= GLFW_MOD_NUM_LOCK;
-
-    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.keycodes[scancode];
-}
-
-// 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 = { 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
-        if (!window->x11.transparent)
-        {
-            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
-        if (!window->x11.transparent)
-        {
-            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);
-            // TODO: Validate hostname
-            while (*line != '/')
-                line++;
-        }
-
-        (*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;
-}
-
-// Encode a Unicode code point to a UTF-8 stream
-// Based on cutef8 by Jeff Bezanson (Public Domain)
-//
-static size_t encodeUTF8(char* s, unsigned int ch)
-{
-    size_t count = 0;
-
-    if (ch < 0x80)
-        s[count++] = (char) ch;
-    else if (ch < 0x800)
-    {
-        s[count++] = (ch >> 6) | 0xc0;
-        s[count++] = (ch & 0x3f) | 0x80;
-    }
-    else if (ch < 0x10000)
-    {
-        s[count++] = (ch >> 12) | 0xe0;
-        s[count++] = ((ch >> 6) & 0x3f) | 0x80;
-        s[count++] = (ch & 0x3f) | 0x80;
-    }
-    else if (ch < 0x110000)
-    {
-        s[count++] = (ch >> 18) | 0xf0;
-        s[count++] = ((ch >> 12) & 0x3f) | 0x80;
-        s[count++] = ((ch >> 6) & 0x3f) | 0x80;
-        s[count++] = (ch & 0x3f) | 0x80;
-    }
-
-    return count;
-}
-
-// 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*/
-
-// Convert the specified Latin-1 string to UTF-8
-//
-static char* convertLatin1toUTF8(const char* source)
-{
-    size_t size = 1;
-    const char* sp;
-
-    for (sp = source;  *sp;  sp++)
-        size += (*sp & 0x80) ? 2 : 1;
-
-    char* target = calloc(size, 1);
-    char* tp = target;
-
-    for (sp = source;  *sp;  sp++)
-        tp += encodeUTF8(tp, *sp);
-
-    return target;
-}
-
-// 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.hiddenCursorHandle);
-    }
-}
-
-// Enable XI2 raw mouse motion events
-//
-static void enableRawMouseMotion(_GLFWwindow* window)
-{
-    XIEventMask em;
-    unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
-
-    em.deviceid = XIAllMasterDevices;
-    em.mask_len = sizeof(mask);
-    em.mask = mask;
-    XISetMask(mask, XI_RawMotion);
-
-    XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
-}
-
-// Disable XI2 raw mouse motion events
-//
-static void disableRawMouseMotion(_GLFWwindow* window)
-{
-    XIEventMask em;
-    unsigned char mask[] = { 0 };
-
-    em.deviceid = XIAllMasterDevices;
-    em.mask_len = sizeof(mask);
-    em.mask = mask;
-
-    XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
-}
-
-// Apply disabled cursor mode to a focused window
-//
-static void disableCursor(_GLFWwindow* window)
-{
-    if (window->rawMouseMotion)
-        enableRawMouseMotion(window);
-
-    _glfw.x11.disabledCursorWindow = window;
-    _glfwPlatformGetCursorPos(window,
-                              &_glfw.x11.restoreCursorPosX,
-                              &_glfw.x11.restoreCursorPosY);
-    updateCursorImage(window);
-    _glfwCenterCursorInContentArea(window);
-    XGrabPointer(_glfw.x11.display, window->x11.handle, True,
-                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
-                 GrabModeAsync, GrabModeAsync,
-                 window->x11.handle,
-                 _glfw.x11.hiddenCursorHandle,
-                 CurrentTime);
-}
-
-// Exit disabled cursor mode for the specified window
-//
-static void enableCursor(_GLFWwindow* window)
-{
-    if (window->rawMouseMotion)
-        disableRawMouseMotion(window);
-
-    _glfw.x11.disabledCursorWindow = NULL;
-    XUngrabPointer(_glfw.x11.display, CurrentTime);
-    _glfwPlatformSetCursorPos(window,
-                              _glfw.x11.restoreCursorPosX,
-                              _glfw.x11.restoreCursorPosY);
-    updateCursorImage(window);
-}
-
-// Create the X11 window (and its colormap)
-//
-static GLFWbool createNativeWindow(_GLFWwindow* window,
-                                   const _GLFWwndconfig* wndconfig,
-                                   Visual* visual, int depth)
-{
-    int width = wndconfig->width;
-    int height = wndconfig->height;
-
-    if (wndconfig->scaleToMonitor)
-    {
-        width *= _glfw.x11.contentScaleX;
-        height *= _glfw.x11.contentScaleY;
-    }
-
-    // Create a colormap based on the visual used by the current context
-    window->x11.colormap = XCreateColormap(_glfw.x11.display,
-                                           _glfw.x11.root,
-                                           visual,
-                                           AllocNone);
-
-    window->x11.transparent = _glfwIsVisualTransparentX11(visual);
-
-    XSetWindowAttributes wa = { 0 };
-    wa.colormap = window->x11.colormap;
-    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,   // Position
-                                       width, height,
-                                       0,      // Border width
-                                       depth,  // Color depth
-                                       InputOutput,
-                                       visual,
-                                       CWBorderPixel | CWColormap | CWEventMask,
-                                       &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)
-        _glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
-
-    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;
-                window->x11.maximized = GLFW_TRUE;
-            }
-        }
-
-        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 long 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, width, height);
-
-    // Set ICCCM WM_CLASS property
-    {
-        XClassHint* hint = XAllocClassHint();
-
-        if (strlen(wndconfig->x11.instanceName) &&
-            strlen(wndconfig->x11.className))
-        {
-            hint->res_name = (char*) wndconfig->x11.instanceName;
-            hint->res_class = (char*) wndconfig->x11.className;
-        }
-        else
-        {
-            const char* resourceName = getenv("RESOURCE_NAME");
-            if (resourceName && strlen(resourceName))
-                hint->res_name = (char*) resourceName;
-            else if (strlen(wndconfig->title))
-                hint->res_name = (char*) wndconfig->title;
-            else
-                hint->res_name = (char*) "glfw-application";
-
-            if (strlen(wndconfig->title))
-                hint->res_class = (char*) wndconfig->title;
-            else
-                hint->res_class = (char*) "GLFW-Application";
-        }
-
-        XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
-        XFree(hint);
-    }
-
-    // Announce support for Xdnd (drag and drop)
-    {
-        const Atom version = _GLFW_XDND_VERSION;
-        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);
-    }
-
-    if (window->x11.ic)
-    {
-        unsigned long filter = 0;
-        if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
-            XSelectInput(_glfw.x11.display, window->x11.handle, wa.event_mask | filter);
-    }
-
-    _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;
-    char* selectionString = NULL;
-    const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
-    const int formatCount = sizeof(formats) / sizeof(formats[0]);
-
-    if (request->selection == _glfw.x11.PRIMARY)
-        selectionString = _glfw.x11.primarySelectionString;
-    else
-        selectionString = _glfw.x11.clipboardString;
-
-    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,
-                                 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 *) selectionString,
-                                strlen(selectionString));
-            }
-            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 *) selectionString,
-                            strlen(selectionString));
-
-            return request->property;
-        }
-    }
-
-    // The requested target is not supported
-
-    return None;
-}
-
-static void handleSelectionClear(XEvent* event)
-{
-    if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
-    {
-        free(_glfw.x11.primarySelectionString);
-        _glfw.x11.primarySelectionString = NULL;
-    }
-    else
-    {
-        free(_glfw.x11.clipboardString);
-        _glfw.x11.clipboardString = NULL;
-    }
-}
-
-static void handleSelectionRequest(XEvent* event)
-{
-    const XSelectionRequestEvent* request = &event->xselectionrequest;
-
-    XEvent reply = { SelectionNotify };
-    reply.xselection.property = writeTargetToProperty(request);
-    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 const char* getSelectionString(Atom selection)
-{
-    char** selectionString = NULL;
-    const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
-    const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
-
-    if (selection == _glfw.x11.PRIMARY)
-        selectionString = &_glfw.x11.primarySelectionString;
-    else
-        selectionString = &_glfw.x11.clipboardString;
-
-    if (XGetSelectionOwner(_glfw.x11.display, selection) ==
-        _glfw.x11.helperWindowHandle)
-    {
-        // 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 *selectionString;
-    }
-
-    free(*selectionString);
-    *selectionString = NULL;
-
-    for (size_t i = 0;  i < targetCount;  i++)
-    {
-        char* data;
-        Atom actualType;
-        int actualFormat;
-        unsigned long itemCount, bytesAfter;
-        XEvent notification, dummy;
-
-        XConvertSelection(_glfw.x11.display,
-                          selection,
-                          targets[i],
-                          _glfw.x11.GLFW_SELECTION,
-                          _glfw.x11.helperWindowHandle,
-                          CurrentTime);
-
-        while (!XCheckTypedWindowEvent(_glfw.x11.display,
-                                       _glfw.x11.helperWindowHandle,
-                                       SelectionNotify,
-                                       &notification))
-        {
-            waitForEvent(NULL);
-        }
-
-        if (notification.xselection.property == None)
-            continue;
-
-        XCheckIfEvent(_glfw.x11.display,
-                      &dummy,
-                      isSelPropNewValueNotify,
-                      (XPointer) &notification);
-
-        XGetWindowProperty(_glfw.x11.display,
-                           notification.xselection.requestor,
-                           notification.xselection.property,
-                           0,
-                           LONG_MAX,
-                           True,
-                           AnyPropertyType,
-                           &actualType,
-                           &actualFormat,
-                           &itemCount,
-                           &bytesAfter,
-                           (unsigned char**) &data);
-
-        if (actualType == _glfw.x11.INCR)
-        {
-            size_t size = 1;
-            char* string = NULL;
-
-            for (;;)
-            {
-                while (!XCheckIfEvent(_glfw.x11.display,
-                                      &dummy,
-                                      isSelPropNewValueNotify,
-                                      (XPointer) &notification))
-                {
-                    waitForEvent(NULL);
-                }
-
-                XFree(data);
-                XGetWindowProperty(_glfw.x11.display,
-                                   notification.xselection.requestor,
-                                   notification.xselection.property,
-                                   0,
-                                   LONG_MAX,
-                                   True,
-                                   AnyPropertyType,
-                                   &actualType,
-                                   &actualFormat,
-                                   &itemCount,
-                                   &bytesAfter,
-                                   (unsigned char**) &data);
-
-                if (itemCount)
-                {
-                    size += itemCount;
-                    string = realloc(string, size);
-                    string[size - itemCount - 1] = '\0';
-                    strcat(string, data);
-                }
-
-                if (!itemCount)
-                {
-                    if (targets[i] == XA_STRING)
-                    {
-                        *selectionString = convertLatin1toUTF8(string);
-                        free(string);
-                    }
-                    else
-                        *selectionString = string;
-
-                    break;
-                }
-            }
-        }
-        else if (actualType == targets[i])
-        {
-            if (targets[i] == XA_STRING)
-                *selectionString = convertLatin1toUTF8(data);
-            else
-                *selectionString = _glfw_strdup(data);
-        }
-
-        XFree(data);
-
-        if (*selectionString)
-            break;
-    }
-
-    if (!*selectionString)
-    {
-        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
-                        "X11: Failed to convert selection to string");
-    }
-
-    return *selectionString;
-}
-
-// Make the specified window and its video mode active on its monitor
-//
-static void acquireMonitor(_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);
-    }
-
-    if (!window->monitor->window)
-        _glfw.x11.saver.count++;
-
-    _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);
-    }
-
-    _glfwInputMonitorWindow(window->monitor, window);
-}
-
-// Remove the window and restore the original video mode
-//
-static void releaseMonitor(_GLFWwindow* window)
-{
-    if (window->monitor->window != window)
-        return;
-
-    _glfwInputMonitorWindow(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);
-    }
-}
-
-// Process the specified X event
-//
-static void processEvent(XEvent *event)
-{
-    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);
-            _glfwPollMonitorsX11();
-            return;
-        }
-    }
-
-    if (_glfw.x11.xkb.available)
-    {
-        if (event->type == _glfw.x11.xkb.eventBase + XkbEventCode)
-        {
-            if (((XkbEvent*) event)->any.xkb_type == XkbStateNotify &&
-                (((XkbEvent*) event)->state.changed & XkbGroupStateMask))
-            {
-                _glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;
-            }
-        }
-    }
-
-    if (event->type == GenericEvent)
-    {
-        if (_glfw.x11.xi.available)
-        {
-            _GLFWwindow* window = _glfw.x11.disabledCursorWindow;
-
-            if (window &&
-                window->rawMouseMotion &&
-                event->xcookie.extension == _glfw.x11.xi.majorOpcode &&
-                XGetEventData(_glfw.x11.display, &event->xcookie) &&
-                event->xcookie.evtype == XI_RawMotion)
-            {
-                XIRawEvent* re = event->xcookie.data;
-                if (re->valuators.mask_len)
-                {
-                    const double* values = re->raw_values;
-                    double xpos = window->virtualCursorPosX;
-                    double ypos = window->virtualCursorPosY;
-
-                    if (XIMaskIsSet(re->valuators.mask, 0))
-                    {
-                        xpos += *values;
-                        values++;
-                    }
-
-                    if (XIMaskIsSet(re->valuators.mask, 1))
-                        ypos += *values;
-
-                    _glfwInputCursorPos(window, xpos, ypos);
-                }
-            }
-
-            XFreeEventData(_glfw.x11.display, &event->xcookie);
-        }
-
-        return;
-    }
-
-    if (event->type == SelectionClear)
-    {
-        handleSelectionClear(event);
-        return;
-    }
-    else if (event->type == SelectionRequest)
-    {
-        handleSelectionRequest(event);
-        return;
-    }
-
-    _GLFWwindow* window = NULL;
-    if (XFindContext(_glfw.x11.display,
-                     event->xany.window,
-                     _glfw.x11.context,
-                     (XPointer*) &window) != 0)
-    {
-        // This is an event for a window that has already been destroyed
-        return;
-    }
-
-    switch (event->type)
-    {
-        case CreateNotify:
-        {
-            window->x11.parent = event->xcreatewindow.parent;
-            return;
-        }
-
-        case ReparentNotify:
-        {
-            window->x11.parent = event->xreparent.parent;
-            return;
-        }
-
-        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
-                //       These have the same timestamp as the original event
-                //       Corresponding release events are filtered out
-                //       implicitly by the GLFW key repeat logic
-                if (window->x11.lastKeyTime < event->xkey.time)
-                {
-                    if (keycode)
-                        _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
-
-                    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:
-        {
-            // XEnterWindowEvent is XCrossingEvent
-            const int x = event->xcrossing.x;
-            const int y = event->xcrossing.y;
-
-            // 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)
-                updateCursorImage(window);
-
-            _glfwInputCursorEnter(window, GLFW_TRUE);
-            _glfwInputCursorPos(window, x, y);
-
-            window->x11.lastCursorPosX = x;
-            window->x11.lastCursorPosY = y;
-            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;
-                    if (window->rawMouseMotion)
-                        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;
-            }
-
-            int xpos = event->xconfigure.x;
-            int ypos = event->xconfigure.y;
-
-            // NOTE: ConfigureNotify events from the server are in local
-            //       coordinates, so if we are reparented we need to translate
-            //       the position into root (screen) coordinates
-            if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
-            {
-                Window dummy;
-                XTranslateCoordinates(_glfw.x11.display,
-                                      window->x11.parent,
-                                      _glfw.x11.root,
-                                      xpos, ypos,
-                                      &xpos, &ypos,
-                                      &dummy);
-            }
-
-            if (xpos != window->x11.xpos || ypos != window->x11.ypos)
-            {
-                _glfwInputWindowPos(window, xpos, ypos);
-                window->x11.xpos = xpos;
-                window->x11.ypos = ypos;
-            }
-
-            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
-                unsigned long i, count;
-                Atom* formats = NULL;
-                const GLFWbool list = event->xclient.data.l[1] & 1;
-
-                _glfw.x11.xdnd.source  = event->xclient.data.l[0];
-                _glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
-                _glfw.x11.xdnd.format  = None;
-
-                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
-                    return;
-
-                if (list)
-                {
-                    count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
-                                                      _glfw.x11.XdndTypeList,
-                                                      XA_ATOM,
-                                                      (unsigned char**) &formats);
-                }
-                else
-                {
-                    count = 3;
-                    formats = (Atom*) event->xclient.data.l + 2;
-                }
-
-                for (i = 0;  i < count;  i++)
-                {
-                    if (formats[i] == _glfw.x11.text_uri_list)
-                    {
-                        _glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
-                        break;
-                    }
-                }
-
-                if (list && formats)
-                    XFree(formats);
-            }
-            else if (event->xclient.message_type == _glfw.x11.XdndDrop)
-            {
-                // The drag operation has finished by dropping on the window
-                Time time = CurrentTime;
-
-                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
-                    return;
-
-                if (_glfw.x11.xdnd.format)
-                {
-                    if (_glfw.x11.xdnd.version >= 1)
-                        time = event->xclient.data.l[2];
-
-                    // Request the chosen format from the source window
-                    XConvertSelection(_glfw.x11.display,
-                                      _glfw.x11.XdndSelection,
-                                      _glfw.x11.xdnd.format,
-                                      _glfw.x11.XdndSelection,
-                                      window->x11.handle,
-                                      time);
-                }
-                else if (_glfw.x11.xdnd.version >= 2)
-                {
-                    XEvent reply = { 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] = 0; // The drag was rejected
-                    reply.xclient.data.l[2] = None;
-
-                    XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
-                               False, NoEventMask, &reply);
-                    XFlush(_glfw.x11.display);
-                }
-            }
-            else if (event->xclient.message_type == _glfw.x11.XdndPosition)
-            {
-                // The drag operation has moved over the window
-                const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
-                const int yabs = (event->xclient.data.l[2]) & 0xffff;
-                Window dummy;
-                int xpos, ypos;
-
-                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
-                    return;
-
-                XTranslateCoordinates(_glfw.x11.display,
-                                      _glfw.x11.root,
-                                      window->x11.handle,
-                                      xabs, yabs,
-                                      &xpos, &ypos,
-                                      &dummy);
-
-                _glfwInputCursorPos(window, xpos, ypos);
-
-                XEvent reply = { ClientMessage };
-                reply.xclient.window = _glfw.x11.xdnd.source;
-                reply.xclient.message_type = _glfw.x11.XdndStatus;
-                reply.xclient.format = 32;
-                reply.xclient.data.l[0] = window->x11.handle;
-                reply.xclient.data.l[2] = 0; // Specify an empty rectangle
-                reply.xclient.data.l[3] = 0;
-
-                if (_glfw.x11.xdnd.format)
-                {
-                    // Reply that we are ready to copy the dragged data
-                    reply.xclient.data.l[1] = 1; // Accept with no rectangle
-                    if (_glfw.x11.xdnd.version >= 2)
-                        reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
-                }
-
-                XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
-                           False, NoEventMask, &reply);
-                XFlush(_glfw.x11.display);
-            }
-
-            return;
-        }
-
-        case SelectionNotify:
-        {
-            if (event->xselection.property == _glfw.x11.XdndSelection)
-            {
-                // The converted data from the drag operation has arrived
-                char* data;
-                const unsigned long 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);
-                }
-
-                if (data)
-                    XFree(data);
-
-                if (_glfw.x11.xdnd.version >= 2)
-                {
-                    XEvent reply = { 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;
-
-                    XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
-                               False, NoEventMask, &reply);
-                    XFlush(_glfw.x11.display);
-                }
-            }
-
-            return;
-        }
-
-        case FocusIn:
-        {
-            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->cursorMode == GLFW_CURSOR_DISABLED)
-                disableCursor(window);
-
-            if (window->x11.ic)
-                XSetICFocus(window->x11.ic);
-
-            _glfwInputWindowFocus(window, GLFW_TRUE);
-            return;
-        }
-
-        case FocusOut:
-        {
-            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->cursorMode == GLFW_CURSOR_DISABLED)
-                enableCursor(window);
-
-            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.state != PropertyNewValue)
-                return;
-
-            if (event->xproperty.atom == _glfw.x11.WM_STATE)
-            {
-                const int state = getWindowState(window);
-                if (state != IconicState && state != NormalState)
-                    return;
-
-                const GLFWbool iconified = (state == IconicState);
-                if (window->x11.iconified != iconified)
-                {
-                    if (window->monitor)
-                    {
-                        if (iconified)
-                            releaseMonitor(window);
-                        else
-                            acquireMonitor(window);
-                    }
-
-                    window->x11.iconified = iconified;
-                    _glfwInputWindowIconify(window, iconified);
-                }
-            }
-            else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
-            {
-                const GLFWbool maximized = _glfwPlatformWindowMaximized(window);
-                if (window->x11.maximized != maximized)
-                {
-                    window->x11.maximized = maximized;
-                    _glfwInputWindowMaximize(window, maximized);
-                }
-            }
-
-            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);
-
-    return itemCount;
-}
-
-GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
-{
-    if (!_glfw.x11.xrender.available)
-        return GLFW_FALSE;
-
-    XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
-    return pf && pf->direct.alphaMask;
-}
-
-// Push contents of our selection to clipboard manager
-//
-void _glfwPushSelectionToManagerX11(void)
-{
-    XConvertSelection(_glfw.x11.display,
-                      _glfw.x11.CLIPBOARD_MANAGER,
-                      _glfw.x11.SAVE_TARGETS,
-                      None,
-                      _glfw.x11.helperWindowHandle,
-                      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);
-    }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       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)
-    {
-        if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
-        {
-            if (!_glfwInitGLX())
-                return GLFW_FALSE;
-            if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
-        {
-            if (!_glfwInitEGL())
-                return GLFW_FALSE;
-            if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwInitOSMesa())
-                return GLFW_FALSE;
-        }
-    }
-
-    if (ctxconfig->client == GLFW_NO_API ||
-        ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-    {
-        visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
-        depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
-    }
-
-    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 (ctxconfig->source == GLFW_EGL_CONTEXT_API)
-        {
-            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
-        {
-            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
-                return GLFW_FALSE;
-        }
-    }
-
-    if (window->monitor)
-    {
-        _glfwPlatformShowWindow(window);
-        updateWindowMode(window);
-        acquireMonitor(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)
-    {
-        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 _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
-                                        float* xscale, float* yscale)
-{
-    if (xscale)
-        *xscale = _glfw.x11.contentScaleX;
-    if (yscale)
-        *yscale = _glfw.x11.contentScaleY;
-}
-
-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)
-    {
-        return;
-    }
-
-    if (_glfwPlatformWindowVisible(window))
-    {
-        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);
-    }
-    else
-    {
-        Atom* states = NULL;
-        unsigned long count =
-            _glfwGetWindowPropertyX11(window->x11.handle,
-                                      _glfw.x11.NET_WM_STATE,
-                                      XA_ATOM,
-                                      (unsigned char**) &states);
-
-        // NOTE: We don't check for failure as this property may not exist yet
-        //       and that's fine (and we'll create it implicitly with append)
-
-        Atom missing[2] =
-        {
-            _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
-            _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
-        };
-        unsigned long missingCount = 2;
-
-        for (unsigned long i = 0;  i < count;  i++)
-        {
-            for (unsigned long j = 0;  j < missingCount;  j++)
-            {
-                if (states[i] == missing[j])
-                {
-                    missing[j] = missing[missingCount - 1];
-                    missingCount--;
-                }
-            }
-        }
-
-        if (states)
-            XFree(states);
-
-        if (!missingCount)
-            return;
-
-        XChangeProperty(_glfw.x11.display, window->x11.handle,
-                        _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
-                        PropModeAppend,
-                        (unsigned char*) missing,
-                        missingCount);
-    }
-
-    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 _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
-{
-    if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION)
-        return;
-
-    sendEventToWM(window,
-                  _glfw.x11.NET_WM_STATE,
-                  _NET_WM_STATE_ADD,
-                  _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION,
-                  0, 1, 0);
-}
-
-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
-        {
-            if (!window->resizable)
-                updateNormalHints(window, width, height);
-
-            XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
-                              xpos, ypos, width, height);
-        }
-
-        XFlush(_glfw.x11.display);
-        return;
-    }
-
-    if (window->monitor)
-        releaseMonitor(window);
-
-    _glfwInputWindowMonitor(window, monitor);
-    updateNormalHints(window, width, height);
-
-    if (window->monitor)
-    {
-        if (!_glfwPlatformWindowVisible(window))
-        {
-            XMapRaised(_glfw.x11.display, window->x11.handle);
-            waitForVisibilityNotify(window);
-        }
-
-        updateWindowMode(window);
-        acquireMonitor(window);
-    }
-    else
-    {
-        updateWindowMode(window);
-        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;
-
-    if (!_glfw.x11.NET_WM_STATE ||
-        !_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
-        !_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
-    {
-        return maximized;
-    }
-
-    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;
-        }
-    }
-
-    if (states)
-        XFree(states);
-
-    return maximized;
-}
-
-int _glfwPlatformWindowHovered(_GLFWwindow* window)
-{
-    Window w = _glfw.x11.root;
-    while (w)
-    {
-        Window root;
-        int rootX, rootY, childX, childY;
-        unsigned int mask;
-
-        if (!XQueryPointer(_glfw.x11.display, w,
-                           &root, &w, &rootX, &rootY, &childX, &childY, &mask))
-        {
-            return GLFW_FALSE;
-        }
-
-        if (w == window->x11.handle)
-            return GLFW_TRUE;
-    }
-
-    return GLFW_FALSE;
-}
-
-int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
-{
-    if (!window->x11.transparent)
-        return GLFW_FALSE;
-
-    return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
-}
-
-void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
-{
-    int width, height;
-    _glfwPlatformGetWindowSize(window, &width, &height);
-    updateNormalHints(window, width, height);
-}
-
-void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
-{
-    struct
-    {
-        unsigned long flags;
-        unsigned long functions;
-        unsigned long decorations;
-        long input_mode;
-        unsigned long status;
-    } hints = {0};
-
-    hints.flags = MWM_HINTS_DECORATIONS;
-    hints.decorations = enabled ? MWM_DECOR_ALL : 0;
-
-    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));
-}
-
-void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
-{
-    if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
-        return;
-
-    if (_glfwPlatformWindowVisible(window))
-    {
-        const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
-        sendEventToWM(window,
-                      _glfw.x11.NET_WM_STATE,
-                      action,
-                      _glfw.x11.NET_WM_STATE_ABOVE,
-                      0, 1, 0);
-    }
-    else
-    {
-        Atom* states = NULL;
-        unsigned long i, count;
-
-        count = _glfwGetWindowPropertyX11(window->x11.handle,
-                                          _glfw.x11.NET_WM_STATE,
-                                          XA_ATOM,
-                                          (unsigned char**) &states);
-
-        // NOTE: We don't check for failure as this property may not exist yet
-        //       and that's fine (and we'll create it implicitly with append)
-
-        if (enabled)
-        {
-            for (i = 0;  i < count;  i++)
-            {
-                if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
-                    break;
-            }
-
-            if (i < count)
-                return;
-
-            XChangeProperty(_glfw.x11.display, window->x11.handle,
-                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
-                            PropModeAppend,
-                            (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
-                            1);
-        }
-        else if (states)
-        {
-            for (i = 0;  i < count;  i++)
-            {
-                if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
-                    break;
-            }
-
-            if (i == count)
-                return;
-
-            states[i] = states[count - 1];
-            count--;
-
-            XChangeProperty(_glfw.x11.display, window->x11.handle,
-                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
-                            PropModeReplace, (unsigned char*) states, count);
-        }
-
-        if (states)
-            XFree(states);
-    }
-
-    XFlush(_glfw.x11.display);
-}
-
-float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
-{
-    float opacity = 1.f;
-
-    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx))
-    {
-        CARD32* value = NULL;
-
-        if (_glfwGetWindowPropertyX11(window->x11.handle,
-                                      _glfw.x11.NET_WM_WINDOW_OPACITY,
-                                      XA_CARDINAL,
-                                      (unsigned char**) &value))
-        {
-            opacity = (float) (*value / (double) 0xffffffffu);
-        }
-
-        if (value)
-            XFree(value);
-    }
-
-    return opacity;
-}
-
-void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
-{
-    const CARD32 value = (CARD32) (0xffffffffu * (double) opacity);
-    XChangeProperty(_glfw.x11.display, window->x11.handle,
-                    _glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
-                    PropModeReplace, (unsigned char*) &value, 1);
-}
-
-void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
-{
-    if (!_glfw.x11.xi.available)
-        return;
-
-    if (_glfw.x11.disabledCursorWindow != window)
-        return;
-
-    if (enabled)
-        enableRawMouseMotion(window);
-    else
-        disableRawMouseMotion(window);
-}
-
-GLFWbool _glfwPlatformRawMouseMotionSupported(void)
-{
-    return _glfw.x11.xi.available;
-}
-
-void _glfwPlatformPollEvents(void)
-{
-    _GLFWwindow* window;
-
-#if defined(__linux__)
-    _glfwDetectJoystickConnectionLinux();
-#endif
-    XPending(_glfw.x11.display);
-
-    while (XQLength(_glfw.x11.display))
-    {
-        XEvent event;
-        XNextEvent(_glfw.x11.display, &event);
-        processEvent(&event);
-    }
-
-    window = _glfw.x11.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 MotionNotify
-        if (window->x11.lastCursorPosX != width / 2 ||
-            window->x11.lastCursorPosY != height / 2)
-        {
-            _glfwPlatformSetCursorPos(window, width / 2, height / 2);
-        }
-    }
-
-    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 = { ClientMessage };
-    event.xclient.window = _glfw.x11.helperWindowHandle;
-    event.xclient.format = 32; // Data is 32-bit longs
-    event.xclient.message_type = _glfw.x11.NULL_;
-
-    XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, 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)
-    {
-        if (_glfwPlatformWindowFocused(window))
-            disableCursor(window);
-    }
-    else if (_glfw.x11.disabledCursorWindow == window)
-        enableCursor(window);
-    else
-        updateCursorImage(window);
-
-    XFlush(_glfw.x11.display);
-}
-
-const char* _glfwPlatformGetScancodeName(int scancode)
-{
-    if (!_glfw.x11.xkb.available)
-        return NULL;
-
-    const int key = _glfw.x11.keycodes[scancode];
-    const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
-                                             scancode, _glfw.x11.xkb.group, 0);
-    if (keysym == NoSymbol)
-        return NULL;
-
-    const long ch = _glfwKeySym2Unicode(keysym);
-    if (ch == -1)
-        return NULL;
-
-    const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch);
-    if (count == 0)
-        return NULL;
-
-    _glfw.x11.keynames[key][count] = '\0';
-    return _glfw.x11.keynames[key];
-}
-
-int _glfwPlatformGetKeyScancode(int key)
-{
-    return _glfw.x11.scancodes[key];
-}
-
-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)
-{
-    int native = 0;
-
-    if (shape == GLFW_ARROW_CURSOR)
-        native = XC_left_ptr;
-    else if (shape == GLFW_IBEAM_CURSOR)
-        native = XC_xterm;
-    else if (shape == GLFW_CROSSHAIR_CURSOR)
-        native = XC_crosshair;
-    else if (shape == GLFW_HAND_CURSOR)
-        native = XC_hand2;
-    else if (shape == GLFW_HRESIZE_CURSOR)
-        native = XC_sb_h_double_arrow;
-    else if (shape == GLFW_VRESIZE_CURSOR)
-        native = XC_sb_v_double_arrow;
-    else
-        return GLFW_FALSE;
-
-    cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
-    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(const char* string)
-{
-    free(_glfw.x11.clipboardString);
-    _glfw.x11.clipboardString = _glfw_strdup(string);
-
-    XSetSelectionOwner(_glfw.x11.display,
-                       _glfw.x11.CLIPBOARD,
-                       _glfw.x11.helperWindowHandle,
-                       CurrentTime);
-
-    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
-        _glfw.x11.helperWindowHandle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "X11: Failed to become owner of clipboard selection");
-    }
-}
-
-const char* _glfwPlatformGetClipboardString(void)
-{
-    return getSelectionString(_glfw.x11.CLIPBOARD);
-}
-
-void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
-{
-    if (!_glfw.vk.KHR_surface)
-        return;
-
-    if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)
-    {
-        if (!_glfw.vk.KHR_xlib_surface)
-            return;
-    }
-
-    extensions[0] = "VK_KHR_surface";
-
-    // NOTE: VK_KHR_xcb_surface is preferred due to some early ICDs exposing but
-    //       not correctly implementing VK_KHR_xlib_surface
-    if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
-        extensions[1] = "VK_KHR_xcb_surface";
-    else
-        extensions[1] = "VK_KHR_xlib_surface";
-}
-
-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 = 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 = 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 native API                       //////
-//////////////////////////////////////////////////////////////////////////
-
-GLFWAPI Display* glfwGetX11Display(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return _glfw.x11.display;
-}
-
-GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
-{
-    _GLFWwindow* window = (_GLFWwindow*) handle;
-    _GLFW_REQUIRE_INIT_OR_RETURN(None);
-    return window->x11.handle;
-}
-
-GLFWAPI void glfwSetX11SelectionString(const char* string)
-{
-    _GLFW_REQUIRE_INIT();
-
-    free(_glfw.x11.primarySelectionString);
-    _glfw.x11.primarySelectionString = _glfw_strdup(string);
-
-    XSetSelectionOwner(_glfw.x11.display,
-                       _glfw.x11.PRIMARY,
-                       _glfw.x11.helperWindowHandle,
-                       CurrentTime);
-
-    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
-        _glfw.x11.helperWindowHandle)
-    {
-        _glfwInputError(GLFW_PLATFORM_ERROR,
-                        "X11: Failed to become owner of primary selection");
-    }
-}
-
-GLFWAPI const char* glfwGetX11SelectionString(void)
-{
-    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
-    return getSelectionString(_glfw.x11.PRIMARY);
-}
-
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#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
+
+// Motif WM hints flags
+#define MWM_HINTS_DECORATIONS   2
+#define MWM_DECOR_ALL           1
+
+#define _GLFW_XDND_VERSION 5
+
+
+// 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;
+
+#if defined(__linux__)
+    if (_glfw.linjs.inotify > fd)
+        count = _glfw.linjs.inotify + 1;
+#endif
+    for (;;)
+    {
+        FD_ZERO(&fds);
+        FD_SET(fd, &fds);
+#if defined(__linux__)
+        if (_glfw.linjs.inotify > 0)
+            FD_SET(_glfw.linjs.inotify, &fds);
+#endif
+
+        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;
+    }
+
+    if (state)
+        XFree(state);
+
+    return result;
+}
+
+// Returns whether the event is a selection event
+//
+static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
+{
+    if (event->xany.window != _glfw.x11.helperWindowHandle)
+        return False;
+
+    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;
+}
+
+// Returns whether it is a property event for the specified selection transfer
+//
+static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer)
+{
+    XEvent* notification = (XEvent*) pointer;
+    return event->type == PropertyNotify &&
+           event->xproperty.state == PropertyNewValue &&
+           event->xproperty.window == notification->xselection.requestor &&
+           event->xproperty.atom == notification->xselection.property;
+}
+
+// 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;
+    if (state & LockMask)
+        mods |= GLFW_MOD_CAPS_LOCK;
+    if (state & Mod2Mask)
+        mods |= GLFW_MOD_NUM_LOCK;
+
+    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.keycodes[scancode];
+}
+
+// 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 = { 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
+        if (!window->x11.transparent)
+        {
+            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
+        if (!window->x11.transparent)
+        {
+            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);
+            // TODO: Validate hostname
+            while (*line != '/')
+                line++;
+        }
+
+        (*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;
+}
+
+// Encode a Unicode code point to a UTF-8 stream
+// Based on cutef8 by Jeff Bezanson (Public Domain)
+//
+static size_t encodeUTF8(char* s, unsigned int ch)
+{
+    size_t count = 0;
+
+    if (ch < 0x80)
+        s[count++] = (char) ch;
+    else if (ch < 0x800)
+    {
+        s[count++] = (ch >> 6) | 0xc0;
+        s[count++] = (ch & 0x3f) | 0x80;
+    }
+    else if (ch < 0x10000)
+    {
+        s[count++] = (ch >> 12) | 0xe0;
+        s[count++] = ((ch >> 6) & 0x3f) | 0x80;
+        s[count++] = (ch & 0x3f) | 0x80;
+    }
+    else if (ch < 0x110000)
+    {
+        s[count++] = (ch >> 18) | 0xf0;
+        s[count++] = ((ch >> 12) & 0x3f) | 0x80;
+        s[count++] = ((ch >> 6) & 0x3f) | 0x80;
+        s[count++] = (ch & 0x3f) | 0x80;
+    }
+
+    return count;
+}
+
+// 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*/
+
+// Convert the specified Latin-1 string to UTF-8
+//
+static char* convertLatin1toUTF8(const char* source)
+{
+    size_t size = 1;
+    const char* sp;
+
+    for (sp = source;  *sp;  sp++)
+        size += (*sp & 0x80) ? 2 : 1;
+
+    char* target = calloc(size, 1);
+    char* tp = target;
+
+    for (sp = source;  *sp;  sp++)
+        tp += encodeUTF8(tp, *sp);
+
+    return target;
+}
+
+// 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.hiddenCursorHandle);
+    }
+}
+
+// Enable XI2 raw mouse motion events
+//
+static void enableRawMouseMotion(_GLFWwindow* window)
+{
+    XIEventMask em;
+    unsigned char mask[XIMaskLen(XI_RawMotion)] = { 0 };
+
+    em.deviceid = XIAllMasterDevices;
+    em.mask_len = sizeof(mask);
+    em.mask = mask;
+    XISetMask(mask, XI_RawMotion);
+
+    XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
+}
+
+// Disable XI2 raw mouse motion events
+//
+static void disableRawMouseMotion(_GLFWwindow* window)
+{
+    XIEventMask em;
+    unsigned char mask[] = { 0 };
+
+    em.deviceid = XIAllMasterDevices;
+    em.mask_len = sizeof(mask);
+    em.mask = mask;
+
+    XISelectEvents(_glfw.x11.display, _glfw.x11.root, &em, 1);
+}
+
+// Apply disabled cursor mode to a focused window
+//
+static void disableCursor(_GLFWwindow* window)
+{
+    if (window->rawMouseMotion)
+        enableRawMouseMotion(window);
+
+    _glfw.x11.disabledCursorWindow = window;
+    _glfwPlatformGetCursorPos(window,
+                              &_glfw.x11.restoreCursorPosX,
+                              &_glfw.x11.restoreCursorPosY);
+    updateCursorImage(window);
+    _glfwCenterCursorInContentArea(window);
+    XGrabPointer(_glfw.x11.display, window->x11.handle, True,
+                 ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+                 GrabModeAsync, GrabModeAsync,
+                 window->x11.handle,
+                 _glfw.x11.hiddenCursorHandle,
+                 CurrentTime);
+}
+
+// Exit disabled cursor mode for the specified window
+//
+static void enableCursor(_GLFWwindow* window)
+{
+    if (window->rawMouseMotion)
+        disableRawMouseMotion(window);
+
+    _glfw.x11.disabledCursorWindow = NULL;
+    XUngrabPointer(_glfw.x11.display, CurrentTime);
+    _glfwPlatformSetCursorPos(window,
+                              _glfw.x11.restoreCursorPosX,
+                              _glfw.x11.restoreCursorPosY);
+    updateCursorImage(window);
+}
+
+// Create the X11 window (and its colormap)
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+                                   const _GLFWwndconfig* wndconfig,
+                                   Visual* visual, int depth)
+{
+    int width = wndconfig->width;
+    int height = wndconfig->height;
+
+    if (wndconfig->scaleToMonitor)
+    {
+        width *= _glfw.x11.contentScaleX;
+        height *= _glfw.x11.contentScaleY;
+    }
+
+    // Create a colormap based on the visual used by the current context
+    window->x11.colormap = XCreateColormap(_glfw.x11.display,
+                                           _glfw.x11.root,
+                                           visual,
+                                           AllocNone);
+
+    window->x11.transparent = _glfwIsVisualTransparentX11(visual);
+
+    XSetWindowAttributes wa = { 0 };
+    wa.colormap = window->x11.colormap;
+    wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+                    PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+                    ExposureMask | FocusChangeMask | VisibilityChangeMask |
+                    EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
+
+    _glfwGrabErrorHandlerX11();
+
+    window->x11.parent = _glfw.x11.root;
+    window->x11.handle = XCreateWindow(_glfw.x11.display,
+                                       _glfw.x11.root,
+                                       0, 0,   // Position
+                                       width, height,
+                                       0,      // Border width
+                                       depth,  // Color depth
+                                       InputOutput,
+                                       visual,
+                                       CWBorderPixel | CWColormap | CWEventMask,
+                                       &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)
+        _glfwPlatformSetWindowDecorated(window, GLFW_FALSE);
+
+    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;
+                window->x11.maximized = GLFW_TRUE;
+            }
+        }
+
+        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 long 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, width, height);
+
+    // Set ICCCM WM_CLASS property
+    {
+        XClassHint* hint = XAllocClassHint();
+
+        if (strlen(wndconfig->x11.instanceName) &&
+            strlen(wndconfig->x11.className))
+        {
+            hint->res_name = (char*) wndconfig->x11.instanceName;
+            hint->res_class = (char*) wndconfig->x11.className;
+        }
+        else
+        {
+            const char* resourceName = getenv("RESOURCE_NAME");
+            if (resourceName && strlen(resourceName))
+                hint->res_name = (char*) resourceName;
+            else if (strlen(wndconfig->title))
+                hint->res_name = (char*) wndconfig->title;
+            else
+                hint->res_name = (char*) "glfw-application";
+
+            if (strlen(wndconfig->title))
+                hint->res_class = (char*) wndconfig->title;
+            else
+                hint->res_class = (char*) "GLFW-Application";
+        }
+
+        XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
+        XFree(hint);
+    }
+
+    // Announce support for Xdnd (drag and drop)
+    {
+        const Atom version = _GLFW_XDND_VERSION;
+        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);
+    }
+
+    if (window->x11.ic)
+    {
+        unsigned long filter = 0;
+        if (XGetICValues(window->x11.ic, XNFilterEvents, &filter, NULL) == NULL)
+            XSelectInput(_glfw.x11.display, window->x11.handle, wa.event_mask | filter);
+    }
+
+    _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;
+    char* selectionString = NULL;
+    const Atom formats[] = { _glfw.x11.UTF8_STRING, XA_STRING };
+    const int formatCount = sizeof(formats) / sizeof(formats[0]);
+
+    if (request->selection == _glfw.x11.PRIMARY)
+        selectionString = _glfw.x11.primarySelectionString;
+    else
+        selectionString = _glfw.x11.clipboardString;
+
+    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,
+                                 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 *) selectionString,
+                                strlen(selectionString));
+            }
+            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 *) selectionString,
+                            strlen(selectionString));
+
+            return request->property;
+        }
+    }
+
+    // The requested target is not supported
+
+    return None;
+}
+
+static void handleSelectionClear(XEvent* event)
+{
+    if (event->xselectionclear.selection == _glfw.x11.PRIMARY)
+    {
+        free(_glfw.x11.primarySelectionString);
+        _glfw.x11.primarySelectionString = NULL;
+    }
+    else
+    {
+        free(_glfw.x11.clipboardString);
+        _glfw.x11.clipboardString = NULL;
+    }
+}
+
+static void handleSelectionRequest(XEvent* event)
+{
+    const XSelectionRequestEvent* request = &event->xselectionrequest;
+
+    XEvent reply = { SelectionNotify };
+    reply.xselection.property = writeTargetToProperty(request);
+    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 const char* getSelectionString(Atom selection)
+{
+    char** selectionString = NULL;
+    const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
+    const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
+
+    if (selection == _glfw.x11.PRIMARY)
+        selectionString = &_glfw.x11.primarySelectionString;
+    else
+        selectionString = &_glfw.x11.clipboardString;
+
+    if (XGetSelectionOwner(_glfw.x11.display, selection) ==
+        _glfw.x11.helperWindowHandle)
+    {
+        // 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 *selectionString;
+    }
+
+    free(*selectionString);
+    *selectionString = NULL;
+
+    for (size_t i = 0;  i < targetCount;  i++)
+    {
+        char* data;
+        Atom actualType;
+        int actualFormat;
+        unsigned long itemCount, bytesAfter;
+        XEvent notification, dummy;
+
+        XConvertSelection(_glfw.x11.display,
+                          selection,
+                          targets[i],
+                          _glfw.x11.GLFW_SELECTION,
+                          _glfw.x11.helperWindowHandle,
+                          CurrentTime);
+
+        while (!XCheckTypedWindowEvent(_glfw.x11.display,
+                                       _glfw.x11.helperWindowHandle,
+                                       SelectionNotify,
+                                       &notification))
+        {
+            waitForEvent(NULL);
+        }
+
+        if (notification.xselection.property == None)
+            continue;
+
+        XCheckIfEvent(_glfw.x11.display,
+                      &dummy,
+                      isSelPropNewValueNotify,
+                      (XPointer) &notification);
+
+        XGetWindowProperty(_glfw.x11.display,
+                           notification.xselection.requestor,
+                           notification.xselection.property,
+                           0,
+                           LONG_MAX,
+                           True,
+                           AnyPropertyType,
+                           &actualType,
+                           &actualFormat,
+                           &itemCount,
+                           &bytesAfter,
+                           (unsigned char**) &data);
+
+        if (actualType == _glfw.x11.INCR)
+        {
+            size_t size = 1;
+            char* string = NULL;
+
+            for (;;)
+            {
+                while (!XCheckIfEvent(_glfw.x11.display,
+                                      &dummy,
+                                      isSelPropNewValueNotify,
+                                      (XPointer) &notification))
+                {
+                    waitForEvent(NULL);
+                }
+
+                XFree(data);
+                XGetWindowProperty(_glfw.x11.display,
+                                   notification.xselection.requestor,
+                                   notification.xselection.property,
+                                   0,
+                                   LONG_MAX,
+                                   True,
+                                   AnyPropertyType,
+                                   &actualType,
+                                   &actualFormat,
+                                   &itemCount,
+                                   &bytesAfter,
+                                   (unsigned char**) &data);
+
+                if (itemCount)
+                {
+                    size += itemCount;
+                    string = realloc(string, size);
+                    string[size - itemCount - 1] = '\0';
+                    strcat(string, data);
+                }
+
+                if (!itemCount)
+                {
+                    if (targets[i] == XA_STRING)
+                    {
+                        *selectionString = convertLatin1toUTF8(string);
+                        free(string);
+                    }
+                    else
+                        *selectionString = string;
+
+                    break;
+                }
+            }
+        }
+        else if (actualType == targets[i])
+        {
+            if (targets[i] == XA_STRING)
+                *selectionString = convertLatin1toUTF8(data);
+            else
+                *selectionString = _glfw_strdup(data);
+        }
+
+        XFree(data);
+
+        if (*selectionString)
+            break;
+    }
+
+    if (!*selectionString)
+    {
+        _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+                        "X11: Failed to convert selection to string");
+    }
+
+    return *selectionString;
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static void acquireMonitor(_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);
+    }
+
+    if (!window->monitor->window)
+        _glfw.x11.saver.count++;
+
+    _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);
+    }
+
+    _glfwInputMonitorWindow(window->monitor, window);
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+    if (window->monitor->window != window)
+        return;
+
+    _glfwInputMonitorWindow(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);
+    }
+}
+
+// Process the specified X event
+//
+static void processEvent(XEvent *event)
+{
+    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);
+            _glfwPollMonitorsX11();
+            return;
+        }
+    }
+
+    if (_glfw.x11.xkb.available)
+    {
+        if (event->type == _glfw.x11.xkb.eventBase + XkbEventCode)
+        {
+            if (((XkbEvent*) event)->any.xkb_type == XkbStateNotify &&
+                (((XkbEvent*) event)->state.changed & XkbGroupStateMask))
+            {
+                _glfw.x11.xkb.group = ((XkbEvent*) event)->state.group;
+            }
+        }
+    }
+
+    if (event->type == GenericEvent)
+    {
+        if (_glfw.x11.xi.available)
+        {
+            _GLFWwindow* window = _glfw.x11.disabledCursorWindow;
+
+            if (window &&
+                window->rawMouseMotion &&
+                event->xcookie.extension == _glfw.x11.xi.majorOpcode &&
+                XGetEventData(_glfw.x11.display, &event->xcookie) &&
+                event->xcookie.evtype == XI_RawMotion)
+            {
+                XIRawEvent* re = event->xcookie.data;
+                if (re->valuators.mask_len)
+                {
+                    const double* values = re->raw_values;
+                    double xpos = window->virtualCursorPosX;
+                    double ypos = window->virtualCursorPosY;
+
+                    if (XIMaskIsSet(re->valuators.mask, 0))
+                    {
+                        xpos += *values;
+                        values++;
+                    }
+
+                    if (XIMaskIsSet(re->valuators.mask, 1))
+                        ypos += *values;
+
+                    _glfwInputCursorPos(window, xpos, ypos);
+                }
+            }
+
+            XFreeEventData(_glfw.x11.display, &event->xcookie);
+        }
+
+        return;
+    }
+
+    if (event->type == SelectionClear)
+    {
+        handleSelectionClear(event);
+        return;
+    }
+    else if (event->type == SelectionRequest)
+    {
+        handleSelectionRequest(event);
+        return;
+    }
+
+    _GLFWwindow* window = NULL;
+    if (XFindContext(_glfw.x11.display,
+                     event->xany.window,
+                     _glfw.x11.context,
+                     (XPointer*) &window) != 0)
+    {
+        // This is an event for a window that has already been destroyed
+        return;
+    }
+
+    switch (event->type)
+    {
+        case ReparentNotify:
+        {
+            window->x11.parent = event->xreparent.parent;
+            return;
+        }
+
+        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
+                //       These have the same timestamp as the original event
+                //       Corresponding release events are filtered out
+                //       implicitly by the GLFW key repeat logic
+                if (window->x11.lastKeyTime < event->xkey.time)
+                {
+                    if (keycode)
+                        _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
+
+                    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:
+        {
+            // XEnterWindowEvent is XCrossingEvent
+            const int x = event->xcrossing.x;
+            const int y = event->xcrossing.y;
+
+            // 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)
+                updateCursorImage(window);
+
+            _glfwInputCursorEnter(window, GLFW_TRUE);
+            _glfwInputCursorPos(window, x, y);
+
+            window->x11.lastCursorPosX = x;
+            window->x11.lastCursorPosY = y;
+            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;
+                    if (window->rawMouseMotion)
+                        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;
+            }
+
+            int xpos = event->xconfigure.x;
+            int ypos = event->xconfigure.y;
+
+            // NOTE: ConfigureNotify events from the server are in local
+            //       coordinates, so if we are reparented we need to translate
+            //       the position into root (screen) coordinates
+            if (!event->xany.send_event && window->x11.parent != _glfw.x11.root)
+            {
+                Window dummy;
+                XTranslateCoordinates(_glfw.x11.display,
+                                      window->x11.parent,
+                                      _glfw.x11.root,
+                                      xpos, ypos,
+                                      &xpos, &ypos,
+                                      &dummy);
+            }
+
+            if (xpos != window->x11.xpos || ypos != window->x11.ypos)
+            {
+                _glfwInputWindowPos(window, xpos, ypos);
+                window->x11.xpos = xpos;
+                window->x11.ypos = ypos;
+            }
+
+            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
+                unsigned long i, count;
+                Atom* formats = NULL;
+                const GLFWbool list = event->xclient.data.l[1] & 1;
+
+                _glfw.x11.xdnd.source  = event->xclient.data.l[0];
+                _glfw.x11.xdnd.version = event->xclient.data.l[1] >> 24;
+                _glfw.x11.xdnd.format  = None;
+
+                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+                    return;
+
+                if (list)
+                {
+                    count = _glfwGetWindowPropertyX11(_glfw.x11.xdnd.source,
+                                                      _glfw.x11.XdndTypeList,
+                                                      XA_ATOM,
+                                                      (unsigned char**) &formats);
+                }
+                else
+                {
+                    count = 3;
+                    formats = (Atom*) event->xclient.data.l + 2;
+                }
+
+                for (i = 0;  i < count;  i++)
+                {
+                    if (formats[i] == _glfw.x11.text_uri_list)
+                    {
+                        _glfw.x11.xdnd.format = _glfw.x11.text_uri_list;
+                        break;
+                    }
+                }
+
+                if (list && formats)
+                    XFree(formats);
+            }
+            else if (event->xclient.message_type == _glfw.x11.XdndDrop)
+            {
+                // The drag operation has finished by dropping on the window
+                Time time = CurrentTime;
+
+                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+                    return;
+
+                if (_glfw.x11.xdnd.format)
+                {
+                    if (_glfw.x11.xdnd.version >= 1)
+                        time = event->xclient.data.l[2];
+
+                    // Request the chosen format from the source window
+                    XConvertSelection(_glfw.x11.display,
+                                      _glfw.x11.XdndSelection,
+                                      _glfw.x11.xdnd.format,
+                                      _glfw.x11.XdndSelection,
+                                      window->x11.handle,
+                                      time);
+                }
+                else if (_glfw.x11.xdnd.version >= 2)
+                {
+                    XEvent reply = { 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] = 0; // The drag was rejected
+                    reply.xclient.data.l[2] = None;
+
+                    XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+                               False, NoEventMask, &reply);
+                    XFlush(_glfw.x11.display);
+                }
+            }
+            else if (event->xclient.message_type == _glfw.x11.XdndPosition)
+            {
+                // The drag operation has moved over the window
+                const int xabs = (event->xclient.data.l[2] >> 16) & 0xffff;
+                const int yabs = (event->xclient.data.l[2]) & 0xffff;
+                Window dummy;
+                int xpos, ypos;
+
+                if (_glfw.x11.xdnd.version > _GLFW_XDND_VERSION)
+                    return;
+
+                XTranslateCoordinates(_glfw.x11.display,
+                                      _glfw.x11.root,
+                                      window->x11.handle,
+                                      xabs, yabs,
+                                      &xpos, &ypos,
+                                      &dummy);
+
+                _glfwInputCursorPos(window, xpos, ypos);
+
+                XEvent reply = { ClientMessage };
+                reply.xclient.window = _glfw.x11.xdnd.source;
+                reply.xclient.message_type = _glfw.x11.XdndStatus;
+                reply.xclient.format = 32;
+                reply.xclient.data.l[0] = window->x11.handle;
+                reply.xclient.data.l[2] = 0; // Specify an empty rectangle
+                reply.xclient.data.l[3] = 0;
+
+                if (_glfw.x11.xdnd.format)
+                {
+                    // Reply that we are ready to copy the dragged data
+                    reply.xclient.data.l[1] = 1; // Accept with no rectangle
+                    if (_glfw.x11.xdnd.version >= 2)
+                        reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
+                }
+
+                XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+                           False, NoEventMask, &reply);
+                XFlush(_glfw.x11.display);
+            }
+
+            return;
+        }
+
+        case SelectionNotify:
+        {
+            if (event->xselection.property == _glfw.x11.XdndSelection)
+            {
+                // The converted data from the drag operation has arrived
+                char* data;
+                const unsigned long 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);
+                }
+
+                if (data)
+                    XFree(data);
+
+                if (_glfw.x11.xdnd.version >= 2)
+                {
+                    XEvent reply = { 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;
+
+                    XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+                               False, NoEventMask, &reply);
+                    XFlush(_glfw.x11.display);
+                }
+            }
+
+            return;
+        }
+
+        case FocusIn:
+        {
+            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->cursorMode == GLFW_CURSOR_DISABLED)
+                disableCursor(window);
+
+            if (window->x11.ic)
+                XSetICFocus(window->x11.ic);
+
+            _glfwInputWindowFocus(window, GLFW_TRUE);
+            return;
+        }
+
+        case FocusOut:
+        {
+            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->cursorMode == GLFW_CURSOR_DISABLED)
+                enableCursor(window);
+
+            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.state != PropertyNewValue)
+                return;
+
+            if (event->xproperty.atom == _glfw.x11.WM_STATE)
+            {
+                const int state = getWindowState(window);
+                if (state != IconicState && state != NormalState)
+                    return;
+
+                const GLFWbool iconified = (state == IconicState);
+                if (window->x11.iconified != iconified)
+                {
+                    if (window->monitor)
+                    {
+                        if (iconified)
+                            releaseMonitor(window);
+                        else
+                            acquireMonitor(window);
+                    }
+
+                    window->x11.iconified = iconified;
+                    _glfwInputWindowIconify(window, iconified);
+                }
+            }
+            else if (event->xproperty.atom == _glfw.x11.NET_WM_STATE)
+            {
+                const GLFWbool maximized = _glfwPlatformWindowMaximized(window);
+                if (window->x11.maximized != maximized)
+                {
+                    window->x11.maximized = maximized;
+                    _glfwInputWindowMaximize(window, maximized);
+                }
+            }
+
+            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);
+
+    return itemCount;
+}
+
+GLFWbool _glfwIsVisualTransparentX11(Visual* visual)
+{
+    if (!_glfw.x11.xrender.available)
+        return GLFW_FALSE;
+
+    XRenderPictFormat* pf = XRenderFindVisualFormat(_glfw.x11.display, visual);
+    return pf && pf->direct.alphaMask;
+}
+
+// Push contents of our selection to clipboard manager
+//
+void _glfwPushSelectionToManagerX11(void)
+{
+    XConvertSelection(_glfw.x11.display,
+                      _glfw.x11.CLIPBOARD_MANAGER,
+                      _glfw.x11.SAVE_TARGETS,
+                      None,
+                      _glfw.x11.helperWindowHandle,
+                      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);
+    }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       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)
+    {
+        if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+        {
+            if (!_glfwInitGLX())
+                return GLFW_FALSE;
+            if (!_glfwChooseVisualGLX(wndconfig, ctxconfig, fbconfig, &visual, &depth))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+        {
+            if (!_glfwInitEGL())
+                return GLFW_FALSE;
+            if (!_glfwChooseVisualEGL(wndconfig, ctxconfig, fbconfig, &visual, &depth))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwInitOSMesa())
+                return GLFW_FALSE;
+        }
+    }
+
+    if (ctxconfig->client == GLFW_NO_API ||
+        ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+    {
+        visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
+        depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
+    }
+
+    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 (ctxconfig->source == GLFW_EGL_CONTEXT_API)
+        {
+            if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+        else if (ctxconfig->source == GLFW_OSMESA_CONTEXT_API)
+        {
+            if (!_glfwCreateContextOSMesa(window, ctxconfig, fbconfig))
+                return GLFW_FALSE;
+        }
+    }
+
+    if (window->monitor)
+    {
+        _glfwPlatformShowWindow(window);
+        updateWindowMode(window);
+        acquireMonitor(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)
+    {
+        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 _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
+                                        float* xscale, float* yscale)
+{
+    if (xscale)
+        *xscale = _glfw.x11.contentScaleX;
+    if (yscale)
+        *yscale = _glfw.x11.contentScaleY;
+}
+
+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)
+    {
+        return;
+    }
+
+    if (_glfwPlatformWindowVisible(window))
+    {
+        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);
+    }
+    else
+    {
+        Atom* states = NULL;
+        unsigned long count =
+            _glfwGetWindowPropertyX11(window->x11.handle,
+                                      _glfw.x11.NET_WM_STATE,
+                                      XA_ATOM,
+                                      (unsigned char**) &states);
+
+        // NOTE: We don't check for failure as this property may not exist yet
+        //       and that's fine (and we'll create it implicitly with append)
+
+        Atom missing[2] =
+        {
+            _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
+            _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ
+        };
+        unsigned long missingCount = 2;
+
+        for (unsigned long i = 0;  i < count;  i++)
+        {
+            for (unsigned long j = 0;  j < missingCount;  j++)
+            {
+                if (states[i] == missing[j])
+                {
+                    missing[j] = missing[missingCount - 1];
+                    missingCount--;
+                }
+            }
+        }
+
+        if (states)
+            XFree(states);
+
+        if (!missingCount)
+            return;
+
+        XChangeProperty(_glfw.x11.display, window->x11.handle,
+                        _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+                        PropModeAppend,
+                        (unsigned char*) missing,
+                        missingCount);
+    }
+
+    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 _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
+{
+    if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION)
+        return;
+
+    sendEventToWM(window,
+                  _glfw.x11.NET_WM_STATE,
+                  _NET_WM_STATE_ADD,
+                  _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION,
+                  0, 1, 0);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+    if (_glfw.x11.NET_ACTIVE_WINDOW)
+        sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
+    else if (_glfwPlatformWindowVisible(window))
+    {
+        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
+        {
+            if (!window->resizable)
+                updateNormalHints(window, width, height);
+
+            XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+                              xpos, ypos, width, height);
+        }
+
+        XFlush(_glfw.x11.display);
+        return;
+    }
+
+    if (window->monitor)
+        releaseMonitor(window);
+
+    _glfwInputWindowMonitor(window, monitor);
+    updateNormalHints(window, width, height);
+
+    if (window->monitor)
+    {
+        if (!_glfwPlatformWindowVisible(window))
+        {
+            XMapRaised(_glfw.x11.display, window->x11.handle);
+            waitForVisibilityNotify(window);
+        }
+
+        updateWindowMode(window);
+        acquireMonitor(window);
+    }
+    else
+    {
+        updateWindowMode(window);
+        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;
+
+    if (!_glfw.x11.NET_WM_STATE ||
+        !_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
+        !_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+    {
+        return maximized;
+    }
+
+    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;
+        }
+    }
+
+    if (states)
+        XFree(states);
+
+    return maximized;
+}
+
+int _glfwPlatformWindowHovered(_GLFWwindow* window)
+{
+    Window w = _glfw.x11.root;
+    while (w)
+    {
+        Window root;
+        int rootX, rootY, childX, childY;
+        unsigned int mask;
+
+        if (!XQueryPointer(_glfw.x11.display, w,
+                           &root, &w, &rootX, &rootY, &childX, &childY, &mask))
+        {
+            return GLFW_FALSE;
+        }
+
+        if (w == window->x11.handle)
+            return GLFW_TRUE;
+    }
+
+    return GLFW_FALSE;
+}
+
+int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
+{
+    if (!window->x11.transparent)
+        return GLFW_FALSE;
+
+    return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
+}
+
+void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
+{
+    int width, height;
+    _glfwPlatformGetWindowSize(window, &width, &height);
+    updateNormalHints(window, width, height);
+}
+
+void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
+{
+    struct
+    {
+        unsigned long flags;
+        unsigned long functions;
+        unsigned long decorations;
+        long input_mode;
+        unsigned long status;
+    } hints = {0};
+
+    hints.flags = MWM_HINTS_DECORATIONS;
+    hints.decorations = enabled ? MWM_DECOR_ALL : 0;
+
+    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));
+}
+
+void _glfwPlatformSetWindowFloating(_GLFWwindow* window, GLFWbool enabled)
+{
+    if (!_glfw.x11.NET_WM_STATE || !_glfw.x11.NET_WM_STATE_ABOVE)
+        return;
+
+    if (_glfwPlatformWindowVisible(window))
+    {
+        const long action = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
+        sendEventToWM(window,
+                      _glfw.x11.NET_WM_STATE,
+                      action,
+                      _glfw.x11.NET_WM_STATE_ABOVE,
+                      0, 1, 0);
+    }
+    else
+    {
+        Atom* states = NULL;
+        unsigned long i, count;
+
+        count = _glfwGetWindowPropertyX11(window->x11.handle,
+                                          _glfw.x11.NET_WM_STATE,
+                                          XA_ATOM,
+                                          (unsigned char**) &states);
+
+        // NOTE: We don't check for failure as this property may not exist yet
+        //       and that's fine (and we'll create it implicitly with append)
+
+        if (enabled)
+        {
+            for (i = 0;  i < count;  i++)
+            {
+                if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
+                    break;
+            }
+
+            if (i < count)
+                return;
+
+            XChangeProperty(_glfw.x11.display, window->x11.handle,
+                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+                            PropModeAppend,
+                            (unsigned char*) &_glfw.x11.NET_WM_STATE_ABOVE,
+                            1);
+        }
+        else if (states)
+        {
+            for (i = 0;  i < count;  i++)
+            {
+                if (states[i] == _glfw.x11.NET_WM_STATE_ABOVE)
+                    break;
+            }
+
+            if (i == count)
+                return;
+
+            states[i] = states[count - 1];
+            count--;
+
+            XChangeProperty(_glfw.x11.display, window->x11.handle,
+                            _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+                            PropModeReplace, (unsigned char*) states, count);
+        }
+
+        if (states)
+            XFree(states);
+    }
+
+    XFlush(_glfw.x11.display);
+}
+
+float _glfwPlatformGetWindowOpacity(_GLFWwindow* window)
+{
+    float opacity = 1.f;
+
+    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx))
+    {
+        CARD32* value = NULL;
+
+        if (_glfwGetWindowPropertyX11(window->x11.handle,
+                                      _glfw.x11.NET_WM_WINDOW_OPACITY,
+                                      XA_CARDINAL,
+                                      (unsigned char**) &value))
+        {
+            opacity = (float) (*value / (double) 0xffffffffu);
+        }
+
+        if (value)
+            XFree(value);
+    }
+
+    return opacity;
+}
+
+void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
+{
+    const CARD32 value = (CARD32) (0xffffffffu * (double) opacity);
+    XChangeProperty(_glfw.x11.display, window->x11.handle,
+                    _glfw.x11.NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
+                    PropModeReplace, (unsigned char*) &value, 1);
+}
+
+void _glfwPlatformSetRawMouseMotion(_GLFWwindow *window, GLFWbool enabled)
+{
+    if (!_glfw.x11.xi.available)
+        return;
+
+    if (_glfw.x11.disabledCursorWindow != window)
+        return;
+
+    if (enabled)
+        enableRawMouseMotion(window);
+    else
+        disableRawMouseMotion(window);
+}
+
+GLFWbool _glfwPlatformRawMouseMotionSupported(void)
+{
+    return _glfw.x11.xi.available;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+    _GLFWwindow* window;
+
+#if defined(__linux__)
+    _glfwDetectJoystickConnectionLinux();
+#endif
+    XPending(_glfw.x11.display);
+
+    while (XQLength(_glfw.x11.display))
+    {
+        XEvent event;
+        XNextEvent(_glfw.x11.display, &event);
+        processEvent(&event);
+    }
+
+    window = _glfw.x11.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 MotionNotify
+        if (window->x11.lastCursorPosX != width / 2 ||
+            window->x11.lastCursorPosY != height / 2)
+        {
+            _glfwPlatformSetCursorPos(window, width / 2, height / 2);
+        }
+    }
+
+    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 = { ClientMessage };
+    event.xclient.window = _glfw.x11.helperWindowHandle;
+    event.xclient.format = 32; // Data is 32-bit longs
+    event.xclient.message_type = _glfw.x11.NULL_;
+
+    XSendEvent(_glfw.x11.display, _glfw.x11.helperWindowHandle, 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)
+    {
+        if (_glfwPlatformWindowFocused(window))
+            disableCursor(window);
+    }
+    else if (_glfw.x11.disabledCursorWindow == window)
+        enableCursor(window);
+    else
+        updateCursorImage(window);
+
+    XFlush(_glfw.x11.display);
+}
+
+const char* _glfwPlatformGetScancodeName(int scancode)
+{
+    if (!_glfw.x11.xkb.available)
+        return NULL;
+
+    if (scancode < 0 || scancode > 0xff ||
+        _glfw.x11.keycodes[scancode] == GLFW_KEY_UNKNOWN)
+    {
+        _glfwInputError(GLFW_INVALID_VALUE, "Invalid scancode");
+        return NULL;
+    }
+
+    const int key = _glfw.x11.keycodes[scancode];
+    const KeySym keysym = XkbKeycodeToKeysym(_glfw.x11.display,
+                                             scancode, _glfw.x11.xkb.group, 0);
+    if (keysym == NoSymbol)
+        return NULL;
+
+    const long ch = _glfwKeySym2Unicode(keysym);
+    if (ch == -1)
+        return NULL;
+
+    const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch);
+    if (count == 0)
+        return NULL;
+
+    _glfw.x11.keynames[key][count] = '\0';
+    return _glfw.x11.keynames[key];
+}
+
+int _glfwPlatformGetKeyScancode(int key)
+{
+    return _glfw.x11.scancodes[key];
+}
+
+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)
+{
+    int native = 0;
+
+    if (shape == GLFW_ARROW_CURSOR)
+        native = XC_left_ptr;
+    else if (shape == GLFW_IBEAM_CURSOR)
+        native = XC_xterm;
+    else if (shape == GLFW_CROSSHAIR_CURSOR)
+        native = XC_crosshair;
+    else if (shape == GLFW_HAND_CURSOR)
+        native = XC_hand2;
+    else if (shape == GLFW_HRESIZE_CURSOR)
+        native = XC_sb_h_double_arrow;
+    else if (shape == GLFW_VRESIZE_CURSOR)
+        native = XC_sb_v_double_arrow;
+    else
+        return GLFW_FALSE;
+
+    cursor->x11.handle = XCreateFontCursor(_glfw.x11.display, native);
+    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(const char* string)
+{
+    free(_glfw.x11.clipboardString);
+    _glfw.x11.clipboardString = _glfw_strdup(string);
+
+    XSetSelectionOwner(_glfw.x11.display,
+                       _glfw.x11.CLIPBOARD,
+                       _glfw.x11.helperWindowHandle,
+                       CurrentTime);
+
+    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
+        _glfw.x11.helperWindowHandle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "X11: Failed to become owner of clipboard selection");
+    }
+}
+
+const char* _glfwPlatformGetClipboardString(void)
+{
+    return getSelectionString(_glfw.x11.CLIPBOARD);
+}
+
+void _glfwPlatformGetRequiredInstanceExtensions(char** extensions)
+{
+    if (!_glfw.vk.KHR_surface)
+        return;
+
+    if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)
+    {
+        if (!_glfw.vk.KHR_xlib_surface)
+            return;
+    }
+
+    extensions[0] = "VK_KHR_surface";
+
+    // NOTE: VK_KHR_xcb_surface is preferred due to some early ICDs exposing but
+    //       not correctly implementing VK_KHR_xlib_surface
+    if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+        extensions[1] = "VK_KHR_xcb_surface";
+    else
+        extensions[1] = "VK_KHR_xlib_surface";
+}
+
+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 = 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 = 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 native API                       //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI Display* glfwGetX11Display(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return _glfw.x11.display;
+}
+
+GLFWAPI Window glfwGetX11Window(GLFWwindow* handle)
+{
+    _GLFWwindow* window = (_GLFWwindow*) handle;
+    _GLFW_REQUIRE_INIT_OR_RETURN(None);
+    return window->x11.handle;
+}
+
+GLFWAPI void glfwSetX11SelectionString(const char* string)
+{
+    _GLFW_REQUIRE_INIT();
+
+    free(_glfw.x11.primarySelectionString);
+    _glfw.x11.primarySelectionString = _glfw_strdup(string);
+
+    XSetSelectionOwner(_glfw.x11.display,
+                       _glfw.x11.PRIMARY,
+                       _glfw.x11.helperWindowHandle,
+                       CurrentTime);
+
+    if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY) !=
+        _glfw.x11.helperWindowHandle)
+    {
+        _glfwInputError(GLFW_PLATFORM_ERROR,
+                        "X11: Failed to become owner of primary selection");
+    }
+}
+
+GLFWAPI const char* glfwGetX11SelectionString(void)
+{
+    _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+    return getSelectionString(_glfw.x11.PRIMARY);
+}
+
diff --git a/glfw/src/xkb_unicode.c b/glfw/src/xkb_unicode.c
--- a/glfw/src/xkb_unicode.c
+++ b/glfw/src/xkb_unicode.c
@@ -1,942 +1,942 @@
-//========================================================================
-// GLFW 3.3 X11 - www.glfw.org
-//------------------------------------------------------------------------
-// Copyright (c) 2002-2006 Marcus Geelnard
-// Copyright (c) 2006-2017 Camilla Löwy <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.
-//
-//========================================================================
-// It is fine to use C99 in this file because it will not be built with VS
-//========================================================================
-
-#include "internal.h"
-
-
-/*
- * Marcus: This code was originally written by Markus G. Kuhn.
- * I have made some slight changes (trimmed it down a bit from >60 KB to
- * 20 KB), but the functionality is the same.
- */
-
-/*
- * This module converts keysym values into the corresponding ISO 10646
- * (UCS, Unicode) values.
- *
- * The array keysymtab[] contains pairs of X11 keysym values for graphical
- * characters and the corresponding Unicode value. The function
- * _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
- * search, therefore keysymtab[] must remain SORTED by keysym value.
- *
- * We allow to represent any UCS character in the range U-00000000 to
- * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
- * This admittedly does not cover the entire 31-bit space of UCS, but
- * it does cover all of the characters up to U-10FFFF, which can be
- * represented by UTF-16, and more, and it is very unlikely that higher
- * UCS codes will ever be assigned by ISO. So to get Unicode character
- * U+ABCD you can directly use keysym 0x0100abcd.
- *
- * Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
- *                  Cambridge, April 2001
- *
- * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
- * an initial draft of the mapping table.
- *
- */
-
-
-//************************************************************************
-//****                KeySym to Unicode mapping table                 ****
-//************************************************************************
-
-static const struct codepair {
-  unsigned short keysym;
-  unsigned short ucs;
-} keysymtab[] = {
-  { 0x01a1, 0x0104 },
-  { 0x01a2, 0x02d8 },
-  { 0x01a3, 0x0141 },
-  { 0x01a5, 0x013d },
-  { 0x01a6, 0x015a },
-  { 0x01a9, 0x0160 },
-  { 0x01aa, 0x015e },
-  { 0x01ab, 0x0164 },
-  { 0x01ac, 0x0179 },
-  { 0x01ae, 0x017d },
-  { 0x01af, 0x017b },
-  { 0x01b1, 0x0105 },
-  { 0x01b2, 0x02db },
-  { 0x01b3, 0x0142 },
-  { 0x01b5, 0x013e },
-  { 0x01b6, 0x015b },
-  { 0x01b7, 0x02c7 },
-  { 0x01b9, 0x0161 },
-  { 0x01ba, 0x015f },
-  { 0x01bb, 0x0165 },
-  { 0x01bc, 0x017a },
-  { 0x01bd, 0x02dd },
-  { 0x01be, 0x017e },
-  { 0x01bf, 0x017c },
-  { 0x01c0, 0x0154 },
-  { 0x01c3, 0x0102 },
-  { 0x01c5, 0x0139 },
-  { 0x01c6, 0x0106 },
-  { 0x01c8, 0x010c },
-  { 0x01ca, 0x0118 },
-  { 0x01cc, 0x011a },
-  { 0x01cf, 0x010e },
-  { 0x01d0, 0x0110 },
-  { 0x01d1, 0x0143 },
-  { 0x01d2, 0x0147 },
-  { 0x01d5, 0x0150 },
-  { 0x01d8, 0x0158 },
-  { 0x01d9, 0x016e },
-  { 0x01db, 0x0170 },
-  { 0x01de, 0x0162 },
-  { 0x01e0, 0x0155 },
-  { 0x01e3, 0x0103 },
-  { 0x01e5, 0x013a },
-  { 0x01e6, 0x0107 },
-  { 0x01e8, 0x010d },
-  { 0x01ea, 0x0119 },
-  { 0x01ec, 0x011b },
-  { 0x01ef, 0x010f },
-  { 0x01f0, 0x0111 },
-  { 0x01f1, 0x0144 },
-  { 0x01f2, 0x0148 },
-  { 0x01f5, 0x0151 },
-  { 0x01f8, 0x0159 },
-  { 0x01f9, 0x016f },
-  { 0x01fb, 0x0171 },
-  { 0x01fe, 0x0163 },
-  { 0x01ff, 0x02d9 },
-  { 0x02a1, 0x0126 },
-  { 0x02a6, 0x0124 },
-  { 0x02a9, 0x0130 },
-  { 0x02ab, 0x011e },
-  { 0x02ac, 0x0134 },
-  { 0x02b1, 0x0127 },
-  { 0x02b6, 0x0125 },
-  { 0x02b9, 0x0131 },
-  { 0x02bb, 0x011f },
-  { 0x02bc, 0x0135 },
-  { 0x02c5, 0x010a },
-  { 0x02c6, 0x0108 },
-  { 0x02d5, 0x0120 },
-  { 0x02d8, 0x011c },
-  { 0x02dd, 0x016c },
-  { 0x02de, 0x015c },
-  { 0x02e5, 0x010b },
-  { 0x02e6, 0x0109 },
-  { 0x02f5, 0x0121 },
-  { 0x02f8, 0x011d },
-  { 0x02fd, 0x016d },
-  { 0x02fe, 0x015d },
-  { 0x03a2, 0x0138 },
-  { 0x03a3, 0x0156 },
-  { 0x03a5, 0x0128 },
-  { 0x03a6, 0x013b },
-  { 0x03aa, 0x0112 },
-  { 0x03ab, 0x0122 },
-  { 0x03ac, 0x0166 },
-  { 0x03b3, 0x0157 },
-  { 0x03b5, 0x0129 },
-  { 0x03b6, 0x013c },
-  { 0x03ba, 0x0113 },
-  { 0x03bb, 0x0123 },
-  { 0x03bc, 0x0167 },
-  { 0x03bd, 0x014a },
-  { 0x03bf, 0x014b },
-  { 0x03c0, 0x0100 },
-  { 0x03c7, 0x012e },
-  { 0x03cc, 0x0116 },
-  { 0x03cf, 0x012a },
-  { 0x03d1, 0x0145 },
-  { 0x03d2, 0x014c },
-  { 0x03d3, 0x0136 },
-  { 0x03d9, 0x0172 },
-  { 0x03dd, 0x0168 },
-  { 0x03de, 0x016a },
-  { 0x03e0, 0x0101 },
-  { 0x03e7, 0x012f },
-  { 0x03ec, 0x0117 },
-  { 0x03ef, 0x012b },
-  { 0x03f1, 0x0146 },
-  { 0x03f2, 0x014d },
-  { 0x03f3, 0x0137 },
-  { 0x03f9, 0x0173 },
-  { 0x03fd, 0x0169 },
-  { 0x03fe, 0x016b },
-  { 0x047e, 0x203e },
-  { 0x04a1, 0x3002 },
-  { 0x04a2, 0x300c },
-  { 0x04a3, 0x300d },
-  { 0x04a4, 0x3001 },
-  { 0x04a5, 0x30fb },
-  { 0x04a6, 0x30f2 },
-  { 0x04a7, 0x30a1 },
-  { 0x04a8, 0x30a3 },
-  { 0x04a9, 0x30a5 },
-  { 0x04aa, 0x30a7 },
-  { 0x04ab, 0x30a9 },
-  { 0x04ac, 0x30e3 },
-  { 0x04ad, 0x30e5 },
-  { 0x04ae, 0x30e7 },
-  { 0x04af, 0x30c3 },
-  { 0x04b0, 0x30fc },
-  { 0x04b1, 0x30a2 },
-  { 0x04b2, 0x30a4 },
-  { 0x04b3, 0x30a6 },
-  { 0x04b4, 0x30a8 },
-  { 0x04b5, 0x30aa },
-  { 0x04b6, 0x30ab },
-  { 0x04b7, 0x30ad },
-  { 0x04b8, 0x30af },
-  { 0x04b9, 0x30b1 },
-  { 0x04ba, 0x30b3 },
-  { 0x04bb, 0x30b5 },
-  { 0x04bc, 0x30b7 },
-  { 0x04bd, 0x30b9 },
-  { 0x04be, 0x30bb },
-  { 0x04bf, 0x30bd },
-  { 0x04c0, 0x30bf },
-  { 0x04c1, 0x30c1 },
-  { 0x04c2, 0x30c4 },
-  { 0x04c3, 0x30c6 },
-  { 0x04c4, 0x30c8 },
-  { 0x04c5, 0x30ca },
-  { 0x04c6, 0x30cb },
-  { 0x04c7, 0x30cc },
-  { 0x04c8, 0x30cd },
-  { 0x04c9, 0x30ce },
-  { 0x04ca, 0x30cf },
-  { 0x04cb, 0x30d2 },
-  { 0x04cc, 0x30d5 },
-  { 0x04cd, 0x30d8 },
-  { 0x04ce, 0x30db },
-  { 0x04cf, 0x30de },
-  { 0x04d0, 0x30df },
-  { 0x04d1, 0x30e0 },
-  { 0x04d2, 0x30e1 },
-  { 0x04d3, 0x30e2 },
-  { 0x04d4, 0x30e4 },
-  { 0x04d5, 0x30e6 },
-  { 0x04d6, 0x30e8 },
-  { 0x04d7, 0x30e9 },
-  { 0x04d8, 0x30ea },
-  { 0x04d9, 0x30eb },
-  { 0x04da, 0x30ec },
-  { 0x04db, 0x30ed },
-  { 0x04dc, 0x30ef },
-  { 0x04dd, 0x30f3 },
-  { 0x04de, 0x309b },
-  { 0x04df, 0x309c },
-  { 0x05ac, 0x060c },
-  { 0x05bb, 0x061b },
-  { 0x05bf, 0x061f },
-  { 0x05c1, 0x0621 },
-  { 0x05c2, 0x0622 },
-  { 0x05c3, 0x0623 },
-  { 0x05c4, 0x0624 },
-  { 0x05c5, 0x0625 },
-  { 0x05c6, 0x0626 },
-  { 0x05c7, 0x0627 },
-  { 0x05c8, 0x0628 },
-  { 0x05c9, 0x0629 },
-  { 0x05ca, 0x062a },
-  { 0x05cb, 0x062b },
-  { 0x05cc, 0x062c },
-  { 0x05cd, 0x062d },
-  { 0x05ce, 0x062e },
-  { 0x05cf, 0x062f },
-  { 0x05d0, 0x0630 },
-  { 0x05d1, 0x0631 },
-  { 0x05d2, 0x0632 },
-  { 0x05d3, 0x0633 },
-  { 0x05d4, 0x0634 },
-  { 0x05d5, 0x0635 },
-  { 0x05d6, 0x0636 },
-  { 0x05d7, 0x0637 },
-  { 0x05d8, 0x0638 },
-  { 0x05d9, 0x0639 },
-  { 0x05da, 0x063a },
-  { 0x05e0, 0x0640 },
-  { 0x05e1, 0x0641 },
-  { 0x05e2, 0x0642 },
-  { 0x05e3, 0x0643 },
-  { 0x05e4, 0x0644 },
-  { 0x05e5, 0x0645 },
-  { 0x05e6, 0x0646 },
-  { 0x05e7, 0x0647 },
-  { 0x05e8, 0x0648 },
-  { 0x05e9, 0x0649 },
-  { 0x05ea, 0x064a },
-  { 0x05eb, 0x064b },
-  { 0x05ec, 0x064c },
-  { 0x05ed, 0x064d },
-  { 0x05ee, 0x064e },
-  { 0x05ef, 0x064f },
-  { 0x05f0, 0x0650 },
-  { 0x05f1, 0x0651 },
-  { 0x05f2, 0x0652 },
-  { 0x06a1, 0x0452 },
-  { 0x06a2, 0x0453 },
-  { 0x06a3, 0x0451 },
-  { 0x06a4, 0x0454 },
-  { 0x06a5, 0x0455 },
-  { 0x06a6, 0x0456 },
-  { 0x06a7, 0x0457 },
-  { 0x06a8, 0x0458 },
-  { 0x06a9, 0x0459 },
-  { 0x06aa, 0x045a },
-  { 0x06ab, 0x045b },
-  { 0x06ac, 0x045c },
-  { 0x06ae, 0x045e },
-  { 0x06af, 0x045f },
-  { 0x06b0, 0x2116 },
-  { 0x06b1, 0x0402 },
-  { 0x06b2, 0x0403 },
-  { 0x06b3, 0x0401 },
-  { 0x06b4, 0x0404 },
-  { 0x06b5, 0x0405 },
-  { 0x06b6, 0x0406 },
-  { 0x06b7, 0x0407 },
-  { 0x06b8, 0x0408 },
-  { 0x06b9, 0x0409 },
-  { 0x06ba, 0x040a },
-  { 0x06bb, 0x040b },
-  { 0x06bc, 0x040c },
-  { 0x06be, 0x040e },
-  { 0x06bf, 0x040f },
-  { 0x06c0, 0x044e },
-  { 0x06c1, 0x0430 },
-  { 0x06c2, 0x0431 },
-  { 0x06c3, 0x0446 },
-  { 0x06c4, 0x0434 },
-  { 0x06c5, 0x0435 },
-  { 0x06c6, 0x0444 },
-  { 0x06c7, 0x0433 },
-  { 0x06c8, 0x0445 },
-  { 0x06c9, 0x0438 },
-  { 0x06ca, 0x0439 },
-  { 0x06cb, 0x043a },
-  { 0x06cc, 0x043b },
-  { 0x06cd, 0x043c },
-  { 0x06ce, 0x043d },
-  { 0x06cf, 0x043e },
-  { 0x06d0, 0x043f },
-  { 0x06d1, 0x044f },
-  { 0x06d2, 0x0440 },
-  { 0x06d3, 0x0441 },
-  { 0x06d4, 0x0442 },
-  { 0x06d5, 0x0443 },
-  { 0x06d6, 0x0436 },
-  { 0x06d7, 0x0432 },
-  { 0x06d8, 0x044c },
-  { 0x06d9, 0x044b },
-  { 0x06da, 0x0437 },
-  { 0x06db, 0x0448 },
-  { 0x06dc, 0x044d },
-  { 0x06dd, 0x0449 },
-  { 0x06de, 0x0447 },
-  { 0x06df, 0x044a },
-  { 0x06e0, 0x042e },
-  { 0x06e1, 0x0410 },
-  { 0x06e2, 0x0411 },
-  { 0x06e3, 0x0426 },
-  { 0x06e4, 0x0414 },
-  { 0x06e5, 0x0415 },
-  { 0x06e6, 0x0424 },
-  { 0x06e7, 0x0413 },
-  { 0x06e8, 0x0425 },
-  { 0x06e9, 0x0418 },
-  { 0x06ea, 0x0419 },
-  { 0x06eb, 0x041a },
-  { 0x06ec, 0x041b },
-  { 0x06ed, 0x041c },
-  { 0x06ee, 0x041d },
-  { 0x06ef, 0x041e },
-  { 0x06f0, 0x041f },
-  { 0x06f1, 0x042f },
-  { 0x06f2, 0x0420 },
-  { 0x06f3, 0x0421 },
-  { 0x06f4, 0x0422 },
-  { 0x06f5, 0x0423 },
-  { 0x06f6, 0x0416 },
-  { 0x06f7, 0x0412 },
-  { 0x06f8, 0x042c },
-  { 0x06f9, 0x042b },
-  { 0x06fa, 0x0417 },
-  { 0x06fb, 0x0428 },
-  { 0x06fc, 0x042d },
-  { 0x06fd, 0x0429 },
-  { 0x06fe, 0x0427 },
-  { 0x06ff, 0x042a },
-  { 0x07a1, 0x0386 },
-  { 0x07a2, 0x0388 },
-  { 0x07a3, 0x0389 },
-  { 0x07a4, 0x038a },
-  { 0x07a5, 0x03aa },
-  { 0x07a7, 0x038c },
-  { 0x07a8, 0x038e },
-  { 0x07a9, 0x03ab },
-  { 0x07ab, 0x038f },
-  { 0x07ae, 0x0385 },
-  { 0x07af, 0x2015 },
-  { 0x07b1, 0x03ac },
-  { 0x07b2, 0x03ad },
-  { 0x07b3, 0x03ae },
-  { 0x07b4, 0x03af },
-  { 0x07b5, 0x03ca },
-  { 0x07b6, 0x0390 },
-  { 0x07b7, 0x03cc },
-  { 0x07b8, 0x03cd },
-  { 0x07b9, 0x03cb },
-  { 0x07ba, 0x03b0 },
-  { 0x07bb, 0x03ce },
-  { 0x07c1, 0x0391 },
-  { 0x07c2, 0x0392 },
-  { 0x07c3, 0x0393 },
-  { 0x07c4, 0x0394 },
-  { 0x07c5, 0x0395 },
-  { 0x07c6, 0x0396 },
-  { 0x07c7, 0x0397 },
-  { 0x07c8, 0x0398 },
-  { 0x07c9, 0x0399 },
-  { 0x07ca, 0x039a },
-  { 0x07cb, 0x039b },
-  { 0x07cc, 0x039c },
-  { 0x07cd, 0x039d },
-  { 0x07ce, 0x039e },
-  { 0x07cf, 0x039f },
-  { 0x07d0, 0x03a0 },
-  { 0x07d1, 0x03a1 },
-  { 0x07d2, 0x03a3 },
-  { 0x07d4, 0x03a4 },
-  { 0x07d5, 0x03a5 },
-  { 0x07d6, 0x03a6 },
-  { 0x07d7, 0x03a7 },
-  { 0x07d8, 0x03a8 },
-  { 0x07d9, 0x03a9 },
-  { 0x07e1, 0x03b1 },
-  { 0x07e2, 0x03b2 },
-  { 0x07e3, 0x03b3 },
-  { 0x07e4, 0x03b4 },
-  { 0x07e5, 0x03b5 },
-  { 0x07e6, 0x03b6 },
-  { 0x07e7, 0x03b7 },
-  { 0x07e8, 0x03b8 },
-  { 0x07e9, 0x03b9 },
-  { 0x07ea, 0x03ba },
-  { 0x07eb, 0x03bb },
-  { 0x07ec, 0x03bc },
-  { 0x07ed, 0x03bd },
-  { 0x07ee, 0x03be },
-  { 0x07ef, 0x03bf },
-  { 0x07f0, 0x03c0 },
-  { 0x07f1, 0x03c1 },
-  { 0x07f2, 0x03c3 },
-  { 0x07f3, 0x03c2 },
-  { 0x07f4, 0x03c4 },
-  { 0x07f5, 0x03c5 },
-  { 0x07f6, 0x03c6 },
-  { 0x07f7, 0x03c7 },
-  { 0x07f8, 0x03c8 },
-  { 0x07f9, 0x03c9 },
-  { 0x08a1, 0x23b7 },
-  { 0x08a2, 0x250c },
-  { 0x08a3, 0x2500 },
-  { 0x08a4, 0x2320 },
-  { 0x08a5, 0x2321 },
-  { 0x08a6, 0x2502 },
-  { 0x08a7, 0x23a1 },
-  { 0x08a8, 0x23a3 },
-  { 0x08a9, 0x23a4 },
-  { 0x08aa, 0x23a6 },
-  { 0x08ab, 0x239b },
-  { 0x08ac, 0x239d },
-  { 0x08ad, 0x239e },
-  { 0x08ae, 0x23a0 },
-  { 0x08af, 0x23a8 },
-  { 0x08b0, 0x23ac },
-  { 0x08bc, 0x2264 },
-  { 0x08bd, 0x2260 },
-  { 0x08be, 0x2265 },
-  { 0x08bf, 0x222b },
-  { 0x08c0, 0x2234 },
-  { 0x08c1, 0x221d },
-  { 0x08c2, 0x221e },
-  { 0x08c5, 0x2207 },
-  { 0x08c8, 0x223c },
-  { 0x08c9, 0x2243 },
-  { 0x08cd, 0x21d4 },
-  { 0x08ce, 0x21d2 },
-  { 0x08cf, 0x2261 },
-  { 0x08d6, 0x221a },
-  { 0x08da, 0x2282 },
-  { 0x08db, 0x2283 },
-  { 0x08dc, 0x2229 },
-  { 0x08dd, 0x222a },
-  { 0x08de, 0x2227 },
-  { 0x08df, 0x2228 },
-  { 0x08ef, 0x2202 },
-  { 0x08f6, 0x0192 },
-  { 0x08fb, 0x2190 },
-  { 0x08fc, 0x2191 },
-  { 0x08fd, 0x2192 },
-  { 0x08fe, 0x2193 },
-  { 0x09e0, 0x25c6 },
-  { 0x09e1, 0x2592 },
-  { 0x09e2, 0x2409 },
-  { 0x09e3, 0x240c },
-  { 0x09e4, 0x240d },
-  { 0x09e5, 0x240a },
-  { 0x09e8, 0x2424 },
-  { 0x09e9, 0x240b },
-  { 0x09ea, 0x2518 },
-  { 0x09eb, 0x2510 },
-  { 0x09ec, 0x250c },
-  { 0x09ed, 0x2514 },
-  { 0x09ee, 0x253c },
-  { 0x09ef, 0x23ba },
-  { 0x09f0, 0x23bb },
-  { 0x09f1, 0x2500 },
-  { 0x09f2, 0x23bc },
-  { 0x09f3, 0x23bd },
-  { 0x09f4, 0x251c },
-  { 0x09f5, 0x2524 },
-  { 0x09f6, 0x2534 },
-  { 0x09f7, 0x252c },
-  { 0x09f8, 0x2502 },
-  { 0x0aa1, 0x2003 },
-  { 0x0aa2, 0x2002 },
-  { 0x0aa3, 0x2004 },
-  { 0x0aa4, 0x2005 },
-  { 0x0aa5, 0x2007 },
-  { 0x0aa6, 0x2008 },
-  { 0x0aa7, 0x2009 },
-  { 0x0aa8, 0x200a },
-  { 0x0aa9, 0x2014 },
-  { 0x0aaa, 0x2013 },
-  { 0x0aae, 0x2026 },
-  { 0x0aaf, 0x2025 },
-  { 0x0ab0, 0x2153 },
-  { 0x0ab1, 0x2154 },
-  { 0x0ab2, 0x2155 },
-  { 0x0ab3, 0x2156 },
-  { 0x0ab4, 0x2157 },
-  { 0x0ab5, 0x2158 },
-  { 0x0ab6, 0x2159 },
-  { 0x0ab7, 0x215a },
-  { 0x0ab8, 0x2105 },
-  { 0x0abb, 0x2012 },
-  { 0x0abc, 0x2329 },
-  { 0x0abe, 0x232a },
-  { 0x0ac3, 0x215b },
-  { 0x0ac4, 0x215c },
-  { 0x0ac5, 0x215d },
-  { 0x0ac6, 0x215e },
-  { 0x0ac9, 0x2122 },
-  { 0x0aca, 0x2613 },
-  { 0x0acc, 0x25c1 },
-  { 0x0acd, 0x25b7 },
-  { 0x0ace, 0x25cb },
-  { 0x0acf, 0x25af },
-  { 0x0ad0, 0x2018 },
-  { 0x0ad1, 0x2019 },
-  { 0x0ad2, 0x201c },
-  { 0x0ad3, 0x201d },
-  { 0x0ad4, 0x211e },
-  { 0x0ad6, 0x2032 },
-  { 0x0ad7, 0x2033 },
-  { 0x0ad9, 0x271d },
-  { 0x0adb, 0x25ac },
-  { 0x0adc, 0x25c0 },
-  { 0x0add, 0x25b6 },
-  { 0x0ade, 0x25cf },
-  { 0x0adf, 0x25ae },
-  { 0x0ae0, 0x25e6 },
-  { 0x0ae1, 0x25ab },
-  { 0x0ae2, 0x25ad },
-  { 0x0ae3, 0x25b3 },
-  { 0x0ae4, 0x25bd },
-  { 0x0ae5, 0x2606 },
-  { 0x0ae6, 0x2022 },
-  { 0x0ae7, 0x25aa },
-  { 0x0ae8, 0x25b2 },
-  { 0x0ae9, 0x25bc },
-  { 0x0aea, 0x261c },
-  { 0x0aeb, 0x261e },
-  { 0x0aec, 0x2663 },
-  { 0x0aed, 0x2666 },
-  { 0x0aee, 0x2665 },
-  { 0x0af0, 0x2720 },
-  { 0x0af1, 0x2020 },
-  { 0x0af2, 0x2021 },
-  { 0x0af3, 0x2713 },
-  { 0x0af4, 0x2717 },
-  { 0x0af5, 0x266f },
-  { 0x0af6, 0x266d },
-  { 0x0af7, 0x2642 },
-  { 0x0af8, 0x2640 },
-  { 0x0af9, 0x260e },
-  { 0x0afa, 0x2315 },
-  { 0x0afb, 0x2117 },
-  { 0x0afc, 0x2038 },
-  { 0x0afd, 0x201a },
-  { 0x0afe, 0x201e },
-  { 0x0ba3, 0x003c },
-  { 0x0ba6, 0x003e },
-  { 0x0ba8, 0x2228 },
-  { 0x0ba9, 0x2227 },
-  { 0x0bc0, 0x00af },
-  { 0x0bc2, 0x22a5 },
-  { 0x0bc3, 0x2229 },
-  { 0x0bc4, 0x230a },
-  { 0x0bc6, 0x005f },
-  { 0x0bca, 0x2218 },
-  { 0x0bcc, 0x2395 },
-  { 0x0bce, 0x22a4 },
-  { 0x0bcf, 0x25cb },
-  { 0x0bd3, 0x2308 },
-  { 0x0bd6, 0x222a },
-  { 0x0bd8, 0x2283 },
-  { 0x0bda, 0x2282 },
-  { 0x0bdc, 0x22a2 },
-  { 0x0bfc, 0x22a3 },
-  { 0x0cdf, 0x2017 },
-  { 0x0ce0, 0x05d0 },
-  { 0x0ce1, 0x05d1 },
-  { 0x0ce2, 0x05d2 },
-  { 0x0ce3, 0x05d3 },
-  { 0x0ce4, 0x05d4 },
-  { 0x0ce5, 0x05d5 },
-  { 0x0ce6, 0x05d6 },
-  { 0x0ce7, 0x05d7 },
-  { 0x0ce8, 0x05d8 },
-  { 0x0ce9, 0x05d9 },
-  { 0x0cea, 0x05da },
-  { 0x0ceb, 0x05db },
-  { 0x0cec, 0x05dc },
-  { 0x0ced, 0x05dd },
-  { 0x0cee, 0x05de },
-  { 0x0cef, 0x05df },
-  { 0x0cf0, 0x05e0 },
-  { 0x0cf1, 0x05e1 },
-  { 0x0cf2, 0x05e2 },
-  { 0x0cf3, 0x05e3 },
-  { 0x0cf4, 0x05e4 },
-  { 0x0cf5, 0x05e5 },
-  { 0x0cf6, 0x05e6 },
-  { 0x0cf7, 0x05e7 },
-  { 0x0cf8, 0x05e8 },
-  { 0x0cf9, 0x05e9 },
-  { 0x0cfa, 0x05ea },
-  { 0x0da1, 0x0e01 },
-  { 0x0da2, 0x0e02 },
-  { 0x0da3, 0x0e03 },
-  { 0x0da4, 0x0e04 },
-  { 0x0da5, 0x0e05 },
-  { 0x0da6, 0x0e06 },
-  { 0x0da7, 0x0e07 },
-  { 0x0da8, 0x0e08 },
-  { 0x0da9, 0x0e09 },
-  { 0x0daa, 0x0e0a },
-  { 0x0dab, 0x0e0b },
-  { 0x0dac, 0x0e0c },
-  { 0x0dad, 0x0e0d },
-  { 0x0dae, 0x0e0e },
-  { 0x0daf, 0x0e0f },
-  { 0x0db0, 0x0e10 },
-  { 0x0db1, 0x0e11 },
-  { 0x0db2, 0x0e12 },
-  { 0x0db3, 0x0e13 },
-  { 0x0db4, 0x0e14 },
-  { 0x0db5, 0x0e15 },
-  { 0x0db6, 0x0e16 },
-  { 0x0db7, 0x0e17 },
-  { 0x0db8, 0x0e18 },
-  { 0x0db9, 0x0e19 },
-  { 0x0dba, 0x0e1a },
-  { 0x0dbb, 0x0e1b },
-  { 0x0dbc, 0x0e1c },
-  { 0x0dbd, 0x0e1d },
-  { 0x0dbe, 0x0e1e },
-  { 0x0dbf, 0x0e1f },
-  { 0x0dc0, 0x0e20 },
-  { 0x0dc1, 0x0e21 },
-  { 0x0dc2, 0x0e22 },
-  { 0x0dc3, 0x0e23 },
-  { 0x0dc4, 0x0e24 },
-  { 0x0dc5, 0x0e25 },
-  { 0x0dc6, 0x0e26 },
-  { 0x0dc7, 0x0e27 },
-  { 0x0dc8, 0x0e28 },
-  { 0x0dc9, 0x0e29 },
-  { 0x0dca, 0x0e2a },
-  { 0x0dcb, 0x0e2b },
-  { 0x0dcc, 0x0e2c },
-  { 0x0dcd, 0x0e2d },
-  { 0x0dce, 0x0e2e },
-  { 0x0dcf, 0x0e2f },
-  { 0x0dd0, 0x0e30 },
-  { 0x0dd1, 0x0e31 },
-  { 0x0dd2, 0x0e32 },
-  { 0x0dd3, 0x0e33 },
-  { 0x0dd4, 0x0e34 },
-  { 0x0dd5, 0x0e35 },
-  { 0x0dd6, 0x0e36 },
-  { 0x0dd7, 0x0e37 },
-  { 0x0dd8, 0x0e38 },
-  { 0x0dd9, 0x0e39 },
-  { 0x0dda, 0x0e3a },
-  { 0x0ddf, 0x0e3f },
-  { 0x0de0, 0x0e40 },
-  { 0x0de1, 0x0e41 },
-  { 0x0de2, 0x0e42 },
-  { 0x0de3, 0x0e43 },
-  { 0x0de4, 0x0e44 },
-  { 0x0de5, 0x0e45 },
-  { 0x0de6, 0x0e46 },
-  { 0x0de7, 0x0e47 },
-  { 0x0de8, 0x0e48 },
-  { 0x0de9, 0x0e49 },
-  { 0x0dea, 0x0e4a },
-  { 0x0deb, 0x0e4b },
-  { 0x0dec, 0x0e4c },
-  { 0x0ded, 0x0e4d },
-  { 0x0df0, 0x0e50 },
-  { 0x0df1, 0x0e51 },
-  { 0x0df2, 0x0e52 },
-  { 0x0df3, 0x0e53 },
-  { 0x0df4, 0x0e54 },
-  { 0x0df5, 0x0e55 },
-  { 0x0df6, 0x0e56 },
-  { 0x0df7, 0x0e57 },
-  { 0x0df8, 0x0e58 },
-  { 0x0df9, 0x0e59 },
-  { 0x0ea1, 0x3131 },
-  { 0x0ea2, 0x3132 },
-  { 0x0ea3, 0x3133 },
-  { 0x0ea4, 0x3134 },
-  { 0x0ea5, 0x3135 },
-  { 0x0ea6, 0x3136 },
-  { 0x0ea7, 0x3137 },
-  { 0x0ea8, 0x3138 },
-  { 0x0ea9, 0x3139 },
-  { 0x0eaa, 0x313a },
-  { 0x0eab, 0x313b },
-  { 0x0eac, 0x313c },
-  { 0x0ead, 0x313d },
-  { 0x0eae, 0x313e },
-  { 0x0eaf, 0x313f },
-  { 0x0eb0, 0x3140 },
-  { 0x0eb1, 0x3141 },
-  { 0x0eb2, 0x3142 },
-  { 0x0eb3, 0x3143 },
-  { 0x0eb4, 0x3144 },
-  { 0x0eb5, 0x3145 },
-  { 0x0eb6, 0x3146 },
-  { 0x0eb7, 0x3147 },
-  { 0x0eb8, 0x3148 },
-  { 0x0eb9, 0x3149 },
-  { 0x0eba, 0x314a },
-  { 0x0ebb, 0x314b },
-  { 0x0ebc, 0x314c },
-  { 0x0ebd, 0x314d },
-  { 0x0ebe, 0x314e },
-  { 0x0ebf, 0x314f },
-  { 0x0ec0, 0x3150 },
-  { 0x0ec1, 0x3151 },
-  { 0x0ec2, 0x3152 },
-  { 0x0ec3, 0x3153 },
-  { 0x0ec4, 0x3154 },
-  { 0x0ec5, 0x3155 },
-  { 0x0ec6, 0x3156 },
-  { 0x0ec7, 0x3157 },
-  { 0x0ec8, 0x3158 },
-  { 0x0ec9, 0x3159 },
-  { 0x0eca, 0x315a },
-  { 0x0ecb, 0x315b },
-  { 0x0ecc, 0x315c },
-  { 0x0ecd, 0x315d },
-  { 0x0ece, 0x315e },
-  { 0x0ecf, 0x315f },
-  { 0x0ed0, 0x3160 },
-  { 0x0ed1, 0x3161 },
-  { 0x0ed2, 0x3162 },
-  { 0x0ed3, 0x3163 },
-  { 0x0ed4, 0x11a8 },
-  { 0x0ed5, 0x11a9 },
-  { 0x0ed6, 0x11aa },
-  { 0x0ed7, 0x11ab },
-  { 0x0ed8, 0x11ac },
-  { 0x0ed9, 0x11ad },
-  { 0x0eda, 0x11ae },
-  { 0x0edb, 0x11af },
-  { 0x0edc, 0x11b0 },
-  { 0x0edd, 0x11b1 },
-  { 0x0ede, 0x11b2 },
-  { 0x0edf, 0x11b3 },
-  { 0x0ee0, 0x11b4 },
-  { 0x0ee1, 0x11b5 },
-  { 0x0ee2, 0x11b6 },
-  { 0x0ee3, 0x11b7 },
-  { 0x0ee4, 0x11b8 },
-  { 0x0ee5, 0x11b9 },
-  { 0x0ee6, 0x11ba },
-  { 0x0ee7, 0x11bb },
-  { 0x0ee8, 0x11bc },
-  { 0x0ee9, 0x11bd },
-  { 0x0eea, 0x11be },
-  { 0x0eeb, 0x11bf },
-  { 0x0eec, 0x11c0 },
-  { 0x0eed, 0x11c1 },
-  { 0x0eee, 0x11c2 },
-  { 0x0eef, 0x316d },
-  { 0x0ef0, 0x3171 },
-  { 0x0ef1, 0x3178 },
-  { 0x0ef2, 0x317f },
-  { 0x0ef3, 0x3181 },
-  { 0x0ef4, 0x3184 },
-  { 0x0ef5, 0x3186 },
-  { 0x0ef6, 0x318d },
-  { 0x0ef7, 0x318e },
-  { 0x0ef8, 0x11eb },
-  { 0x0ef9, 0x11f0 },
-  { 0x0efa, 0x11f9 },
-  { 0x0eff, 0x20a9 },
-  { 0x13a4, 0x20ac },
-  { 0x13bc, 0x0152 },
-  { 0x13bd, 0x0153 },
-  { 0x13be, 0x0178 },
-  { 0x20ac, 0x20ac },
-  { 0xfe50,    '`' },
-  { 0xfe51, 0x00b4 },
-  { 0xfe52,    '^' },
-  { 0xfe53,    '~' },
-  { 0xfe54, 0x00af },
-  { 0xfe55, 0x02d8 },
-  { 0xfe56, 0x02d9 },
-  { 0xfe57, 0x00a8 },
-  { 0xfe58, 0x02da },
-  { 0xfe59, 0x02dd },
-  { 0xfe5a, 0x02c7 },
-  { 0xfe5b, 0x00b8 },
-  { 0xfe5c, 0x02db },
-  { 0xfe5d, 0x037a },
-  { 0xfe5e, 0x309b },
-  { 0xfe5f, 0x309c },
-  { 0xfe63,    '/' },
-  { 0xfe64, 0x02bc },
-  { 0xfe65, 0x02bd },
-  { 0xfe66, 0x02f5 },
-  { 0xfe67, 0x02f3 },
-  { 0xfe68, 0x02cd },
-  { 0xfe69, 0xa788 },
-  { 0xfe6a, 0x02f7 },
-  { 0xfe6e,    ',' },
-  { 0xfe6f, 0x00a4 },
-  { 0xfe80,    'a' }, // XK_dead_a
-  { 0xfe81,    'A' }, // XK_dead_A
-  { 0xfe82,    'e' }, // XK_dead_e
-  { 0xfe83,    'E' }, // XK_dead_E
-  { 0xfe84,    'i' }, // XK_dead_i
-  { 0xfe85,    'I' }, // XK_dead_I
-  { 0xfe86,    'o' }, // XK_dead_o
-  { 0xfe87,    'O' }, // XK_dead_O
-  { 0xfe88,    'u' }, // XK_dead_u
-  { 0xfe89,    'U' }, // XK_dead_U
-  { 0xfe8a, 0x0259 },
-  { 0xfe8b, 0x018f },
-  { 0xfe8c, 0x00b5 },
-  { 0xfe90,    '_' },
-  { 0xfe91, 0x02c8 },
-  { 0xfe92, 0x02cc },
-  { 0xff80 /*XKB_KEY_KP_Space*/,     ' ' },
-  { 0xff95 /*XKB_KEY_KP_7*/, 0x0037 },
-  { 0xff96 /*XKB_KEY_KP_4*/, 0x0034 },
-  { 0xff97 /*XKB_KEY_KP_8*/, 0x0038 },
-  { 0xff98 /*XKB_KEY_KP_6*/, 0x0036 },
-  { 0xff99 /*XKB_KEY_KP_2*/, 0x0032 },
-  { 0xff9a /*XKB_KEY_KP_9*/, 0x0039 },
-  { 0xff9b /*XKB_KEY_KP_3*/, 0x0033 },
-  { 0xff9c /*XKB_KEY_KP_1*/, 0x0031 },
-  { 0xff9d /*XKB_KEY_KP_5*/, 0x0035 },
-  { 0xff9e /*XKB_KEY_KP_0*/, 0x0030 },
-  { 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 },
-  { 0xffbd /*XKB_KEY_KP_Equal*/,     '=' }
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-//////                       GLFW internal API                      //////
-//////////////////////////////////////////////////////////////////////////
-
-// Convert XKB KeySym to Unicode
-//
-long _glfwKeySym2Unicode(unsigned int keysym)
-{
-    int min = 0;
-    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
-    int mid;
-
-    // First check for Latin-1 characters (1:1 mapping)
-    if ((keysym >= 0x0020 && keysym <= 0x007e) ||
-        (keysym >= 0x00a0 && keysym <= 0x00ff))
-    {
-        return keysym;
-    }
-
-    // Also check for directly encoded 24-bit UCS characters
-    if ((keysym & 0xff000000) == 0x01000000)
-        return keysym & 0x00ffffff;
-
-    // Binary search in table
-    while (max >= min)
-    {
-        mid = (min + max) / 2;
-        if (keysymtab[mid].keysym < keysym)
-            min = mid + 1;
-        else if (keysymtab[mid].keysym > keysym)
-            max = mid - 1;
-        else
-            return keysymtab[mid].ucs;
-    }
-
-    // No matching Unicode value found
-    return -1;
-}
-
+//========================================================================
+// GLFW 3.3 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2017 Camilla Löwy <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.
+//
+//========================================================================
+// It is fine to use C99 in this file because it will not be built with VS
+//========================================================================
+
+#include "internal.h"
+
+
+/*
+ * Marcus: This code was originally written by Markus G. Kuhn.
+ * I have made some slight changes (trimmed it down a bit from >60 KB to
+ * 20 KB), but the functionality is the same.
+ */
+
+/*
+ * This module converts keysym values into the corresponding ISO 10646
+ * (UCS, Unicode) values.
+ *
+ * The array keysymtab[] contains pairs of X11 keysym values for graphical
+ * characters and the corresponding Unicode value. The function
+ * _glfwKeySym2Unicode() maps a keysym onto a Unicode value using a binary
+ * search, therefore keysymtab[] must remain SORTED by keysym value.
+ *
+ * We allow to represent any UCS character in the range U-00000000 to
+ * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
+ * This admittedly does not cover the entire 31-bit space of UCS, but
+ * it does cover all of the characters up to U-10FFFF, which can be
+ * represented by UTF-16, and more, and it is very unlikely that higher
+ * UCS codes will ever be assigned by ISO. So to get Unicode character
+ * U+ABCD you can directly use keysym 0x0100abcd.
+ *
+ * Original author: Markus G. Kuhn <mkuhn@acm.org>, University of
+ *                  Cambridge, April 2001
+ *
+ * Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
+ * an initial draft of the mapping table.
+ *
+ */
+
+
+//************************************************************************
+//****                KeySym to Unicode mapping table                 ****
+//************************************************************************
+
+static const struct codepair {
+  unsigned short keysym;
+  unsigned short ucs;
+} keysymtab[] = {
+  { 0x01a1, 0x0104 },
+  { 0x01a2, 0x02d8 },
+  { 0x01a3, 0x0141 },
+  { 0x01a5, 0x013d },
+  { 0x01a6, 0x015a },
+  { 0x01a9, 0x0160 },
+  { 0x01aa, 0x015e },
+  { 0x01ab, 0x0164 },
+  { 0x01ac, 0x0179 },
+  { 0x01ae, 0x017d },
+  { 0x01af, 0x017b },
+  { 0x01b1, 0x0105 },
+  { 0x01b2, 0x02db },
+  { 0x01b3, 0x0142 },
+  { 0x01b5, 0x013e },
+  { 0x01b6, 0x015b },
+  { 0x01b7, 0x02c7 },
+  { 0x01b9, 0x0161 },
+  { 0x01ba, 0x015f },
+  { 0x01bb, 0x0165 },
+  { 0x01bc, 0x017a },
+  { 0x01bd, 0x02dd },
+  { 0x01be, 0x017e },
+  { 0x01bf, 0x017c },
+  { 0x01c0, 0x0154 },
+  { 0x01c3, 0x0102 },
+  { 0x01c5, 0x0139 },
+  { 0x01c6, 0x0106 },
+  { 0x01c8, 0x010c },
+  { 0x01ca, 0x0118 },
+  { 0x01cc, 0x011a },
+  { 0x01cf, 0x010e },
+  { 0x01d0, 0x0110 },
+  { 0x01d1, 0x0143 },
+  { 0x01d2, 0x0147 },
+  { 0x01d5, 0x0150 },
+  { 0x01d8, 0x0158 },
+  { 0x01d9, 0x016e },
+  { 0x01db, 0x0170 },
+  { 0x01de, 0x0162 },
+  { 0x01e0, 0x0155 },
+  { 0x01e3, 0x0103 },
+  { 0x01e5, 0x013a },
+  { 0x01e6, 0x0107 },
+  { 0x01e8, 0x010d },
+  { 0x01ea, 0x0119 },
+  { 0x01ec, 0x011b },
+  { 0x01ef, 0x010f },
+  { 0x01f0, 0x0111 },
+  { 0x01f1, 0x0144 },
+  { 0x01f2, 0x0148 },
+  { 0x01f5, 0x0151 },
+  { 0x01f8, 0x0159 },
+  { 0x01f9, 0x016f },
+  { 0x01fb, 0x0171 },
+  { 0x01fe, 0x0163 },
+  { 0x01ff, 0x02d9 },
+  { 0x02a1, 0x0126 },
+  { 0x02a6, 0x0124 },
+  { 0x02a9, 0x0130 },
+  { 0x02ab, 0x011e },
+  { 0x02ac, 0x0134 },
+  { 0x02b1, 0x0127 },
+  { 0x02b6, 0x0125 },
+  { 0x02b9, 0x0131 },
+  { 0x02bb, 0x011f },
+  { 0x02bc, 0x0135 },
+  { 0x02c5, 0x010a },
+  { 0x02c6, 0x0108 },
+  { 0x02d5, 0x0120 },
+  { 0x02d8, 0x011c },
+  { 0x02dd, 0x016c },
+  { 0x02de, 0x015c },
+  { 0x02e5, 0x010b },
+  { 0x02e6, 0x0109 },
+  { 0x02f5, 0x0121 },
+  { 0x02f8, 0x011d },
+  { 0x02fd, 0x016d },
+  { 0x02fe, 0x015d },
+  { 0x03a2, 0x0138 },
+  { 0x03a3, 0x0156 },
+  { 0x03a5, 0x0128 },
+  { 0x03a6, 0x013b },
+  { 0x03aa, 0x0112 },
+  { 0x03ab, 0x0122 },
+  { 0x03ac, 0x0166 },
+  { 0x03b3, 0x0157 },
+  { 0x03b5, 0x0129 },
+  { 0x03b6, 0x013c },
+  { 0x03ba, 0x0113 },
+  { 0x03bb, 0x0123 },
+  { 0x03bc, 0x0167 },
+  { 0x03bd, 0x014a },
+  { 0x03bf, 0x014b },
+  { 0x03c0, 0x0100 },
+  { 0x03c7, 0x012e },
+  { 0x03cc, 0x0116 },
+  { 0x03cf, 0x012a },
+  { 0x03d1, 0x0145 },
+  { 0x03d2, 0x014c },
+  { 0x03d3, 0x0136 },
+  { 0x03d9, 0x0172 },
+  { 0x03dd, 0x0168 },
+  { 0x03de, 0x016a },
+  { 0x03e0, 0x0101 },
+  { 0x03e7, 0x012f },
+  { 0x03ec, 0x0117 },
+  { 0x03ef, 0x012b },
+  { 0x03f1, 0x0146 },
+  { 0x03f2, 0x014d },
+  { 0x03f3, 0x0137 },
+  { 0x03f9, 0x0173 },
+  { 0x03fd, 0x0169 },
+  { 0x03fe, 0x016b },
+  { 0x047e, 0x203e },
+  { 0x04a1, 0x3002 },
+  { 0x04a2, 0x300c },
+  { 0x04a3, 0x300d },
+  { 0x04a4, 0x3001 },
+  { 0x04a5, 0x30fb },
+  { 0x04a6, 0x30f2 },
+  { 0x04a7, 0x30a1 },
+  { 0x04a8, 0x30a3 },
+  { 0x04a9, 0x30a5 },
+  { 0x04aa, 0x30a7 },
+  { 0x04ab, 0x30a9 },
+  { 0x04ac, 0x30e3 },
+  { 0x04ad, 0x30e5 },
+  { 0x04ae, 0x30e7 },
+  { 0x04af, 0x30c3 },
+  { 0x04b0, 0x30fc },
+  { 0x04b1, 0x30a2 },
+  { 0x04b2, 0x30a4 },
+  { 0x04b3, 0x30a6 },
+  { 0x04b4, 0x30a8 },
+  { 0x04b5, 0x30aa },
+  { 0x04b6, 0x30ab },
+  { 0x04b7, 0x30ad },
+  { 0x04b8, 0x30af },
+  { 0x04b9, 0x30b1 },
+  { 0x04ba, 0x30b3 },
+  { 0x04bb, 0x30b5 },
+  { 0x04bc, 0x30b7 },
+  { 0x04bd, 0x30b9 },
+  { 0x04be, 0x30bb },
+  { 0x04bf, 0x30bd },
+  { 0x04c0, 0x30bf },
+  { 0x04c1, 0x30c1 },
+  { 0x04c2, 0x30c4 },
+  { 0x04c3, 0x30c6 },
+  { 0x04c4, 0x30c8 },
+  { 0x04c5, 0x30ca },
+  { 0x04c6, 0x30cb },
+  { 0x04c7, 0x30cc },
+  { 0x04c8, 0x30cd },
+  { 0x04c9, 0x30ce },
+  { 0x04ca, 0x30cf },
+  { 0x04cb, 0x30d2 },
+  { 0x04cc, 0x30d5 },
+  { 0x04cd, 0x30d8 },
+  { 0x04ce, 0x30db },
+  { 0x04cf, 0x30de },
+  { 0x04d0, 0x30df },
+  { 0x04d1, 0x30e0 },
+  { 0x04d2, 0x30e1 },
+  { 0x04d3, 0x30e2 },
+  { 0x04d4, 0x30e4 },
+  { 0x04d5, 0x30e6 },
+  { 0x04d6, 0x30e8 },
+  { 0x04d7, 0x30e9 },
+  { 0x04d8, 0x30ea },
+  { 0x04d9, 0x30eb },
+  { 0x04da, 0x30ec },
+  { 0x04db, 0x30ed },
+  { 0x04dc, 0x30ef },
+  { 0x04dd, 0x30f3 },
+  { 0x04de, 0x309b },
+  { 0x04df, 0x309c },
+  { 0x05ac, 0x060c },
+  { 0x05bb, 0x061b },
+  { 0x05bf, 0x061f },
+  { 0x05c1, 0x0621 },
+  { 0x05c2, 0x0622 },
+  { 0x05c3, 0x0623 },
+  { 0x05c4, 0x0624 },
+  { 0x05c5, 0x0625 },
+  { 0x05c6, 0x0626 },
+  { 0x05c7, 0x0627 },
+  { 0x05c8, 0x0628 },
+  { 0x05c9, 0x0629 },
+  { 0x05ca, 0x062a },
+  { 0x05cb, 0x062b },
+  { 0x05cc, 0x062c },
+  { 0x05cd, 0x062d },
+  { 0x05ce, 0x062e },
+  { 0x05cf, 0x062f },
+  { 0x05d0, 0x0630 },
+  { 0x05d1, 0x0631 },
+  { 0x05d2, 0x0632 },
+  { 0x05d3, 0x0633 },
+  { 0x05d4, 0x0634 },
+  { 0x05d5, 0x0635 },
+  { 0x05d6, 0x0636 },
+  { 0x05d7, 0x0637 },
+  { 0x05d8, 0x0638 },
+  { 0x05d9, 0x0639 },
+  { 0x05da, 0x063a },
+  { 0x05e0, 0x0640 },
+  { 0x05e1, 0x0641 },
+  { 0x05e2, 0x0642 },
+  { 0x05e3, 0x0643 },
+  { 0x05e4, 0x0644 },
+  { 0x05e5, 0x0645 },
+  { 0x05e6, 0x0646 },
+  { 0x05e7, 0x0647 },
+  { 0x05e8, 0x0648 },
+  { 0x05e9, 0x0649 },
+  { 0x05ea, 0x064a },
+  { 0x05eb, 0x064b },
+  { 0x05ec, 0x064c },
+  { 0x05ed, 0x064d },
+  { 0x05ee, 0x064e },
+  { 0x05ef, 0x064f },
+  { 0x05f0, 0x0650 },
+  { 0x05f1, 0x0651 },
+  { 0x05f2, 0x0652 },
+  { 0x06a1, 0x0452 },
+  { 0x06a2, 0x0453 },
+  { 0x06a3, 0x0451 },
+  { 0x06a4, 0x0454 },
+  { 0x06a5, 0x0455 },
+  { 0x06a6, 0x0456 },
+  { 0x06a7, 0x0457 },
+  { 0x06a8, 0x0458 },
+  { 0x06a9, 0x0459 },
+  { 0x06aa, 0x045a },
+  { 0x06ab, 0x045b },
+  { 0x06ac, 0x045c },
+  { 0x06ae, 0x045e },
+  { 0x06af, 0x045f },
+  { 0x06b0, 0x2116 },
+  { 0x06b1, 0x0402 },
+  { 0x06b2, 0x0403 },
+  { 0x06b3, 0x0401 },
+  { 0x06b4, 0x0404 },
+  { 0x06b5, 0x0405 },
+  { 0x06b6, 0x0406 },
+  { 0x06b7, 0x0407 },
+  { 0x06b8, 0x0408 },
+  { 0x06b9, 0x0409 },
+  { 0x06ba, 0x040a },
+  { 0x06bb, 0x040b },
+  { 0x06bc, 0x040c },
+  { 0x06be, 0x040e },
+  { 0x06bf, 0x040f },
+  { 0x06c0, 0x044e },
+  { 0x06c1, 0x0430 },
+  { 0x06c2, 0x0431 },
+  { 0x06c3, 0x0446 },
+  { 0x06c4, 0x0434 },
+  { 0x06c5, 0x0435 },
+  { 0x06c6, 0x0444 },
+  { 0x06c7, 0x0433 },
+  { 0x06c8, 0x0445 },
+  { 0x06c9, 0x0438 },
+  { 0x06ca, 0x0439 },
+  { 0x06cb, 0x043a },
+  { 0x06cc, 0x043b },
+  { 0x06cd, 0x043c },
+  { 0x06ce, 0x043d },
+  { 0x06cf, 0x043e },
+  { 0x06d0, 0x043f },
+  { 0x06d1, 0x044f },
+  { 0x06d2, 0x0440 },
+  { 0x06d3, 0x0441 },
+  { 0x06d4, 0x0442 },
+  { 0x06d5, 0x0443 },
+  { 0x06d6, 0x0436 },
+  { 0x06d7, 0x0432 },
+  { 0x06d8, 0x044c },
+  { 0x06d9, 0x044b },
+  { 0x06da, 0x0437 },
+  { 0x06db, 0x0448 },
+  { 0x06dc, 0x044d },
+  { 0x06dd, 0x0449 },
+  { 0x06de, 0x0447 },
+  { 0x06df, 0x044a },
+  { 0x06e0, 0x042e },
+  { 0x06e1, 0x0410 },
+  { 0x06e2, 0x0411 },
+  { 0x06e3, 0x0426 },
+  { 0x06e4, 0x0414 },
+  { 0x06e5, 0x0415 },
+  { 0x06e6, 0x0424 },
+  { 0x06e7, 0x0413 },
+  { 0x06e8, 0x0425 },
+  { 0x06e9, 0x0418 },
+  { 0x06ea, 0x0419 },
+  { 0x06eb, 0x041a },
+  { 0x06ec, 0x041b },
+  { 0x06ed, 0x041c },
+  { 0x06ee, 0x041d },
+  { 0x06ef, 0x041e },
+  { 0x06f0, 0x041f },
+  { 0x06f1, 0x042f },
+  { 0x06f2, 0x0420 },
+  { 0x06f3, 0x0421 },
+  { 0x06f4, 0x0422 },
+  { 0x06f5, 0x0423 },
+  { 0x06f6, 0x0416 },
+  { 0x06f7, 0x0412 },
+  { 0x06f8, 0x042c },
+  { 0x06f9, 0x042b },
+  { 0x06fa, 0x0417 },
+  { 0x06fb, 0x0428 },
+  { 0x06fc, 0x042d },
+  { 0x06fd, 0x0429 },
+  { 0x06fe, 0x0427 },
+  { 0x06ff, 0x042a },
+  { 0x07a1, 0x0386 },
+  { 0x07a2, 0x0388 },
+  { 0x07a3, 0x0389 },
+  { 0x07a4, 0x038a },
+  { 0x07a5, 0x03aa },
+  { 0x07a7, 0x038c },
+  { 0x07a8, 0x038e },
+  { 0x07a9, 0x03ab },
+  { 0x07ab, 0x038f },
+  { 0x07ae, 0x0385 },
+  { 0x07af, 0x2015 },
+  { 0x07b1, 0x03ac },
+  { 0x07b2, 0x03ad },
+  { 0x07b3, 0x03ae },
+  { 0x07b4, 0x03af },
+  { 0x07b5, 0x03ca },
+  { 0x07b6, 0x0390 },
+  { 0x07b7, 0x03cc },
+  { 0x07b8, 0x03cd },
+  { 0x07b9, 0x03cb },
+  { 0x07ba, 0x03b0 },
+  { 0x07bb, 0x03ce },
+  { 0x07c1, 0x0391 },
+  { 0x07c2, 0x0392 },
+  { 0x07c3, 0x0393 },
+  { 0x07c4, 0x0394 },
+  { 0x07c5, 0x0395 },
+  { 0x07c6, 0x0396 },
+  { 0x07c7, 0x0397 },
+  { 0x07c8, 0x0398 },
+  { 0x07c9, 0x0399 },
+  { 0x07ca, 0x039a },
+  { 0x07cb, 0x039b },
+  { 0x07cc, 0x039c },
+  { 0x07cd, 0x039d },
+  { 0x07ce, 0x039e },
+  { 0x07cf, 0x039f },
+  { 0x07d0, 0x03a0 },
+  { 0x07d1, 0x03a1 },
+  { 0x07d2, 0x03a3 },
+  { 0x07d4, 0x03a4 },
+  { 0x07d5, 0x03a5 },
+  { 0x07d6, 0x03a6 },
+  { 0x07d7, 0x03a7 },
+  { 0x07d8, 0x03a8 },
+  { 0x07d9, 0x03a9 },
+  { 0x07e1, 0x03b1 },
+  { 0x07e2, 0x03b2 },
+  { 0x07e3, 0x03b3 },
+  { 0x07e4, 0x03b4 },
+  { 0x07e5, 0x03b5 },
+  { 0x07e6, 0x03b6 },
+  { 0x07e7, 0x03b7 },
+  { 0x07e8, 0x03b8 },
+  { 0x07e9, 0x03b9 },
+  { 0x07ea, 0x03ba },
+  { 0x07eb, 0x03bb },
+  { 0x07ec, 0x03bc },
+  { 0x07ed, 0x03bd },
+  { 0x07ee, 0x03be },
+  { 0x07ef, 0x03bf },
+  { 0x07f0, 0x03c0 },
+  { 0x07f1, 0x03c1 },
+  { 0x07f2, 0x03c3 },
+  { 0x07f3, 0x03c2 },
+  { 0x07f4, 0x03c4 },
+  { 0x07f5, 0x03c5 },
+  { 0x07f6, 0x03c6 },
+  { 0x07f7, 0x03c7 },
+  { 0x07f8, 0x03c8 },
+  { 0x07f9, 0x03c9 },
+  { 0x08a1, 0x23b7 },
+  { 0x08a2, 0x250c },
+  { 0x08a3, 0x2500 },
+  { 0x08a4, 0x2320 },
+  { 0x08a5, 0x2321 },
+  { 0x08a6, 0x2502 },
+  { 0x08a7, 0x23a1 },
+  { 0x08a8, 0x23a3 },
+  { 0x08a9, 0x23a4 },
+  { 0x08aa, 0x23a6 },
+  { 0x08ab, 0x239b },
+  { 0x08ac, 0x239d },
+  { 0x08ad, 0x239e },
+  { 0x08ae, 0x23a0 },
+  { 0x08af, 0x23a8 },
+  { 0x08b0, 0x23ac },
+  { 0x08bc, 0x2264 },
+  { 0x08bd, 0x2260 },
+  { 0x08be, 0x2265 },
+  { 0x08bf, 0x222b },
+  { 0x08c0, 0x2234 },
+  { 0x08c1, 0x221d },
+  { 0x08c2, 0x221e },
+  { 0x08c5, 0x2207 },
+  { 0x08c8, 0x223c },
+  { 0x08c9, 0x2243 },
+  { 0x08cd, 0x21d4 },
+  { 0x08ce, 0x21d2 },
+  { 0x08cf, 0x2261 },
+  { 0x08d6, 0x221a },
+  { 0x08da, 0x2282 },
+  { 0x08db, 0x2283 },
+  { 0x08dc, 0x2229 },
+  { 0x08dd, 0x222a },
+  { 0x08de, 0x2227 },
+  { 0x08df, 0x2228 },
+  { 0x08ef, 0x2202 },
+  { 0x08f6, 0x0192 },
+  { 0x08fb, 0x2190 },
+  { 0x08fc, 0x2191 },
+  { 0x08fd, 0x2192 },
+  { 0x08fe, 0x2193 },
+  { 0x09e0, 0x25c6 },
+  { 0x09e1, 0x2592 },
+  { 0x09e2, 0x2409 },
+  { 0x09e3, 0x240c },
+  { 0x09e4, 0x240d },
+  { 0x09e5, 0x240a },
+  { 0x09e8, 0x2424 },
+  { 0x09e9, 0x240b },
+  { 0x09ea, 0x2518 },
+  { 0x09eb, 0x2510 },
+  { 0x09ec, 0x250c },
+  { 0x09ed, 0x2514 },
+  { 0x09ee, 0x253c },
+  { 0x09ef, 0x23ba },
+  { 0x09f0, 0x23bb },
+  { 0x09f1, 0x2500 },
+  { 0x09f2, 0x23bc },
+  { 0x09f3, 0x23bd },
+  { 0x09f4, 0x251c },
+  { 0x09f5, 0x2524 },
+  { 0x09f6, 0x2534 },
+  { 0x09f7, 0x252c },
+  { 0x09f8, 0x2502 },
+  { 0x0aa1, 0x2003 },
+  { 0x0aa2, 0x2002 },
+  { 0x0aa3, 0x2004 },
+  { 0x0aa4, 0x2005 },
+  { 0x0aa5, 0x2007 },
+  { 0x0aa6, 0x2008 },
+  { 0x0aa7, 0x2009 },
+  { 0x0aa8, 0x200a },
+  { 0x0aa9, 0x2014 },
+  { 0x0aaa, 0x2013 },
+  { 0x0aae, 0x2026 },
+  { 0x0aaf, 0x2025 },
+  { 0x0ab0, 0x2153 },
+  { 0x0ab1, 0x2154 },
+  { 0x0ab2, 0x2155 },
+  { 0x0ab3, 0x2156 },
+  { 0x0ab4, 0x2157 },
+  { 0x0ab5, 0x2158 },
+  { 0x0ab6, 0x2159 },
+  { 0x0ab7, 0x215a },
+  { 0x0ab8, 0x2105 },
+  { 0x0abb, 0x2012 },
+  { 0x0abc, 0x2329 },
+  { 0x0abe, 0x232a },
+  { 0x0ac3, 0x215b },
+  { 0x0ac4, 0x215c },
+  { 0x0ac5, 0x215d },
+  { 0x0ac6, 0x215e },
+  { 0x0ac9, 0x2122 },
+  { 0x0aca, 0x2613 },
+  { 0x0acc, 0x25c1 },
+  { 0x0acd, 0x25b7 },
+  { 0x0ace, 0x25cb },
+  { 0x0acf, 0x25af },
+  { 0x0ad0, 0x2018 },
+  { 0x0ad1, 0x2019 },
+  { 0x0ad2, 0x201c },
+  { 0x0ad3, 0x201d },
+  { 0x0ad4, 0x211e },
+  { 0x0ad6, 0x2032 },
+  { 0x0ad7, 0x2033 },
+  { 0x0ad9, 0x271d },
+  { 0x0adb, 0x25ac },
+  { 0x0adc, 0x25c0 },
+  { 0x0add, 0x25b6 },
+  { 0x0ade, 0x25cf },
+  { 0x0adf, 0x25ae },
+  { 0x0ae0, 0x25e6 },
+  { 0x0ae1, 0x25ab },
+  { 0x0ae2, 0x25ad },
+  { 0x0ae3, 0x25b3 },
+  { 0x0ae4, 0x25bd },
+  { 0x0ae5, 0x2606 },
+  { 0x0ae6, 0x2022 },
+  { 0x0ae7, 0x25aa },
+  { 0x0ae8, 0x25b2 },
+  { 0x0ae9, 0x25bc },
+  { 0x0aea, 0x261c },
+  { 0x0aeb, 0x261e },
+  { 0x0aec, 0x2663 },
+  { 0x0aed, 0x2666 },
+  { 0x0aee, 0x2665 },
+  { 0x0af0, 0x2720 },
+  { 0x0af1, 0x2020 },
+  { 0x0af2, 0x2021 },
+  { 0x0af3, 0x2713 },
+  { 0x0af4, 0x2717 },
+  { 0x0af5, 0x266f },
+  { 0x0af6, 0x266d },
+  { 0x0af7, 0x2642 },
+  { 0x0af8, 0x2640 },
+  { 0x0af9, 0x260e },
+  { 0x0afa, 0x2315 },
+  { 0x0afb, 0x2117 },
+  { 0x0afc, 0x2038 },
+  { 0x0afd, 0x201a },
+  { 0x0afe, 0x201e },
+  { 0x0ba3, 0x003c },
+  { 0x0ba6, 0x003e },
+  { 0x0ba8, 0x2228 },
+  { 0x0ba9, 0x2227 },
+  { 0x0bc0, 0x00af },
+  { 0x0bc2, 0x22a5 },
+  { 0x0bc3, 0x2229 },
+  { 0x0bc4, 0x230a },
+  { 0x0bc6, 0x005f },
+  { 0x0bca, 0x2218 },
+  { 0x0bcc, 0x2395 },
+  { 0x0bce, 0x22a4 },
+  { 0x0bcf, 0x25cb },
+  { 0x0bd3, 0x2308 },
+  { 0x0bd6, 0x222a },
+  { 0x0bd8, 0x2283 },
+  { 0x0bda, 0x2282 },
+  { 0x0bdc, 0x22a2 },
+  { 0x0bfc, 0x22a3 },
+  { 0x0cdf, 0x2017 },
+  { 0x0ce0, 0x05d0 },
+  { 0x0ce1, 0x05d1 },
+  { 0x0ce2, 0x05d2 },
+  { 0x0ce3, 0x05d3 },
+  { 0x0ce4, 0x05d4 },
+  { 0x0ce5, 0x05d5 },
+  { 0x0ce6, 0x05d6 },
+  { 0x0ce7, 0x05d7 },
+  { 0x0ce8, 0x05d8 },
+  { 0x0ce9, 0x05d9 },
+  { 0x0cea, 0x05da },
+  { 0x0ceb, 0x05db },
+  { 0x0cec, 0x05dc },
+  { 0x0ced, 0x05dd },
+  { 0x0cee, 0x05de },
+  { 0x0cef, 0x05df },
+  { 0x0cf0, 0x05e0 },
+  { 0x0cf1, 0x05e1 },
+  { 0x0cf2, 0x05e2 },
+  { 0x0cf3, 0x05e3 },
+  { 0x0cf4, 0x05e4 },
+  { 0x0cf5, 0x05e5 },
+  { 0x0cf6, 0x05e6 },
+  { 0x0cf7, 0x05e7 },
+  { 0x0cf8, 0x05e8 },
+  { 0x0cf9, 0x05e9 },
+  { 0x0cfa, 0x05ea },
+  { 0x0da1, 0x0e01 },
+  { 0x0da2, 0x0e02 },
+  { 0x0da3, 0x0e03 },
+  { 0x0da4, 0x0e04 },
+  { 0x0da5, 0x0e05 },
+  { 0x0da6, 0x0e06 },
+  { 0x0da7, 0x0e07 },
+  { 0x0da8, 0x0e08 },
+  { 0x0da9, 0x0e09 },
+  { 0x0daa, 0x0e0a },
+  { 0x0dab, 0x0e0b },
+  { 0x0dac, 0x0e0c },
+  { 0x0dad, 0x0e0d },
+  { 0x0dae, 0x0e0e },
+  { 0x0daf, 0x0e0f },
+  { 0x0db0, 0x0e10 },
+  { 0x0db1, 0x0e11 },
+  { 0x0db2, 0x0e12 },
+  { 0x0db3, 0x0e13 },
+  { 0x0db4, 0x0e14 },
+  { 0x0db5, 0x0e15 },
+  { 0x0db6, 0x0e16 },
+  { 0x0db7, 0x0e17 },
+  { 0x0db8, 0x0e18 },
+  { 0x0db9, 0x0e19 },
+  { 0x0dba, 0x0e1a },
+  { 0x0dbb, 0x0e1b },
+  { 0x0dbc, 0x0e1c },
+  { 0x0dbd, 0x0e1d },
+  { 0x0dbe, 0x0e1e },
+  { 0x0dbf, 0x0e1f },
+  { 0x0dc0, 0x0e20 },
+  { 0x0dc1, 0x0e21 },
+  { 0x0dc2, 0x0e22 },
+  { 0x0dc3, 0x0e23 },
+  { 0x0dc4, 0x0e24 },
+  { 0x0dc5, 0x0e25 },
+  { 0x0dc6, 0x0e26 },
+  { 0x0dc7, 0x0e27 },
+  { 0x0dc8, 0x0e28 },
+  { 0x0dc9, 0x0e29 },
+  { 0x0dca, 0x0e2a },
+  { 0x0dcb, 0x0e2b },
+  { 0x0dcc, 0x0e2c },
+  { 0x0dcd, 0x0e2d },
+  { 0x0dce, 0x0e2e },
+  { 0x0dcf, 0x0e2f },
+  { 0x0dd0, 0x0e30 },
+  { 0x0dd1, 0x0e31 },
+  { 0x0dd2, 0x0e32 },
+  { 0x0dd3, 0x0e33 },
+  { 0x0dd4, 0x0e34 },
+  { 0x0dd5, 0x0e35 },
+  { 0x0dd6, 0x0e36 },
+  { 0x0dd7, 0x0e37 },
+  { 0x0dd8, 0x0e38 },
+  { 0x0dd9, 0x0e39 },
+  { 0x0dda, 0x0e3a },
+  { 0x0ddf, 0x0e3f },
+  { 0x0de0, 0x0e40 },
+  { 0x0de1, 0x0e41 },
+  { 0x0de2, 0x0e42 },
+  { 0x0de3, 0x0e43 },
+  { 0x0de4, 0x0e44 },
+  { 0x0de5, 0x0e45 },
+  { 0x0de6, 0x0e46 },
+  { 0x0de7, 0x0e47 },
+  { 0x0de8, 0x0e48 },
+  { 0x0de9, 0x0e49 },
+  { 0x0dea, 0x0e4a },
+  { 0x0deb, 0x0e4b },
+  { 0x0dec, 0x0e4c },
+  { 0x0ded, 0x0e4d },
+  { 0x0df0, 0x0e50 },
+  { 0x0df1, 0x0e51 },
+  { 0x0df2, 0x0e52 },
+  { 0x0df3, 0x0e53 },
+  { 0x0df4, 0x0e54 },
+  { 0x0df5, 0x0e55 },
+  { 0x0df6, 0x0e56 },
+  { 0x0df7, 0x0e57 },
+  { 0x0df8, 0x0e58 },
+  { 0x0df9, 0x0e59 },
+  { 0x0ea1, 0x3131 },
+  { 0x0ea2, 0x3132 },
+  { 0x0ea3, 0x3133 },
+  { 0x0ea4, 0x3134 },
+  { 0x0ea5, 0x3135 },
+  { 0x0ea6, 0x3136 },
+  { 0x0ea7, 0x3137 },
+  { 0x0ea8, 0x3138 },
+  { 0x0ea9, 0x3139 },
+  { 0x0eaa, 0x313a },
+  { 0x0eab, 0x313b },
+  { 0x0eac, 0x313c },
+  { 0x0ead, 0x313d },
+  { 0x0eae, 0x313e },
+  { 0x0eaf, 0x313f },
+  { 0x0eb0, 0x3140 },
+  { 0x0eb1, 0x3141 },
+  { 0x0eb2, 0x3142 },
+  { 0x0eb3, 0x3143 },
+  { 0x0eb4, 0x3144 },
+  { 0x0eb5, 0x3145 },
+  { 0x0eb6, 0x3146 },
+  { 0x0eb7, 0x3147 },
+  { 0x0eb8, 0x3148 },
+  { 0x0eb9, 0x3149 },
+  { 0x0eba, 0x314a },
+  { 0x0ebb, 0x314b },
+  { 0x0ebc, 0x314c },
+  { 0x0ebd, 0x314d },
+  { 0x0ebe, 0x314e },
+  { 0x0ebf, 0x314f },
+  { 0x0ec0, 0x3150 },
+  { 0x0ec1, 0x3151 },
+  { 0x0ec2, 0x3152 },
+  { 0x0ec3, 0x3153 },
+  { 0x0ec4, 0x3154 },
+  { 0x0ec5, 0x3155 },
+  { 0x0ec6, 0x3156 },
+  { 0x0ec7, 0x3157 },
+  { 0x0ec8, 0x3158 },
+  { 0x0ec9, 0x3159 },
+  { 0x0eca, 0x315a },
+  { 0x0ecb, 0x315b },
+  { 0x0ecc, 0x315c },
+  { 0x0ecd, 0x315d },
+  { 0x0ece, 0x315e },
+  { 0x0ecf, 0x315f },
+  { 0x0ed0, 0x3160 },
+  { 0x0ed1, 0x3161 },
+  { 0x0ed2, 0x3162 },
+  { 0x0ed3, 0x3163 },
+  { 0x0ed4, 0x11a8 },
+  { 0x0ed5, 0x11a9 },
+  { 0x0ed6, 0x11aa },
+  { 0x0ed7, 0x11ab },
+  { 0x0ed8, 0x11ac },
+  { 0x0ed9, 0x11ad },
+  { 0x0eda, 0x11ae },
+  { 0x0edb, 0x11af },
+  { 0x0edc, 0x11b0 },
+  { 0x0edd, 0x11b1 },
+  { 0x0ede, 0x11b2 },
+  { 0x0edf, 0x11b3 },
+  { 0x0ee0, 0x11b4 },
+  { 0x0ee1, 0x11b5 },
+  { 0x0ee2, 0x11b6 },
+  { 0x0ee3, 0x11b7 },
+  { 0x0ee4, 0x11b8 },
+  { 0x0ee5, 0x11b9 },
+  { 0x0ee6, 0x11ba },
+  { 0x0ee7, 0x11bb },
+  { 0x0ee8, 0x11bc },
+  { 0x0ee9, 0x11bd },
+  { 0x0eea, 0x11be },
+  { 0x0eeb, 0x11bf },
+  { 0x0eec, 0x11c0 },
+  { 0x0eed, 0x11c1 },
+  { 0x0eee, 0x11c2 },
+  { 0x0eef, 0x316d },
+  { 0x0ef0, 0x3171 },
+  { 0x0ef1, 0x3178 },
+  { 0x0ef2, 0x317f },
+  { 0x0ef3, 0x3181 },
+  { 0x0ef4, 0x3184 },
+  { 0x0ef5, 0x3186 },
+  { 0x0ef6, 0x318d },
+  { 0x0ef7, 0x318e },
+  { 0x0ef8, 0x11eb },
+  { 0x0ef9, 0x11f0 },
+  { 0x0efa, 0x11f9 },
+  { 0x0eff, 0x20a9 },
+  { 0x13a4, 0x20ac },
+  { 0x13bc, 0x0152 },
+  { 0x13bd, 0x0153 },
+  { 0x13be, 0x0178 },
+  { 0x20ac, 0x20ac },
+  { 0xfe50,    '`' },
+  { 0xfe51, 0x00b4 },
+  { 0xfe52,    '^' },
+  { 0xfe53,    '~' },
+  { 0xfe54, 0x00af },
+  { 0xfe55, 0x02d8 },
+  { 0xfe56, 0x02d9 },
+  { 0xfe57, 0x00a8 },
+  { 0xfe58, 0x02da },
+  { 0xfe59, 0x02dd },
+  { 0xfe5a, 0x02c7 },
+  { 0xfe5b, 0x00b8 },
+  { 0xfe5c, 0x02db },
+  { 0xfe5d, 0x037a },
+  { 0xfe5e, 0x309b },
+  { 0xfe5f, 0x309c },
+  { 0xfe63,    '/' },
+  { 0xfe64, 0x02bc },
+  { 0xfe65, 0x02bd },
+  { 0xfe66, 0x02f5 },
+  { 0xfe67, 0x02f3 },
+  { 0xfe68, 0x02cd },
+  { 0xfe69, 0xa788 },
+  { 0xfe6a, 0x02f7 },
+  { 0xfe6e,    ',' },
+  { 0xfe6f, 0x00a4 },
+  { 0xfe80,    'a' }, // XK_dead_a
+  { 0xfe81,    'A' }, // XK_dead_A
+  { 0xfe82,    'e' }, // XK_dead_e
+  { 0xfe83,    'E' }, // XK_dead_E
+  { 0xfe84,    'i' }, // XK_dead_i
+  { 0xfe85,    'I' }, // XK_dead_I
+  { 0xfe86,    'o' }, // XK_dead_o
+  { 0xfe87,    'O' }, // XK_dead_O
+  { 0xfe88,    'u' }, // XK_dead_u
+  { 0xfe89,    'U' }, // XK_dead_U
+  { 0xfe8a, 0x0259 },
+  { 0xfe8b, 0x018f },
+  { 0xfe8c, 0x00b5 },
+  { 0xfe90,    '_' },
+  { 0xfe91, 0x02c8 },
+  { 0xfe92, 0x02cc },
+  { 0xff80 /*XKB_KEY_KP_Space*/,     ' ' },
+  { 0xff95 /*XKB_KEY_KP_7*/, 0x0037 },
+  { 0xff96 /*XKB_KEY_KP_4*/, 0x0034 },
+  { 0xff97 /*XKB_KEY_KP_8*/, 0x0038 },
+  { 0xff98 /*XKB_KEY_KP_6*/, 0x0036 },
+  { 0xff99 /*XKB_KEY_KP_2*/, 0x0032 },
+  { 0xff9a /*XKB_KEY_KP_9*/, 0x0039 },
+  { 0xff9b /*XKB_KEY_KP_3*/, 0x0033 },
+  { 0xff9c /*XKB_KEY_KP_1*/, 0x0031 },
+  { 0xff9d /*XKB_KEY_KP_5*/, 0x0035 },
+  { 0xff9e /*XKB_KEY_KP_0*/, 0x0030 },
+  { 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 },
+  { 0xffbd /*XKB_KEY_KP_Equal*/,     '=' }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+//////                       GLFW internal API                      //////
+//////////////////////////////////////////////////////////////////////////
+
+// Convert XKB KeySym to Unicode
+//
+long _glfwKeySym2Unicode(unsigned int keysym)
+{
+    int min = 0;
+    int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
+    int mid;
+
+    // First check for Latin-1 characters (1:1 mapping)
+    if ((keysym >= 0x0020 && keysym <= 0x007e) ||
+        (keysym >= 0x00a0 && keysym <= 0x00ff))
+    {
+        return keysym;
+    }
+
+    // Also check for directly encoded 24-bit UCS characters
+    if ((keysym & 0xff000000) == 0x01000000)
+        return keysym & 0x00ffffff;
+
+    // Binary search in table
+    while (max >= min)
+    {
+        mid = (min + max) / 2;
+        if (keysymtab[mid].keysym < keysym)
+            min = mid + 1;
+        else if (keysymtab[mid].keysym > keysym)
+            max = mid - 1;
+        else
+            return keysymtab[mid].ucs;
+    }
+
+    // No matching Unicode value found
+    return -1;
+}
+
