aboutsummaryrefslogtreecommitdiff
path: root/glfw-3.2.1/src
diff options
context:
space:
mode:
authorAndreas Grois <andi@grois.info>2018-03-09 21:36:10 +0100
committerAndreas Grois <andi@grois.info>2018-03-09 21:36:10 +0100
commit3b734f0d6b9e28c1f2c4ae54e3f46e573e02f4a5 (patch)
tree444542870666e41594e7b493f625ade81d64f885 /glfw-3.2.1/src
Initial Commit
Diffstat (limited to 'glfw-3.2.1/src')
-rw-r--r--glfw-3.2.1/src/CMakeLists.txt120
-rw-r--r--glfw-3.2.1/src/cocoa_init.m398
-rw-r--r--glfw-3.2.1/src/cocoa_joystick.h60
-rw-r--r--glfw-3.2.1/src/cocoa_joystick.m511
-rw-r--r--glfw-3.2.1/src/cocoa_monitor.m413
-rw-r--r--glfw-3.2.1/src/cocoa_platform.h150
-rw-r--r--glfw-3.2.1/src/cocoa_time.c60
-rw-r--r--glfw-3.2.1/src/cocoa_window.m1653
-rw-r--r--glfw-3.2.1/src/context.c720
-rw-r--r--glfw-3.2.1/src/egl_context.c746
-rw-r--r--glfw-3.2.1/src/egl_context.h213
-rw-r--r--glfw-3.2.1/src/glfw3.pc.in13
-rw-r--r--glfw-3.2.1/src/glfw3Config.cmake.in1
-rw-r--r--glfw-3.2.1/src/glfw_config.h.in65
-rw-r--r--glfw-3.2.1/src/glx_context.c677
-rw-r--r--glfw-3.2.1/src/glx_context.h182
-rw-r--r--glfw-3.2.1/src/init.c200
-rw-r--r--glfw-3.2.1/src/input.c659
-rw-r--r--glfw-3.2.1/src/internal.h1055
-rw-r--r--glfw-3.2.1/src/linux_joystick.c341
-rw-r--r--glfw-3.2.1/src/linux_joystick.h68
-rw-r--r--glfw-3.2.1/src/mir_init.c238
-rw-r--r--glfw-3.2.1/src/mir_monitor.c182
-rw-r--r--glfw-3.2.1/src/mir_platform.h130
-rw-r--r--glfw-3.2.1/src/mir_window.c848
-rw-r--r--glfw-3.2.1/src/monitor.c477
-rw-r--r--glfw-3.2.1/src/nsgl_context.h60
-rw-r--r--glfw-3.2.1/src/nsgl_context.m308
-rw-r--r--glfw-3.2.1/src/posix_time.c85
-rw-r--r--glfw-3.2.1/src/posix_time.h48
-rw-r--r--glfw-3.2.1/src/posix_tls.c68
-rw-r--r--glfw-3.2.1/src/posix_tls.h49
-rw-r--r--glfw-3.2.1/src/vulkan.c302
-rw-r--r--glfw-3.2.1/src/wgl_context.c718
-rw-r--r--glfw-3.2.1/src/wgl_context.h157
-rw-r--r--glfw-3.2.1/src/win32_init.c473
-rw-r--r--glfw-3.2.1/src/win32_joystick.c763
-rw-r--r--glfw-3.2.1/src/win32_joystick.h64
-rw-r--r--glfw-3.2.1/src/win32_monitor.c401
-rw-r--r--glfw-3.2.1/src/win32_platform.h350
-rw-r--r--glfw-3.2.1/src/win32_time.c74
-rw-r--r--glfw-3.2.1/src/win32_tls.c69
-rw-r--r--glfw-3.2.1/src/win32_window.c1724
-rw-r--r--glfw-3.2.1/src/window.c904
-rw-r--r--glfw-3.2.1/src/wl_init.c658
-rw-r--r--glfw-3.2.1/src/wl_monitor.c269
-rw-r--r--glfw-3.2.1/src/wl_platform.h179
-rw-r--r--glfw-3.2.1/src/wl_window.c1050
-rw-r--r--glfw-3.2.1/src/x11_init.c833
-rw-r--r--glfw-3.2.1/src/x11_monitor.c491
-rw-r--r--glfw-3.2.1/src/x11_platform.h296
-rw-r--r--glfw-3.2.1/src/x11_window.c2475
-rw-r--r--glfw-3.2.1/src/xkb_unicode.c889
-rw-r--r--glfw-3.2.1/src/xkb_unicode.h33
54 files changed, 23970 insertions, 0 deletions
diff --git a/glfw-3.2.1/src/CMakeLists.txt b/glfw-3.2.1/src/CMakeLists.txt
new file mode 100644
index 0000000..5042aba
--- /dev/null
+++ b/glfw-3.2.1/src/CMakeLists.txt
@@ -0,0 +1,120 @@
+
+set(common_HEADERS internal.h
+ "${GLFW_BINARY_DIR}/src/glfw_config.h"
+ "${GLFW_SOURCE_DIR}/include/GLFW/glfw3.h"
+ "${GLFW_SOURCE_DIR}/include/GLFW/glfw3native.h")
+set(common_SOURCES context.c init.c input.c monitor.c vulkan.c window.c)
+
+if (_GLFW_COCOA)
+ set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h cocoa_joystick.h
+ posix_tls.h nsgl_context.h)
+ set(glfw_SOURCES ${common_SOURCES} cocoa_init.m cocoa_joystick.m
+ cocoa_monitor.m cocoa_window.m cocoa_time.c posix_tls.c
+ nsgl_context.m)
+elseif (_GLFW_WIN32)
+ set(glfw_HEADERS ${common_HEADERS} win32_platform.h win32_joystick.h
+ wgl_context.h egl_context.h)
+ set(glfw_SOURCES ${common_SOURCES} win32_init.c win32_joystick.c
+ win32_monitor.c win32_time.c win32_tls.c win32_window.c
+ wgl_context.c egl_context.c)
+elseif (_GLFW_X11)
+ set(glfw_HEADERS ${common_HEADERS} x11_platform.h xkb_unicode.h
+ linux_joystick.h posix_time.h posix_tls.h glx_context.h
+ egl_context.h)
+ set(glfw_SOURCES ${common_SOURCES} x11_init.c x11_monitor.c x11_window.c
+ xkb_unicode.c linux_joystick.c posix_time.c posix_tls.c
+ glx_context.c egl_context.c)
+elseif (_GLFW_WAYLAND)
+ set(glfw_HEADERS ${common_HEADERS} wl_platform.h linux_joystick.h
+ posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
+ set(glfw_SOURCES ${common_SOURCES} wl_init.c wl_monitor.c wl_window.c
+ linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
+ egl_context.c)
+
+ ecm_add_wayland_client_protocol(glfw_SOURCES
+ PROTOCOL
+ ${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/relative-pointer/relative-pointer-unstable-v1.xml
+ BASENAME relative-pointer-unstable-v1)
+ ecm_add_wayland_client_protocol(glfw_SOURCES
+ PROTOCOL
+ ${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
+ BASENAME pointer-constraints-unstable-v1)
+elseif (_GLFW_MIR)
+ set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
+ posix_time.h posix_tls.h xkb_unicode.h egl_context.h)
+ set(glfw_SOURCES ${common_SOURCES} mir_init.c mir_monitor.c mir_window.c
+ linux_joystick.c posix_time.c posix_tls.c xkb_unicode.c
+ egl_context.c)
+endif()
+
+if (APPLE)
+ # For some reason, CMake doesn't know about .m
+ set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
+endif()
+
+add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
+set_target_properties(glfw PROPERTIES
+ OUTPUT_NAME ${GLFW_LIB_NAME}
+ VERSION ${GLFW_VERSION}
+ SOVERSION ${GLFW_VERSION_MAJOR}
+ POSITION_INDEPENDENT_CODE ON
+ FOLDER "GLFW3")
+
+target_compile_definitions(glfw PRIVATE -D_GLFW_USE_CONFIG_H)
+target_include_directories(glfw PUBLIC
+ $<BUILD_INTERFACE:${GLFW_SOURCE_DIR}/include>
+ $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>)
+target_include_directories(glfw PRIVATE
+ "${GLFW_SOURCE_DIR}/src"
+ "${GLFW_BINARY_DIR}/src"
+ ${glfw_INCLUDE_DIRS})
+
+# HACK: When building on MinGW, WINVER and UNICODE need to be defined before
+# the inclusion of stddef.h (by glfw3.h), which is itself included before
+# win32_platform.h. We define them here until a saner solution can be found
+# NOTE: MinGW-w64 and Visual C++ do /not/ need this hack.
+target_compile_definitions(glfw PRIVATE
+ "$<$<BOOL:${MINGW}>:UNICODE;WINVER=0x0501>")
+
+# Enable a reasonable set of warnings (no, -Wextra is not reasonable)
+target_compile_options(glfw PRIVATE
+ "$<$<C_COMPILER_ID:Clang>:-Wall>"
+ "$<$<C_COMPILER_ID:GNU>:-Wall>")
+
+if (BUILD_SHARED_LIBS)
+ if (WIN32)
+ if (MINGW)
+ # Remove the lib prefix on the DLL (but not the import library
+ set_target_properties(glfw PROPERTIES PREFIX "")
+
+ # Add a suffix to the import library to avoid naming conflicts
+ set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.a")
+ else()
+ # Add a suffix to the import library to avoid naming conflicts
+ set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib")
+ endif()
+ elseif (APPLE)
+ # Add -fno-common to work around a bug in Apple's GCC
+ target_compile_options(glfw PRIVATE "-fno-common")
+
+ set_target_properties(glfw PROPERTIES
+ INSTALL_NAME_DIR "lib${LIB_SUFFIX}")
+ elseif (UNIX)
+ # Hide symbols not explicitly tagged for export from the shared library
+ target_compile_options(glfw PRIVATE "-fvisibility=hidden")
+ endif()
+
+ target_compile_definitions(glfw INTERFACE -DGLFW_DLL)
+ target_link_libraries(glfw PRIVATE ${glfw_LIBRARIES})
+else()
+ target_link_libraries(glfw INTERFACE ${glfw_LIBRARIES})
+endif()
+
+if (MSVC)
+ target_compile_definitions(glfw PRIVATE _CRT_SECURE_NO_WARNINGS)
+endif()
+
+if (GLFW_INSTALL)
+ install(TARGETS glfw EXPORT glfwTargets DESTINATION lib${LIB_SUFFIX})
+endif()
+
diff --git a/glfw-3.2.1/src/cocoa_init.m b/glfw-3.2.1/src/cocoa_init.m
new file mode 100644
index 0000000..f10d638
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_init.m
@@ -0,0 +1,398 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+#include <sys/param.h> // For MAXPATHLEN
+
+
+#if defined(_GLFW_USE_CHDIR)
+
+// 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);
+}
+
+#endif /* _GLFW_USE_CHDIR */
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.ns.publicKeys, -1, sizeof(_glfw.ns.publicKeys));
+ memset(_glfw.ns.nativeKeys, -1, sizeof(_glfw.ns.nativeKeys));
+
+ _glfw.ns.publicKeys[0x1D] = GLFW_KEY_0;
+ _glfw.ns.publicKeys[0x12] = GLFW_KEY_1;
+ _glfw.ns.publicKeys[0x13] = GLFW_KEY_2;
+ _glfw.ns.publicKeys[0x14] = GLFW_KEY_3;
+ _glfw.ns.publicKeys[0x15] = GLFW_KEY_4;
+ _glfw.ns.publicKeys[0x17] = GLFW_KEY_5;
+ _glfw.ns.publicKeys[0x16] = GLFW_KEY_6;
+ _glfw.ns.publicKeys[0x1A] = GLFW_KEY_7;
+ _glfw.ns.publicKeys[0x1C] = GLFW_KEY_8;
+ _glfw.ns.publicKeys[0x19] = GLFW_KEY_9;
+ _glfw.ns.publicKeys[0x00] = GLFW_KEY_A;
+ _glfw.ns.publicKeys[0x0B] = GLFW_KEY_B;
+ _glfw.ns.publicKeys[0x08] = GLFW_KEY_C;
+ _glfw.ns.publicKeys[0x02] = GLFW_KEY_D;
+ _glfw.ns.publicKeys[0x0E] = GLFW_KEY_E;
+ _glfw.ns.publicKeys[0x03] = GLFW_KEY_F;
+ _glfw.ns.publicKeys[0x05] = GLFW_KEY_G;
+ _glfw.ns.publicKeys[0x04] = GLFW_KEY_H;
+ _glfw.ns.publicKeys[0x22] = GLFW_KEY_I;
+ _glfw.ns.publicKeys[0x26] = GLFW_KEY_J;
+ _glfw.ns.publicKeys[0x28] = GLFW_KEY_K;
+ _glfw.ns.publicKeys[0x25] = GLFW_KEY_L;
+ _glfw.ns.publicKeys[0x2E] = GLFW_KEY_M;
+ _glfw.ns.publicKeys[0x2D] = GLFW_KEY_N;
+ _glfw.ns.publicKeys[0x1F] = GLFW_KEY_O;
+ _glfw.ns.publicKeys[0x23] = GLFW_KEY_P;
+ _glfw.ns.publicKeys[0x0C] = GLFW_KEY_Q;
+ _glfw.ns.publicKeys[0x0F] = GLFW_KEY_R;
+ _glfw.ns.publicKeys[0x01] = GLFW_KEY_S;
+ _glfw.ns.publicKeys[0x11] = GLFW_KEY_T;
+ _glfw.ns.publicKeys[0x20] = GLFW_KEY_U;
+ _glfw.ns.publicKeys[0x09] = GLFW_KEY_V;
+ _glfw.ns.publicKeys[0x0D] = GLFW_KEY_W;
+ _glfw.ns.publicKeys[0x07] = GLFW_KEY_X;
+ _glfw.ns.publicKeys[0x10] = GLFW_KEY_Y;
+ _glfw.ns.publicKeys[0x06] = GLFW_KEY_Z;
+
+ _glfw.ns.publicKeys[0x27] = GLFW_KEY_APOSTROPHE;
+ _glfw.ns.publicKeys[0x2A] = GLFW_KEY_BACKSLASH;
+ _glfw.ns.publicKeys[0x2B] = GLFW_KEY_COMMA;
+ _glfw.ns.publicKeys[0x18] = GLFW_KEY_EQUAL;
+ _glfw.ns.publicKeys[0x32] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.ns.publicKeys[0x21] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.ns.publicKeys[0x1B] = GLFW_KEY_MINUS;
+ _glfw.ns.publicKeys[0x2F] = GLFW_KEY_PERIOD;
+ _glfw.ns.publicKeys[0x1E] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.ns.publicKeys[0x29] = GLFW_KEY_SEMICOLON;
+ _glfw.ns.publicKeys[0x2C] = GLFW_KEY_SLASH;
+ _glfw.ns.publicKeys[0x0A] = GLFW_KEY_WORLD_1;
+
+ _glfw.ns.publicKeys[0x33] = GLFW_KEY_BACKSPACE;
+ _glfw.ns.publicKeys[0x39] = GLFW_KEY_CAPS_LOCK;
+ _glfw.ns.publicKeys[0x75] = GLFW_KEY_DELETE;
+ _glfw.ns.publicKeys[0x7D] = GLFW_KEY_DOWN;
+ _glfw.ns.publicKeys[0x77] = GLFW_KEY_END;
+ _glfw.ns.publicKeys[0x24] = GLFW_KEY_ENTER;
+ _glfw.ns.publicKeys[0x35] = GLFW_KEY_ESCAPE;
+ _glfw.ns.publicKeys[0x7A] = GLFW_KEY_F1;
+ _glfw.ns.publicKeys[0x78] = GLFW_KEY_F2;
+ _glfw.ns.publicKeys[0x63] = GLFW_KEY_F3;
+ _glfw.ns.publicKeys[0x76] = GLFW_KEY_F4;
+ _glfw.ns.publicKeys[0x60] = GLFW_KEY_F5;
+ _glfw.ns.publicKeys[0x61] = GLFW_KEY_F6;
+ _glfw.ns.publicKeys[0x62] = GLFW_KEY_F7;
+ _glfw.ns.publicKeys[0x64] = GLFW_KEY_F8;
+ _glfw.ns.publicKeys[0x65] = GLFW_KEY_F9;
+ _glfw.ns.publicKeys[0x6D] = GLFW_KEY_F10;
+ _glfw.ns.publicKeys[0x67] = GLFW_KEY_F11;
+ _glfw.ns.publicKeys[0x6F] = GLFW_KEY_F12;
+ _glfw.ns.publicKeys[0x69] = GLFW_KEY_F13;
+ _glfw.ns.publicKeys[0x6B] = GLFW_KEY_F14;
+ _glfw.ns.publicKeys[0x71] = GLFW_KEY_F15;
+ _glfw.ns.publicKeys[0x6A] = GLFW_KEY_F16;
+ _glfw.ns.publicKeys[0x40] = GLFW_KEY_F17;
+ _glfw.ns.publicKeys[0x4F] = GLFW_KEY_F18;
+ _glfw.ns.publicKeys[0x50] = GLFW_KEY_F19;
+ _glfw.ns.publicKeys[0x5A] = GLFW_KEY_F20;
+ _glfw.ns.publicKeys[0x73] = GLFW_KEY_HOME;
+ _glfw.ns.publicKeys[0x72] = GLFW_KEY_INSERT;
+ _glfw.ns.publicKeys[0x7B] = GLFW_KEY_LEFT;
+ _glfw.ns.publicKeys[0x3A] = GLFW_KEY_LEFT_ALT;
+ _glfw.ns.publicKeys[0x3B] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.ns.publicKeys[0x38] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.ns.publicKeys[0x37] = GLFW_KEY_LEFT_SUPER;
+ _glfw.ns.publicKeys[0x6E] = GLFW_KEY_MENU;
+ _glfw.ns.publicKeys[0x47] = GLFW_KEY_NUM_LOCK;
+ _glfw.ns.publicKeys[0x79] = GLFW_KEY_PAGE_DOWN;
+ _glfw.ns.publicKeys[0x74] = GLFW_KEY_PAGE_UP;
+ _glfw.ns.publicKeys[0x7C] = GLFW_KEY_RIGHT;
+ _glfw.ns.publicKeys[0x3D] = GLFW_KEY_RIGHT_ALT;
+ _glfw.ns.publicKeys[0x3E] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.ns.publicKeys[0x3C] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.ns.publicKeys[0x36] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.ns.publicKeys[0x31] = GLFW_KEY_SPACE;
+ _glfw.ns.publicKeys[0x30] = GLFW_KEY_TAB;
+ _glfw.ns.publicKeys[0x7E] = GLFW_KEY_UP;
+
+ _glfw.ns.publicKeys[0x52] = GLFW_KEY_KP_0;
+ _glfw.ns.publicKeys[0x53] = GLFW_KEY_KP_1;
+ _glfw.ns.publicKeys[0x54] = GLFW_KEY_KP_2;
+ _glfw.ns.publicKeys[0x55] = GLFW_KEY_KP_3;
+ _glfw.ns.publicKeys[0x56] = GLFW_KEY_KP_4;
+ _glfw.ns.publicKeys[0x57] = GLFW_KEY_KP_5;
+ _glfw.ns.publicKeys[0x58] = GLFW_KEY_KP_6;
+ _glfw.ns.publicKeys[0x59] = GLFW_KEY_KP_7;
+ _glfw.ns.publicKeys[0x5B] = GLFW_KEY_KP_8;
+ _glfw.ns.publicKeys[0x5C] = GLFW_KEY_KP_9;
+ _glfw.ns.publicKeys[0x45] = GLFW_KEY_KP_ADD;
+ _glfw.ns.publicKeys[0x41] = GLFW_KEY_KP_DECIMAL;
+ _glfw.ns.publicKeys[0x4B] = GLFW_KEY_KP_DIVIDE;
+ _glfw.ns.publicKeys[0x4C] = GLFW_KEY_KP_ENTER;
+ _glfw.ns.publicKeys[0x51] = GLFW_KEY_KP_EQUAL;
+ _glfw.ns.publicKeys[0x43] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.ns.publicKeys[0x4E] = GLFW_KEY_KP_SUBTRACT;
+
+ for (scancode = 0; scancode < 256; scancode++)
+ {
+ // Store the reverse translation for faster key name lookup
+ if (_glfw.ns.publicKeys[scancode] >= 0)
+ _glfw.ns.nativeKeys[_glfw.ns.publicKeys[scancode]] = scancode;
+ }
+}
+
+// Retrieve Unicode data for the current keyboard layout
+//
+static GLFWbool updateUnicodeDataNS(void)
+{
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ _glfw.ns.inputSource = TISCopyCurrentKeyboardLayoutInputSource();
+ if (!_glfw.ns.inputSource)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout input source");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.unicodeData = TISGetInputSourceProperty(_glfw.ns.inputSource,
+ kTISPropertyUnicodeKeyLayoutData);
+ if (!_glfw.ns.unicodeData)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve keyboard layout Unicode data");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Load HIToolbox.framework and the TIS symbols we need from it
+//
+static GLFWbool initializeTIS(void)
+{
+ // This works only because Cocoa has already loaded it properly
+ _glfw.ns.tis.bundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.HIToolbox"));
+ if (!_glfw.ns.tis.bundle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load HIToolbox.framework");
+ return GLFW_FALSE;
+ }
+
+ CFStringRef* kPropertyUnicodeKeyLayoutData =
+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("kTISPropertyUnicodeKeyLayoutData"));
+ CFStringRef* kNotifySelectedKeyboardInputSourceChanged =
+ CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("kTISNotifySelectedKeyboardInputSourceChanged"));
+ _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
+ _glfw.ns.tis.GetInputSourceProperty =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("TISGetInputSourceProperty"));
+ _glfw.ns.tis.GetKbdType =
+ CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
+ CFSTR("LMGetKbdType"));
+
+ if (!kPropertyUnicodeKeyLayoutData ||
+ !kNotifySelectedKeyboardInputSourceChanged ||
+ !TISCopyCurrentKeyboardLayoutInputSource ||
+ !TISGetInputSourceProperty ||
+ !LMGetKbdType)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to load TIS API symbols");
+ return GLFW_FALSE;
+ }
+
+ _glfw.ns.tis.kPropertyUnicodeKeyLayoutData =
+ *kPropertyUnicodeKeyLayoutData;
+ _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged =
+ *kNotifySelectedKeyboardInputSourceChanged;
+
+ return updateUnicodeDataNS();
+}
+
+@interface GLFWLayoutListener : NSObject
+@end
+
+@implementation GLFWLayoutListener
+
+- (void)selectedKeyboardInputSourceChanged:(NSObject* )object
+{
+ updateUnicodeDataNS();
+}
+
+@end
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+
+ _glfw.ns.listener = [[GLFWLayoutListener alloc] init];
+ [[NSDistributedNotificationCenter defaultCenter]
+ addObserver:_glfw.ns.listener
+ selector:@selector(selectedKeyboardInputSourceChanged:)
+ name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
+ object:nil];
+
+#if defined(_GLFW_USE_CHDIR)
+ changeToResourcesDirectory();
+#endif
+
+ createKeyTables();
+
+ _glfw.ns.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ if (!_glfw.ns.eventSource)
+ return GLFW_FALSE;
+
+ CGEventSourceSetLocalEventsSuppressionInterval(_glfw.ns.eventSource, 0.0);
+
+ if (!initializeTIS())
+ return GLFW_FALSE;
+
+ if (!_glfwInitThreadLocalStoragePOSIX())
+ return GLFW_FALSE;
+
+ _glfwInitTimerNS();
+ _glfwInitJoysticksNS();
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ if (_glfw.ns.inputSource)
+ {
+ CFRelease(_glfw.ns.inputSource);
+ _glfw.ns.inputSource = NULL;
+ _glfw.ns.unicodeData = nil;
+ }
+
+ if (_glfw.ns.eventSource)
+ {
+ CFRelease(_glfw.ns.eventSource);
+ _glfw.ns.eventSource = NULL;
+ }
+
+ if (_glfw.ns.delegate)
+ {
+ [NSApp setDelegate:nil];
+ [_glfw.ns.delegate release];
+ _glfw.ns.delegate = nil;
+ }
+
+ if (_glfw.ns.listener)
+ {
+ [[NSDistributedNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.listener
+ name:(__bridge NSString*)kTISNotifySelectedKeyboardInputSourceChanged
+ object:nil];
+ [[NSDistributedNotificationCenter defaultCenter]
+ removeObserver:_glfw.ns.listener];
+ [_glfw.ns.listener release];
+ _glfw.ns.listener = nil;
+ }
+
+ [_glfw.ns.cursor release];
+ _glfw.ns.cursor = nil;
+
+ free(_glfw.ns.clipboardString);
+
+ _glfwTerminateNSGL();
+ _glfwTerminateJoysticksNS();
+ _glfwTerminateThreadLocalStoragePOSIX();
+
+ [_glfw.ns.autoreleasePool release];
+ _glfw.ns.autoreleasePool = nil;
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Cocoa NSGL"
+#if defined(_GLFW_USE_CHDIR)
+ " chdir"
+#endif
+#if defined(_GLFW_USE_MENUBAR)
+ " menubar"
+#endif
+#if defined(_GLFW_USE_RETINA)
+ " retina"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " dynamic"
+#endif
+ ;
+}
+
diff --git a/glfw-3.2.1/src/cocoa_joystick.h b/glfw-3.2.1/src/cocoa_joystick.h
new file mode 100644
index 0000000..3b80634
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_joystick.h
@@ -0,0 +1,60 @@
+//========================================================================
+// GLFW 3.2 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_cocoa_joystick_h_
+#define _glfw3_cocoa_joystick_h_
+
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/hid/IOHIDLib.h>
+#include <IOKit/hid/IOHIDKeys.h>
+
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
+ _GLFWjoystickNS ns_js[GLFW_JOYSTICK_LAST + 1]
+
+
+// Cocoa-specific per-joystick data
+//
+typedef struct _GLFWjoystickNS
+{
+ GLFWbool present;
+ char name[256];
+
+ IOHIDDeviceRef deviceRef;
+
+ CFMutableArrayRef axisElements;
+ CFMutableArrayRef buttonElements;
+ CFMutableArrayRef hatElements;
+
+ float* axes;
+ unsigned char* buttons;
+} _GLFWjoystickNS;
+
+
+void _glfwInitJoysticksNS(void);
+void _glfwTerminateJoysticksNS(void);
+
+#endif // _glfw3_cocoa_joystick_h_
diff --git a/glfw-3.2.1/src/cocoa_joystick.m b/glfw-3.2.1/src/cocoa_joystick.m
new file mode 100644
index 0000000..7423e3d
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_joystick.m
@@ -0,0 +1,511 @@
+//========================================================================
+// GLFW 3.2 Cocoa - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
+
+
+// Joystick element information
+//
+typedef struct _GLFWjoyelementNS
+{
+ IOHIDElementRef elementRef;
+
+ long min;
+ long max;
+
+ long minReport;
+ long maxReport;
+
+} _GLFWjoyelementNS;
+
+
+static void getElementsCFArrayHandler(const void* value, void* parameter);
+
+// Adds an element to the specified joystick
+//
+static void addJoystickElement(_GLFWjoystickNS* js,
+ IOHIDElementRef elementRef)
+{
+ IOHIDElementType elementType;
+ long usagePage, usage;
+ CFMutableArrayRef elementsArray = NULL;
+
+ elementType = IOHIDElementGetType(elementRef);
+ usagePage = IOHIDElementGetUsagePage(elementRef);
+ usage = IOHIDElementGetUsage(elementRef);
+
+ if ((elementType != kIOHIDElementTypeInput_Axis) &&
+ (elementType != kIOHIDElementTypeInput_Button) &&
+ (elementType != kIOHIDElementTypeInput_Misc))
+ {
+ return;
+ }
+
+ switch (usagePage)
+ {
+ case kHIDPage_GenericDesktop:
+ {
+ switch (usage)
+ {
+ case kHIDUsage_GD_X:
+ case kHIDUsage_GD_Y:
+ case kHIDUsage_GD_Z:
+ case kHIDUsage_GD_Rx:
+ case kHIDUsage_GD_Ry:
+ case kHIDUsage_GD_Rz:
+ case kHIDUsage_GD_Slider:
+ case kHIDUsage_GD_Dial:
+ case kHIDUsage_GD_Wheel:
+ elementsArray = js->axisElements;
+ break;
+ case kHIDUsage_GD_Hatswitch:
+ elementsArray = js->hatElements;
+ break;
+ }
+
+ break;
+ }
+
+ case kHIDPage_Button:
+ elementsArray = js->buttonElements;
+ break;
+ default:
+ break;
+ }
+
+ if (elementsArray)
+ {
+ _GLFWjoyelementNS* element = calloc(1, sizeof(_GLFWjoyelementNS));
+
+ CFArrayAppendValue(elementsArray, element);
+
+ element->elementRef = elementRef;
+
+ element->minReport = IOHIDElementGetLogicalMin(elementRef);
+ element->maxReport = IOHIDElementGetLogicalMax(elementRef);
+ }
+}
+
+// Adds an element to the specified joystick
+//
+static void getElementsCFArrayHandler(const void* value, void* parameter)
+{
+ if (CFGetTypeID(value) == IOHIDElementGetTypeID())
+ {
+ addJoystickElement((_GLFWjoystickNS*) parameter,
+ (IOHIDElementRef) value);
+ }
+}
+
+// Returns the value of the specified element of the specified joystick
+//
+static long getElementValue(_GLFWjoystickNS* js, _GLFWjoyelementNS* element)
+{
+ IOReturn result = kIOReturnSuccess;
+ IOHIDValueRef valueRef;
+ long value = 0;
+
+ if (js && element && js->deviceRef)
+ {
+ result = IOHIDDeviceGetValue(js->deviceRef,
+ element->elementRef,
+ &valueRef);
+
+ if (kIOReturnSuccess == result)
+ {
+ value = IOHIDValueGetIntegerValue(valueRef);
+
+ // Record min and max for auto calibration
+ if (value < element->minReport)
+ element->minReport = value;
+ if (value > element->maxReport)
+ element->maxReport = value;
+ }
+ }
+
+ // Auto user scale
+ return value;
+}
+
+// Removes the specified joystick
+//
+static void removeJoystick(_GLFWjoystickNS* js)
+{
+ int i;
+
+ if (!js->present)
+ return;
+
+ for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
+ free((void*) CFArrayGetValueAtIndex(js->axisElements, i));
+ CFArrayRemoveAllValues(js->axisElements);
+ CFRelease(js->axisElements);
+
+ for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
+ free((void*) CFArrayGetValueAtIndex(js->buttonElements, i));
+ CFArrayRemoveAllValues(js->buttonElements);
+ CFRelease(js->buttonElements);
+
+ for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
+ free((void*) CFArrayGetValueAtIndex(js->hatElements, i));
+ CFArrayRemoveAllValues(js->hatElements);
+ CFRelease(js->hatElements);
+
+ free(js->axes);
+ free(js->buttons);
+
+ memset(js, 0, sizeof(_GLFWjoystickNS));
+
+ _glfwInputJoystickChange(js - _glfw.ns_js, GLFW_DISCONNECTED);
+}
+
+// Polls for joystick axis events and updates GLFW state
+//
+static GLFWbool pollJoystickAxisEvents(_GLFWjoystickNS* js)
+{
+ CFIndex i;
+
+ if (!js->present)
+ return GLFW_FALSE;
+
+ for (i = 0; i < CFArrayGetCount(js->axisElements); i++)
+ {
+ _GLFWjoyelementNS* axis = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->axisElements, i);
+
+ long value = getElementValue(js, axis);
+ long readScale = axis->maxReport - axis->minReport;
+
+ if (readScale == 0)
+ js->axes[i] = value;
+ else
+ js->axes[i] = (2.f * (value - axis->minReport) / readScale) - 1.f;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Polls for joystick button events and updates GLFW state
+//
+static GLFWbool pollJoystickButtonEvents(_GLFWjoystickNS* js)
+{
+ CFIndex i;
+ int buttonIndex = 0;
+
+ if (!js->present)
+ return GLFW_FALSE;
+
+ for (i = 0; i < CFArrayGetCount(js->buttonElements); i++)
+ {
+ _GLFWjoyelementNS* button = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->buttonElements, i);
+
+ if (getElementValue(js, button))
+ js->buttons[buttonIndex++] = GLFW_PRESS;
+ else
+ js->buttons[buttonIndex++] = GLFW_RELEASE;
+ }
+
+ for (i = 0; i < CFArrayGetCount(js->hatElements); i++)
+ {
+ _GLFWjoyelementNS* hat = (_GLFWjoyelementNS*)
+ CFArrayGetValueAtIndex(js->hatElements, i);
+
+ // Bit fields of button presses for each direction, including nil
+ const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
+
+ long j, value = getElementValue(js, hat);
+ if (value < 0 || value > 8)
+ value = 8;
+
+ for (j = 0; j < 4; j++)
+ {
+ if (directions[value] & (1 << j))
+ js->buttons[buttonIndex++] = GLFW_PRESS;
+ else
+ js->buttons[buttonIndex++] = GLFW_RELEASE;
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+// Callback for user-initiated joystick addition
+//
+static void matchCallback(void* context,
+ IOReturn result,
+ void* sender,
+ IOHIDDeviceRef deviceRef)
+{
+ _GLFWjoystickNS* js;
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (_glfw.ns_js[joy].present && _glfw.ns_js[joy].deviceRef == deviceRef)
+ return;
+ }
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.ns_js[joy].present)
+ break;
+ }
+
+ if (joy > GLFW_JOYSTICK_LAST)
+ return;
+
+ js = _glfw.ns_js + joy;
+ js->present = GLFW_TRUE;
+ js->deviceRef = deviceRef;
+
+ CFStringRef name = IOHIDDeviceGetProperty(deviceRef,
+ CFSTR(kIOHIDProductKey));
+ if (name)
+ {
+ CFStringGetCString(name,
+ js->name,
+ sizeof(js->name),
+ kCFStringEncodingUTF8);
+ }
+ else
+ strncpy(js->name, "Unknown", sizeof(js->name));
+
+ js->axisElements = CFArrayCreateMutable(NULL, 0, NULL);
+ js->buttonElements = CFArrayCreateMutable(NULL, 0, NULL);
+ js->hatElements = CFArrayCreateMutable(NULL, 0, NULL);
+
+ CFArrayRef arrayRef = IOHIDDeviceCopyMatchingElements(deviceRef,
+ NULL,
+ kIOHIDOptionsTypeNone);
+ CFRange range = { 0, CFArrayGetCount(arrayRef) };
+ CFArrayApplyFunction(arrayRef,
+ range,
+ getElementsCFArrayHandler,
+ (void*) js);
+
+ CFRelease(arrayRef);
+
+ js->axes = calloc(CFArrayGetCount(js->axisElements), sizeof(float));
+ js->buttons = calloc(CFArrayGetCount(js->buttonElements) +
+ CFArrayGetCount(js->hatElements) * 4, 1);
+
+ _glfwInputJoystickChange(joy, GLFW_CONNECTED);
+}
+
+// Callback for user-initiated joystick removal
+//
+static void removeCallback(void* context,
+ IOReturn result,
+ void* sender,
+ IOHIDDeviceRef deviceRef)
+{
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (_glfw.ns_js[joy].deviceRef == deviceRef)
+ {
+ removeJoystick(_glfw.ns_js + joy);
+ break;
+ }
+ }
+}
+
+// Creates a dictionary to match against devices with the specified usage page
+// and usage
+//
+static CFMutableDictionaryRef createMatchingDictionary(long usagePage,
+ long usage)
+{
+ CFMutableDictionaryRef result =
+ CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeDictionaryKeyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+
+ if (result)
+ {
+ CFNumberRef pageRef = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberLongType,
+ &usagePage);
+ if (pageRef)
+ {
+ CFDictionarySetValue(result,
+ CFSTR(kIOHIDDeviceUsagePageKey),
+ pageRef);
+ CFRelease(pageRef);
+
+ CFNumberRef usageRef = CFNumberCreate(kCFAllocatorDefault,
+ kCFNumberLongType,
+ &usage);
+ if (usageRef)
+ {
+ CFDictionarySetValue(result,
+ CFSTR(kIOHIDDeviceUsageKey),
+ usageRef);
+ CFRelease(usageRef);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksNS(void)
+{
+ CFMutableArrayRef matchingCFArrayRef;
+
+ _glfw.ns.hidManager = IOHIDManagerCreate(kCFAllocatorDefault,
+ kIOHIDOptionsTypeNone);
+
+ matchingCFArrayRef = CFArrayCreateMutable(kCFAllocatorDefault,
+ 0,
+ &kCFTypeArrayCallBacks);
+ if (matchingCFArrayRef)
+ {
+ CFDictionaryRef matchingCFDictRef =
+ createMatchingDictionary(kHIDPage_GenericDesktop,
+ kHIDUsage_GD_Joystick);
+ if (matchingCFDictRef)
+ {
+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
+ CFRelease(matchingCFDictRef);
+ }
+
+ matchingCFDictRef = createMatchingDictionary(kHIDPage_GenericDesktop,
+ kHIDUsage_GD_GamePad);
+ if (matchingCFDictRef)
+ {
+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
+ CFRelease(matchingCFDictRef);
+ }
+
+ matchingCFDictRef =
+ createMatchingDictionary(kHIDPage_GenericDesktop,
+ kHIDUsage_GD_MultiAxisController);
+ if (matchingCFDictRef)
+ {
+ CFArrayAppendValue(matchingCFArrayRef, matchingCFDictRef);
+ CFRelease(matchingCFDictRef);
+ }
+
+ IOHIDManagerSetDeviceMatchingMultiple(_glfw.ns.hidManager,
+ matchingCFArrayRef);
+ CFRelease(matchingCFArrayRef);
+ }
+
+ IOHIDManagerRegisterDeviceMatchingCallback(_glfw.ns.hidManager,
+ &matchCallback, NULL);
+ IOHIDManagerRegisterDeviceRemovalCallback(_glfw.ns.hidManager,
+ &removeCallback, NULL);
+
+ IOHIDManagerScheduleWithRunLoop(_glfw.ns.hidManager,
+ CFRunLoopGetMain(),
+ kCFRunLoopDefaultMode);
+
+ IOHIDManagerOpen(_glfw.ns.hidManager, kIOHIDOptionsTypeNone);
+
+ // Execute the run loop once in order to register any initially-attached
+ // joysticks
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksNS(void)
+{
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ _GLFWjoystickNS* js = _glfw.ns_js + joy;
+ removeJoystick(js);
+ }
+
+ CFRelease(_glfw.ns.hidManager);
+ _glfw.ns.hidManager = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformJoystickPresent(int joy)
+{
+ _GLFWjoystickNS* js = _glfw.ns_js + joy;
+ return js->present;
+}
+
+const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
+{
+ _GLFWjoystickNS* js = _glfw.ns_js + joy;
+ if (!pollJoystickAxisEvents(js))
+ return NULL;
+
+ *count = (int) CFArrayGetCount(js->axisElements);
+ return js->axes;
+}
+
+const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
+{
+ _GLFWjoystickNS* js = _glfw.ns_js + joy;
+ if (!pollJoystickButtonEvents(js))
+ return NULL;
+
+ *count = (int) CFArrayGetCount(js->buttonElements) +
+ (int) CFArrayGetCount(js->hatElements) * 4;
+ return js->buttons;
+}
+
+const char* _glfwPlatformGetJoystickName(int joy)
+{
+ _GLFWjoystickNS* js = _glfw.ns_js + joy;
+ if (!js->present)
+ return NULL;
+
+ return js->name;
+}
+
diff --git a/glfw-3.2.1/src/cocoa_monitor.m b/glfw-3.2.1/src/cocoa_monitor.m
new file mode 100644
index 0000000..9ac0a83
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_monitor.m
@@ -0,0 +1,413 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <limits.h>
+
+#include <IOKit/graphics/IOGraphicsLib.h>
+#include <CoreVideo/CVBase.h>
+#include <CoreVideo/CVDisplayLink.h>
+#include <ApplicationServices/ApplicationServices.h>
+
+
+// Get the name of the specified display
+//
+static char* getDisplayName(CGDirectDisplayID displayID)
+{
+ char* name;
+ CFDictionaryRef info, names;
+ CFStringRef value;
+ CFIndex size;
+
+ // NOTE: This uses a deprecated function because Apple has
+ // (as of January 2015) not provided any alternative
+ info = IODisplayCreateInfoDictionary(CGDisplayIOServicePort(displayID),
+ kIODisplayOnlyPreferredName);
+ names = CFDictionaryGetValue(info, CFSTR(kDisplayProductName));
+
+ if (!names || !CFDictionaryGetValueIfPresent(names, CFSTR("en_US"),
+ (const void**) &value))
+ {
+ // This may happen if a desktop Mac is running headless
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve display name");
+
+ CFRelease(info);
+ return strdup("Unknown");
+ }
+
+ size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(value),
+ kCFStringEncodingUTF8);
+ name = calloc(size + 1, 1);
+ CFStringGetCString(value, 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;
+
+ CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+ if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) &&
+ CFStringCompare(format, CFSTR(IO32BitDirectPixels), 0))
+ {
+ CFRelease(format);
+ return GLFW_FALSE;
+ }
+
+ CFRelease(format);
+ return GLFW_TRUE;
+}
+
+// Convert Core Graphics display mode to GLFW video mode
+//
+static GLFWvidmode vidmodeFromCGDisplayMode(CGDisplayModeRef mode,
+ CVDisplayLinkRef link)
+{
+ GLFWvidmode result;
+ result.width = (int) CGDisplayModeGetWidth(mode);
+ result.height = (int) CGDisplayModeGetHeight(mode);
+ result.refreshRate = (int) CGDisplayModeGetRefreshRate(mode);
+
+ if (result.refreshRate == 0)
+ {
+ const CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
+ if (!(time.flags & kCVTimeIsIndefinite))
+ result.refreshRate = (int) (time.timeScale / (double) time.timeValue);
+ }
+
+ CFStringRef format = CGDisplayModeCopyPixelEncoding(mode);
+
+ if (CFStringCompare(format, CFSTR(IO16BitDirectPixels), 0) == 0)
+ {
+ result.redBits = 5;
+ result.greenBits = 5;
+ result.blueBits = 5;
+ }
+ else
+ {
+ result.redBits = 8;
+ result.greenBits = 8;
+ result.blueBits = 8;
+ }
+
+ CFRelease(format);
+ 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);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Change the current video mode
+//
+GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ CFArrayRef modes;
+ CFIndex count, i;
+ CVDisplayLinkRef link;
+ CGDisplayModeRef native = NULL;
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return GLFW_TRUE;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+ count = CFArrayGetCount(modes);
+
+ for (i = 0; i < count; i++)
+ {
+ CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+ if (!modeIsGood(dm))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
+ 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);
+ CVDisplayLinkRelease(link);
+
+ if (!native)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Monitor mode list changed");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// 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 //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ uint32_t i, found = 0, displayCount;
+ _GLFWmonitor** monitors;
+ CGDirectDisplayID* displays;
+
+ *count = 0;
+
+ CGGetOnlineDisplayList(0, NULL, &displayCount);
+ displays = calloc(displayCount, sizeof(CGDirectDisplayID));
+ monitors = calloc(displayCount, sizeof(_GLFWmonitor*));
+
+ CGGetOnlineDisplayList(displayCount, displays, &displayCount);
+
+ for (i = 0; i < displayCount; i++)
+ {
+ _GLFWmonitor* monitor;
+
+ if (CGDisplayIsAsleep(displays[i]))
+ continue;
+
+ const CGSize size = CGDisplayScreenSize(displays[i]);
+ char* name = getDisplayName(displays[i]);
+
+ monitor = _glfwAllocMonitor(name, size.width, size.height);
+ monitor->ns.displayID = displays[i];
+ monitor->ns.unitNumber = CGDisplayUnitNumber(displays[i]);
+
+ free(name);
+
+ found++;
+ monitors[found - 1] = monitor;
+ }
+
+ free(displays);
+
+ *count = found;
+ return monitors;
+}
+
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ // HACK: Compare unit numbers instead of display IDs to work around display
+ // replacement on machines with automatic graphics switching
+ return first->ns.unitNumber == second->ns.unitNumber;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ const CGRect bounds = CGDisplayBounds(monitor->ns.displayID);
+
+ if (xpos)
+ *xpos = (int) bounds.origin.x;
+ if (ypos)
+ *ypos = (int) bounds.origin.y;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+ CFArrayRef modes;
+ CFIndex found, i, j;
+ GLFWvidmode* result;
+ CVDisplayLinkRef link;
+
+ *count = 0;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
+ found = CFArrayGetCount(modes);
+ result = calloc(found, sizeof(GLFWvidmode));
+
+ for (i = 0; i < found; i++)
+ {
+ CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
+ if (!modeIsGood(dm))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
+
+ 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);
+ CVDisplayLinkRelease(link);
+ return result;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
+{
+ CGDisplayModeRef displayMode;
+ CVDisplayLinkRef link;
+
+ CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
+
+ displayMode = CGDisplayCopyDisplayMode(monitor->ns.displayID);
+ *mode = vidmodeFromCGDisplayMode(displayMode, link);
+ CGDisplayModeRelease(displayMode);
+
+ CVDisplayLinkRelease(link);
+}
+
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ uint32_t i, 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 (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);
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ int i;
+ CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
+
+ for (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);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// 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-3.2.1/src/cocoa_platform.h b/glfw-3.2.1/src/cocoa_platform.h
new file mode 100644
index 0000000..9221427
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_platform.h
@@ -0,0 +1,150 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_cocoa_platform_h_
+#define _glfw3_cocoa_platform_h_
+
+#include <stdint.h>
+#include <dlfcn.h>
+
+#if defined(__OBJC__)
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#else
+#include <Carbon/Carbon.h>
+#include <ApplicationServices/ApplicationServices.h>
+typedef void* id;
+#endif
+
+#include "posix_tls.h"
+#include "cocoa_joystick.h"
+#include "nsgl_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_PLATFORM_WINDOW_STATE _GLFWwindowNS ns
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryNS ns
+#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeNS ns_time
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorNS ns
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorNS ns
+
+#define _GLFW_EGL_CONTEXT_STATE
+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE
+
+// HIToolbox.framework pointer typedefs
+#define kTISPropertyUnicodeKeyLayoutData _glfw.ns.tis.kPropertyUnicodeKeyLayoutData
+#define kTISNotifySelectedKeyboardInputSourceChanged _glfw.ns.tis.kNotifySelectedKeyboardInputSourceChanged
+typedef TISInputSourceRef (*PFN_TISCopyCurrentKeyboardLayoutInputSource)(void);
+#define TISCopyCurrentKeyboardLayoutInputSource _glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource
+typedef void* (*PFN_TISGetInputSourceProperty)(TISInputSourceRef,CFStringRef);
+#define TISGetInputSourceProperty _glfw.ns.tis.GetInputSourceProperty
+typedef UInt8 (*PFN_LMGetKbdType)(void);
+#define LMGetKbdType _glfw.ns.tis.GetKbdType
+
+
+// Cocoa-specific per-window data
+//
+typedef struct _GLFWwindowNS
+{
+ id object;
+ id delegate;
+ id view;
+
+ // 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;
+ id autoreleasePool;
+ id cursor;
+ TISInputSourceRef inputSource;
+ IOHIDManagerRef hidManager;
+ id unicodeData;
+ id listener;
+
+ char keyName[64];
+ short int publicKeys[256];
+ short int nativeKeys[GLFW_KEY_LAST + 1];
+ char* clipboardString;
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+
+ struct {
+ CFBundleRef bundle;
+ PFN_TISCopyCurrentKeyboardLayoutInputSource CopyCurrentKeyboardLayoutInputSource;
+ PFN_TISGetInputSourceProperty GetInputSourceProperty;
+ PFN_LMGetKbdType GetKbdType;
+ CFStringRef kPropertyUnicodeKeyLayoutData;
+ CFStringRef kNotifySelectedKeyboardInputSourceChanged;
+ } tis;
+
+} _GLFWlibraryNS;
+
+// Cocoa-specific per-monitor data
+//
+typedef struct _GLFWmonitorNS
+{
+ CGDirectDisplayID displayID;
+ CGDisplayModeRef previousMode;
+ uint32_t unitNumber;
+
+} _GLFWmonitorNS;
+
+// Cocoa-specific per-cursor data
+//
+typedef struct _GLFWcursorNS
+{
+ id object;
+
+} _GLFWcursorNS;
+
+// Cocoa-specific global timer data
+//
+typedef struct _GLFWtimeNS
+{
+ uint64_t frequency;
+
+} _GLFWtimeNS;
+
+
+void _glfwInitTimerNS(void);
+
+GLFWbool _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
+
+#endif // _glfw3_cocoa_platform_h_
diff --git a/glfw-3.2.1/src/cocoa_time.c b/glfw-3.2.1/src/cocoa_time.c
new file mode 100644
index 0000000..dacfed0
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_time.c
@@ -0,0 +1,60 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <mach/mach_time.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerNS(void)
+{
+ mach_timebase_info_data_t info;
+ mach_timebase_info(&info);
+
+ _glfw.ns_time.frequency = (info.denom * 1e9) / info.numer;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+ return mach_absolute_time();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.ns_time.frequency;
+}
+
diff --git a/glfw-3.2.1/src/cocoa_window.m b/glfw-3.2.1/src/cocoa_window.m
new file mode 100644
index 0000000..b002e99
--- /dev/null
+++ b/glfw-3.2.1/src/cocoa_window.m
@@ -0,0 +1,1653 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <float.h>
+#include <string.h>
+
+// Needed for _NSGetProgname
+#include <crt_externs.h>
+
+
+// Returns the specified standard cursor
+//
+static NSCursor* getStandardCursor(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return [NSCursor arrowCursor];
+ case GLFW_IBEAM_CURSOR:
+ return [NSCursor IBeamCursor];
+ case GLFW_CROSSHAIR_CURSOR:
+ return [NSCursor crosshairCursor];
+ case GLFW_HAND_CURSOR:
+ return [NSCursor pointingHandCursor];
+ case GLFW_HRESIZE_CURSOR:
+ return [NSCursor resizeLeftRightCursor];
+ case GLFW_VRESIZE_CURSOR:
+ return [NSCursor resizeUpDownCursor];
+ }
+
+ return nil;
+}
+
+// Returns the style mask corresponding to the window settings
+//
+static NSUInteger getStyleMask(_GLFWwindow* window)
+{
+ NSUInteger styleMask = 0;
+
+ if (window->monitor || !window->decorated)
+ styleMask |= NSBorderlessWindowMask;
+ else
+ {
+ styleMask |= NSTitledWindowMask | NSClosableWindowMask |
+ NSMiniaturizableWindowMask;
+
+ if (window->resizable)
+ styleMask |= NSResizableWindowMask;
+ }
+
+ return styleMask;
+}
+
+// Center the cursor in the view of the window
+//
+static void centerCursor(_GLFWwindow *window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Returns whether the cursor is in the client area of the specified window
+//
+static GLFWbool cursorInClientArea(_GLFWwindow* window)
+{
+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+ return [window->ns.view mouse:pos inRect:[window->ns.view frame]];
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (window->cursor)
+ [(NSCursor*) window->cursor->ns.object set];
+ else
+ [[NSCursor arrowCursor] set];
+ }
+ else
+ [(NSCursor*) _glfw.ns.cursor set];
+}
+
+// Transforms the specified y-coordinate between the CG display and NS screen
+// coordinate systems
+//
+static float transformY(float y)
+{
+ return CGDisplayBounds(CGMainDisplayID()).size.height - y;
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static GLFWbool acquireMonitor(_GLFWwindow* window)
+{
+ const GLFWbool status = _glfwSetVideoModeNS(window->monitor, &window->videoMode);
+ const CGRect bounds = CGDisplayBounds(window->monitor->ns.displayID);
+ const NSRect frame = NSMakeRect(bounds.origin.x,
+ transformY(bounds.origin.y + bounds.size.height),
+ bounds.size.width,
+ bounds.size.height);
+
+ [window->ns.object setFrame:frame display:YES];
+
+ _glfwInputMonitorWindowChange(window->monitor, window);
+ return status;
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfwInputMonitorWindowChange(window->monitor, NULL);
+ _glfwRestoreVideoModeNS(window->monitor);
+}
+
+// Translates OS X key modifiers into GLFW ones
+//
+static int translateFlags(NSUInteger flags)
+{
+ int mods = 0;
+
+ if (flags & NSShiftKeyMask)
+ mods |= GLFW_MOD_SHIFT;
+ if (flags & NSControlKeyMask)
+ mods |= GLFW_MOD_CONTROL;
+ if (flags & NSAlternateKeyMask)
+ mods |= GLFW_MOD_ALT;
+ if (flags & NSCommandKeyMask)
+ mods |= GLFW_MOD_SUPER;
+
+ return mods;
+}
+
+// Translates a OS X keycode to a GLFW keycode
+//
+static int translateKey(unsigned int key)
+{
+ if (key >= sizeof(_glfw.ns.publicKeys) / sizeof(_glfw.ns.publicKeys[0]))
+ return GLFW_KEY_UNKNOWN;
+
+ return _glfw.ns.publicKeys[key];
+}
+
+// Translate a GLFW keycode to a Cocoa modifier flag
+//
+static NSUInteger translateKeyToModifierFlag(int key)
+{
+ switch (key)
+ {
+ case GLFW_KEY_LEFT_SHIFT:
+ case GLFW_KEY_RIGHT_SHIFT:
+ return NSShiftKeyMask;
+ case GLFW_KEY_LEFT_CONTROL:
+ case GLFW_KEY_RIGHT_CONTROL:
+ return NSControlKeyMask;
+ case GLFW_KEY_LEFT_ALT:
+ case GLFW_KEY_RIGHT_ALT:
+ return NSAlternateKeyMask;
+ case GLFW_KEY_LEFT_SUPER:
+ case GLFW_KEY_RIGHT_SUPER:
+ return NSCommandKeyMask;
+ }
+
+ return 0;
+}
+
+// Defines a constant for empty ranges in NSTextInputClient
+//
+static const NSRange kEmptyRange = { NSNotFound, 0 };
+
+
+//------------------------------------------------------------------------
+// Delegate for window related notifications
+//------------------------------------------------------------------------
+
+@interface GLFWWindowDelegate : NSObject
+{
+ _GLFWwindow* window;
+}
+
+- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWWindowDelegate
+
+- (id)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)
+ centerCursor(window);
+
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.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)
+ centerCursor(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)
+ centerCursor(window);
+
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+ _glfwPlatformSetCursorMode(window, window->cursorMode);
+}
+
+- (void)windowDidResignKey:(NSNotification *)notification
+{
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// Delegate for application related notifications
+//------------------------------------------------------------------------
+
+@interface GLFWApplicationDelegate : NSObject
+@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
+{
+ _glfwInputMonitorChange();
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+ [NSApp stop:nil];
+
+ _glfwPlatformPostEmptyEvent();
+}
+
+- (void)applicationDidHide:(NSNotification *)notification
+{
+ int i;
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ _glfwRestoreVideoModeNS(_glfw.monitors[i]);
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// Content view class for the GLFW window
+//------------------------------------------------------------------------
+
+@interface GLFWContentView : NSView <NSTextInputClient>
+{
+ _GLFWwindow* window;
+ NSTrackingArea* trackingArea;
+ NSMutableAttributedString* markedText;
+}
+
+- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow;
+
+@end
+
+@implementation GLFWContentView
+
++ (void)initialize
+{
+ if (self == [GLFWContentView class])
+ {
+ if (_glfw.ns.cursor == nil)
+ {
+ NSImage* data = [[NSImage alloc] initWithSize:NSMakeSize(16, 16)];
+ _glfw.ns.cursor = [[NSCursor alloc] initWithImage:data
+ hotSpot:NSZeroPoint];
+ [data release];
+ }
+ }
+}
+
+- (id)initWithGlfwWindow:(_GLFWwindow *)initWindow
+{
+ self = [super init];
+ if (self != nil)
+ {
+ window = initWindow;
+ trackingArea = nil;
+ markedText = [[NSMutableAttributedString alloc] init];
+
+ [self updateTrackingAreas];
+ [self registerForDraggedTypes:[NSArray arrayWithObjects:
+ NSFilenamesPboardType, nil]];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [trackingArea release];
+ [markedText release];
+ [super dealloc];
+}
+
+- (BOOL)isOpaque
+{
+ return YES;
+}
+
+- (BOOL)canBecomeKeyView
+{
+ return YES;
+}
+
+- (BOOL)acceptsFirstResponder
+{
+ return YES;
+}
+
+- (void)cursorUpdate:(NSEvent *)event
+{
+ updateCursorImage(window);
+}
+
+- (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];
+ 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
+{
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+- (void)mouseEntered:(NSEvent *)event
+{
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+}
+
+- (void)viewDidChangeBackingProperties
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ _glfwInputFramebufferSize(window, fbRect.size.width, fbRect.size.height);
+}
+
+- (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:[NSArray arrayWithObject:event]];
+}
+
+- (void)flagsChanged:(NSEvent *)event
+{
+ int action;
+ const unsigned int modifierFlags =
+ [event modifierFlags] & NSDeviceIndependentModifierFlagsMask;
+ 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, deltaY;
+
+ deltaX = [event scrollingDeltaX];
+ 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
+{
+ if ((NSDragOperationGeneric & [sender draggingSourceOperationMask])
+ == NSDragOperationGeneric)
+ {
+ [self setNeedsDisplay:YES];
+ return NSDragOperationGeneric;
+ }
+
+ return NSDragOperationNone;
+}
+
+- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
+{
+ [self setNeedsDisplay:YES];
+ return YES;
+}
+
+- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
+{
+ NSPasteboard* pasteboard = [sender draggingPasteboard];
+ NSArray* files = [pasteboard propertyListForType:NSFilenamesPboardType];
+
+ const NSRect contentRect = [window->ns.view frame];
+ _glfwInputCursorPos(window,
+ [sender draggingLocation].x,
+ contentRect.size.height - [sender draggingLocation].y);
+
+ const int count = [files count];
+ if (count)
+ {
+ NSEnumerator* e = [files objectEnumerator];
+ char** paths = calloc(count, sizeof(char*));
+ int i;
+
+ for (i = 0; i < count; i++)
+ paths[i] = strdup([[e nextObject] UTF8String]);
+
+ _glfwInputDrop(window, count, (const char**) paths);
+
+ for (i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+ }
+
+ return YES;
+}
+
+- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
+{
+ [self setNeedsDisplay:YES];
+}
+
+- (BOOL)hasMarkedText
+{
+ return [markedText length] > 0;
+}
+
+- (NSRange)markedRange
+{
+ if ([markedText length] > 0)
+ return NSMakeRange(0, [markedText length] - 1);
+ else
+ return kEmptyRange;
+}
+
+- (NSRange)selectedRange
+{
+ return kEmptyRange;
+}
+
+- (void)setMarkedText:(id)string
+ selectedRange:(NSRange)selectedRange
+ replacementRange:(NSRange)replacementRange
+{
+ if ([string isKindOfClass:[NSAttributedString class]])
+ [markedText initWithAttributedString:string];
+ else
+ [markedText initWithString:string];
+}
+
+- (void)unmarkText
+{
+ [[markedText mutableString] setString:@""];
+}
+
+- (NSArray*)validAttributesForMarkedText
+{
+ return [NSArray array];
+}
+
+- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange
+{
+ return nil;
+}
+
+- (NSUInteger)characterIndexForPoint:(NSPoint)point
+{
+ return 0;
+}
+
+- (NSRect)firstRectForCharacterRange:(NSRange)range
+ actualRange:(NSRangePointer)actualRange
+{
+ int xpos, ypos;
+ _glfwPlatformGetWindowPos(window, &xpos, &ypos);
+ const NSRect contentRect = [window->ns.view frame];
+ return NSMakeRect(xpos, transformY(ypos + contentRect.size.height), 0.0, 0.0);
+}
+
+- (void)insertText:(id)string replacementRange:(NSRange)replacementRange
+{
+ NSString* characters;
+ NSEvent* event = [NSApp currentEvent];
+ const int mods = translateFlags([event modifierFlags]);
+ const int plain = !(mods & GLFW_MOD_SUPER);
+
+ if ([string isKindOfClass:[NSAttributedString class]])
+ characters = [string string];
+ else
+ characters = (NSString*) string;
+
+ NSUInteger i, length = [characters length];
+
+ for (i = 0; i < length; i++)
+ {
+ const unichar codepoint = [characters characterAtIndex:i];
+ if ((codepoint & 0xff00) == 0xf700)
+ continue;
+
+ _glfwInputChar(window, codepoint, mods, plain);
+ }
+}
+
+- (void)doCommandBySelector:(SEL)selector
+{
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// GLFW window class
+//------------------------------------------------------------------------
+
+@interface GLFWWindow : NSWindow {}
+@end
+
+@implementation GLFWWindow
+
+- (BOOL)canBecomeKeyWindow
+{
+ // Required for NSBorderlessWindowMask windows
+ return YES;
+}
+
+@end
+
+
+//------------------------------------------------------------------------
+// GLFW application class
+//------------------------------------------------------------------------
+
+@interface GLFWApplication : NSApplication
+@end
+
+@implementation GLFWApplication
+
+// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
+// This works around an AppKit bug, where key up events while holding
+// down the command key don't get sent to the key window.
+- (void)sendEvent:(NSEvent *)event
+{
+ if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask))
+ [[self keyWindow] sendEvent:event];
+ else
+ [super sendEvent:event];
+}
+
+
+// No-op thread entry point
+//
+- (void)doNothing:(id)object
+{
+}
+@end
+
+#if defined(_GLFW_USE_MENUBAR)
+
+// Try to figure out what the calling application is called
+//
+static NSString* findAppName(void)
+{
+ size_t i;
+ NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
+
+ // Keys to search for as potential application names
+ NSString* GLFWNameKeys[] =
+ {
+ @"CFBundleDisplayName",
+ @"CFBundleName",
+ @"CFBundleExecutable",
+ };
+
+ for (i = 0; i < sizeof(GLFWNameKeys) / sizeof(GLFWNameKeys[0]); i++)
+ {
+ id name = [infoDictionary objectForKey:GLFWNameKeys[i]];
+ if (name &&
+ [name isKindOfClass:[NSString class]] &&
+ ![name isEqualToString:@""])
+ {
+ return name;
+ }
+ }
+
+ char** progname = _NSGetProgname();
+ if (progname && *progname)
+ return [NSString stringWithUTF8String:*progname];
+
+ // Really shouldn't get here
+ return @"GLFW Application";
+}
+
+// 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. Loading a nib would save us this horror, but that
+// doesn't seem like a good thing to require of GLFW users.
+//
+static void createMenuBar(void)
+{
+ NSString* appName = findAppName();
+
+ 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:NSAlternateKeyMask | NSCommandKeyMask];
+ [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:NSControlKeyMask | NSCommandKeyMask];
+
+ // 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];
+}
+
+#endif /* _GLFW_USE_MENUBAR */
+
+// Initialize the Cocoa Application Kit
+//
+static GLFWbool initializeAppKit(void)
+{
+ if (NSApp)
+ return GLFW_TRUE;
+
+ // Implicitly create shared NSApplication instance
+ [GLFWApplication sharedApplication];
+
+ // Make Cocoa enter multi-threaded mode
+ [NSThread detachNewThreadSelector:@selector(doNothing:)
+ toTarget:NSApp
+ withObject:nil];
+
+ // In case we are unbundled, make us a proper UI application
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
+
+#if defined(_GLFW_USE_MENUBAR)
+ // Menu bar setup must go between sharedApplication above and
+ // finishLaunching below, in order to properly emulate the behavior
+ // of NSApplicationMain
+ createMenuBar();
+#endif
+
+ // There can only be one application delegate, but we allocate it the
+ // first time a window is created to keep all window code in this file
+ _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];
+ [NSApp run];
+
+ return GLFW_TRUE;
+}
+
+// Create the Cocoa window
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig)
+{
+ window->ns.delegate = [[GLFWWindowDelegate alloc] initWithGlfwWindow:window];
+ if (window->ns.delegate == nil)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to create window delegate");
+ return 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
+ {
+ [window->ns.object center];
+
+ if (wndconfig->resizable)
+ [window->ns.object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+
+ if (wndconfig->floating)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+
+ if (wndconfig->maximized)
+ [window->ns.object zoom:nil];
+ }
+
+ window->ns.view = [[GLFWContentView alloc] initWithGlfwWindow:window];
+
+#if defined(_GLFW_USE_RETINA)
+ [window->ns.view setWantsBestResolutionOpenGLSurface:YES];
+#endif /*_GLFW_USE_RETINA*/
+
+ [window->ns.object makeFirstResponder:window->ns.view];
+ [window->ns.object setTitle:[NSString stringWithUTF8String:wndconfig->title]];
+ [window->ns.object setDelegate:window->ns.delegate];
+ [window->ns.object setAcceptsMouseMovedEvents:YES];
+ [window->ns.object setContentView:window->ns.view];
+ [window->ns.object setRestorable:NO];
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!initializeAppKit())
+ return GLFW_FALSE;
+
+ if (!createNativeWindow(window, wndconfig))
+ 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
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Cocoa: EGL not available");
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ _glfwPlatformFocusWindow(window);
+ if (!acquireMonitor(window))
+ return GLFW_FALSE;
+
+ centerCursor(window);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (_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;
+
+ [_glfw.ns.autoreleasePool drain];
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char *title)
+{
+ [window->ns.object setTitle:[NSString stringWithUTF8String:title]];
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ // Regular windows do not have icons
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ const NSRect contentRect =
+ [window->ns.object contentRectForFrameRect:[window->ns.object frame]];
+
+ if (xpos)
+ *xpos = contentRect.origin.x;
+ if (ypos)
+ *ypos = transformY(contentRect.origin.y + contentRect.size.height);
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect dummyRect = NSMakeRect(x, transformY(y + contentRect.size.height), 0, 0);
+ const NSRect frameRect = [window->ns.object frameRectForContentRect:dummyRect];
+ [window->ns.object setFrameOrigin:frameRect.origin];
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ const NSRect contentRect = [window->ns.view frame];
+
+ if (width)
+ *width = contentRect.size.width;
+ if (height)
+ *height = contentRect.size.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ [window->ns.object setContentSize:NSMakeSize(width, height)];
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
+ [window->ns.object setContentMinSize:NSMakeSize(0, 0)];
+ else
+ [window->ns.object setContentMinSize:NSMakeSize(minwidth, minheight)];
+
+ if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
+ [window->ns.object setContentMaxSize:NSMakeSize(DBL_MAX, DBL_MAX)];
+ else
+ [window->ns.object setContentMaxSize:NSMakeSize(maxwidth, maxheight)];
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
+ [window->ns.object setContentAspectRatio:NSMakeSize(0, 0)];
+ else
+ [window->ns.object setContentAspectRatio:NSMakeSize(numer, denom)];
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSRect fbRect = [window->ns.view convertRectToBacking:contentRect];
+
+ if (width)
+ *width = (int) fbRect.size.width;
+ if (height)
+ *height = (int) fbRect.size.height;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ 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;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ [window->ns.object miniaturize:nil];
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ if ([window->ns.object isMiniaturized])
+ [window->ns.object deminiaturize:nil];
+ else if ([window->ns.object isZoomed])
+ [window->ns.object zoom:nil];
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (![window->ns.object isZoomed])
+ [window->ns.object zoom:nil];
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ [window->ns.object orderFront:nil];
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ [window->ns.object orderOut:nil];
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ // Make us the active application
+ // HACK: This has been moved here from initializeAppKit to prevent
+ // applications using only hidden windows from being activated, but
+ // should probably not be done every time any window is shown
+ [NSApp activateIgnoringOtherApps:YES];
+
+ [window->ns.object makeKeyAndOrderFront:nil];
+}
+
+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
+ {
+ const NSRect contentRect =
+ NSMakeRect(xpos, transformY(ypos + height), 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);
+
+ _glfwInputWindowMonitorChange(window, monitor);
+
+ const NSUInteger styleMask = getStyleMask(window);
+ [window->ns.object setStyleMask:styleMask];
+ [window->ns.object makeFirstResponder:window->ns.view];
+
+ NSRect contentRect;
+
+ if (monitor)
+ {
+ GLFWvidmode mode;
+
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+
+ contentRect = NSMakeRect(xpos, transformY(ypos + mode.height),
+ mode.width, mode.height);
+ }
+ else
+ {
+ contentRect = NSMakeRect(xpos, transformY(ypos + height),
+ width, height);
+ }
+
+ NSRect frameRect = [window->ns.object frameRectForContentRect:contentRect
+ styleMask:styleMask];
+ [window->ns.object setFrame:frameRect display:YES];
+
+ if (monitor)
+ {
+ [window->ns.object setLevel:NSMainMenuWindowLevel + 1];
+ [window->ns.object setHasShadow:NO];
+
+ acquireMonitor(window);
+ }
+ else
+ {
+ if (window->numer != GLFW_DONT_CARE &&
+ window->denom != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentAspectRatio:NSMakeSize(window->numer,
+ window->denom)];
+ }
+
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentMinSize:NSMakeSize(window->minwidth,
+ window->minheight)];
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ [window->ns.object setContentMaxSize:NSMakeSize(window->maxwidth,
+ window->maxheight)];
+ }
+
+ if (window->floating)
+ [window->ns.object setLevel:NSFloatingWindowLevel];
+ else
+ [window->ns.object setLevel:NSNormalWindowLevel];
+
+ [window->ns.object setHasShadow:YES];
+ }
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return [window->ns.object isKeyWindow];
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return [window->ns.object isMiniaturized];
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return [window->ns.object isVisible];
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return [window->ns.object isZoomed];
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ for (;;)
+ {
+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event == nil)
+ break;
+
+ [NSApp sendEvent:event];
+ }
+
+ [_glfw.ns.autoreleasePool drain];
+ _glfw.ns.autoreleasePool = [[NSAutoreleasePool alloc] init];
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ // 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:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ [NSApp sendEvent:event];
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ NSDate* date = [NSDate dateWithTimeIntervalSinceNow:timeout];
+ NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:date
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ if (event)
+ [NSApp sendEvent:event];
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
+ location:NSMakePoint(0, 0)
+ modifierFlags:0
+ timestamp:0
+ windowNumber:0
+ context:nil
+ subtype:0
+ data1:0
+ data2:0];
+ [NSApp postEvent:event atStart:YES];
+ [pool drain];
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ const NSRect contentRect = [window->ns.view frame];
+ const NSPoint pos = [window->ns.object mouseLocationOutsideOfEventStream];
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = contentRect.size.height - pos.y - 1;
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+ updateCursorImage(window);
+
+ const NSRect contentRect = [window->ns.view frame];
+ 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,
+ transformY(globalPoint.y)));
+ }
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (mode == GLFW_CURSOR_DISABLED)
+ {
+ _glfw.ns.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.ns.restoreCursorPosX,
+ &_glfw.ns.restoreCursorPosY);
+ centerCursor(window);
+ CGAssociateMouseAndMouseCursorPosition(false);
+ }
+ else if (_glfw.ns.disabledCursorWindow == window)
+ {
+ _glfw.ns.disabledCursorWindow = NULL;
+ CGAssociateMouseAndMouseCursorPosition(true);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.ns.restoreCursorPosX,
+ _glfw.ns.restoreCursorPosY);
+ }
+
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+const char* _glfwPlatformGetKeyName(int key, int scancode)
+{
+ if (key != GLFW_KEY_UNKNOWN)
+ scancode = _glfw.ns.nativeKeys[key];
+
+ if (!_glfwIsPrintable(_glfw.ns.publicKeys[scancode]))
+ return NULL;
+
+ UInt32 deadKeyState = 0;
+ UniChar characters[8];
+ UniCharCount characterCount = 0;
+
+ if (UCKeyTranslate([(NSData*) _glfw.ns.unicodeData bytes],
+ scancode,
+ kUCKeyActionDisplay,
+ 0,
+ LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysBit,
+ &deadKeyState,
+ sizeof(characters) / sizeof(characters[0]),
+ &characterCount,
+ characters) != noErr)
+ {
+ return NULL;
+ }
+
+ if (!characterCount)
+ return NULL;
+
+ CFStringRef string = CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault,
+ characters,
+ characterCount,
+ kCFAllocatorNull);
+ CFStringGetCString(string,
+ _glfw.ns.keyName,
+ sizeof(_glfw.ns.keyName),
+ kCFStringEncodingUTF8);
+ CFRelease(string);
+
+ return _glfw.ns.keyName;
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ NSImage* native;
+ NSBitmapImageRep* rep;
+
+ if (!initializeAppKit())
+ return GLFW_FALSE;
+
+ rep = [[NSBitmapImageRep alloc]
+ initWithBitmapDataPlanes:NULL
+ pixelsWide:image->width
+ pixelsHigh:image->height
+ bitsPerSample:8
+ samplesPerPixel:4
+ hasAlpha:YES
+ isPlanar:NO
+ colorSpaceName:NSCalibratedRGBColorSpace
+ bitmapFormat:NSAlphaNonpremultipliedBitmapFormat
+ 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;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ if (!initializeAppKit())
+ return GLFW_FALSE;
+
+ cursor->ns.object = getStandardCursor(shape);
+ if (!cursor->ns.object)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve standard cursor");
+ return GLFW_FALSE;
+ }
+
+ [cursor->ns.object retain];
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->ns.object)
+ [(NSCursor*) cursor->ns.object release];
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ NSArray* types = [NSArray arrayWithObjects:NSStringPboardType, nil];
+
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+ [pasteboard declareTypes:types owner:nil];
+ [pasteboard setString:[NSString stringWithUTF8String:string]
+ forType:NSStringPboardType];
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
+
+ if (![[pasteboard types] containsObject:NSStringPboardType])
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "Cocoa: Failed to retrieve string from pasteboard");
+ return NULL;
+ }
+
+ NSString* object = [pasteboard stringForType:NSStringPboardType];
+ if (!object)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Cocoa: Failed to retrieve object from pasteboard");
+ return NULL;
+ }
+
+ free(_glfw.ns.clipboardString);
+ _glfw.ns.clipboardString = strdup([object UTF8String]);
+
+ return _glfw.ns.clipboardString;
+}
+
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
+{
+ *count = 0;
+ return NULL;
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ return GLFW_FALSE;
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW 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-3.2.1/src/context.c b/glfw-3.2.1/src/context.c
new file mode 100644
index 0000000..85bce7f
--- /dev/null
+++ b/glfw-3.2.1/src/context.c
@@ -0,0 +1,720 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
+{
+ if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
+ ctxconfig->source != GLFW_EGL_CONTEXT_API)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid context creation API %i",
+ 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 %i",
+ ctxconfig->client);
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->client == GLFW_OPENGL_API)
+ {
+ if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
+ (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
+ (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
+ (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 %i",
+ 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 %i",
+ 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 %i",
+ ctxconfig->release);
+ return GLFW_FALSE;
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+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++;
+ }
+ }
+
+ // 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;
+}
+
+GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig)
+{
+ int i;
+ _GLFWwindow* window;
+ const char* version;
+ const char* prefixes[] =
+ {
+ "OpenGL ES-CM ",
+ "OpenGL ES-CL ",
+ "OpenGL ES ",
+ NULL
+ };
+
+ window = _glfwPlatformGetCurrentContext();
+
+ window->context.source = ctxconfig->source;
+ window->context.client = GLFW_OPENGL_API;
+
+ window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
+ window->context.getProcAddress("glGetIntegerv");
+ window->context.GetString = (PFNGLGETSTRINGPROC)
+ window->context.getProcAddress("glGetString");
+ if (!window->context.GetIntegerv || !window->context.GetString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
+ 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");
+ }
+
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; prefixes[i]; i++)
+ {
+ const size_t length = strlen(prefixes[i]);
+
+ if (strncmp(version, prefixes[i], length) == 0)
+ {
+ version += length;
+ window->context.client = GLFW_OPENGL_ES_API;
+ break;
+ }
+ }
+
+ if (!sscanf(version, "%d.%d.%d",
+ &window->context.major,
+ &window->context.minor,
+ &window->context.revision))
+ {
+ if (window->context.client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "No version found in OpenGL version string");
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "No version found in OpenGL ES version string");
+ }
+
+ return GLFW_FALSE;
+ }
+
+ if (window->context.major < ctxconfig->major ||
+ (window->context.major == ctxconfig->major &&
+ window->context.minor < ctxconfig->minor))
+ {
+ // The desired OpenGL version is greater than the actual version
+ // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
+ // /and/ the user has requested an OpenGL version greater than 1.0
+
+ // For API consistency, we emulate the behavior of the
+ // {GLX|WGL}_ARB_create_context extension and fail here
+
+ if (window->context.client == GLFW_OPENGL_API)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "Requested OpenGL version %i.%i, got version %i.%i",
+ ctxconfig->major, ctxconfig->minor,
+ window->context.major, window->context.minor);
+ }
+ else
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "Requested OpenGL ES version %i.%i, got version %i.%i",
+ ctxconfig->major, ctxconfig->minor,
+ window->context.major, window->context.minor);
+ }
+
+ return GLFW_FALSE;
+ }
+
+ if (window->context.major >= 3)
+ {
+ // OpenGL 3.0+ uses a different function for extension string retrieval
+ // We cache it here instead of in glfwExtensionSupported mostly to alert
+ // users as early as possible that their build may be broken
+
+ window->context.GetStringi = (PFNGLGETSTRINGIPROC)
+ window->context.getProcAddress("glGetStringi");
+ if (!window->context.GetStringi)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Entry point retrieval is broken");
+ 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);
+ }
+
+ return GLFW_TRUE;
+}
+
+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 = _glfwPlatformGetCurrentContext();
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window && window->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ 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 (GLFWwindow*) _glfwPlatformGetCurrentContext();
+}
+
+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, NULL);
+ return;
+ }
+
+ window->context.swapBuffers(window);
+}
+
+GLFWAPI void glfwSwapInterval(int interval)
+{
+ _GLFWwindow* window;
+
+ _GLFW_REQUIRE_INIT();
+
+ window = _glfwPlatformGetCurrentContext();
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
+ return;
+ }
+
+ window->context.swapInterval(interval);
+}
+
+GLFWAPI int glfwExtensionSupported(const char* extension)
+{
+ _GLFWwindow* window;
+
+ assert(extension != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ window = _glfwPlatformGetCurrentContext();
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
+ return GLFW_FALSE;
+ }
+
+ if (*extension == '\0')
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Extension name is 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 = _glfwPlatformGetCurrentContext();
+ if (!window)
+ {
+ _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL);
+ return NULL;
+ }
+
+ return window->context.getProcAddress(procname);
+}
+
diff --git a/glfw-3.2.1/src/egl_context.c b/glfw-3.2.1/src/egl_context.c
new file mode 100644
index 0000000..e3d6260
--- /dev/null
+++ b/glfw-3.2.1/src/egl_context.c
@@ -0,0 +1,746 @@
+//========================================================================
+// GLFW 3.2 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <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)
+ // Only consider EGLConfigs with associated Visuals
+ if (!getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID))
+ continue;
+#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;
+ }
+ }
+
+ _glfwPlatformSetCurrentContext(window);
+}
+
+static void swapBuffersEGL(_GLFWwindow* window)
+{
+ if (window != _glfwPlatformGetCurrentContext())
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: The context must be current on the calling thread when swapping buffers");
+ return;
+ }
+
+ eglSwapBuffers(_glfw.egl.display, window->context.egl.surface);
+}
+
+static void swapIntervalEGL(int interval)
+{
+ eglSwapInterval(_glfw.egl.display, interval);
+}
+
+static int extensionSupportedEGL(const char* extension)
+{
+ const char* extensions = eglQueryString(_glfw.egl.display, EGL_EXTENSIONS);
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressEGL(const char* procname)
+{
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
+
+ if (window->context.egl.client)
+ {
+ GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client,
+ procname);
+ if (proc)
+ return proc;
+ }
+
+ return eglGetProcAddress(procname);
+}
+
+static void destroyContextEGL(_GLFWwindow* window)
+{
+#if defined(_GLFW_X11)
+ // NOTE: Do not unload libGL.so.1 while the X11 display is still open,
+ // as it will make XCloseDisplay segfault
+ if (window->context.client != GLFW_OPENGL_API)
+#endif // _GLFW_X11
+ {
+ if (window->context.egl.client)
+ {
+ _glfw_dlclose(window->context.egl.client);
+ window->context.egl.client = NULL;
+ }
+ }
+
+ if (window->context.egl.surface)
+ {
+ eglDestroySurface(_glfw.egl.display, window->context.egl.surface);
+ window->context.egl.surface = EGL_NO_SURFACE;
+ }
+
+ if (window->context.egl.handle)
+ {
+ eglDestroyContext(_glfw.egl.display, window->context.egl.handle);
+ window->context.egl.handle = EGL_NO_CONTEXT;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize EGL
+//
+GLFWbool _glfwInitEGL(void)
+{
+ int i;
+ const char* sonames[] =
+ {
+#if defined(_GLFW_WIN32)
+ "libEGL.dll",
+ "EGL.dll",
+#elif defined(_GLFW_COCOA)
+ "libEGL.dylib",
+#else
+ "libEGL.so.1",
+#endif
+ NULL
+ };
+
+ if (_glfw.egl.handle)
+ return GLFW_TRUE;
+
+ for (i = 0; sonames[i]; i++)
+ {
+ _glfw.egl.handle = _glfw_dlopen(sonames[i]);
+ if (_glfw.egl.handle)
+ break;
+ }
+
+ if (!_glfw.egl.handle)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found");
+ return GLFW_FALSE;
+ }
+
+ _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
+
+ _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib");
+ _glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs");
+ _glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay");
+ _glfw.egl.GetError = (PFNEGLGETERRORPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetError");
+ _glfw.egl.Initialize = (PFNEGLINITIALIZEPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglInitialize");
+ _glfw.egl.Terminate = (PFNEGLTERMINATEPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglTerminate");
+ _glfw.egl.BindAPI = (PFNEGLBINDAPIPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglBindAPI");
+ _glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglCreateContext");
+ _glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
+ _glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
+ _glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
+ _glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
+ _glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
+ _glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
+ _glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglQueryString");
+ _glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC)
+ _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
+
+ if (!_glfw.egl.GetConfigAttrib ||
+ !_glfw.egl.GetConfigs ||
+ !_glfw.egl.GetDisplay ||
+ !_glfw.egl.GetError ||
+ !_glfw.egl.Initialize ||
+ !_glfw.egl.Terminate ||
+ !_glfw.egl.BindAPI ||
+ !_glfw.egl.CreateContext ||
+ !_glfw.egl.DestroySurface ||
+ !_glfw.egl.DestroyContext ||
+ !_glfw.egl.CreateWindowSurface ||
+ !_glfw.egl.MakeCurrent ||
+ !_glfw.egl.SwapBuffers ||
+ !_glfw.egl.SwapInterval ||
+ !_glfw.egl.QueryString ||
+ !_glfw.egl.GetProcAddress)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "EGL: Failed to load required entry points");
+
+ _glfwTerminateEGL();
+ return GLFW_FALSE;
+ }
+
+ _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY);
+ if (_glfw.egl.display == EGL_NO_DISPLAY)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "EGL: Failed to get EGL display: %s",
+ 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");
+
+ 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 setEGLattrib(attribName, attribValue) \
+{ \
+ attribs[index++] = attribName; \
+ attribs[index++] = attribValue; \
+ assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
+}
+
+// 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;
+
+ 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 index = 0, 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 (_glfw.egl.KHR_create_context_no_error)
+ {
+ if (ctxconfig->noerror)
+ flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
+ }
+ }
+
+ if (ctxconfig->debug)
+ flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+
+ if (ctxconfig->robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+ EGL_NO_RESET_NOTIFICATION_KHR);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR,
+ EGL_LOSE_CONTEXT_ON_RESET_KHR);
+ }
+
+ flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+ }
+
+ if (ctxconfig->major != 1 || ctxconfig->minor != 0)
+ {
+ setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major);
+ setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor);
+ }
+
+ if (mask)
+ setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask);
+
+ if (flags)
+ setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags);
+
+ setEGLattrib(EGL_NONE, EGL_NONE);
+ }
+ else
+ {
+ int index = 0;
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major);
+
+ setEGLattrib(EGL_NONE, EGL_NONE);
+ }
+
+ // Context release behaviors (GL_KHR_context_flush_control) are not yet
+ // supported on EGL but are not a hard constraint, so ignore and continue
+
+ window->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)
+ {
+ setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR);
+ }
+ }
+
+ setEGLattrib(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
+ {
+ int i;
+ const char** sonames;
+ const char* es1sonames[] =
+ {
+#if 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_WIN32)
+ "GLESv2.dll",
+ "libGLESv2.dll",
+#elif defined(_GLFW_COCOA)
+ "libGLESv2.dylib",
+#else
+ "libGLESv2.so.2",
+#endif
+ NULL
+ };
+ const char* glsonames[] =
+ {
+#if defined(_GLFW_WIN32)
+#elif defined(_GLFW_COCOA)
+#else
+ "libGL.so.1",
+#endif
+ NULL
+ };
+
+ 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 setEGLattrib
+
+// Returns the Visual and depth of the chosen EGLConfig
+//
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth)
+{
+ 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-3.2.1/src/egl_context.h b/glfw-3.2.1/src/egl_context.h
new file mode 100644
index 0000000..9bd8bb4
--- /dev/null
+++ b/glfw-3.2.1/src/egl_context.h
@@ -0,0 +1,213 @@
+//========================================================================
+// GLFW 3.2 EGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_egl_context_h_
+#define _glfw3_egl_context_h_
+
+#if defined(_GLFW_USE_EGLPLATFORM_H)
+ #include <EGL/eglplatform.h>
+#elif defined(_GLFW_WIN32)
+ #define EGLAPIENTRY __stdcall
+typedef HDC EGLNativeDisplayType;
+typedef HWND EGLNativeWindowType;
+#elif defined(_GLFW_X11)
+ #define EGLAPIENTRY
+typedef Display* EGLNativeDisplayType;
+typedef Window EGLNativeWindowType;
+#elif defined(_GLFW_WAYLAND)
+ #define EGLAPIENTRY
+typedef struct wl_display* EGLNativeDisplayType;
+typedef struct wl_egl_window* EGLNativeWindowType;
+#elif defined(_GLFW_MIR)
+ #define EGLAPIENTRY
+typedef MirEGLNativeDisplayType EGLNativeDisplayType;
+typedef MirEGLNativeWindowType EGLNativeWindowType;
+#else
+ #error "No supported EGL platform selected"
+#endif
+
+#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
+
+typedef int EGLint;
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef void* EGLConfig;
+typedef void* EGLContext;
+typedef void* EGLDisplay;
+typedef void* EGLSurface;
+
+// EGL function pointer typedefs
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGATTRIBPROC)(EGLDisplay,EGLConfig,EGLint,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLGETCONFIGSPROC)(EGLDisplay,EGLConfig*,EGLint,EGLint*);
+typedef EGLDisplay (EGLAPIENTRY * PFNEGLGETDISPLAYPROC)(EGLNativeDisplayType);
+typedef EGLint (EGLAPIENTRY * PFNEGLGETERRORPROC)(void);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLINITIALIZEPROC)(EGLDisplay,EGLint*,EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLTERMINATEPROC)(EGLDisplay);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLBINDAPIPROC)(EGLenum);
+typedef EGLContext (EGLAPIENTRY * PFNEGLCREATECONTEXTPROC)(EGLDisplay,EGLConfig,EGLContext,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYSURFACEPROC)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLDESTROYCONTEXTPROC)(EGLDisplay,EGLContext);
+typedef EGLSurface (EGLAPIENTRY * PFNEGLCREATEWINDOWSURFACEPROC)(EGLDisplay,EGLConfig,EGLNativeWindowType,const EGLint*);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLMAKECURRENTPROC)(EGLDisplay,EGLSurface,EGLSurface,EGLContext);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPBUFFERSPROC)(EGLDisplay,EGLSurface);
+typedef EGLBoolean (EGLAPIENTRY * PFNEGLSWAPINTERVALPROC)(EGLDisplay,EGLint);
+typedef const char* (EGLAPIENTRY * PFNEGLQUERYSTRINGPROC)(EGLDisplay,EGLint);
+typedef GLFWglproc (EGLAPIENTRY * PFNEGLGETPROCADDRESSPROC)(const char*);
+#define eglGetConfigAttrib _glfw.egl.GetConfigAttrib
+#define eglGetConfigs _glfw.egl.GetConfigs
+#define eglGetDisplay _glfw.egl.GetDisplay
+#define eglGetError _glfw.egl.GetError
+#define eglInitialize _glfw.egl.Initialize
+#define eglTerminate _glfw.egl.Terminate
+#define eglBindAPI _glfw.egl.BindAPI
+#define eglCreateContext _glfw.egl.CreateContext
+#define eglDestroySurface _glfw.egl.DestroySurface
+#define eglDestroyContext _glfw.egl.DestroyContext
+#define eglCreateWindowSurface _glfw.egl.CreateWindowSurface
+#define eglMakeCurrent _glfw.egl.MakeCurrent
+#define eglSwapBuffers _glfw.egl.SwapBuffers
+#define eglSwapInterval _glfw.egl.SwapInterval
+#define eglQueryString _glfw.egl.QueryString
+#define eglGetProcAddress _glfw.egl.GetProcAddress
+
+#define _GLFW_EGL_CONTEXT_STATE _GLFWcontextEGL egl
+#define _GLFW_EGL_LIBRARY_CONTEXT_STATE _GLFWlibraryEGL egl
+
+
+// EGL-specific per-context data
+//
+typedef struct _GLFWcontextEGL
+{
+ EGLConfig config;
+ EGLContext 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;
+
+ void* handle;
+
+ PFNEGLGETCONFIGATTRIBPROC GetConfigAttrib;
+ PFNEGLGETCONFIGSPROC GetConfigs;
+ PFNEGLGETDISPLAYPROC GetDisplay;
+ PFNEGLGETERRORPROC GetError;
+ PFNEGLINITIALIZEPROC Initialize;
+ PFNEGLTERMINATEPROC Terminate;
+ PFNEGLBINDAPIPROC BindAPI;
+ PFNEGLCREATECONTEXTPROC CreateContext;
+ PFNEGLDESTROYSURFACEPROC DestroySurface;
+ PFNEGLDESTROYCONTEXTPROC DestroyContext;
+ PFNEGLCREATEWINDOWSURFACEPROC CreateWindowSurface;
+ PFNEGLMAKECURRENTPROC MakeCurrent;
+ PFNEGLSWAPBUFFERSPROC SwapBuffers;
+ PFNEGLSWAPINTERVALPROC SwapInterval;
+ PFNEGLQUERYSTRINGPROC QueryString;
+ PFNEGLGETPROCADDRESSPROC GetProcAddress;
+
+} _GLFWlibraryEGL;
+
+
+GLFWbool _glfwInitEGL(void);
+void _glfwTerminateEGL(void);
+GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+#if defined(_GLFW_X11)
+GLFWbool _glfwChooseVisualEGL(const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth);
+#endif /*_GLFW_X11*/
+
+#endif // _glfw3_egl_context_h_
diff --git a/glfw-3.2.1/src/glfw3.pc.in b/glfw-3.2.1/src/glfw3.pc.in
new file mode 100644
index 0000000..f2e4d97
--- /dev/null
+++ b/glfw-3.2.1/src/glfw3.pc.in
@@ -0,0 +1,13 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib@LIB_SUFFIX@
+
+Name: GLFW
+Description: A multi-platform library for OpenGL, window and input
+Version: @GLFW_VERSION_FULL@
+URL: http://www.glfw.org/
+Requires.private: @GLFW_PKG_DEPS@
+Libs: -L${libdir} -l@GLFW_LIB_NAME@
+Libs.private: @GLFW_PKG_LIBS@
+Cflags: -I${includedir}
diff --git a/glfw-3.2.1/src/glfw3Config.cmake.in b/glfw-3.2.1/src/glfw3Config.cmake.in
new file mode 100644
index 0000000..1fa200e
--- /dev/null
+++ b/glfw-3.2.1/src/glfw3Config.cmake.in
@@ -0,0 +1 @@
+include("${CMAKE_CURRENT_LIST_DIR}/glfw3Targets.cmake")
diff --git a/glfw-3.2.1/src/glfw_config.h.in b/glfw-3.2.1/src/glfw_config.h.in
new file mode 100644
index 0000000..cf253d3
--- /dev/null
+++ b/glfw-3.2.1/src/glfw_config.h.in
@@ -0,0 +1,65 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2010-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+// As glfw_config.h.in, this file is used by CMake to produce the
+// glfw_config.h configuration header file. If you are adding a feature
+// requiring conditional compilation, this is where to add the macro.
+//========================================================================
+// As glfw_config.h, this file defines compile-time option macros for a
+// specific platform and development environment. If you are using the
+// GLFW CMake files, modify glfw_config.h.in instead of this file. If you
+// are using your own build system, make this file define the appropriate
+// macros in whatever way is suitable.
+//========================================================================
+
+// Define this to 1 if building GLFW for X11
+#cmakedefine _GLFW_X11
+// Define this to 1 if building GLFW for Win32
+#cmakedefine _GLFW_WIN32
+// Define this to 1 if building GLFW for Cocoa
+#cmakedefine _GLFW_COCOA
+// Define this to 1 if building GLFW for Wayland
+#cmakedefine _GLFW_WAYLAND
+// Define this to 1 if building GLFW for Mir
+#cmakedefine _GLFW_MIR
+
+// Define this to 1 if building as a shared library / dynamic library / DLL
+#cmakedefine _GLFW_BUILD_DLL
+// Define this to 1 to use Vulkan loader linked statically into application
+#cmakedefine _GLFW_VULKAN_STATIC
+
+// Define this to 1 to force use of high-performance GPU on hybrid systems
+#cmakedefine _GLFW_USE_HYBRID_HPG
+
+// Define this to 1 if the Xxf86vm X11 extension is available
+#cmakedefine _GLFW_HAS_XF86VM
+
+// Define this to 1 if glfwInit should change the current directory
+#cmakedefine _GLFW_USE_CHDIR
+// Define this to 1 if glfwCreateWindow should populate the menu bar
+#cmakedefine _GLFW_USE_MENUBAR
+// Define this to 1 if windows should use full resolution on Retina displays
+#cmakedefine _GLFW_USE_RETINA
+
diff --git a/glfw-3.2.1/src/glx_context.c b/glfw-3.2.1/src/glx_context.c
new file mode 100644
index 0000000..251b7fc
--- /dev/null
+++ b/glfw-3.2.1/src/glx_context.c
@@ -0,0 +1,677 @@
+//========================================================================
+// GLFW 3.2 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <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 (strcmp(vendor, "Chromium") == 0)
+ trustWindowBit = GLFW_FALSE;
+
+ nativeConfigs =
+ glXGetFBConfigs(_glfw.x11.display, _glfw.x11.screen, &nativeCount);
+ if (!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;
+ }
+
+ 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;
+ }
+ }
+
+ _glfwPlatformSetCurrentContext(window);
+}
+
+static void swapBuffersGLX(_GLFWwindow* window)
+{
+ glXSwapBuffers(_glfw.x11.display, window->context.glx.window);
+}
+
+static void swapIntervalGLX(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
+
+ if (_glfw.glx.EXT_swap_control)
+ {
+ _glfw.glx.SwapIntervalEXT(_glfw.x11.display,
+ window->context.glx.window,
+ interval);
+ }
+ else if (_glfw.glx.MESA_swap_control)
+ _glfw.glx.SwapIntervalMESA(interval);
+ else if (_glfw.glx.SGI_swap_control)
+ {
+ if (interval > 0)
+ _glfw.glx.SwapIntervalSGI(interval);
+ }
+}
+
+static int extensionSupportedGLX(const char* extension)
+{
+ const char* extensions =
+ glXQueryExtensionsString(_glfw.x11.display, _glfw.x11.screen);
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressGLX(const char* procname)
+{
+ if (_glfw.glx.GetProcAddress)
+ return _glfw.glx.GetProcAddress((const GLubyte*) procname);
+ else if (_glfw.glx.GetProcAddressARB)
+ return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
+ else
+ return dlsym(_glfw.glx.handle, procname);
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextGLX(_GLFWwindow* window)
+{
+ if (window->context.glx.window)
+ {
+ glXDestroyWindow(_glfw.x11.display, window->context.glx.window);
+ window->context.glx.window = None;
+ }
+
+ if (window->context.glx.handle)
+ {
+ glXDestroyContext(_glfw.x11.display, window->context.glx.handle);
+ window->context.glx.handle = NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize GLX
+//
+GLFWbool _glfwInitGLX(void)
+{
+ int i;
+ const char* sonames[] =
+ {
+#if 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 = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL);
+ if (_glfw.glx.handle)
+ break;
+ }
+
+ if (!_glfw.glx.handle)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: Failed to load GLX");
+ return GLFW_FALSE;
+ }
+
+ _glfw.glx.GetFBConfigs =
+ dlsym(_glfw.glx.handle, "glXGetFBConfigs");
+ _glfw.glx.GetFBConfigAttrib =
+ dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib");
+ _glfw.glx.GetClientString =
+ dlsym(_glfw.glx.handle, "glXGetClientString");
+ _glfw.glx.QueryExtension =
+ dlsym(_glfw.glx.handle, "glXQueryExtension");
+ _glfw.glx.QueryVersion =
+ dlsym(_glfw.glx.handle, "glXQueryVersion");
+ _glfw.glx.DestroyContext =
+ dlsym(_glfw.glx.handle, "glXDestroyContext");
+ _glfw.glx.MakeCurrent =
+ dlsym(_glfw.glx.handle, "glXMakeCurrent");
+ _glfw.glx.SwapBuffers =
+ dlsym(_glfw.glx.handle, "glXSwapBuffers");
+ _glfw.glx.QueryExtensionsString =
+ dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
+ _glfw.glx.CreateNewContext =
+ dlsym(_glfw.glx.handle, "glXCreateNewContext");
+ _glfw.glx.CreateWindow =
+ dlsym(_glfw.glx.handle, "glXCreateWindow");
+ _glfw.glx.DestroyWindow =
+ dlsym(_glfw.glx.handle, "glXDestroyWindow");
+ _glfw.glx.GetProcAddress =
+ dlsym(_glfw.glx.handle, "glXGetProcAddress");
+ _glfw.glx.GetProcAddressARB =
+ dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
+ _glfw.glx.GetVisualFromFBConfig =
+ dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
+
+ if (!_glfw.glx.GetFBConfigs ||
+ !_glfw.glx.GetFBConfigAttrib ||
+ !_glfw.glx.GetClientString ||
+ !_glfw.glx.QueryExtension ||
+ !_glfw.glx.QueryVersion ||
+ !_glfw.glx.DestroyContext ||
+ !_glfw.glx.MakeCurrent ||
+ !_glfw.glx.SwapBuffers ||
+ !_glfw.glx.QueryExtensionsString ||
+ !_glfw.glx.CreateNewContext ||
+ !_glfw.glx.CreateWindow ||
+ !_glfw.glx.DestroyWindow ||
+ !_glfw.glx.GetProcAddress ||
+ !_glfw.glx.GetProcAddressARB ||
+ !_glfw.glx.GetVisualFromFBConfig)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "GLX: Failed to load required entry points");
+ return GLFW_FALSE;
+ }
+
+ if (!glXQueryExtension(_glfw.x11.display,
+ &_glfw.glx.errorBase,
+ &_glfw.glx.eventBase))
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "GLX: GLX extension not found");
+ return 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_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)
+ {
+ dlclose(_glfw.glx.handle);
+ _glfw.glx.handle = NULL;
+ }
+}
+
+#define setGLXattrib(attribName, attribValue) \
+{ \
+ attribs[index++] = attribName; \
+ attribs[index++] = attribValue; \
+ assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
+}
+
+// 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->noerror)
+ flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
+
+ if (ctxconfig->robustness)
+ {
+ if (_glfw.glx.ARB_create_context_robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setGLXattrib(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ GLX_NO_RESET_NOTIFICATION_ARB);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setGLXattrib(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)
+ {
+ setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+ }
+ else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ setGLXattrib(GLX_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+ }
+ }
+ }
+
+ // 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)
+ {
+ setGLXattrib(GLX_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+ setGLXattrib(GLX_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+ }
+
+ if (mask)
+ setGLXattrib(GLX_CONTEXT_PROFILE_MASK_ARB, mask);
+
+ if (flags)
+ setGLXattrib(GLX_CONTEXT_FLAGS_ARB, flags);
+
+ setGLXattrib(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 setGLXattrib
+
+// Returns the Visual and depth of the chosen GLXFBConfig
+//
+GLFWbool _glfwChooseVisualGLX(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-3.2.1/src/glx_context.h b/glfw-3.2.1/src/glx_context.h
new file mode 100644
index 0000000..3abed0e
--- /dev/null
+++ b/glfw-3.2.1/src/glx_context.h
@@ -0,0 +1,182 @@
+//========================================================================
+// GLFW 3.2 GLX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_glx_context_h_
+#define _glfw3_glx_context_h_
+
+#define GLX_VENDOR 1
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_RGBA_TYPE 0x8014
+#define GLX_DOUBLEBUFFER 5
+#define GLX_STEREO 6
+#define GLX_AUX_BUFFERS 7
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_STENCIL_SIZE 13
+#define GLX_ACCUM_RED_SIZE 14
+#define GLX_ACCUM_GREEN_SIZE 15
+#define GLX_ACCUM_BLUE_SIZE 16
+#define GLX_ACCUM_ALPHA_SIZE 17
+#define GLX_SAMPLES 0x186a1
+#define GLX_VISUAL_ID 0x800b
+
+#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
+
+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 int (*PFNGLXSWAPINTERVALMESAPROC)(int);
+typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
+typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
+typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLXContext,Bool,const int*);
+typedef XVisualInfo* (*PFNGLXGETVISUALFROMFBCONFIGPROC)(Display*,GLXFBConfig);
+typedef GLXWindow (*PFNGLXCREATEWINDOWPROC)(Display*,GLXFBConfig,Window,const int*);
+typedef void (*PFNGLXDESTROYWINDOWPROC)(Display*,GLXWindow);
+
+// 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_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 _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig,
+ Visual** visual, int* depth);
+
+#endif // _glfw3_glx_context_h_
diff --git a/glfw-3.2.1/src/init.c b/glfw-3.2.1/src/init.c
new file mode 100644
index 0000000..9d4a2b2
--- /dev/null
+++ b/glfw-3.2.1/src/init.c
@@ -0,0 +1,200 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+
+// The three global variables below comprise all global data in GLFW.
+// Any other global variable is a bug.
+
+// Global state shared between compilation units of GLFW
+// These are documented in internal.h
+//
+GLFWbool _glfwInitialized = GLFW_FALSE;
+_GLFWlibrary _glfw;
+
+// This is outside of _glfw so it can be initialized and usable before
+// glfwInit is called, which lets that function report errors
+//
+static GLFWerrorfun _glfwErrorCallback = NULL;
+
+
+// Returns a generic string representation of the specified error
+//
+static const char* getErrorString(int error)
+{
+ switch (error)
+ {
+ case GLFW_NOT_INITIALIZED:
+ return "The GLFW library is not initialized";
+ case GLFW_NO_CURRENT_CONTEXT:
+ return "There is no current context";
+ case GLFW_INVALID_ENUM:
+ return "Invalid argument for enum parameter";
+ case GLFW_INVALID_VALUE:
+ return "Invalid value for parameter";
+ case GLFW_OUT_OF_MEMORY:
+ return "Out of memory";
+ case GLFW_API_UNAVAILABLE:
+ return "The requested API is unavailable";
+ case GLFW_VERSION_UNAVAILABLE:
+ return "The requested API version is unavailable";
+ case GLFW_PLATFORM_ERROR:
+ return "A platform-specific error occurred";
+ case GLFW_FORMAT_UNAVAILABLE:
+ return "The requested format is unavailable";
+ case GLFW_NO_WINDOW_CONTEXT:
+ return "The specified window has no context";
+ default:
+ return "ERROR: UNKNOWN GLFW ERROR";
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInputError(int error, const char* format, ...)
+{
+ if (_glfwErrorCallback)
+ {
+ char buffer[8192];
+ const char* description;
+
+ if (format)
+ {
+ int count;
+ va_list vl;
+
+ va_start(vl, format);
+ count = vsnprintf(buffer, sizeof(buffer), format, vl);
+ va_end(vl);
+
+ if (count < 0)
+ buffer[sizeof(buffer) - 1] = '\0';
+
+ description = buffer;
+ }
+ else
+ description = getErrorString(error);
+
+ _glfwErrorCallback(error, description);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwInit(void)
+{
+ if (_glfwInitialized)
+ return GLFW_TRUE;
+
+ memset(&_glfw, 0, sizeof(_glfw));
+
+ if (!_glfwPlatformInit())
+ {
+ _glfwPlatformTerminate();
+ return GLFW_FALSE;
+ }
+
+ _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
+ _glfwInitialized = GLFW_TRUE;
+
+ _glfw.timerOffset = _glfwPlatformGetTimerValue();
+
+ // Not all window hints have zero as their default value
+ glfwDefaultWindowHints();
+
+ return GLFW_TRUE;
+}
+
+GLFWAPI void glfwTerminate(void)
+{
+ int i;
+
+ if (!_glfwInitialized)
+ return;
+
+ 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);
+ }
+
+ _glfwTerminateVulkan();
+
+ _glfwFreeMonitors(_glfw.monitors, _glfw.monitorCount);
+ _glfw.monitors = NULL;
+ _glfw.monitorCount = 0;
+
+ _glfwPlatformTerminate();
+
+ memset(&_glfw, 0, sizeof(_glfw));
+ _glfwInitialized = GLFW_FALSE;
+}
+
+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 GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun)
+{
+ _GLFW_SWAP_POINTERS(_glfwErrorCallback, cbfun);
+ return cbfun;
+}
+
diff --git a/glfw-3.2.1/src/input.c b/glfw-3.2.1/src/input.c
new file mode 100644
index 0000000..614c6ef
--- /dev/null
+++ b/glfw-3.2.1/src/input.c
@@ -0,0 +1,659 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <float.h>
+#include <stdlib.h>
+
+// Internal key state used for sticky keys
+#define _GLFW_STICK 3
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+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->callbacks.key)
+ window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
+}
+
+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain)
+{
+ if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
+ return;
+
+ if (window->callbacks.charmods)
+ window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
+
+ if (plain)
+ {
+ if (window->callbacks.character)
+ window->callbacks.character((GLFWwindow*) window, codepoint);
+ }
+}
+
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
+{
+ if (window->callbacks.scroll)
+ window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
+}
+
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
+{
+ if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
+ return;
+
+ // Register mouse button action
+ 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);
+}
+
+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);
+}
+
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
+{
+ if (window->callbacks.cursorEnter)
+ window->callbacks.cursorEnter((GLFWwindow*) window, entered);
+}
+
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
+{
+ if (window->callbacks.drop)
+ window->callbacks.drop((GLFWwindow*) window, count, paths);
+}
+
+void _glfwInputJoystickChange(int joy, int event)
+{
+ if (_glfw.callbacks.joystick)
+ _glfw.callbacks.joystick(joy, event);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwIsPrintable(int key)
+{
+ return (key >= GLFW_KEY_APOSTROPHE && key <= GLFW_KEY_WORLD_2) ||
+ (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) ||
+ key == GLFW_KEY_KP_EQUAL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+ switch (mode)
+ {
+ case GLFW_CURSOR:
+ return window->cursorMode;
+ case GLFW_STICKY_KEYS:
+ return window->stickyKeys;
+ case GLFW_STICKY_MOUSE_BUTTONS:
+ return window->stickyMouseButtons;
+ default:
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
+ return 0;
+ }
+}
+
+GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ switch (mode)
+ {
+ case GLFW_CURSOR:
+ {
+ if (value != GLFW_CURSOR_NORMAL &&
+ value != GLFW_CURSOR_HIDDEN &&
+ value != GLFW_CURSOR_DISABLED)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM,
+ "Invalid cursor mode %i",
+ value);
+ return;
+ }
+
+ if (window->cursorMode == value)
+ return;
+
+ window->cursorMode = value;
+
+ _glfwPlatformGetCursorPos(window,
+ &window->virtualCursorPosX,
+ &window->virtualCursorPosY);
+
+ if (_glfwPlatformWindowFocused(window))
+ _glfwPlatformSetCursorMode(window, value);
+
+ return;
+ }
+
+ case GLFW_STICKY_KEYS:
+ {
+ if (window->stickyKeys == value)
+ return;
+
+ if (!value)
+ {
+ int i;
+
+ // Release all sticky keys
+ for (i = 0; i <= GLFW_KEY_LAST; i++)
+ {
+ if (window->keys[i] == _GLFW_STICK)
+ window->keys[i] = GLFW_RELEASE;
+ }
+ }
+
+ window->stickyKeys = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ }
+
+ case GLFW_STICKY_MOUSE_BUTTONS:
+ {
+ if (window->stickyMouseButtons == value)
+ return;
+
+ if (!value)
+ {
+ int i;
+
+ // Release all sticky mouse buttons
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButtons[i] == _GLFW_STICK)
+ window->mouseButtons[i] = GLFW_RELEASE;
+ }
+ }
+
+ window->stickyMouseButtons = value ? GLFW_TRUE : GLFW_FALSE;
+ return;
+ }
+ }
+
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode %i", mode);
+}
+
+GLFWAPI const char* glfwGetKeyName(int key, int scancode)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfwPlatformGetKeyName(key, scancode);
+}
+
+GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
+
+ if (key < 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 %i", 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 joy)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+
+ if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
+ return 0;
+ }
+
+ return _glfwPlatformJoystickPresent(joy);
+}
+
+GLFWAPI const float* glfwGetJoystickAxes(int joy, int* count)
+{
+ assert(count != NULL);
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
+ return NULL;
+ }
+
+ return _glfwPlatformGetJoystickAxes(joy, count);
+}
+
+GLFWAPI const unsigned char* glfwGetJoystickButtons(int joy, int* count)
+{
+ assert(count != NULL);
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
+ return NULL;
+ }
+
+ return _glfwPlatformGetJoystickButtons(joy, count);
+}
+
+GLFWAPI const char* glfwGetJoystickName(int joy)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (joy < 0 || joy > GLFW_JOYSTICK_LAST)
+ {
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick %i", joy);
+ return NULL;
+ }
+
+ return _glfwPlatformGetJoystickName(joy);
+}
+
+GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun);
+ return cbfun;
+}
+
+GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(string != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformSetClipboardString(window, string);
+}
+
+GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfwPlatformGetClipboardString(window);
+}
+
+GLFWAPI double glfwGetTime(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
+ return (double) (_glfwPlatformGetTimerValue() - _glfw.timerOffset) /
+ _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.timerOffset = _glfwPlatformGetTimerValue() -
+ (uint64_t) (time * _glfwPlatformGetTimerFrequency());
+}
+
+GLFWAPI uint64_t glfwGetTimerValue(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return _glfwPlatformGetTimerValue();
+}
+
+GLFWAPI uint64_t glfwGetTimerFrequency(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return _glfwPlatformGetTimerFrequency();
+}
+
diff --git a/glfw-3.2.1/src/internal.h b/glfw-3.2.1/src/internal.h
new file mode 100644
index 0000000..8e84efd
--- /dev/null
+++ b/glfw-3.2.1/src/internal.h
@@ -0,0 +1,1055 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_internal_h_
+#define _glfw3_internal_h_
+
+
+#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_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"
+
+typedef int GLFWbool;
+
+typedef struct _GLFWwndconfig _GLFWwndconfig;
+typedef struct _GLFWctxconfig _GLFWctxconfig;
+typedef struct _GLFWfbconfig _GLFWfbconfig;
+typedef struct _GLFWcontext _GLFWcontext;
+typedef struct _GLFWwindow _GLFWwindow;
+typedef struct _GLFWlibrary _GLFWlibrary;
+typedef struct _GLFWmonitor _GLFWmonitor;
+typedef struct _GLFWcursor _GLFWcursor;
+
+typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*);
+typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*);
+typedef void (* _GLFWswapintervalfun)(int);
+typedef int (* _GLFWextensionsupportedfun)(const char*);
+typedef GLFWglproc (* _GLFWgetprocaddressfun)(const char*);
+typedef void (* _GLFWdestroycontextfun)(_GLFWwindow*);
+
+#define GL_VERSION 0x1f02
+#define GL_NONE 0
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_EXTENSIONS 0x1f03
+#define GL_NUM_EXTENSIONS 0x821d
+#define GL_CONTEXT_FLAGS 0x821e
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define GL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82fb
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82fc
+#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008
+
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef unsigned int GLenum;
+typedef unsigned int GLbitfield;
+typedef unsigned char GLubyte;
+
+typedef void (APIENTRY * PFNGLCLEARPROC)(GLbitfield);
+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGPROC)(GLenum);
+typedef void (APIENTRY * PFNGLGETINTEGERVPROC)(GLenum,GLint*);
+typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint);
+
+#define VK_NULL_HANDLE 0
+
+typedef void* VkInstance;
+typedef void* VkPhysicalDevice;
+typedef uint64_t VkSurfaceKHR;
+typedef uint32_t VkFlags;
+typedef uint32_t VkBool32;
+
+typedef enum VkStructureType
+{
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR = 1000004000,
+ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR = 1000005000,
+ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
+ VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
+ VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkStructureType;
+
+typedef enum VkResult
+{
+ VK_SUCCESS = 0,
+ VK_NOT_READY = 1,
+ VK_TIMEOUT = 2,
+ VK_EVENT_SET = 3,
+ VK_EVENT_RESET = 4,
+ VK_INCOMPLETE = 5,
+ VK_ERROR_OUT_OF_HOST_MEMORY = -1,
+ VK_ERROR_OUT_OF_DEVICE_MEMORY = -2,
+ VK_ERROR_INITIALIZATION_FAILED = -3,
+ VK_ERROR_DEVICE_LOST = -4,
+ VK_ERROR_MEMORY_MAP_FAILED = -5,
+ VK_ERROR_LAYER_NOT_PRESENT = -6,
+ VK_ERROR_EXTENSION_NOT_PRESENT = -7,
+ VK_ERROR_FEATURE_NOT_PRESENT = -8,
+ VK_ERROR_INCOMPATIBLE_DRIVER = -9,
+ VK_ERROR_TOO_MANY_OBJECTS = -10,
+ VK_ERROR_FORMAT_NOT_SUPPORTED = -11,
+ VK_ERROR_SURFACE_LOST_KHR = -1000000000,
+ VK_SUBOPTIMAL_KHR = 1000001003,
+ VK_ERROR_OUT_OF_DATE_KHR = -1000001004,
+ VK_ERROR_INCOMPATIBLE_DISPLAY_KHR = -1000003001,
+ VK_ERROR_NATIVE_WINDOW_IN_USE_KHR = -1000000001,
+ VK_ERROR_VALIDATION_FAILED_EXT = -1000011001,
+ VK_RESULT_MAX_ENUM = 0x7FFFFFFF
+} VkResult;
+
+typedef struct VkAllocationCallbacks VkAllocationCallbacks;
+
+typedef struct VkExtensionProperties
+{
+ char extensionName[256];
+ uint32_t specVersion;
+} VkExtensionProperties;
+
+typedef void (APIENTRY * PFN_vkVoidFunction)(void);
+
+#if defined(_GLFW_VULKAN_STATIC)
+ PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance,const char*);
+ VkResult vkEnumerateInstanceExtensionProperties(const char*,uint32_t*,VkExtensionProperties*);
+#else
+ typedef PFN_vkVoidFunction (APIENTRY * PFN_vkGetInstanceProcAddr)(VkInstance,const char*);
+ typedef VkResult (APIENTRY * PFN_vkEnumerateInstanceExtensionProperties)(const char*,uint32_t*,VkExtensionProperties*);
+ #define vkEnumerateInstanceExtensionProperties _glfw.vk.EnumerateInstanceExtensionProperties
+ #define vkGetInstanceProcAddr _glfw.vk.GetInstanceProcAddr
+#endif
+
+#if defined(_GLFW_COCOA)
+ #include "cocoa_platform.h"
+#elif defined(_GLFW_WIN32)
+ #include "win32_platform.h"
+#elif defined(_GLFW_X11)
+ #include "x11_platform.h"
+#elif defined(_GLFW_WAYLAND)
+ #include "wl_platform.h"
+#elif defined(_GLFW_MIR)
+ #include "mir_platform.h"
+#else
+ #error "No supported window creation API selected"
+#endif
+
+
+//========================================================================
+// Doxygen group definitions
+//========================================================================
+
+/*! @defgroup platform Platform interface
+ * @brief The interface implemented by the platform-specific code.
+ *
+ * The platform API is the interface exposed by the platform-specific code for
+ * each platform and is called by the shared code of the public API It mirrors
+ * the public API except it uses objects instead of handles.
+ */
+/*! @defgroup event Event interface
+ * @brief The interface used by the platform-specific code to report events.
+ *
+ * The event API is used by the platform-specific code to notify the shared
+ * code of events that can be translated into state changes and/or callback
+ * calls.
+ */
+/*! @defgroup utility Utility functions
+ * @brief Various utility functions for internal use.
+ *
+ * These functions are shared code and may be used by any part of GLFW
+ * Each platform may add its own utility functions, but those must only be
+ * called by the platform-specific code
+ */
+
+
+//========================================================================
+// Helper macros
+//========================================================================
+
+// Constructs a version number string from the public header macros
+#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
+#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
+#define _GLFW_VERSION_NUMBER _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR, \
+ GLFW_VERSION_MINOR, \
+ GLFW_VERSION_REVISION)
+
+// Checks for whether the library has been initialized
+#define _GLFW_REQUIRE_INIT() \
+ if (!_glfwInitialized) \
+ { \
+ _glfwInputError(GLFW_NOT_INITIALIZED, NULL); \
+ return; \
+ }
+#define _GLFW_REQUIRE_INIT_OR_RETURN(x) \
+ if (!_glfwInitialized) \
+ { \
+ _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; \
+ }
+
+
+//========================================================================
+// Platform-independent structures
+//========================================================================
+
+/*! @brief 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;
+};
+
+/*! @brief 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;
+};
+
+/*! @brief 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;
+ uintptr_t handle;
+};
+
+/*! @brief Context structure.
+ */
+struct _GLFWcontext
+{
+ int client;
+ int source;
+ int major, minor, revision;
+ GLFWbool forward, debug, noerror;
+ int profile;
+ int robustness;
+ int release;
+
+ PFNGLGETSTRINGIPROC GetStringi;
+ PFNGLGETINTEGERVPROC GetIntegerv;
+ PFNGLGETSTRINGPROC GetString;
+
+ _GLFWmakecontextcurrentfun makeCurrent;
+ _GLFWswapbuffersfun swapBuffers;
+ _GLFWswapintervalfun swapInterval;
+ _GLFWextensionsupportedfun extensionSupported;
+ _GLFWgetprocaddressfun getProcAddress;
+ _GLFWdestroycontextfun destroy;
+
+ // This is defined in the context API's context.h
+ _GLFW_PLATFORM_CONTEXT_STATE;
+ // This is defined in egl_context.h
+ _GLFW_EGL_CONTEXT_STATE;
+};
+
+/*! @brief Window and context structure.
+ */
+struct _GLFWwindow
+{
+ struct _GLFWwindow* next;
+
+ // Window settings and state
+ GLFWbool resizable;
+ GLFWbool decorated;
+ GLFWbool autoIconify;
+ GLFWbool floating;
+ GLFWbool closed;
+ void* userPointer;
+ GLFWvidmode videoMode;
+ _GLFWmonitor* monitor;
+ _GLFWcursor* cursor;
+
+ int minwidth, minheight;
+ int maxwidth, maxheight;
+ int numer, denom;
+
+ GLFWbool stickyKeys;
+ GLFWbool stickyMouseButtons;
+ int cursorMode;
+ char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
+ char keys[GLFW_KEY_LAST + 1];
+ // Virtual cursor position when cursor is disabled
+ double virtualCursorPosX, virtualCursorPosY;
+
+ _GLFWcontext context;
+
+ struct {
+ GLFWwindowposfun pos;
+ GLFWwindowsizefun size;
+ GLFWwindowclosefun close;
+ GLFWwindowrefreshfun refresh;
+ GLFWwindowfocusfun focus;
+ GLFWwindowiconifyfun iconify;
+ GLFWframebuffersizefun fbsize;
+ 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;
+};
+
+/*! @brief Monitor structure.
+ */
+struct _GLFWmonitor
+{
+ char* name;
+
+ // 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;
+};
+
+/*! @brief Cursor structure
+ */
+struct _GLFWcursor
+{
+ _GLFWcursor* next;
+
+ // This is defined in the window API's platform.h
+ _GLFW_PLATFORM_CURSOR_STATE;
+};
+
+/*! @brief Library global data.
+ */
+struct _GLFWlibrary
+{
+ struct {
+ _GLFWfbconfig framebuffer;
+ _GLFWwndconfig window;
+ _GLFWctxconfig context;
+ int refreshRate;
+ } hints;
+
+ _GLFWcursor* cursorListHead;
+
+ _GLFWwindow* windowListHead;
+
+ _GLFWmonitor** monitors;
+ int monitorCount;
+
+ uint64_t timerOffset;
+
+ struct {
+ GLFWbool available;
+ void* handle;
+ char** extensions;
+ uint32_t extensionCount;
+#if !defined(_GLFW_VULKAN_STATIC)
+ PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
+ PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
+#endif
+ GLFWbool KHR_surface;
+ GLFWbool KHR_win32_surface;
+ GLFWbool KHR_xlib_surface;
+ GLFWbool KHR_xcb_surface;
+ GLFWbool KHR_wayland_surface;
+ GLFWbool KHR_mir_surface;
+ } vk;
+
+ struct {
+ GLFWmonitorfun monitor;
+ GLFWjoystickfun joystick;
+ } callbacks;
+
+ // This is defined in the window API's platform.h
+ _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 time.h
+ _GLFW_PLATFORM_LIBRARY_TIME_STATE;
+ // This is defined in the platform's joystick.h
+ _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE;
+ // This is defined in the platform's tls.h
+ _GLFW_PLATFORM_LIBRARY_TLS_STATE;
+ // This is defined in egl_context.h
+ _GLFW_EGL_LIBRARY_CONTEXT_STATE;
+};
+
+
+//========================================================================
+// Global state shared between compilation units of GLFW
+//========================================================================
+
+/*! @brief Flag indicating whether GLFW has been successfully initialized.
+ */
+extern GLFWbool _glfwInitialized;
+
+/*! @brief All global data protected by @ref _glfwInitialized.
+ * This should only be touched after a call to @ref glfwInit that has not been
+ * followed by a call to @ref glfwTerminate.
+ */
+extern _GLFWlibrary _glfw;
+
+
+//========================================================================
+// Platform API functions
+//========================================================================
+
+/*! @brief Initializes the platform-specific part of the library.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an error occurred.
+ * @ingroup platform
+ */
+int _glfwPlatformInit(void);
+
+/*! @brief Terminates the platform-specific part of the library.
+ * @ingroup platform
+ */
+void _glfwPlatformTerminate(void);
+
+/*! @copydoc glfwGetVersionString
+ * @ingroup platform
+ *
+ * @note The returned string must be available for the duration of the program.
+ *
+ * @note The returned string must not change for the duration of the program.
+ */
+const char* _glfwPlatformGetVersionString(void);
+
+/*! @copydoc glfwGetCursorPos
+ * @ingroup platform
+ */
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos);
+
+/*! @copydoc glfwSetCursorPos
+ * @ingroup platform
+ */
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief Sets the specified cursor mode of the specified window.
+ * @param[in] window The window whose cursor mode to set.
+ * @ingroup platform
+ */
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode);
+
+/*! @copydoc glfwGetKeyName
+ * @ingroup platform
+ */
+const char* _glfwPlatformGetKeyName(int key, int scancode);
+
+/*! @copydoc glfwGetMonitors
+ * @ingroup platform
+ */
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count);
+
+/*! @brief Checks whether two monitor objects represent the same monitor.
+ *
+ * @param[in] first The first monitor.
+ * @param[in] second The second monitor.
+ * @return @c GLFW_TRUE if the monitor objects represent the same monitor, or
+ * @c GLFW_FALSE otherwise.
+ * @ingroup platform
+ */
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second);
+
+/*! @copydoc glfwGetMonitorPos
+ * @ingroup platform
+ */
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos);
+
+/*! @copydoc glfwGetVideoModes
+ * @ingroup platform
+ */
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count);
+
+/*! @ingroup platform
+ */
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode);
+
+/*! @copydoc glfwGetGammaRamp
+ * @ingroup platform
+ */
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
+
+/*! @copydoc glfwSetGammaRamp
+ * @ingroup platform
+ */
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
+
+/*! @copydoc glfwSetClipboardString
+ * @ingroup platform
+ */
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string);
+
+/*! @copydoc glfwGetClipboardString
+ * @ingroup platform
+ *
+ * @note The returned string must be valid until the next call to @ref
+ * _glfwPlatformGetClipboardString or @ref _glfwPlatformSetClipboardString.
+ */
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window);
+
+/*! @copydoc glfwJoystickPresent
+ * @ingroup platform
+ */
+int _glfwPlatformJoystickPresent(int joy);
+
+/*! @copydoc glfwGetJoystickAxes
+ * @ingroup platform
+ */
+const float* _glfwPlatformGetJoystickAxes(int joy, int* count);
+
+/*! @copydoc glfwGetJoystickButtons
+ * @ingroup platform
+ */
+const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count);
+
+/*! @copydoc glfwGetJoystickName
+ * @ingroup platform
+ */
+const char* _glfwPlatformGetJoystickName(int joy);
+
+/*! @copydoc glfwGetTimerValue
+ * @ingroup platform
+ */
+uint64_t _glfwPlatformGetTimerValue(void);
+
+/*! @copydoc glfwGetTimerFrequency
+ * @ingroup platform
+ */
+uint64_t _glfwPlatformGetTimerFrequency(void);
+
+/*! @ingroup platform
+ */
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+
+/*! @ingroup platform
+ */
+void _glfwPlatformDestroyWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwSetWindowTitle
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title);
+
+/*! @copydoc glfwSetWindowIcon
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window, int count, const GLFWimage* images);
+
+/*! @copydoc glfwGetWindowPos
+ * @ingroup platform
+ */
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos);
+
+/*! @copydoc glfwSetWindowPos
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos);
+
+/*! @copydoc glfwGetWindowSize
+ * @ingroup platform
+ */
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height);
+
+/*! @copydoc glfwSetWindowSize
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
+
+/*! @copydoc glfwSetWindowSizeLimits
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
+
+/*! @copydoc glfwSetWindowAspectRatio
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom);
+
+/*! @copydoc glfwGetFramebufferSize
+ * @ingroup platform
+ */
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height);
+
+/*! @copydoc glfwGetWindowFrameSize
+ * @ingroup platform
+ */
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
+
+/*! @copydoc glfwIconifyWindow
+ * @ingroup platform
+ */
+void _glfwPlatformIconifyWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwRestoreWindow
+ * @ingroup platform
+ */
+void _glfwPlatformRestoreWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwMaximizeWindow
+ * @ingroup platform
+ */
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwShowWindow
+ * @ingroup platform
+ */
+void _glfwPlatformShowWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwHideWindow
+ * @ingroup platform
+ */
+void _glfwPlatformHideWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwFocusWindow
+ * @ingroup platform
+ */
+void _glfwPlatformFocusWindow(_GLFWwindow* window);
+
+/*! @copydoc glfwSetWindowMonitor
+ * @ingroup platform
+ */
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
+
+/*! @brief Returns whether the window is focused.
+ * @ingroup platform
+ */
+int _glfwPlatformWindowFocused(_GLFWwindow* window);
+
+/*! @brief Returns whether the window is iconified.
+ * @ingroup platform
+ */
+int _glfwPlatformWindowIconified(_GLFWwindow* window);
+
+/*! @brief Returns whether the window is visible.
+ * @ingroup platform
+ */
+int _glfwPlatformWindowVisible(_GLFWwindow* window);
+
+/*! @brief Returns whether the window is maximized.
+ * @ingroup platform
+ */
+int _glfwPlatformWindowMaximized(_GLFWwindow* window);
+
+/*! @copydoc glfwPollEvents
+ * @ingroup platform
+ */
+void _glfwPlatformPollEvents(void);
+
+/*! @copydoc glfwWaitEvents
+ * @ingroup platform
+ */
+void _glfwPlatformWaitEvents(void);
+
+/*! @copydoc glfwWaitEventsTimeout
+ * @ingroup platform
+ */
+void _glfwPlatformWaitEventsTimeout(double timeout);
+
+/*! @copydoc glfwPostEmptyEvent
+ * @ingroup platform
+ */
+void _glfwPlatformPostEmptyEvent(void);
+
+/*! @ingroup platform
+ */
+void _glfwPlatformSetCurrentContext(_GLFWwindow* context);
+
+/*! @copydoc glfwGetCurrentContext
+ * @ingroup platform
+ */
+_GLFWwindow* _glfwPlatformGetCurrentContext(void);
+
+/*! @copydoc glfwCreateCursor
+ * @ingroup platform
+ */
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
+
+/*! @copydoc glfwCreateStandardCursor
+ * @ingroup platform
+ */
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape);
+
+/*! @copydoc glfwDestroyCursor
+ * @ingroup platform
+ */
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor);
+
+/*! @copydoc glfwSetCursor
+ * @ingroup platform
+ */
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor);
+
+/*! @ingroup platform
+ */
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count);
+
+/*! @ingroup platform
+ */
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
+
+/*! @ingroup platform
+ */
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
+
+
+//========================================================================
+// Event API functions
+//========================================================================
+
+/*! @brief Notifies shared code of a window focus event.
+ * @param[in] window The window that received the event.
+ * @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE`
+ * if it lost focus.
+ * @ingroup event
+ */
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused);
+
+/*! @brief Notifies shared code of a window movement event.
+ * @param[in] window The window that received the event.
+ * @param[in] xpos The new x-coordinate of the client area of the window.
+ * @param[in] ypos The new y-coordinate of the client area of the window.
+ * @ingroup event
+ */
+void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos);
+
+/*! @brief Notifies shared code of a window resize event.
+ * @param[in] window The window that received the event.
+ * @param[in] width The new width of the client area of the window.
+ * @param[in] height The new height of the client area of the window.
+ * @ingroup event
+ */
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
+
+/*! @brief Notifies shared code of a framebuffer resize event.
+ * @param[in] window The window that received the event.
+ * @param[in] width The new width, in pixels, of the framebuffer.
+ * @param[in] height The new height, in pixels, of the framebuffer.
+ * @ingroup event
+ */
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height);
+
+/*! @brief Notifies shared code of a window iconification event.
+ * @param[in] window The window that received the event.
+ * @param[in] iconified `GLFW_TRUE` if the window was iconified, or
+ * `GLFW_FALSE` if it was restored.
+ * @ingroup event
+ */
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified);
+
+/*! @brief Notifies shared code of a window damage event.
+ * @param[in] window The window that received the event.
+ */
+void _glfwInputWindowDamage(_GLFWwindow* window);
+
+/*! @brief Notifies shared code of a window close request event
+ * @param[in] window The window that received the event.
+ * @ingroup event
+ */
+void _glfwInputWindowCloseRequest(_GLFWwindow* window);
+
+void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor);
+
+/*! @brief Notifies shared code of a physical key event.
+ * @param[in] window The window that received the event.
+ * @param[in] key The key that was pressed or released.
+ * @param[in] scancode The system-specific scan code of the key.
+ * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
+ * @param[in] mods The modifiers pressed when the event was generated.
+ * @ingroup event
+ */
+void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods);
+
+/*! @brief Notifies shared code of a Unicode character input event.
+ * @param[in] window The window that received the event.
+ * @param[in] codepoint The Unicode code point of the input character.
+ * @param[in] mods Bit field describing which modifier keys were held down.
+ * @param[in] plain `GLFW_TRUE` if the character is regular text input, or
+ * `GLFW_FALSE` otherwise.
+ * @ingroup event
+ */
+void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain);
+
+/*! @brief Notifies shared code of a scroll event.
+ * @param[in] window The window that received the event.
+ * @param[in] xoffset The scroll offset along the x-axis.
+ * @param[in] yoffset The scroll offset along the y-axis.
+ * @ingroup event
+ */
+void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset);
+
+/*! @brief Notifies shared code of a mouse button click event.
+ * @param[in] window The window that received the event.
+ * @param[in] button The button that was pressed or released.
+ * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE.
+ * @ingroup event
+ */
+void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods);
+
+/*! @brief Notifies shared code of a cursor motion event.
+ * @param[in] window The window that received the event.
+ * @param[in] xpos The new x-coordinate of the cursor, relative to the left
+ * edge of the client area of the window.
+ * @param[in] ypos The new y-coordinate of the cursor, relative to the top edge
+ * of the client area of the window.
+ * @ingroup event
+ */
+void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos);
+
+/*! @brief Notifies shared code of a cursor enter/leave event.
+ * @param[in] window The window that received the event.
+ * @param[in] entered `GLFW_TRUE` if the cursor entered the client area of the
+ * window, or `GLFW_FALSE` if it left it.
+ * @ingroup event
+ */
+void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered);
+
+/*! @ingroup event
+ */
+void _glfwInputMonitorChange(void);
+
+/*! @ingroup event
+ */
+void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window);
+
+/*! @brief Notifies shared code of an error.
+ * @param[in] error The error code most suitable for the error.
+ * @param[in] format The `printf` style format string of the error
+ * description.
+ * @ingroup event
+ */
+#if defined(__GNUC__)
+void _glfwInputError(int error, const char* format, ...) __attribute__((format(printf, 2, 3)));
+#else
+void _glfwInputError(int error, const char* format, ...);
+#endif
+
+/*! @brief Notifies dropped object over window.
+ * @param[in] window The window that received the event.
+ * @param[in] count The number of dropped objects.
+ * @param[in] names The names of the dropped objects.
+ * @ingroup event
+ */
+void _glfwInputDrop(_GLFWwindow* window, int count, const char** names);
+
+/*! @brief Notifies shared code of a joystick connection/disconnection event.
+ * @param[in] joy The joystick that was connected or disconnected.
+ * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`.
+ * @ingroup event
+ */
+void _glfwInputJoystickChange(int joy, int event);
+
+
+//========================================================================
+// Utility functions
+//========================================================================
+
+/*! @ingroup utility
+ */
+const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor,
+ const GLFWvidmode* desired);
+
+/*! @brief Performs lexical comparison between two @ref GLFWvidmode structures.
+ * @ingroup utility
+ */
+int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second);
+
+/*! @brief Splits a color depth into red, green and blue bit depths.
+ * @ingroup utility
+ */
+void _glfwSplitBPP(int bpp, int* red, int* green, int* blue);
+
+/*! @brief Searches an extension string for the specified extension.
+ * @param[in] string The extension string to search.
+ * @param[in] extensions The extension to search for.
+ * @return `GLFW_TRUE` if the extension was found, or `GLFW_FALSE` otherwise.
+ * @ingroup utility
+ */
+GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions);
+
+/*! @brief Chooses the framebuffer config that best matches the desired one.
+ * @param[in] desired The desired framebuffer config.
+ * @param[in] alternatives The framebuffer configs supported by the system.
+ * @param[in] count The number of entries in the alternatives array.
+ * @return The framebuffer config most closely matching the desired one, or @c
+ * NULL if none fulfilled the hard constraints of the desired values.
+ * @ingroup utility
+ */
+const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
+ const _GLFWfbconfig* alternatives,
+ unsigned int count);
+
+/*! @brief Retrieves the attributes of the current context.
+ * @param[in] ctxconfig The desired context attributes.
+ * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if the context is
+ * unusable.
+ * @ingroup utility
+ */
+GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig);
+
+/*! @brief Checks whether the desired context attributes are valid.
+ * @param[in] ctxconfig The context attributes to check.
+ * @return `GLFW_TRUE` if the context attributes are valid, or `GLFW_FALSE`
+ * otherwise.
+ * @ingroup utility
+ *
+ * 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);
+
+/*! @ingroup utility
+ */
+void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size);
+
+/*! @ingroup utility
+ */
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp);
+
+/*! @brief Allocates and returns a monitor object with the specified name
+ * and dimensions.
+ * @param[in] name The name of the monitor.
+ * @param[in] widthMM The width, in mm, of the monitor's display area.
+ * @param[in] heightMM The height, in mm, of the monitor's display area.
+ * @return The newly created object.
+ * @ingroup utility
+ */
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM);
+
+/*! @brief Frees a monitor object and any data associated with it.
+ * @ingroup utility
+ */
+void _glfwFreeMonitor(_GLFWmonitor* monitor);
+
+/*! @ingroup utility
+ */
+void _glfwFreeMonitors(_GLFWmonitor** monitors, int count);
+
+/*! @ingroup utility
+ */
+GLFWbool _glfwIsPrintable(int key);
+
+/*! @ingroup utility
+ */
+GLFWbool _glfwInitVulkan(void);
+
+/*! @ingroup utility
+ */
+void _glfwTerminateVulkan(void);
+
+/*! @ingroup utility
+ */
+const char* _glfwGetVulkanResultString(VkResult result);
+
+#endif // _glfw3_internal_h_
diff --git a/glfw-3.2.1/src/linux_joystick.c b/glfw-3.2.1/src/linux_joystick.c
new file mode 100644
index 0000000..561b1eb
--- /dev/null
+++ b/glfw-3.2.1/src/linux_joystick.c
@@ -0,0 +1,341 @@
+//========================================================================
+// GLFW 3.2 Linux - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#if defined(__linux__)
+#include <linux/joystick.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>
+#endif // __linux__
+
+
+// Attempt to open the specified joystick device
+//
+#if defined(__linux__)
+static GLFWbool openJoystickDevice(const char* path)
+{
+ char axisCount, buttonCount;
+ char name[256] = "";
+ int joy, fd, version;
+ _GLFWjoystickLinux* js;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.linux_js.js[joy].present)
+ continue;
+
+ if (strcmp(_glfw.linux_js.js[joy].path, path) == 0)
+ return GLFW_FALSE;
+ }
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.linux_js.js[joy].present)
+ break;
+ }
+
+ if (joy > GLFW_JOYSTICK_LAST)
+ return GLFW_FALSE;
+
+ fd = open(path, O_RDONLY | O_NONBLOCK);
+ if (fd == -1)
+ return GLFW_FALSE;
+
+ // Verify that the joystick driver version is at least 1.0
+ ioctl(fd, JSIOCGVERSION, &version);
+ if (version < 0x010000)
+ {
+ // It's an old 0.x interface (we don't support it)
+ close(fd);
+ return GLFW_FALSE;
+ }
+
+ if (ioctl(fd, JSIOCGNAME(sizeof(name)), name) < 0)
+ strncpy(name, "Unknown", sizeof(name));
+
+ js = _glfw.linux_js.js + joy;
+ js->present = GLFW_TRUE;
+ js->name = strdup(name);
+ js->path = strdup(path);
+ js->fd = fd;
+
+ ioctl(fd, JSIOCGAXES, &axisCount);
+ js->axisCount = (int) axisCount;
+ js->axes = calloc(axisCount, sizeof(float));
+
+ ioctl(fd, JSIOCGBUTTONS, &buttonCount);
+ js->buttonCount = (int) buttonCount;
+ js->buttons = calloc(buttonCount, 1);
+
+ _glfwInputJoystickChange(joy, GLFW_CONNECTED);
+ return GLFW_TRUE;
+}
+#endif // __linux__
+
+// Polls for and processes events the specified joystick
+//
+static GLFWbool pollJoystickEvents(_GLFWjoystickLinux* js)
+{
+#if defined(__linux__)
+ _glfwPollJoystickEvents();
+
+ if (!js->present)
+ return GLFW_FALSE;
+
+ // Read all queued events (non-blocking)
+ for (;;)
+ {
+ struct js_event e;
+
+ errno = 0;
+ if (read(js->fd, &e, sizeof(e)) < 0)
+ {
+ // Reset the joystick slot if the device was disconnected
+ if (errno == ENODEV)
+ {
+ free(js->axes);
+ free(js->buttons);
+ free(js->name);
+ free(js->path);
+
+ memset(js, 0, sizeof(_GLFWjoystickLinux));
+
+ _glfwInputJoystickChange(js - _glfw.linux_js.js,
+ GLFW_DISCONNECTED);
+ }
+
+ break;
+ }
+
+ // Clear the initial-state bit
+ e.type &= ~JS_EVENT_INIT;
+
+ if (e.type == JS_EVENT_AXIS)
+ js->axes[e.number] = (float) e.value / 32767.0f;
+ else if (e.type == JS_EVENT_BUTTON)
+ js->buttons[e.number] = e.value ? GLFW_PRESS : GLFW_RELEASE;
+ }
+#endif // __linux__
+ return js->present;
+}
+
+// Lexically compare joysticks by name; used by qsort
+//
+#if defined(__linux__)
+static int compareJoysticks(const void* fp, const void* sp)
+{
+ const _GLFWjoystickLinux* fj = fp;
+ const _GLFWjoystickLinux* sj = sp;
+ return strcmp(fj->path, sj->path);
+}
+#endif // __linux__
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+GLFWbool _glfwInitJoysticksLinux(void)
+{
+#if defined(__linux__)
+ DIR* dir;
+ int count = 0;
+ const char* dirname = "/dev/input";
+
+ _glfw.linux_js.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
+ if (_glfw.linux_js.inotify == -1)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Linux: Failed to initialize inotify: %s",
+ strerror(errno));
+ return GLFW_FALSE;
+ }
+
+ // HACK: Register for IN_ATTRIB as well to get notified when udev is done
+ // This works well in practice but the true way is libudev
+
+ _glfw.linux_js.watch = inotify_add_watch(_glfw.linux_js.inotify,
+ dirname,
+ IN_CREATE | IN_ATTRIB);
+ if (_glfw.linux_js.watch == -1)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Linux: Failed to watch for joystick connections in %s: %s",
+ dirname,
+ strerror(errno));
+ // Continue without device connection notifications
+ }
+
+ if (regcomp(&_glfw.linux_js.regex, "^js[0-9]\\+$", 0) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Linux: Failed to compile regex");
+ return GLFW_FALSE;
+ }
+
+ dir = opendir(dirname);
+ if (dir)
+ {
+ struct dirent* entry;
+
+ while ((entry = readdir(dir)))
+ {
+ char path[20];
+ regmatch_t match;
+
+ if (regexec(&_glfw.linux_js.regex, entry->d_name, 1, &match, 0) != 0)
+ continue;
+
+ snprintf(path, sizeof(path), "%s/%s", dirname, entry->d_name);
+ if (openJoystickDevice(path))
+ count++;
+ }
+
+ closedir(dir);
+ }
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Linux: Failed to open joystick device directory %s: %s",
+ dirname,
+ strerror(errno));
+ // Continue with no joysticks detected
+ }
+
+ qsort(_glfw.linux_js.js, count, sizeof(_GLFWjoystickLinux), compareJoysticks);
+#endif // __linux__
+
+ return GLFW_TRUE;
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksLinux(void)
+{
+#if defined(__linux__)
+ int i;
+
+ for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
+ {
+ if (_glfw.linux_js.js[i].present)
+ {
+ close(_glfw.linux_js.js[i].fd);
+ free(_glfw.linux_js.js[i].axes);
+ free(_glfw.linux_js.js[i].buttons);
+ free(_glfw.linux_js.js[i].name);
+ free(_glfw.linux_js.js[i].path);
+ }
+ }
+
+ regfree(&_glfw.linux_js.regex);
+
+ if (_glfw.linux_js.inotify > 0)
+ {
+ if (_glfw.linux_js.watch > 0)
+ inotify_rm_watch(_glfw.linux_js.inotify, _glfw.linux_js.watch);
+
+ close(_glfw.linux_js.inotify);
+ }
+#endif // __linux__
+}
+
+void _glfwPollJoystickEvents(void)
+{
+#if defined(__linux__)
+ ssize_t offset = 0;
+ char buffer[16384];
+
+ const ssize_t size = read(_glfw.linux_js.inotify, buffer, sizeof(buffer));
+
+ while (size > offset)
+ {
+ regmatch_t match;
+ const struct inotify_event* e = (struct inotify_event*) (buffer + offset);
+
+ if (regexec(&_glfw.linux_js.regex, e->name, 1, &match, 0) == 0)
+ {
+ char path[20];
+ snprintf(path, sizeof(path), "/dev/input/%s", e->name);
+ openJoystickDevice(path);
+ }
+
+ offset += sizeof(struct inotify_event) + e->len;
+ }
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformJoystickPresent(int joy)
+{
+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
+ return pollJoystickEvents(js);
+}
+
+const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
+{
+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
+ if (!pollJoystickEvents(js))
+ return NULL;
+
+ *count = js->axisCount;
+ return js->axes;
+}
+
+const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
+{
+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
+ if (!pollJoystickEvents(js))
+ return NULL;
+
+ *count = js->buttonCount;
+ return js->buttons;
+}
+
+const char* _glfwPlatformGetJoystickName(int joy)
+{
+ _GLFWjoystickLinux* js = _glfw.linux_js.js + joy;
+ if (!pollJoystickEvents(js))
+ return NULL;
+
+ return js->name;
+}
+
diff --git a/glfw-3.2.1/src/linux_joystick.h b/glfw-3.2.1/src/linux_joystick.h
new file mode 100644
index 0000000..e9d1f2b
--- /dev/null
+++ b/glfw-3.2.1/src/linux_joystick.h
@@ -0,0 +1,68 @@
+//========================================================================
+// GLFW 3.2 Linux - 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.
+//
+//========================================================================
+
+#ifndef _glfw3_linux_joystick_h_
+#define _glfw3_linux_joystick_h_
+
+#include <regex.h>
+
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWjoylistLinux linux_js
+
+
+// Linux-specific joystick data
+//
+typedef struct _GLFWjoystickLinux
+{
+ GLFWbool present;
+ int fd;
+ float* axes;
+ int axisCount;
+ unsigned char* buttons;
+ int buttonCount;
+ char* name;
+ char* path;
+} _GLFWjoystickLinux;
+
+// Linux-specific joystick API data
+//
+typedef struct _GLFWjoylistLinux
+{
+ _GLFWjoystickLinux js[GLFW_JOYSTICK_LAST + 1];
+
+#if defined(__linux__)
+ int inotify;
+ int watch;
+ regex_t regex;
+#endif /*__linux__*/
+} _GLFWjoylistLinux;
+
+
+GLFWbool _glfwInitJoysticksLinux(void);
+void _glfwTerminateJoysticksLinux(void);
+
+void _glfwPollJoystickEvents(void);
+
+#endif // _glfw3_linux_joystick_h_
diff --git a/glfw-3.2.1/src/mir_init.c b/glfw-3.2.1/src/mir_init.c
new file mode 100644
index 0000000..3076f5f
--- /dev/null
+++ b/glfw-3.2.1/src/mir_init.c
@@ -0,0 +1,238 @@
+//========================================================================
+// GLFW 3.2 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <linux/input.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ memset(_glfw.mir.publicKeys, -1, sizeof(_glfw.mir.publicKeys));
+
+ _glfw.mir.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.mir.publicKeys[KEY_1] = GLFW_KEY_1;
+ _glfw.mir.publicKeys[KEY_2] = GLFW_KEY_2;
+ _glfw.mir.publicKeys[KEY_3] = GLFW_KEY_3;
+ _glfw.mir.publicKeys[KEY_4] = GLFW_KEY_4;
+ _glfw.mir.publicKeys[KEY_5] = GLFW_KEY_5;
+ _glfw.mir.publicKeys[KEY_6] = GLFW_KEY_6;
+ _glfw.mir.publicKeys[KEY_7] = GLFW_KEY_7;
+ _glfw.mir.publicKeys[KEY_8] = GLFW_KEY_8;
+ _glfw.mir.publicKeys[KEY_9] = GLFW_KEY_9;
+ _glfw.mir.publicKeys[KEY_0] = GLFW_KEY_0;
+ _glfw.mir.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
+ _glfw.mir.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
+ _glfw.mir.publicKeys[KEY_Q] = GLFW_KEY_Q;
+ _glfw.mir.publicKeys[KEY_W] = GLFW_KEY_W;
+ _glfw.mir.publicKeys[KEY_E] = GLFW_KEY_E;
+ _glfw.mir.publicKeys[KEY_R] = GLFW_KEY_R;
+ _glfw.mir.publicKeys[KEY_T] = GLFW_KEY_T;
+ _glfw.mir.publicKeys[KEY_Y] = GLFW_KEY_Y;
+ _glfw.mir.publicKeys[KEY_U] = GLFW_KEY_U;
+ _glfw.mir.publicKeys[KEY_I] = GLFW_KEY_I;
+ _glfw.mir.publicKeys[KEY_O] = GLFW_KEY_O;
+ _glfw.mir.publicKeys[KEY_P] = GLFW_KEY_P;
+ _glfw.mir.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.mir.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.mir.publicKeys[KEY_A] = GLFW_KEY_A;
+ _glfw.mir.publicKeys[KEY_S] = GLFW_KEY_S;
+ _glfw.mir.publicKeys[KEY_D] = GLFW_KEY_D;
+ _glfw.mir.publicKeys[KEY_F] = GLFW_KEY_F;
+ _glfw.mir.publicKeys[KEY_G] = GLFW_KEY_G;
+ _glfw.mir.publicKeys[KEY_H] = GLFW_KEY_H;
+ _glfw.mir.publicKeys[KEY_J] = GLFW_KEY_J;
+ _glfw.mir.publicKeys[KEY_K] = GLFW_KEY_K;
+ _glfw.mir.publicKeys[KEY_L] = GLFW_KEY_L;
+ _glfw.mir.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
+ _glfw.mir.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
+ _glfw.mir.publicKeys[KEY_Z] = GLFW_KEY_Z;
+ _glfw.mir.publicKeys[KEY_X] = GLFW_KEY_X;
+ _glfw.mir.publicKeys[KEY_C] = GLFW_KEY_C;
+ _glfw.mir.publicKeys[KEY_V] = GLFW_KEY_V;
+ _glfw.mir.publicKeys[KEY_B] = GLFW_KEY_B;
+ _glfw.mir.publicKeys[KEY_N] = GLFW_KEY_N;
+ _glfw.mir.publicKeys[KEY_M] = GLFW_KEY_M;
+ _glfw.mir.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
+ _glfw.mir.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
+ _glfw.mir.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
+ _glfw.mir.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
+ _glfw.mir.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
+ _glfw.mir.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
+ _glfw.mir.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.mir.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.mir.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.mir.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.mir.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
+ _glfw.mir.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
+ _glfw.mir.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
+ _glfw.mir.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.mir.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
+ _glfw.mir.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
+ _glfw.mir.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
+ _glfw.mir.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.mir.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.mir.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
+ _glfw.mir.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
+ _glfw.mir.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
+ _glfw.mir.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
+ _glfw.mir.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
+ _glfw.mir.publicKeys[KEY_END] = GLFW_KEY_END;
+ _glfw.mir.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
+ _glfw.mir.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
+ _glfw.mir.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
+ _glfw.mir.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
+ _glfw.mir.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
+ _glfw.mir.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
+ _glfw.mir.publicKeys[KEY_UP] = GLFW_KEY_UP;
+ _glfw.mir.publicKeys[KEY_F1] = GLFW_KEY_F1;
+ _glfw.mir.publicKeys[KEY_F2] = GLFW_KEY_F2;
+ _glfw.mir.publicKeys[KEY_F3] = GLFW_KEY_F3;
+ _glfw.mir.publicKeys[KEY_F4] = GLFW_KEY_F4;
+ _glfw.mir.publicKeys[KEY_F5] = GLFW_KEY_F5;
+ _glfw.mir.publicKeys[KEY_F6] = GLFW_KEY_F6;
+ _glfw.mir.publicKeys[KEY_F7] = GLFW_KEY_F7;
+ _glfw.mir.publicKeys[KEY_F8] = GLFW_KEY_F8;
+ _glfw.mir.publicKeys[KEY_F9] = GLFW_KEY_F9;
+ _glfw.mir.publicKeys[KEY_F10] = GLFW_KEY_F10;
+ _glfw.mir.publicKeys[KEY_F11] = GLFW_KEY_F11;
+ _glfw.mir.publicKeys[KEY_F12] = GLFW_KEY_F12;
+ _glfw.mir.publicKeys[KEY_F13] = GLFW_KEY_F13;
+ _glfw.mir.publicKeys[KEY_F14] = GLFW_KEY_F14;
+ _glfw.mir.publicKeys[KEY_F15] = GLFW_KEY_F15;
+ _glfw.mir.publicKeys[KEY_F16] = GLFW_KEY_F16;
+ _glfw.mir.publicKeys[KEY_F17] = GLFW_KEY_F17;
+ _glfw.mir.publicKeys[KEY_F18] = GLFW_KEY_F18;
+ _glfw.mir.publicKeys[KEY_F19] = GLFW_KEY_F19;
+ _glfw.mir.publicKeys[KEY_F20] = GLFW_KEY_F20;
+ _glfw.mir.publicKeys[KEY_F21] = GLFW_KEY_F21;
+ _glfw.mir.publicKeys[KEY_F22] = GLFW_KEY_F22;
+ _glfw.mir.publicKeys[KEY_F23] = GLFW_KEY_F23;
+ _glfw.mir.publicKeys[KEY_F24] = GLFW_KEY_F24;
+ _glfw.mir.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
+ _glfw.mir.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.mir.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
+ _glfw.mir.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
+ _glfw.mir.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
+ _glfw.mir.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
+ _glfw.mir.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
+ _glfw.mir.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
+ _glfw.mir.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
+ _glfw.mir.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
+ _glfw.mir.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
+ _glfw.mir.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
+ _glfw.mir.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
+ _glfw.mir.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
+ _glfw.mir.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
+ _glfw.mir.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
+ _glfw.mir.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ int error;
+
+ _glfw.mir.connection = mir_connect_sync(NULL, __PRETTY_FUNCTION__);
+
+ if (!mir_connection_is_valid(_glfw.mir.connection))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to connect to server: %s",
+ mir_connection_get_error_message(_glfw.mir.connection));
+
+ return GLFW_FALSE;
+ }
+
+ _glfw.mir.display =
+ mir_connection_get_egl_native_display(_glfw.mir.connection);
+
+ createKeyTables();
+
+ if (!_glfwInitThreadLocalStoragePOSIX())
+ return GLFW_FALSE;
+
+ if (!_glfwInitJoysticksLinux())
+ return GLFW_FALSE;
+
+ _glfwInitTimerPOSIX();
+
+ // Need the default conf for when we set a NULL cursor
+ _glfw.mir.default_conf = mir_cursor_configuration_from_name(mir_arrow_cursor_name);
+
+ _glfw.mir.event_queue = calloc(1, sizeof(EventQueue));
+ _glfwInitEventQueueMir(_glfw.mir.event_queue);
+
+ error = pthread_mutex_init(&_glfw.mir.event_mutex, NULL);
+ if (error)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Failed to create event mutex: %s",
+ strerror(error));
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ _glfwTerminateEGL();
+ _glfwTerminateJoysticksLinux();
+ _glfwTerminateThreadLocalStoragePOSIX();
+
+ _glfwDeleteEventQueueMir(_glfw.mir.event_queue);
+
+ pthread_mutex_destroy(&_glfw.mir.event_mutex);
+
+ mir_connection_release(_glfw.mir.connection);
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Mir EGL"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#else
+ " gettimeofday"
+#endif
+#if defined(__linux__)
+ " /dev/js"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+}
+
diff --git a/glfw-3.2.1/src/mir_monitor.c b/glfw-3.2.1/src/mir_monitor.c
new file mode 100644
index 0000000..90aa6c9
--- /dev/null
+++ b/glfw-3.2.1/src/mir_monitor.c
@@ -0,0 +1,182 @@
+//========================================================================
+// GLFW 3.2 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ int i, found = 0;
+ _GLFWmonitor** monitors = NULL;
+ MirDisplayConfiguration* displayConfig =
+ mir_connection_create_display_config(_glfw.mir.connection);
+
+ *count = 0;
+
+ for (i = 0; i < displayConfig->num_outputs; i++)
+ {
+ const MirDisplayOutput* out = displayConfig->outputs + i;
+
+ if (out->used &&
+ out->connected &&
+ out->num_modes &&
+ out->current_mode < out->num_modes)
+ {
+ found++;
+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
+ monitors[i] = _glfwAllocMonitor("Unknown",
+ out->physical_width_mm,
+ out->physical_height_mm);
+
+ monitors[i]->mir.x = out->position_x;
+ monitors[i]->mir.y = out->position_y;
+ monitors[i]->mir.output_id = out->output_id;
+ monitors[i]->mir.cur_mode = out->current_mode;
+
+ monitors[i]->modes = _glfwPlatformGetVideoModes(monitors[i],
+ &monitors[i]->modeCount);
+ }
+ }
+
+ mir_display_config_destroy(displayConfig);
+
+ *count = found;
+ return monitors;
+}
+
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ return first->mir.output_id == second->mir.output_id;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (xpos)
+ *xpos = monitor->mir.x;
+ if (ypos)
+ *ypos = monitor->mir.y;
+}
+
+void FillInRGBBitsFromPixelFormat(GLFWvidmode* mode, const MirPixelFormat pf)
+{
+ switch (pf)
+ {
+ case mir_pixel_format_rgb_565:
+ mode->redBits = 5;
+ mode->greenBits = 6;
+ mode->blueBits = 5;
+ break;
+ case mir_pixel_format_rgba_5551:
+ mode->redBits = 5;
+ mode->greenBits = 5;
+ mode->blueBits = 5;
+ break;
+ case mir_pixel_format_rgba_4444:
+ mode->redBits = 4;
+ mode->greenBits = 4;
+ mode->blueBits = 4;
+ break;
+ case mir_pixel_format_abgr_8888:
+ case mir_pixel_format_xbgr_8888:
+ case mir_pixel_format_argb_8888:
+ case mir_pixel_format_xrgb_8888:
+ case mir_pixel_format_bgr_888:
+ case mir_pixel_format_rgb_888:
+ default:
+ mode->redBits = 8;
+ mode->greenBits = 8;
+ mode->blueBits = 8;
+ break;
+ }
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+ int i;
+ GLFWvidmode* modes = NULL;
+ MirDisplayConfiguration* displayConfig =
+ mir_connection_create_display_config(_glfw.mir.connection);
+
+ for (i = 0; i < displayConfig->num_outputs; i++)
+ {
+ const MirDisplayOutput* out = displayConfig->outputs + i;
+ if (out->output_id != monitor->mir.output_id)
+ continue;
+
+ modes = calloc(out->num_modes, sizeof(GLFWvidmode));
+
+ for (*found = 0; *found < out->num_modes; (*found)++)
+ {
+ modes[*found].width = out->modes[*found].horizontal_resolution;
+ modes[*found].height = out->modes[*found].vertical_resolution;
+ modes[*found].refreshRate = out->modes[*found].refresh_rate;
+
+ FillInRGBBitsFromPixelFormat(&modes[*found], out->output_formats[*found]);
+ }
+
+ break;
+ }
+
+ mir_display_config_destroy(displayConfig);
+
+ return modes;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ *mode = monitor->modes[monitor->mir.cur_mode];
+}
+
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwGetMirMonitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
+ return monitor->mir.output_id;
+}
+
diff --git a/glfw-3.2.1/src/mir_platform.h b/glfw-3.2.1/src/mir_platform.h
new file mode 100644
index 0000000..8f1cf4e
--- /dev/null
+++ b/glfw-3.2.1/src/mir_platform.h
@@ -0,0 +1,130 @@
+//========================================================================
+// GLFW 3.2 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// 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_mir_platform_h_
+#define _glfw3_mir_platform_h_
+
+#include <sys/queue.h>
+#include <pthread.h>
+#include <dlfcn.h>
+
+#include <mir_toolkit/mir_client_library.h>
+
+typedef VkFlags VkMirSurfaceCreateFlagsKHR;
+
+typedef struct VkMirSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkMirSurfaceCreateFlagsKHR flags;
+ MirConnection* connection;
+ MirSurface* mirSurface;
+} VkMirSurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateMirSurfaceKHR)(VkInstance,const VkMirSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)(VkPhysicalDevice,uint32_t,MirConnection*);
+
+#include "posix_tls.h"
+#include "posix_time.h"
+#include "linux_joystick.h"
+#include "xkb_unicode.h"
+#include "egl_context.h"
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->mir.window)
+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.mir.display)
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowMir mir
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorMir mir
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryMir mir
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorMir mir
+
+#define _GLFW_PLATFORM_CONTEXT_STATE
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
+
+
+// Mir-specific Event Queue
+//
+typedef struct EventQueue
+{
+ TAILQ_HEAD(, EventNode) head;
+} EventQueue;
+
+// Mir-specific per-window data
+//
+typedef struct _GLFWwindowMir
+{
+ MirSurface* surface;
+ int width;
+ int height;
+ MirEGLNativeWindowType window;
+
+} _GLFWwindowMir;
+
+// Mir-specific per-monitor data
+//
+typedef struct _GLFWmonitorMir
+{
+ int cur_mode;
+ int output_id;
+ int x;
+ int y;
+
+} _GLFWmonitorMir;
+
+// Mir-specific global data
+//
+typedef struct _GLFWlibraryMir
+{
+ MirConnection* connection;
+ MirEGLNativeDisplayType display;
+ MirCursorConfiguration* default_conf;
+ EventQueue* event_queue;
+
+ short int publicKeys[256];
+
+ pthread_mutex_t event_mutex;
+ pthread_cond_t event_cond;
+
+} _GLFWlibraryMir;
+
+// Mir-specific per-cursor data
+// TODO: Only system cursors are implemented in Mir atm. Need to wait for support.
+//
+typedef struct _GLFWcursorMir
+{
+ MirCursorConfiguration* conf;
+ MirBufferStream* custom_cursor;
+} _GLFWcursorMir;
+
+
+extern void _glfwInitEventQueueMir(EventQueue* queue);
+extern void _glfwDeleteEventQueueMir(EventQueue* queue);
+
+#endif // _glfw3_mir_platform_h_
diff --git a/glfw-3.2.1/src/mir_window.c b/glfw-3.2.1/src/mir_window.c
new file mode 100644
index 0000000..411f906
--- /dev/null
+++ b/glfw-3.2.1/src/mir_window.c
@@ -0,0 +1,848 @@
+//========================================================================
+// GLFW 3.2 Mir - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2014-2015 Brandon Schaefer <brandon.schaefer@canonical.com>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <linux/input.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+typedef struct EventNode
+{
+ TAILQ_ENTRY(EventNode) entries;
+ const MirEvent* event;
+ _GLFWwindow* window;
+} EventNode;
+
+static void deleteNode(EventQueue* queue, EventNode* node)
+{
+ mir_event_unref(node->event);
+ free(node);
+}
+
+static GLFWbool emptyEventQueue(EventQueue* queue)
+{
+ return queue->head.tqh_first == NULL;
+}
+
+// TODO The mir_event_ref is not supposed to be used but ... its needed
+// in this case. Need to wait until we can read from an FD set up by mir
+// for single threaded event handling.
+static EventNode* newEventNode(const MirEvent* event, _GLFWwindow* context)
+{
+ EventNode* new_node = calloc(1, sizeof(EventNode));
+ new_node->event = mir_event_ref(event);
+ new_node->window = context;
+
+ return new_node;
+}
+
+static void enqueueEvent(const MirEvent* event, _GLFWwindow* context)
+{
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ EventNode* new_node = newEventNode(event, context);
+ TAILQ_INSERT_TAIL(&_glfw.mir.event_queue->head, new_node, entries);
+
+ pthread_cond_signal(&_glfw.mir.event_cond);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+}
+
+static EventNode* dequeueEvent(EventQueue* queue)
+{
+ EventNode* node = NULL;
+
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ node = queue->head.tqh_first;
+
+ if (node)
+ TAILQ_REMOVE(&queue->head, node, entries);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+
+ return node;
+}
+
+/* FIXME Soon to be changed upstream mir! So we can use an egl config to figure out
+ the best pixel format!
+*/
+static MirPixelFormat findValidPixelFormat(void)
+{
+ unsigned int i, validFormats, mirPixelFormats = 32;
+ MirPixelFormat formats[mir_pixel_formats];
+
+ mir_connection_get_available_surface_formats(_glfw.mir.connection, formats,
+ mirPixelFormats, &validFormats);
+
+ for (i = 0; i < validFormats; i++)
+ {
+ if (formats[i] == mir_pixel_format_abgr_8888 ||
+ formats[i] == mir_pixel_format_xbgr_8888 ||
+ formats[i] == mir_pixel_format_argb_8888 ||
+ formats[i] == mir_pixel_format_xrgb_8888)
+ {
+ return formats[i];
+ }
+ }
+
+ return mir_pixel_format_invalid;
+}
+
+static int mirModToGLFWMod(uint32_t mods)
+{
+ int publicMods = 0x0;
+
+ if (mods & mir_input_event_modifier_alt)
+ publicMods |= GLFW_MOD_ALT;
+ else if (mods & mir_input_event_modifier_shift)
+ publicMods |= GLFW_MOD_SHIFT;
+ else if (mods & mir_input_event_modifier_ctrl)
+ publicMods |= GLFW_MOD_CONTROL;
+ else if (mods & mir_input_event_modifier_meta)
+ publicMods |= GLFW_MOD_SUPER;
+
+ return publicMods;
+}
+
+static int toGLFWKeyCode(uint32_t key)
+{
+ if (key < sizeof(_glfw.mir.publicKeys) / sizeof(_glfw.mir.publicKeys[0]))
+ return _glfw.mir.publicKeys[key];
+
+ return GLFW_KEY_UNKNOWN;
+}
+
+static void handleKeyEvent(const MirKeyboardEvent* key_event, _GLFWwindow* window)
+{
+ const int action = mir_keyboard_event_action (key_event);
+ const int scan_code = mir_keyboard_event_scan_code(key_event);
+ const int key_code = mir_keyboard_event_key_code (key_event);
+ const int modifiers = mir_keyboard_event_modifiers(key_event);
+
+ const int pressed = action == mir_keyboard_action_up ? GLFW_RELEASE : GLFW_PRESS;
+ const int mods = mirModToGLFWMod(modifiers);
+ const long text = _glfwKeySym2Unicode(key_code);
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+
+ _glfwInputKey(window, toGLFWKeyCode(scan_code), scan_code, pressed, mods);
+
+ if (text != -1)
+ _glfwInputChar(window, text, mods, plain);
+}
+
+static void handlePointerButton(_GLFWwindow* window,
+ int pressed,
+ const MirPointerEvent* pointer_event)
+{
+ int mods = mir_pointer_event_modifiers(pointer_event);
+ const int publicMods = mirModToGLFWMod(mods);
+ MirPointerButton button = mir_pointer_button_primary;
+ static uint32_t oldButtonStates = 0;
+ uint32_t newButtonStates = mir_pointer_event_buttons(pointer_event);
+ int publicButton = GLFW_MOUSE_BUTTON_LEFT;
+
+ // XOR our old button states our new states to figure out what was added or removed
+ button = newButtonStates ^ oldButtonStates;
+
+ switch (button)
+ {
+ case mir_pointer_button_primary:
+ publicButton = GLFW_MOUSE_BUTTON_LEFT;
+ break;
+ case mir_pointer_button_secondary:
+ publicButton = GLFW_MOUSE_BUTTON_RIGHT;
+ break;
+ case mir_pointer_button_tertiary:
+ publicButton = GLFW_MOUSE_BUTTON_MIDDLE;
+ break;
+ case mir_pointer_button_forward:
+ // FIXME What is the forward button?
+ publicButton = GLFW_MOUSE_BUTTON_4;
+ break;
+ case mir_pointer_button_back:
+ // FIXME What is the back button?
+ publicButton = GLFW_MOUSE_BUTTON_5;
+ break;
+ default:
+ break;
+ }
+
+ oldButtonStates = newButtonStates;
+
+ _glfwInputMouseClick(window, publicButton, pressed, publicMods);
+}
+
+static void handlePointerMotion(_GLFWwindow* window,
+ const MirPointerEvent* pointer_event)
+{
+ int current_x = window->virtualCursorPosX;
+ int current_y = window->virtualCursorPosY;
+ int x = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_x);
+ int y = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_y);
+ int dx = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_hscroll);
+ int dy = mir_pointer_event_axis_value(pointer_event, mir_pointer_axis_vscroll);
+
+ _glfwInputCursorPos(window, x, y);
+ if (dx != 0 || dy != 0)
+ _glfwInputScroll(window, dx, dy);
+}
+
+static void handlePointerEvent(const MirPointerEvent* pointer_event,
+ _GLFWwindow* window)
+{
+ int action = mir_pointer_event_action(pointer_event);
+
+ switch (action)
+ {
+ case mir_pointer_action_button_down:
+ handlePointerButton(window, GLFW_PRESS, pointer_event);
+ break;
+ case mir_pointer_action_button_up:
+ handlePointerButton(window, GLFW_RELEASE, pointer_event);
+ break;
+ case mir_pointer_action_motion:
+ handlePointerMotion(window, pointer_event);
+ break;
+ case mir_pointer_action_enter:
+ case mir_pointer_action_leave:
+ break;
+ default:
+ break;
+
+ }
+}
+
+static void handleInput(const MirInputEvent* input_event, _GLFWwindow* window)
+{
+ int type = mir_input_event_get_type(input_event);
+
+ switch (type)
+ {
+ case mir_input_event_type_key:
+ handleKeyEvent(mir_input_event_get_keyboard_event(input_event), window);
+ break;
+ case mir_input_event_type_pointer:
+ handlePointerEvent(mir_input_event_get_pointer_event(input_event), window);
+ break;
+ default:
+ break;
+ }
+}
+
+static void handleEvent(const MirEvent* event, _GLFWwindow* window)
+{
+ int type = mir_event_get_type(event);
+
+ switch (type)
+ {
+ case mir_event_type_input:
+ handleInput(mir_event_get_input_event(event), window);
+ break;
+ default:
+ break;
+ }
+}
+
+static void addNewEvent(MirSurface* surface, const MirEvent* event, void* context)
+{
+ enqueueEvent(event, context);
+}
+
+static GLFWbool createSurface(_GLFWwindow* window)
+{
+ MirSurfaceSpec* spec;
+ MirBufferUsage buffer_usage = mir_buffer_usage_hardware;
+ MirPixelFormat pixel_format = findValidPixelFormat();
+
+ if (pixel_format == mir_pixel_format_invalid)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to find a correct pixel format");
+ return GLFW_FALSE;
+ }
+
+ spec = mir_connection_create_spec_for_normal_surface(_glfw.mir.connection,
+ window->mir.width,
+ window->mir.height,
+ pixel_format);
+
+ mir_surface_spec_set_buffer_usage(spec, buffer_usage);
+ mir_surface_spec_set_name(spec, "MirSurface");
+
+ window->mir.surface = mir_surface_create_sync(spec);
+ mir_surface_spec_release(spec);
+
+ if (!mir_surface_is_valid(window->mir.surface))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to create surface: %s",
+ mir_surface_get_error_message(window->mir.surface));
+
+ return GLFW_FALSE;
+ }
+
+ mir_surface_set_event_handler(window->mir.surface, addNewEvent, window);
+
+ return GLFW_TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInitEventQueueMir(EventQueue* queue)
+{
+ TAILQ_INIT(&queue->head);
+}
+
+void _glfwDeleteEventQueueMir(EventQueue* queue)
+{
+ if (queue)
+ {
+ EventNode* node, *node_next;
+ node = queue->head.tqh_first;
+
+ while (node != NULL)
+ {
+ node_next = node->entries.tqe_next;
+
+ TAILQ_REMOVE(&queue->head, node, entries);
+ deleteNode(queue, node);
+
+ node = node_next;
+ }
+
+ free(queue);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (window->monitor)
+ {
+ GLFWvidmode mode;
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+
+ mir_surface_set_state(window->mir.surface, mir_surface_state_fullscreen);
+
+ if (wndconfig->width > mode.width || wndconfig->height > mode.height)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Requested surface size too large: %ix%i",
+ wndconfig->width, wndconfig->height);
+
+ return GLFW_FALSE;
+ }
+ }
+
+ window->mir.width = wndconfig->width;
+ window->mir.height = wndconfig->height;
+
+ if (!createSurface(window))
+ return GLFW_FALSE;
+
+ window->mir.window = mir_buffer_stream_get_egl_native_window(
+ mir_surface_get_buffer_stream(window->mir.surface));
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (mir_surface_is_valid(window->mir.surface))
+ {
+ mir_surface_release_sync(window->mir.surface);
+ window->mir.surface = NULL;
+ }
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+ MirSurfaceSpec* spec;
+ const char* e_title = title ? title : "";
+
+ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
+ mir_surface_spec_set_name(spec, e_title);
+
+ mir_surface_apply_spec(window->mir.surface, spec);
+ mir_surface_spec_release(spec);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ MirSurfaceSpec* spec;
+
+ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
+ mir_surface_spec_set_width (spec, width);
+ mir_surface_spec_set_height(spec, height);
+
+ mir_surface_apply_spec(window->mir.surface, spec);
+ mir_surface_spec_release(spec);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->mir.width;
+ if (height)
+ *height = window->mir.height;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ mir_surface_set_state(window->mir.surface, mir_surface_state_minimized);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ mir_surface_set_state(window->mir.surface, mir_surface_state_restored);
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ MirSurfaceSpec* spec;
+
+ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
+ mir_surface_spec_set_state(spec, mir_surface_state_hidden);
+
+ mir_surface_apply_spec(window->mir.surface, spec);
+ mir_surface_spec_release(spec);
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ MirSurfaceSpec* spec;
+
+ spec = mir_connection_create_spec_for_changes(_glfw.mir.connection);
+ mir_surface_spec_set_state(spec, mir_surface_state_restored);
+
+ mir_surface_apply_spec(window->mir.surface, spec);
+ mir_surface_spec_release(spec);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return mir_surface_get_visibility(window->mir.surface) == mir_surface_visibility_exposed;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ EventNode* node = NULL;
+
+ while ((node = dequeueEvent(_glfw.mir.event_queue)))
+ {
+ handleEvent(node->event, node->window);
+ deleteNode(_glfw.mir.event_queue, node);
+ }
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ if (emptyEventQueue(_glfw.mir.event_queue))
+ pthread_cond_wait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex);
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ pthread_mutex_lock(&_glfw.mir.event_mutex);
+
+ if (emptyEventQueue(_glfw.mir.event_queue))
+ {
+ struct timespec time;
+ clock_gettime(CLOCK_REALTIME, &time);
+ time.tv_sec += (long) timeout;
+ time.tv_nsec += (long) ((timeout - (long) timeout) * 1e9);
+ pthread_cond_timedwait(&_glfw.mir.event_cond, &_glfw.mir.event_mutex, &time);
+ }
+
+ pthread_mutex_unlock(&_glfw.mir.event_mutex);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ if (width)
+ *width = window->mir.width;
+ if (height)
+ *height = window->mir.height;
+}
+
+// FIXME implement
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ MirBufferStream* stream;
+ MirPixelFormat pixel_format = findValidPixelFormat();
+
+ int i_w = image->width;
+ int i_h = image->height;
+
+ if (pixel_format == mir_pixel_format_invalid)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unable to find a correct pixel format");
+ return GLFW_FALSE;
+ }
+
+ stream = mir_connection_create_buffer_stream_sync(_glfw.mir.connection,
+ i_w, i_h,
+ pixel_format,
+ mir_buffer_usage_software);
+
+ cursor->mir.conf = mir_cursor_configuration_from_buffer_stream(stream, xhot, yhot);
+
+ char* dest;
+ unsigned char *pixels;
+ int i, r_stride, bytes_per_pixel, bytes_per_row;
+
+ MirGraphicsRegion region;
+ mir_buffer_stream_get_graphics_region(stream, &region);
+
+ // FIXME Figure this out based on the current_pf
+ bytes_per_pixel = 4;
+ bytes_per_row = bytes_per_pixel * i_w;
+
+ dest = region.vaddr;
+ pixels = image->pixels;
+
+ r_stride = region.stride;
+
+ for (i = 0; i < i_h; i++)
+ {
+ memcpy(dest, pixels, bytes_per_row);
+ dest += r_stride;
+ pixels += r_stride;
+ }
+
+ cursor->mir.custom_cursor = stream;
+
+ return GLFW_TRUE;
+}
+
+const char* getSystemCursorName(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return mir_arrow_cursor_name;
+ case GLFW_IBEAM_CURSOR:
+ return mir_caret_cursor_name;
+ case GLFW_CROSSHAIR_CURSOR:
+ return mir_crosshair_cursor_name;
+ case GLFW_HAND_CURSOR:
+ return mir_open_hand_cursor_name;
+ case GLFW_HRESIZE_CURSOR:
+ return mir_horizontal_resize_cursor_name;
+ case GLFW_VRESIZE_CURSOR:
+ return mir_vertical_resize_cursor_name;
+ }
+
+ return NULL;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ const char* cursor_name = getSystemCursorName(shape);
+
+ if (cursor_name)
+ {
+ cursor->mir.conf = mir_cursor_configuration_from_name(cursor_name);
+ cursor->mir.custom_cursor = NULL;
+
+ return GLFW_TRUE;
+ }
+
+ return GLFW_FALSE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->mir.conf)
+ mir_cursor_configuration_destroy(cursor->mir.conf);
+ if (cursor->mir.custom_cursor)
+ mir_buffer_stream_release_sync(cursor->mir.custom_cursor);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (cursor && cursor->mir.conf)
+ {
+ mir_wait_for(mir_surface_configure_cursor(window->mir.surface, cursor->mir.conf));
+ if (cursor->mir.custom_cursor)
+ {
+ mir_buffer_stream_swap_buffers_sync(cursor->mir.custom_cursor);
+ }
+ }
+ else
+ {
+ mir_wait_for(mir_surface_configure_cursor(window->mir.surface, _glfw.mir.default_conf));
+ }
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+const char* _glfwPlatformGetKeyName(int key, int scancode)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+ return NULL;
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Unsupported function %s", __PRETTY_FUNCTION__);
+
+ return NULL;
+}
+
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
+{
+ char** extensions;
+
+ *count = 0;
+
+ if (!_glfw.vk.KHR_mir_surface)
+ return NULL;
+
+ extensions = calloc(2, sizeof(char*));
+ extensions[0] = strdup("VK_KHR_surface");
+ extensions[1] = strdup("VK_KHR_mir_surface");
+
+ *count = 2;
+ return extensions;
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ PFN_vkGetPhysicalDeviceMirPresentationSupportKHR vkGetPhysicalDeviceMirPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceMirPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceMirPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceMirPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Mir: Vulkan instance missing VK_KHR_mir_surface extension");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceMirPresentationSupportKHR(device,
+ queuefamily,
+ _glfw.mir.connection);
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ VkResult err;
+ VkMirSurfaceCreateInfoKHR sci;
+ PFN_vkCreateMirSurfaceKHR vkCreateMirSurfaceKHR;
+
+ vkCreateMirSurfaceKHR = (PFN_vkCreateMirSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateMirSurfaceKHR");
+ if (!vkCreateMirSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Mir: Vulkan instance missing VK_KHR_mir_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR;
+ sci.connection = _glfw.mir.connection;
+ sci.mirSurface = window->mir.surface;
+
+ err = vkCreateMirSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Mir: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI MirConnection* glfwGetMirDisplay(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfw.mir.connection;
+}
+
+GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return window->mir.surface;
+}
+
diff --git a/glfw-3.2.1/src/monitor.c b/glfw-3.2.1/src/monitor.c
new file mode 100644
index 0000000..b6c312d
--- /dev/null
+++ b/glfw-3.2.1/src/monitor.c
@@ -0,0 +1,477 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <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;
+
+ // 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 //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInputMonitorChange(void)
+{
+ int i, j, monitorCount = _glfw.monitorCount;
+ _GLFWmonitor** monitors = _glfw.monitors;
+
+ _glfw.monitors = _glfwPlatformGetMonitors(&_glfw.monitorCount);
+
+ // Re-use still connected monitor objects
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ {
+ for (j = 0; j < monitorCount; j++)
+ {
+ if (_glfwPlatformIsSameMonitor(_glfw.monitors[i], monitors[j]))
+ {
+ _glfwFreeMonitor(_glfw.monitors[i]);
+ _glfw.monitors[i] = monitors[j];
+ break;
+ }
+ }
+ }
+
+ // Find and report disconnected monitors (not in the new list)
+
+ for (i = 0; i < monitorCount; i++)
+ {
+ _GLFWwindow* window;
+
+ for (j = 0; j < _glfw.monitorCount; j++)
+ {
+ if (monitors[i] == _glfw.monitors[j])
+ break;
+ }
+
+ if (j < _glfw.monitorCount)
+ continue;
+
+ for (window = _glfw.windowListHead; window; window = window->next)
+ {
+ if (window->monitor == monitors[i])
+ {
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetWindowMonitor(window, NULL, 0, 0, width, height, 0);
+ }
+ }
+
+ if (_glfw.callbacks.monitor)
+ _glfw.callbacks.monitor((GLFWmonitor*) monitors[i], GLFW_DISCONNECTED);
+ }
+
+ // Find and report newly connected monitors (not in the old list)
+ // Re-used monitor objects are then removed from the old list to avoid
+ // having them destroyed at the end of this function
+
+ for (i = 0; i < _glfw.monitorCount; i++)
+ {
+ for (j = 0; j < monitorCount; j++)
+ {
+ if (_glfw.monitors[i] == monitors[j])
+ {
+ monitors[j] = NULL;
+ break;
+ }
+ }
+
+ if (j < monitorCount)
+ continue;
+
+ if (_glfw.callbacks.monitor)
+ _glfw.callbacks.monitor((GLFWmonitor*) _glfw.monitors[i], GLFW_CONNECTED);
+ }
+
+ _glfwFreeMonitors(monitors, monitorCount);
+}
+
+void _glfwInputMonitorWindowChange(_GLFWmonitor* monitor, _GLFWwindow* window)
+{
+ monitor->window = window;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM)
+{
+ _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor));
+ monitor->name = strdup(name);
+ monitor->widthMM = widthMM;
+ monitor->heightMM = heightMM;
+
+ return monitor;
+}
+
+void _glfwFreeMonitor(_GLFWmonitor* monitor)
+{
+ if (monitor == NULL)
+ return;
+
+ _glfwFreeGammaArrays(&monitor->originalRamp);
+ _glfwFreeGammaArrays(&monitor->currentRamp);
+
+ free(monitor->modes);
+ free(monitor->name);
+ free(monitor);
+}
+
+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;
+}
+
+void _glfwFreeGammaArrays(GLFWgammaramp* ramp)
+{
+ free(ramp->red);
+ free(ramp->green);
+ free(ramp->blue);
+
+ memset(ramp, 0, sizeof(GLFWgammaramp));
+}
+
+void _glfwFreeMonitors(_GLFWmonitor** monitors, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ _glfwFreeMonitor(monitors[i]);
+
+ free(monitors);
+}
+
+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;
+}
+
+int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm)
+{
+ return compareVideoModes(fm, sm);
+}
+
+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 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 const char* glfwGetMonitorName(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->name;
+}
+
+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)
+{
+ int i;
+ unsigned short values[256];
+ GLFWgammaramp ramp;
+
+ _GLFW_REQUIRE_INIT();
+
+ if (gamma != gamma || gamma <= 0.f || gamma > FLT_MAX)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
+ return;
+ }
+
+ for (i = 0; i < 256; i++)
+ {
+ double value;
+
+ // Calculate intensity
+ value = i / 255.0;
+ // Apply gamma curve
+ value = pow(value, 1.0 / gamma) * 65535.0 + 0.5;
+
+ // Clamp to value range
+ if (value > 65535.0)
+ value = 65535.0;
+
+ values[i] = (unsigned short) value;
+ }
+
+ ramp.red = values;
+ ramp.green = values;
+ ramp.blue = values;
+ ramp.size = 256;
+
+ glfwSetGammaRamp(handle, &ramp);
+}
+
+GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ _glfwFreeGammaArrays(&monitor->currentRamp);
+ _glfwPlatformGetGammaRamp(monitor, &monitor->currentRamp);
+
+ return &monitor->currentRamp;
+}
+
+GLFWAPI void glfwSetGammaRamp(GLFWmonitor* handle, const GLFWgammaramp* ramp)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ assert(monitor != NULL);
+ assert(ramp != NULL);
+ assert(ramp->red != NULL);
+ assert(ramp->green != NULL);
+ assert(ramp->blue != NULL);
+
+ if (ramp->size <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid gamma ramp size %i",
+ ramp->size);
+ return;
+ }
+
+ _GLFW_REQUIRE_INIT();
+
+ if (!monitor->originalRamp.size)
+ _glfwPlatformGetGammaRamp(monitor, &monitor->originalRamp);
+
+ _glfwPlatformSetGammaRamp(monitor, ramp);
+}
+
diff --git a/glfw-3.2.1/src/nsgl_context.h b/glfw-3.2.1/src/nsgl_context.h
new file mode 100644
index 0000000..1304f2e
--- /dev/null
+++ b/glfw-3.2.1/src/nsgl_context.h
@@ -0,0 +1,60 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_nsgl_context_h_
+#define _glfw3_nsgl_context_h_
+
+#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl
+
+
+// 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);
+
+#endif // _glfw3_nsgl_context_h_
diff --git a/glfw-3.2.1/src/nsgl_context.m b/glfw-3.2.1/src/nsgl_context.m
new file mode 100644
index 0000000..22ebdba
--- /dev/null
+++ b/glfw-3.2.1/src/nsgl_context.m
@@ -0,0 +1,308 @@
+//========================================================================
+// GLFW 3.2 OS X - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2009-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+static void makeContextCurrentNSGL(_GLFWwindow* window)
+{
+ if (window)
+ [window->context.nsgl.object makeCurrentContext];
+ else
+ [NSOpenGLContext clearCurrentContext];
+
+ _glfwPlatformSetCurrentContext(window);
+}
+
+static void swapBuffersNSGL(_GLFWwindow* window)
+{
+ // ARP appears to be unnecessary, but this is future-proof
+ [window->context.nsgl.object flushBuffer];
+}
+
+static void swapIntervalNSGL(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
+
+ GLint sync = interval;
+ [window->context.nsgl.object setValues:&sync
+ forParameter:NSOpenGLCPSwapInterval];
+}
+
+static int extensionSupportedNSGL(const char* extension)
+{
+ // There are no NSGL extensions
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressNSGL(const char* procname)
+{
+ CFStringRef symbolName = CFStringCreateWithCString(kCFAllocatorDefault,
+ procname,
+ kCFStringEncodingASCII);
+
+ GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
+ symbolName);
+
+ CFRelease(symbolName);
+
+ return symbol;
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextNSGL(_GLFWwindow* window)
+{
+ [window->context.nsgl.pixelFormat release];
+ window->context.nsgl.pixelFormat = nil;
+
+ [window->context.nsgl.object release];
+ window->context.nsgl.object = nil;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize OpenGL support
+//
+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)
+{
+ unsigned int attributeCount = 0;
+
+ if (ctxconfig->client == GLFW_OPENGL_ES_API)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "NSGL: OpenGL ES is not available on OS X");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->major == 3 && ctxconfig->minor < 2)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: The targeted version of OS X does not support OpenGL 3.0 or 3.1");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->major > 2)
+ {
+ if (!ctxconfig->forward)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: The targeted version of OS X only supports forward-compatible contexts for OpenGL 3.2 and above");
+ return GLFW_FALSE;
+ }
+
+ if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "NSGL: The targeted version of OS X only supports core profile contexts for OpenGL 3.2 and above");
+ return GLFW_FALSE;
+ }
+ }
+
+ // Context robustness modes (GL_KHR_robustness) are not yet supported on
+ // OS X but are not a hard constraint, so ignore and continue
+
+ // Context release behaviors (GL_KHR_context_flush_control) are not yet
+ // supported on OS X but are not a hard constraint, so ignore and continue
+
+#define ADD_ATTR(x) { attributes[attributeCount++] = x; }
+#define ADD_ATTR2(x, y) { ADD_ATTR(x); ADD_ATTR(y); }
+
+ // Arbitrary array size here
+ NSOpenGLPixelFormatAttribute attributes[40];
+
+ ADD_ATTR(NSOpenGLPFAAccelerated);
+ ADD_ATTR(NSOpenGLPFAClosestPolicy);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+ if (ctxconfig->major >= 4)
+ {
+ ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core);
+ }
+ else
+#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
+ if (ctxconfig->major >= 3)
+ {
+ ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
+ }
+
+ if (ctxconfig->major <= 2)
+ {
+ if (fbconfig->auxBuffers != GLFW_DONT_CARE)
+ ADD_ATTR2(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;
+
+ ADD_ATTR2(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;
+
+ // OS X needs non-zero color size, so set reasonable values
+ if (colorBits == 0)
+ colorBits = 24;
+ else if (colorBits < 15)
+ colorBits = 15;
+
+ ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
+ }
+
+ if (fbconfig->alphaBits != GLFW_DONT_CARE)
+ ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
+
+ if (fbconfig->depthBits != GLFW_DONT_CARE)
+ ADD_ATTR2(NSOpenGLPFADepthSize, fbconfig->depthBits);
+
+ if (fbconfig->stencilBits != GLFW_DONT_CARE)
+ ADD_ATTR2(NSOpenGLPFAStencilSize, fbconfig->stencilBits);
+
+ if (fbconfig->stereo)
+ ADD_ATTR(NSOpenGLPFAStereo);
+
+ if (fbconfig->doublebuffer)
+ ADD_ATTR(NSOpenGLPFADoubleBuffer);
+
+ if (fbconfig->samples != GLFW_DONT_CARE)
+ {
+ if (fbconfig->samples == 0)
+ {
+ ADD_ATTR2(NSOpenGLPFASampleBuffers, 0);
+ }
+ else
+ {
+ ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
+ ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
+ }
+ }
+
+ // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
+ // framebuffer, so there's no need (and no way) to request it
+
+ ADD_ATTR(0);
+
+#undef ADD_ATTR
+#undef ADD_ATTR2
+
+ window->context.nsgl.pixelFormat =
+ [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ if (window->context.nsgl.pixelFormat == nil)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "NSGL: Failed to find a suitable pixel format");
+ return GLFW_FALSE;
+ }
+
+ NSOpenGLContext* share = NULL;
+
+ 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;
+ }
+
+ [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 NULL;
+ }
+
+ return window->context.nsgl.object;
+}
+
diff --git a/glfw-3.2.1/src/posix_time.c b/glfw-3.2.1/src/posix_time.c
new file mode 100644
index 0000000..8d0d4cd
--- /dev/null
+++ b/glfw-3.2.1/src/posix_time.c
@@ -0,0 +1,85 @@
+//========================================================================
+// GLFW 3.2 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <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.posix_time.monotonic = GLFW_TRUE;
+ _glfw.posix_time.frequency = 1000000000;
+ }
+ else
+#endif
+ {
+ _glfw.posix_time.monotonic = GLFW_FALSE;
+ _glfw.posix_time.frequency = 1000000;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+#if defined(CLOCK_MONOTONIC)
+ if (_glfw.posix_time.monotonic)
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (uint64_t) ts.tv_sec * (uint64_t) 1000000000 + (uint64_t) ts.tv_nsec;
+ }
+ else
+#endif
+ {
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (uint64_t) tv.tv_sec * (uint64_t) 1000000 + (uint64_t) tv.tv_usec;
+ }
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.posix_time.frequency;
+}
+
diff --git a/glfw-3.2.1/src/posix_time.h b/glfw-3.2.1/src/posix_time.h
new file mode 100644
index 0000000..4730ca7
--- /dev/null
+++ b/glfw-3.2.1/src/posix_time.h
@@ -0,0 +1,48 @@
+//========================================================================
+// GLFW 3.2 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_posix_time_h_
+#define _glfw3_posix_time_h_
+
+#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimePOSIX posix_time
+
+#include <stdint.h>
+
+
+// POSIX-specific global timer data
+//
+typedef struct _GLFWtimePOSIX
+{
+ GLFWbool monotonic;
+ uint64_t frequency;
+
+} _GLFWtimePOSIX;
+
+
+void _glfwInitTimerPOSIX(void);
+
+#endif // _glfw3_posix_time_h_
diff --git a/glfw-3.2.1/src/posix_tls.c b/glfw-3.2.1/src/posix_tls.c
new file mode 100644
index 0000000..c9517c6
--- /dev/null
+++ b/glfw-3.2.1/src/posix_tls.c
@@ -0,0 +1,68 @@
+//========================================================================
+// GLFW 3.2 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitThreadLocalStoragePOSIX(void)
+{
+ if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "POSIX: Failed to create context TLS");
+ return GLFW_FALSE;
+ }
+
+ _glfw.posix_tls.allocated = GLFW_TRUE;
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateThreadLocalStoragePOSIX(void)
+{
+ if (_glfw.posix_tls.allocated)
+ pthread_key_delete(_glfw.posix_tls.context);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
+{
+ pthread_setspecific(_glfw.posix_tls.context, context);
+}
+
+_GLFWwindow* _glfwPlatformGetCurrentContext(void)
+{
+ return pthread_getspecific(_glfw.posix_tls.context);
+}
+
diff --git a/glfw-3.2.1/src/posix_tls.h b/glfw-3.2.1/src/posix_tls.h
new file mode 100644
index 0000000..0d408ae
--- /dev/null
+++ b/glfw-3.2.1/src/posix_tls.h
@@ -0,0 +1,49 @@
+//========================================================================
+// GLFW 3.2 POSIX - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_posix_tls_h_
+#define _glfw3_posix_tls_h_
+
+#include <pthread.h>
+
+#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls
+
+
+// POSIX-specific global TLS data
+//
+typedef struct _GLFWtlsPOSIX
+{
+ GLFWbool allocated;
+ pthread_key_t context;
+
+} _GLFWtlsPOSIX;
+
+
+GLFWbool _glfwInitThreadLocalStoragePOSIX(void);
+void _glfwTerminateThreadLocalStoragePOSIX(void);
+
+#endif // _glfw3_posix_tls_h_
diff --git a/glfw-3.2.1/src/vulkan.c b/glfw-3.2.1/src/vulkan.c
new file mode 100644
index 0000000..20011de
--- /dev/null
+++ b/glfw-3.2.1/src/vulkan.c
@@ -0,0 +1,302 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitVulkan(void)
+{
+ VkResult err;
+ VkExtensionProperties* ep;
+ uint32_t i, count;
+
+#if !defined(_GLFW_VULKAN_STATIC)
+#if defined(_GLFW_WIN32)
+ const char* name = "vulkan-1.dll";
+#else
+ const char* name = "libvulkan.so.1";
+#endif
+
+ if (_glfw.vk.available)
+ return GLFW_TRUE;
+
+ _glfw.vk.handle = _glfw_dlopen(name);
+ if (!_glfw.vk.handle)
+ return GLFW_FALSE;
+
+ _glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
+ _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
+ if (!_glfw.vk.GetInstanceProcAddr)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Loader does not export vkGetInstanceProcAddr");
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ _glfw.vk.EnumerateInstanceExtensionProperties = (PFN_vkEnumerateInstanceExtensionProperties)
+ vkGetInstanceProcAddr(NULL, "vkEnumerateInstanceExtensionProperties");
+ if (!_glfw.vk.EnumerateInstanceExtensionProperties)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Failed to retrieve vkEnumerateInstanceExtensionProperties");
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+#endif // _GLFW_VULKAN_STATIC
+
+ err = vkEnumerateInstanceExtensionProperties(NULL, &count, NULL);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Vulkan: Failed to query instance extension count: %s",
+ _glfwGetVulkanResultString(err));
+
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ ep = calloc(count, sizeof(VkExtensionProperties));
+
+ err = vkEnumerateInstanceExtensionProperties(NULL, &count, ep);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Vulkan: Failed to query instance extensions: %s",
+ _glfwGetVulkanResultString(err));
+
+ free(ep);
+ _glfwTerminateVulkan();
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (strcmp(ep[i].extensionName, "VK_KHR_surface") == 0)
+ _glfw.vk.KHR_surface = GLFW_TRUE;
+ if (strcmp(ep[i].extensionName, "VK_KHR_win32_surface") == 0)
+ _glfw.vk.KHR_win32_surface = GLFW_TRUE;
+ if (strcmp(ep[i].extensionName, "VK_KHR_xlib_surface") == 0)
+ _glfw.vk.KHR_xlib_surface = GLFW_TRUE;
+ if (strcmp(ep[i].extensionName, "VK_KHR_xcb_surface") == 0)
+ _glfw.vk.KHR_xcb_surface = GLFW_TRUE;
+ if (strcmp(ep[i].extensionName, "VK_KHR_wayland_surface") == 0)
+ _glfw.vk.KHR_wayland_surface = GLFW_TRUE;
+ if (strcmp(ep[i].extensionName, "VK_KHR_mir_surface") == 0)
+ _glfw.vk.KHR_mir_surface = GLFW_TRUE;
+ }
+
+ free(ep);
+
+ _glfw.vk.available = GLFW_TRUE;
+
+ if (_glfw.vk.KHR_surface)
+ {
+ _glfw.vk.extensions =
+ _glfwPlatformGetRequiredInstanceExtensions(&_glfw.vk.extensionCount);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateVulkan(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < _glfw.vk.extensionCount; i++)
+ free(_glfw.vk.extensions[i]);
+ free(_glfw.vk.extensions);
+
+ if (_glfw.vk.handle)
+ _glfw_dlclose(_glfw.vk.handle);
+}
+
+const char* _glfwGetVulkanResultString(VkResult result)
+{
+ switch (result)
+ {
+ case VK_SUCCESS:
+ return "Success";
+ case VK_NOT_READY:
+ return "A fence or query has not yet completed";
+ case VK_TIMEOUT:
+ return "A wait operation has not completed in the specified time";
+ case VK_EVENT_SET:
+ return "An event is signaled";
+ case VK_EVENT_RESET:
+ return "An event is unsignaled";
+ case VK_INCOMPLETE:
+ return "A return array was too small for the result";
+ case VK_ERROR_OUT_OF_HOST_MEMORY:
+ return "A host memory allocation has failed";
+ case VK_ERROR_OUT_OF_DEVICE_MEMORY:
+ return "A device memory allocation has failed";
+ case VK_ERROR_INITIALIZATION_FAILED:
+ return "Initialization of an object could not be completed for implementation-specific reasons";
+ case VK_ERROR_DEVICE_LOST:
+ return "The logical or physical device has been lost";
+ case VK_ERROR_MEMORY_MAP_FAILED:
+ return "Mapping of a memory object has failed";
+ case VK_ERROR_LAYER_NOT_PRESENT:
+ return "A requested layer is not present or could not be loaded";
+ case VK_ERROR_EXTENSION_NOT_PRESENT:
+ return "A requested extension is not supported";
+ case VK_ERROR_FEATURE_NOT_PRESENT:
+ return "A requested feature is not supported";
+ case VK_ERROR_INCOMPATIBLE_DRIVER:
+ return "The requested version of Vulkan is not supported by the driver or is otherwise incompatible";
+ case VK_ERROR_TOO_MANY_OBJECTS:
+ return "Too many objects of the type have already been created";
+ case VK_ERROR_FORMAT_NOT_SUPPORTED:
+ return "A requested format is not supported on this device";
+ case VK_ERROR_SURFACE_LOST_KHR:
+ return "A surface is no longer available";
+ case VK_SUBOPTIMAL_KHR:
+ return "A swapchain no longer matches the surface properties exactly, but can still be used";
+ case VK_ERROR_OUT_OF_DATE_KHR:
+ return "A surface has changed in such a way that it is no longer compatible with the swapchain";
+ case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:
+ return "The display used by a swapchain does not use the same presentable image layout";
+ case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:
+ return "The requested window is already connected to a VkSurfaceKHR, or to some other non-Vulkan API";
+ case VK_ERROR_VALIDATION_FAILED_EXT:
+ return "A validation layer found an error";
+ default:
+ return "ERROR: UNKNOWN VULKAN ERROR";
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI int glfwVulkanSupported(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+ return _glfwInitVulkan();
+}
+
+GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count)
+{
+ *count = 0;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!_glfwInitVulkan())
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
+ return NULL;
+ }
+
+ *count = _glfw.vk.extensionCount;
+ return (const char**) _glfw.vk.extensions;
+}
+
+GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
+ const char* procname)
+{
+ GLFWvkproc proc;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (!_glfwInitVulkan())
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
+ return NULL;
+ }
+
+ proc = (GLFWvkproc) vkGetInstanceProcAddr(instance, procname);
+ if (!proc)
+ proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname);
+
+ return proc;
+}
+
+GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
+
+ if (!_glfwInitVulkan())
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
+ return GLFW_FALSE;
+ }
+
+ if (!_glfw.vk.extensions)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Window surface creation extensions not found");
+ return GLFW_FALSE;
+ }
+
+ return _glfwPlatformGetPhysicalDevicePresentationSupport(instance,
+ device,
+ queuefamily);
+}
+
+GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance,
+ GLFWwindow* handle,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+ assert(surface != NULL);
+
+ *surface = VK_NULL_HANDLE;
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(VK_ERROR_INITIALIZATION_FAILED);
+
+ if (!_glfwInitVulkan())
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE, "Vulkan: API not available");
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
+ if (!_glfw.vk.extensions)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Vulkan: Window surface creation extensions not found");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ return _glfwPlatformCreateWindowSurface(instance, window, allocator, surface);
+}
+
diff --git a/glfw-3.2.1/src/wgl_context.c b/glfw-3.2.1/src/wgl_context.c
new file mode 100644
index 0000000..696c4cb
--- /dev/null
+++ b/glfw-3.2.1/src/wgl_context.c
@@ -0,0 +1,718 @@
+//========================================================================
+// GLFW 3.2 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <assert.h>
+
+
+// Returns the specified attribute of the specified pixel format
+//
+static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
+{
+ int value = 0;
+
+ assert(_glfw.wgl.ARB_pixel_format);
+
+ if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
+ pixelFormat,
+ 0, 1, &attrib, &value))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve pixel format attribute %i",
+ attrib);
+ return 0;
+ }
+
+ return value;
+}
+
+// Return a list of available and usable framebuffer configs
+//
+static int choosePixelFormat(_GLFWwindow* window, const _GLFWfbconfig* desired)
+{
+ _GLFWfbconfig* usableConfigs;
+ const _GLFWfbconfig* closest;
+ int i, pixelFormat, nativeCount, usableCount;
+
+ if (_glfw.wgl.ARB_pixel_format)
+ {
+ nativeCount = getPixelFormatAttrib(window,
+ 1,
+ WGL_NUMBER_PIXEL_FORMATS_ARB);
+ }
+ else
+ {
+ nativeCount = DescribePixelFormat(window->context.wgl.dc,
+ 1,
+ sizeof(PIXELFORMATDESCRIPTOR),
+ NULL);
+ }
+
+ usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
+ usableCount = 0;
+
+ for (i = 0; i < nativeCount; i++)
+ {
+ const int n = i + 1;
+ _GLFWfbconfig* u = usableConfigs + usableCount;
+
+ if (_glfw.wgl.ARB_pixel_format)
+ {
+ // Get pixel format attributes through "modern" extension
+
+ if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
+ !getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
+ {
+ continue;
+ }
+
+ if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
+ WGL_TYPE_RGBA_ARB)
+ {
+ continue;
+ }
+
+ if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
+ WGL_NO_ACCELERATION_ARB)
+ {
+ continue;
+ }
+
+ u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
+ u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
+ u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
+ u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
+
+ u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
+ u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
+
+ u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
+ u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
+ u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
+ u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
+
+ u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
+
+ if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
+ u->stereo = GLFW_TRUE;
+ if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
+ u->doublebuffer = GLFW_TRUE;
+
+ if (_glfw.wgl.ARB_multisample)
+ u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
+
+ if (_glfw.wgl.ARB_framebuffer_sRGB ||
+ _glfw.wgl.EXT_framebuffer_sRGB)
+ {
+ if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
+ u->sRGB = GLFW_TRUE;
+ }
+ }
+ else
+ {
+ PIXELFORMATDESCRIPTOR pfd;
+
+ // Get pixel format attributes through legacy PFDs
+
+ if (!DescribePixelFormat(window->context.wgl.dc,
+ n,
+ sizeof(PIXELFORMATDESCRIPTOR),
+ &pfd))
+ {
+ continue;
+ }
+
+ 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 = n;
+ usableCount++;
+ }
+
+ if (!usableCount)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "WGL: The driver does not appear to support OpenGL");
+
+ free(usableConfigs);
+ return 0;
+ }
+
+ closest = _glfwChooseFBConfig(desired, 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;
+}
+
+// Returns whether desktop compositing is enabled
+//
+static GLFWbool isCompositionEnabled(void)
+{
+ BOOL enabled;
+
+ if (!_glfw_DwmIsCompositionEnabled)
+ return FALSE;
+
+ if (_glfw_DwmIsCompositionEnabled(&enabled) != S_OK)
+ return FALSE;
+
+ return enabled;
+}
+
+static void makeContextCurrentWGL(_GLFWwindow* window)
+{
+ if (window)
+ {
+ if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
+ _glfwPlatformSetCurrentContext(window);
+ else
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to make context current");
+ _glfwPlatformSetCurrentContext(NULL);
+ }
+ }
+ else
+ {
+ if (!wglMakeCurrent(NULL, NULL))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to clear current context");
+ }
+
+ _glfwPlatformSetCurrentContext(NULL);
+ }
+}
+
+static void swapBuffersWGL(_GLFWwindow* window)
+{
+ // HACK: Use DwmFlush when desktop composition is enabled
+ if (isCompositionEnabled() && !window->monitor)
+ {
+ int count = abs(window->context.wgl.interval);
+ while (count--)
+ _glfw_DwmFlush();
+ }
+
+ SwapBuffers(window->context.wgl.dc);
+}
+
+static void swapIntervalWGL(int interval)
+{
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
+
+ window->context.wgl.interval = interval;
+
+ // HACK: Disable WGL swap interval when desktop composition is enabled to
+ // avoid interfering with DWM vsync
+ if (isCompositionEnabled() && !window->monitor)
+ interval = 0;
+
+ if (_glfw.wgl.EXT_swap_control)
+ _glfw.wgl.SwapIntervalEXT(interval);
+}
+
+static int extensionSupportedWGL(const char* extension)
+{
+ const char* extensions;
+
+ if (_glfw.wgl.GetExtensionsStringEXT)
+ {
+ extensions = _glfw.wgl.GetExtensionsStringEXT();
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+ }
+
+ if (_glfw.wgl.GetExtensionsStringARB)
+ {
+ extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
+ if (extensions)
+ {
+ if (_glfwStringInExtensionString(extension, extensions))
+ return GLFW_TRUE;
+ }
+ }
+
+ return GLFW_FALSE;
+}
+
+static GLFWglproc getProcAddressWGL(const char* procname)
+{
+ const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
+ if (proc)
+ return proc;
+
+ return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
+}
+
+// Destroy the OpenGL context
+//
+static void destroyContextWGL(_GLFWwindow* window)
+{
+ if (window->context.wgl.handle)
+ {
+ wglDeleteContext(window->context.wgl.handle);
+ window->context.wgl.handle = NULL;
+ }
+}
+
+// Initialize WGL-specific extensions
+//
+static void loadWGLExtensions(void)
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ HGLRC rc;
+ HDC dc = GetDC(_glfw.win32.helperWindowHandle);;
+
+ _glfw.wgl.extensionsLoaded = GLFW_TRUE;
+
+ // NOTE: A dummy context has to be created for opengl32.dll to load the
+ // OpenGL ICD, from which we can then query WGL extensions
+ // NOTE: This code will accept the Microsoft GDI ICD; accelerated context
+ // creation failure occurs during manual pixel format enumeration
+
+ ZeroMemory(&pfd, sizeof(pfd));
+ pfd.nSize = sizeof(pfd);
+ pfd.nVersion = 1;
+ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
+ pfd.iPixelType = PFD_TYPE_RGBA;
+ pfd.cColorBits = 24;
+
+ if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to set pixel format for dummy context");
+ return;
+ }
+
+ rc = wglCreateContext(dc);
+ if (!rc)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to create dummy context");
+ return;
+ }
+
+ if (!wglMakeCurrent(dc, rc))
+ {
+ wglDeleteContext(rc);
+
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to make dummy context current");
+ return;
+ }
+
+ // NOTE: Functions must be loaded first as they're needed to retrieve the
+ // extension string that tells us whether the functions are supported
+ _glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
+ wglGetProcAddress("wglGetExtensionsStringEXT");
+ _glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
+ wglGetProcAddress("wglGetExtensionsStringARB");
+ _glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
+ wglGetProcAddress("wglCreateContextAttribsARB");
+ _glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
+ wglGetProcAddress("wglSwapIntervalEXT");
+ _glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
+ wglGetProcAddress("wglGetPixelFormatAttribivARB");
+
+ // NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
+ // checked below as we are already using them
+ _glfw.wgl.ARB_multisample =
+ extensionSupportedWGL("WGL_ARB_multisample");
+ _glfw.wgl.ARB_framebuffer_sRGB =
+ extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
+ _glfw.wgl.EXT_framebuffer_sRGB =
+ extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
+ _glfw.wgl.ARB_create_context =
+ extensionSupportedWGL("WGL_ARB_create_context");
+ _glfw.wgl.ARB_create_context_profile =
+ extensionSupportedWGL("WGL_ARB_create_context_profile");
+ _glfw.wgl.EXT_create_context_es2_profile =
+ extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
+ _glfw.wgl.ARB_create_context_robustness =
+ extensionSupportedWGL("WGL_ARB_create_context_robustness");
+ _glfw.wgl.EXT_swap_control =
+ extensionSupportedWGL("WGL_EXT_swap_control");
+ _glfw.wgl.ARB_pixel_format =
+ extensionSupportedWGL("WGL_ARB_pixel_format");
+ _glfw.wgl.ARB_context_flush_control =
+ extensionSupportedWGL("WGL_ARB_context_flush_control");
+
+ wglMakeCurrent(dc, NULL);
+ wglDeleteContext(rc);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize WGL
+//
+GLFWbool _glfwInitWGL(void)
+{
+ if (_glfw.wgl.instance)
+ return GLFW_TRUE;
+
+ _glfw.wgl.instance = LoadLibraryA("opengl32.dll");
+ if (!_glfw.wgl.instance)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "WGL: Failed to load opengl32.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.wgl.CreateContext = (WGLCREATECONTEXT_T)
+ GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
+ _glfw.wgl.DeleteContext = (WGLDELETECONTEXT_T)
+ GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
+ _glfw.wgl.GetProcAddress = (WGLGETPROCADDRESS_T)
+ GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
+ _glfw.wgl.GetCurrentDC = (WGLGETCURRENTDC_T)
+ GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
+ _glfw.wgl.MakeCurrent = (WGLMAKECURRENT_T)
+ GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
+ _glfw.wgl.ShareLists = (WGLSHARELISTS_T)
+ GetProcAddress(_glfw.wgl.instance, "wglShareLists");
+
+ return GLFW_TRUE;
+}
+
+// Terminate WGL
+//
+void _glfwTerminateWGL(void)
+{
+ if (_glfw.wgl.instance)
+ FreeLibrary(_glfw.wgl.instance);
+}
+
+#define setWGLattrib(attribName, attribValue) \
+{ \
+ attribs[index++] = attribName; \
+ attribs[index++] = attribValue; \
+ assert((size_t) index < sizeof(attribs) / sizeof(attribs[0])); \
+}
+
+// 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 (!_glfw.wgl.extensionsLoaded)
+ loadWGLExtensions();
+
+ 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, fbconfig);
+ if (!pixelFormat)
+ return GLFW_FALSE;
+
+ if (!DescribePixelFormat(window->context.wgl.dc,
+ pixelFormat, sizeof(pfd), &pfd))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "WGL: Failed to retrieve PFD for selected pixel format");
+ return GLFW_FALSE;
+ }
+
+ if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
+ {
+ _glfwInputError(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->noerror)
+ flags |= GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR;
+
+ if (ctxconfig->robustness)
+ {
+ if (_glfw.wgl.ARB_create_context_robustness)
+ {
+ if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
+ {
+ setWGLattrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
+ WGL_NO_RESET_NOTIFICATION_ARB);
+ }
+ else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
+ {
+ setWGLattrib(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)
+ {
+ setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
+ }
+ else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
+ {
+ setWGLattrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
+ WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
+ }
+ }
+ }
+
+ // 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)
+ {
+ setWGLattrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
+ setWGLattrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
+ }
+
+ if (flags)
+ setWGLattrib(WGL_CONTEXT_FLAGS_ARB, flags);
+
+ if (mask)
+ setWGLattrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
+
+ setWGLattrib(0, 0);
+
+ window->context.wgl.handle =
+ _glfw.wgl.CreateContextAttribsARB(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 (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)
+ {
+ _glfwInputError(GLFW_VERSION_UNAVAILABLE,
+ "WGL: Failed to create OpenGL context");
+ return GLFW_FALSE;
+ }
+
+ if (share)
+ {
+ if (!wglShareLists(share, window->context.wgl.handle))
+ {
+ _glfwInputError(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 setWGLattrib
+
+
+//////////////////////////////////////////////////////////////////////////
+////// 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-3.2.1/src/wgl_context.h b/glfw-3.2.1/src/wgl_context.h
new file mode 100644
index 0000000..b837d43
--- /dev/null
+++ b/glfw-3.2.1/src/wgl_context.h
@@ -0,0 +1,157 @@
+//========================================================================
+// GLFW 3.2 WGL - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_wgl_context_h_
+#define _glfw3_wgl_context_h_
+
+
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_TYPE_RGBA_ARB 0x202b
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201a
+#define WGL_ALPHA_BITS_ARB 0x201b
+#define WGL_ALPHA_SHIFT_ARB 0x201c
+#define WGL_ACCUM_BITS_ARB 0x201d
+#define WGL_ACCUM_RED_BITS_ARB 0x201e
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_STEREO_ARB 0x2012
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_SAMPLES_ARB 0x2042
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+
+#define ERROR_INVALID_VERSION_ARB 0x2095
+#define ERROR_INVALID_PROFILE_ARB 0x2096
+
+typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
+typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
+typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
+typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
+
+typedef HGLRC (WINAPI * WGLCREATECONTEXT_T)(HDC);
+typedef BOOL (WINAPI * WGLDELETECONTEXT_T)(HGLRC);
+typedef PROC (WINAPI * WGLGETPROCADDRESS_T)(LPCSTR);
+typedef HDC (WINAPI * WGLGETCURRENTDC_T)(void);
+typedef BOOL (WINAPI * WGLMAKECURRENT_T)(HDC,HGLRC);
+typedef BOOL (WINAPI * WGLSHARELISTS_T)(HGLRC,HGLRC);
+
+// opengl32.dll function pointer typedefs
+#define wglCreateContext _glfw.wgl.CreateContext
+#define wglDeleteContext _glfw.wgl.DeleteContext
+#define wglGetProcAddress _glfw.wgl.GetProcAddress
+#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
+#define wglMakeCurrent _glfw.wgl.MakeCurrent
+#define wglShareLists _glfw.wgl.ShareLists
+
+#define _GLFW_RECREATION_NOT_NEEDED 0
+#define _GLFW_RECREATION_REQUIRED 1
+#define _GLFW_RECREATION_IMPOSSIBLE 2
+
+#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
+
+
+// WGL-specific per-context data
+//
+typedef struct _GLFWcontextWGL
+{
+ HDC dc;
+ HGLRC handle;
+ int interval;
+
+} _GLFWcontextWGL;
+
+// WGL-specific global data
+//
+typedef struct _GLFWlibraryWGL
+{
+ HINSTANCE instance;
+ WGLCREATECONTEXT_T CreateContext;
+ WGLDELETECONTEXT_T DeleteContext;
+ WGLGETPROCADDRESS_T GetProcAddress;
+ WGLGETCURRENTDC_T GetCurrentDC;
+ WGLMAKECURRENT_T MakeCurrent;
+ WGLSHARELISTS_T ShareLists;
+
+ GLFWbool extensionsLoaded;
+
+ PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
+ PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
+ PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
+ PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
+ PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
+ GLFWbool EXT_swap_control;
+ GLFWbool ARB_multisample;
+ GLFWbool ARB_framebuffer_sRGB;
+ GLFWbool EXT_framebuffer_sRGB;
+ GLFWbool ARB_pixel_format;
+ GLFWbool ARB_create_context;
+ GLFWbool ARB_create_context_profile;
+ GLFWbool EXT_create_context_es2_profile;
+ GLFWbool ARB_create_context_robustness;
+ GLFWbool ARB_context_flush_control;
+
+} _GLFWlibraryWGL;
+
+
+GLFWbool _glfwInitWGL(void);
+void _glfwTerminateWGL(void);
+GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig);
+
+#endif // _glfw3_wgl_context_h_
diff --git a/glfw-3.2.1/src/win32_init.c b/glfw-3.2.1/src/win32_init.c
new file mode 100644
index 0000000..b2a0a67
--- /dev/null
+++ b/glfw-3.2.1/src/win32_init.c
@@ -0,0 +1,473 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <malloc.h>
+
+#include <initguid.h>
+DEFINE_GUID(GUID_DEVINTERFACE_HID,0x4d1e55b2,0xf16f,0x11cf,0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30);
+
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+
+// Applications exporting this symbol with this value will be automatically
+// directed to the high-performance GPU on Nvidia Optimus systems with
+// up-to-date drivers
+//
+__declspec(dllexport) DWORD NvOptimusEnablement = 1;
+
+// Applications exporting this symbol with this value will be automatically
+// directed to the high-performance GPU on 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)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load winmm.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.winmm.timeGetTime = (TIMEGETTIME_T)
+ GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime");
+
+ _glfw.win32.user32.instance = LoadLibraryA("user32.dll");
+ if (!_glfw.win32.user32.instance)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to load user32.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.user32.SetProcessDPIAware = (SETPROCESSDPIAWARE_T)
+ GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware");
+ _glfw.win32.user32.ChangeWindowMessageFilterEx = (CHANGEWINDOWMESSAGEFILTEREX_T)
+ GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
+
+ _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll");
+ if (_glfw.win32.dinput8.instance)
+ {
+ _glfw.win32.dinput8.DirectInput8Create = (DIRECTINPUT8CREATE_T)
+ 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.XInputGetCapabilities = (XINPUTGETCAPABILITIES_T)
+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities");
+ _glfw.win32.xinput.XInputGetState = (XINPUTGETSTATE_T)
+ GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState");
+
+ break;
+ }
+ }
+ }
+
+ _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll");
+ if (_glfw.win32.dwmapi.instance)
+ {
+ _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
+ _glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
+ GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
+ }
+
+ _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
+ if (_glfw.win32.shcore.instance)
+ {
+ _glfw.win32.shcore.SetProcessDpiAwareness = (SETPROCESSDPIAWARENESS_T)
+ GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
+ }
+
+ return GLFW_TRUE;
+}
+
+// Unload used libraries (DLLs)
+//
+static void 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);
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.win32.publicKeys, -1, sizeof(_glfw.win32.publicKeys));
+ memset(_glfw.win32.nativeKeys, -1, sizeof(_glfw.win32.nativeKeys));
+
+ _glfw.win32.publicKeys[0x00B] = GLFW_KEY_0;
+ _glfw.win32.publicKeys[0x002] = GLFW_KEY_1;
+ _glfw.win32.publicKeys[0x003] = GLFW_KEY_2;
+ _glfw.win32.publicKeys[0x004] = GLFW_KEY_3;
+ _glfw.win32.publicKeys[0x005] = GLFW_KEY_4;
+ _glfw.win32.publicKeys[0x006] = GLFW_KEY_5;
+ _glfw.win32.publicKeys[0x007] = GLFW_KEY_6;
+ _glfw.win32.publicKeys[0x008] = GLFW_KEY_7;
+ _glfw.win32.publicKeys[0x009] = GLFW_KEY_8;
+ _glfw.win32.publicKeys[0x00A] = GLFW_KEY_9;
+ _glfw.win32.publicKeys[0x01E] = GLFW_KEY_A;
+ _glfw.win32.publicKeys[0x030] = GLFW_KEY_B;
+ _glfw.win32.publicKeys[0x02E] = GLFW_KEY_C;
+ _glfw.win32.publicKeys[0x020] = GLFW_KEY_D;
+ _glfw.win32.publicKeys[0x012] = GLFW_KEY_E;
+ _glfw.win32.publicKeys[0x021] = GLFW_KEY_F;
+ _glfw.win32.publicKeys[0x022] = GLFW_KEY_G;
+ _glfw.win32.publicKeys[0x023] = GLFW_KEY_H;
+ _glfw.win32.publicKeys[0x017] = GLFW_KEY_I;
+ _glfw.win32.publicKeys[0x024] = GLFW_KEY_J;
+ _glfw.win32.publicKeys[0x025] = GLFW_KEY_K;
+ _glfw.win32.publicKeys[0x026] = GLFW_KEY_L;
+ _glfw.win32.publicKeys[0x032] = GLFW_KEY_M;
+ _glfw.win32.publicKeys[0x031] = GLFW_KEY_N;
+ _glfw.win32.publicKeys[0x018] = GLFW_KEY_O;
+ _glfw.win32.publicKeys[0x019] = GLFW_KEY_P;
+ _glfw.win32.publicKeys[0x010] = GLFW_KEY_Q;
+ _glfw.win32.publicKeys[0x013] = GLFW_KEY_R;
+ _glfw.win32.publicKeys[0x01F] = GLFW_KEY_S;
+ _glfw.win32.publicKeys[0x014] = GLFW_KEY_T;
+ _glfw.win32.publicKeys[0x016] = GLFW_KEY_U;
+ _glfw.win32.publicKeys[0x02F] = GLFW_KEY_V;
+ _glfw.win32.publicKeys[0x011] = GLFW_KEY_W;
+ _glfw.win32.publicKeys[0x02D] = GLFW_KEY_X;
+ _glfw.win32.publicKeys[0x015] = GLFW_KEY_Y;
+ _glfw.win32.publicKeys[0x02C] = GLFW_KEY_Z;
+
+ _glfw.win32.publicKeys[0x028] = GLFW_KEY_APOSTROPHE;
+ _glfw.win32.publicKeys[0x02B] = GLFW_KEY_BACKSLASH;
+ _glfw.win32.publicKeys[0x033] = GLFW_KEY_COMMA;
+ _glfw.win32.publicKeys[0x00D] = GLFW_KEY_EQUAL;
+ _glfw.win32.publicKeys[0x029] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.win32.publicKeys[0x01A] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.win32.publicKeys[0x00C] = GLFW_KEY_MINUS;
+ _glfw.win32.publicKeys[0x034] = GLFW_KEY_PERIOD;
+ _glfw.win32.publicKeys[0x01B] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.win32.publicKeys[0x027] = GLFW_KEY_SEMICOLON;
+ _glfw.win32.publicKeys[0x035] = GLFW_KEY_SLASH;
+ _glfw.win32.publicKeys[0x056] = GLFW_KEY_WORLD_2;
+
+ _glfw.win32.publicKeys[0x00E] = GLFW_KEY_BACKSPACE;
+ _glfw.win32.publicKeys[0x153] = GLFW_KEY_DELETE;
+ _glfw.win32.publicKeys[0x14F] = GLFW_KEY_END;
+ _glfw.win32.publicKeys[0x01C] = GLFW_KEY_ENTER;
+ _glfw.win32.publicKeys[0x001] = GLFW_KEY_ESCAPE;
+ _glfw.win32.publicKeys[0x147] = GLFW_KEY_HOME;
+ _glfw.win32.publicKeys[0x152] = GLFW_KEY_INSERT;
+ _glfw.win32.publicKeys[0x15D] = GLFW_KEY_MENU;
+ _glfw.win32.publicKeys[0x151] = GLFW_KEY_PAGE_DOWN;
+ _glfw.win32.publicKeys[0x149] = GLFW_KEY_PAGE_UP;
+ _glfw.win32.publicKeys[0x045] = GLFW_KEY_PAUSE;
+ _glfw.win32.publicKeys[0x146] = GLFW_KEY_PAUSE;
+ _glfw.win32.publicKeys[0x039] = GLFW_KEY_SPACE;
+ _glfw.win32.publicKeys[0x00F] = GLFW_KEY_TAB;
+ _glfw.win32.publicKeys[0x03A] = GLFW_KEY_CAPS_LOCK;
+ _glfw.win32.publicKeys[0x145] = GLFW_KEY_NUM_LOCK;
+ _glfw.win32.publicKeys[0x046] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.win32.publicKeys[0x03B] = GLFW_KEY_F1;
+ _glfw.win32.publicKeys[0x03C] = GLFW_KEY_F2;
+ _glfw.win32.publicKeys[0x03D] = GLFW_KEY_F3;
+ _glfw.win32.publicKeys[0x03E] = GLFW_KEY_F4;
+ _glfw.win32.publicKeys[0x03F] = GLFW_KEY_F5;
+ _glfw.win32.publicKeys[0x040] = GLFW_KEY_F6;
+ _glfw.win32.publicKeys[0x041] = GLFW_KEY_F7;
+ _glfw.win32.publicKeys[0x042] = GLFW_KEY_F8;
+ _glfw.win32.publicKeys[0x043] = GLFW_KEY_F9;
+ _glfw.win32.publicKeys[0x044] = GLFW_KEY_F10;
+ _glfw.win32.publicKeys[0x057] = GLFW_KEY_F11;
+ _glfw.win32.publicKeys[0x058] = GLFW_KEY_F12;
+ _glfw.win32.publicKeys[0x064] = GLFW_KEY_F13;
+ _glfw.win32.publicKeys[0x065] = GLFW_KEY_F14;
+ _glfw.win32.publicKeys[0x066] = GLFW_KEY_F15;
+ _glfw.win32.publicKeys[0x067] = GLFW_KEY_F16;
+ _glfw.win32.publicKeys[0x068] = GLFW_KEY_F17;
+ _glfw.win32.publicKeys[0x069] = GLFW_KEY_F18;
+ _glfw.win32.publicKeys[0x06A] = GLFW_KEY_F19;
+ _glfw.win32.publicKeys[0x06B] = GLFW_KEY_F20;
+ _glfw.win32.publicKeys[0x06C] = GLFW_KEY_F21;
+ _glfw.win32.publicKeys[0x06D] = GLFW_KEY_F22;
+ _glfw.win32.publicKeys[0x06E] = GLFW_KEY_F23;
+ _glfw.win32.publicKeys[0x076] = GLFW_KEY_F24;
+ _glfw.win32.publicKeys[0x038] = GLFW_KEY_LEFT_ALT;
+ _glfw.win32.publicKeys[0x01D] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.win32.publicKeys[0x02A] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.win32.publicKeys[0x15B] = GLFW_KEY_LEFT_SUPER;
+ _glfw.win32.publicKeys[0x137] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.win32.publicKeys[0x138] = GLFW_KEY_RIGHT_ALT;
+ _glfw.win32.publicKeys[0x11D] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.win32.publicKeys[0x036] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.win32.publicKeys[0x15C] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.win32.publicKeys[0x150] = GLFW_KEY_DOWN;
+ _glfw.win32.publicKeys[0x14B] = GLFW_KEY_LEFT;
+ _glfw.win32.publicKeys[0x14D] = GLFW_KEY_RIGHT;
+ _glfw.win32.publicKeys[0x148] = GLFW_KEY_UP;
+
+ _glfw.win32.publicKeys[0x052] = GLFW_KEY_KP_0;
+ _glfw.win32.publicKeys[0x04F] = GLFW_KEY_KP_1;
+ _glfw.win32.publicKeys[0x050] = GLFW_KEY_KP_2;
+ _glfw.win32.publicKeys[0x051] = GLFW_KEY_KP_3;
+ _glfw.win32.publicKeys[0x04B] = GLFW_KEY_KP_4;
+ _glfw.win32.publicKeys[0x04C] = GLFW_KEY_KP_5;
+ _glfw.win32.publicKeys[0x04D] = GLFW_KEY_KP_6;
+ _glfw.win32.publicKeys[0x047] = GLFW_KEY_KP_7;
+ _glfw.win32.publicKeys[0x048] = GLFW_KEY_KP_8;
+ _glfw.win32.publicKeys[0x049] = GLFW_KEY_KP_9;
+ _glfw.win32.publicKeys[0x04E] = GLFW_KEY_KP_ADD;
+ _glfw.win32.publicKeys[0x053] = GLFW_KEY_KP_DECIMAL;
+ _glfw.win32.publicKeys[0x135] = GLFW_KEY_KP_DIVIDE;
+ _glfw.win32.publicKeys[0x11C] = GLFW_KEY_KP_ENTER;
+ _glfw.win32.publicKeys[0x037] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.win32.publicKeys[0x04A] = GLFW_KEY_KP_SUBTRACT;
+
+ for (scancode = 0; scancode < 512; scancode++)
+ {
+ if (_glfw.win32.publicKeys[scancode] > 0)
+ _glfw.win32.nativeKeys[_glfw.win32.publicKeys[scancode]] = scancode;
+ }
+}
+
+// Creates a dummy window for behind-the-scenes work
+//
+static HWND createHelperWindow(void)
+{
+ HWND window = CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
+ _GLFW_WNDCLASSNAME,
+ L"GLFW helper window",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ 0, 0, 1, 1,
+ HWND_MESSAGE, NULL,
+ GetModuleHandleW(NULL),
+ NULL);
+ if (!window)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create helper window");
+ return NULL;
+ }
+
+ // HACK: The first call to ShowWindow is ignored if the parent process
+ // passed along a STARTUPINFO, so clear that flag with a no-op call
+ ShowWindow(window, SW_HIDE);
+
+ // 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;
+
+ RegisterDeviceNotificationW(window,
+ (DEV_BROADCAST_HDR*) &dbi,
+ DEVICE_NOTIFY_WINDOW_HANDLE);
+ }
+
+ return window;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns a wide string version of the specified UTF-8 string
+//
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
+{
+ WCHAR* target;
+ int length;
+
+ length = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
+ if (!length)
+ return NULL;
+
+ target = calloc(length, sizeof(WCHAR));
+
+ if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, length))
+ {
+ 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 length;
+
+ length = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+ if (!length)
+ return NULL;
+
+ target = calloc(length, 1);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, length, NULL, NULL))
+ {
+ free(target);
+ return NULL;
+ }
+
+ return target;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ if (!_glfwInitThreadLocalStorageWin32())
+ return GLFW_FALSE;
+
+ // To make SetForegroundWindow work as we want, we need to fiddle
+ // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early
+ // as possible in the hope of still being the foreground process)
+ SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0,
+ &_glfw.win32.foregroundLockTimeout, 0);
+ SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0),
+ SPIF_SENDCHANGE);
+
+ if (!loadLibraries())
+ return GLFW_FALSE;
+
+ createKeyTables();
+
+ if (_glfw_SetProcessDpiAwareness)
+ _glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+ else if (_glfw_SetProcessDPIAware)
+ _glfw_SetProcessDPIAware();
+
+ if (!_glfwRegisterWindowClassWin32())
+ return GLFW_FALSE;
+
+ _glfw.win32.helperWindowHandle = createHelperWindow();
+ if (!_glfw.win32.helperWindowHandle)
+ return GLFW_FALSE;
+
+ _glfwPlatformPollEvents();
+
+ _glfwInitTimerWin32();
+ _glfwInitJoysticksWin32();
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ 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);
+
+ _glfwTerminateWGL();
+ _glfwTerminateEGL();
+
+ _glfwTerminateJoysticksWin32();
+ _glfwTerminateThreadLocalStorageWin32();
+
+ freeLibraries();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Win32 WGL EGL"
+#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-3.2.1/src/win32_joystick.c b/glfw-3.2.1/src/win32_joystick.c
new file mode 100644
index 0000000..49f3b87
--- /dev/null
+++ b/glfw-3.2.1/src/win32_joystick.c
@@ -0,0 +1,763 @@
+//========================================================================
+// GLFW 3.1 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <math.h>
+
+#include <initguid.h>
+
+#define _GLFW_PRESENCE_ONLY 1
+#define _GLFW_UPDATE_STATE 2
+
+#define _GLFW_TYPE_AXIS 0
+#define _GLFW_TYPE_SLIDER 1
+#define _GLFW_TYPE_BUTTON 2
+#define _GLFW_TYPE_POV 3
+
+// Data produced with DirectInput device object enumeration
+//
+typedef struct _GLFWobjenumWin32
+{
+ IDirectInputDevice8W* device;
+ _GLFWjoyobjectWin32* objects;
+ int objectCount;
+ int axisCount;
+ int sliderCount;
+ int buttonCount;
+ int povCount;
+} _GLFWobjenumWin32;
+
+// Define only the necessary GUIDs (it's bad enough that we're exporting these)
+//
+DEFINE_GUID(IID_IDirectInput8W,0xbf798031,0x483a,0x4da2,0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00);
+DEFINE_GUID(GUID_XAxis,0xa36d02e0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_YAxis,0xa36d02e1,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_ZAxis,0xa36d02e2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RxAxis,0xa36d02f4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RyAxis,0xa36d02f5,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_RzAxis,0xa36d02e3,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Slider,0xa36d02e4,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_Button,0xa36d02f0,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+DEFINE_GUID(GUID_POV,0xa36d02f2,0xc9f3,0x11cf,0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00);
+
+// Object data array for our clone of c_dfDIJoystick
+// Generated with https://github.com/elmindreda/c_dfDIJoystick2
+//
+static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
+{
+ { &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
+ { &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+ { NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
+};
+
+// Our clone of c_dfDIJoystick
+//
+static const DIDATAFORMAT _glfwDataFormat =
+{
+ sizeof(DIDATAFORMAT),
+ sizeof(DIOBJECTDATAFORMAT),
+ DIDFT_ABSAXIS,
+ sizeof(DIJOYSTATE),
+ sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
+ _glfwObjectDataFormats
+};
+
+// Returns a description fitting the specified XInput capabilities
+//
+static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
+{
+ switch (xic->SubType)
+ {
+ case XINPUT_DEVSUBTYPE_WHEEL:
+ return "XInput Wheel";
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
+ return "XInput Arcade Stick";
+ case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
+ return "XInput Flight Stick";
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
+ return "XInput Dance Pad";
+ case XINPUT_DEVSUBTYPE_GUITAR:
+ return "XInput Guitar";
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
+ return "XInput Drum Kit";
+ case XINPUT_DEVSUBTYPE_GAMEPAD:
+ {
+ if (xic->Flags & XINPUT_CAPS_WIRELESS)
+ return "Wireless Xbox 360 Controller";
+ else
+ return "Xbox 360 Controller";
+ }
+ }
+
+ return "Unknown XInput Device";
+}
+
+// Lexically compare device objects
+//
+static int compareJoystickObjects(const void* first, const void* second)
+{
+ const _GLFWjoyobjectWin32* fo = first;
+ const _GLFWjoyobjectWin32* so = second;
+
+ if (fo->type != so->type)
+ return fo->type - so->type;
+
+ return fo->offset - so->offset;
+}
+
+// Checks whether the specified device supports XInput
+// Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
+//
+static GLFWbool supportsXInput(const GUID* guid)
+{
+ UINT i, count = 0;
+ RAWINPUTDEVICELIST* ridl;
+ GLFWbool result = GLFW_FALSE;
+
+ if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
+ return GLFW_FALSE;
+
+ ridl = calloc(count, sizeof(RAWINPUTDEVICELIST));
+
+ if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
+ {
+ free(ridl);
+ return GLFW_FALSE;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ RID_DEVICE_INFO rdi;
+ char name[256];
+ UINT size;
+
+ if (ridl[i].dwType != RIM_TYPEHID)
+ continue;
+
+ ZeroMemory(&rdi, sizeof(rdi));
+ rdi.cbSize = sizeof(rdi);
+ size = sizeof(rdi);
+
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
+ RIDI_DEVICEINFO,
+ &rdi, &size) == -1)
+ {
+ continue;
+ }
+
+ if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
+ continue;
+
+ memset(name, 0, sizeof(name));
+ size = sizeof(name);
+
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
+ RIDI_DEVICENAME,
+ name, &size) == -1)
+ {
+ break;
+ }
+
+ name[sizeof(name) - 1] = '\0';
+ if (strstr(name, "IG_"))
+ {
+ result = GLFW_TRUE;
+ break;
+ }
+ }
+
+ free(ridl);
+ return result;
+}
+
+// Frees all resources associated with the specified joystick
+//
+static void closeJoystick(_GLFWjoystickWin32* js)
+{
+ if (js->device)
+ {
+ IDirectInputDevice8_Unacquire(js->device);
+ IDirectInputDevice8_Release(js->device);
+ }
+
+ free(js->name);
+ free(js->axes);
+ free(js->buttons);
+ free(js->objects);
+ memset(js, 0, sizeof(_GLFWjoystickWin32));
+
+ _glfwInputJoystickChange((int) (js - _glfw.win32_js), GLFW_DISCONNECTED);
+}
+
+// DirectInput device object enumeration callback
+// Insights gleaned from SDL2
+//
+static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
+ void* user)
+{
+ _GLFWobjenumWin32* data = user;
+ _GLFWjoyobjectWin32* object = data->objects + data->objectCount;
+
+ if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
+ {
+ DIPROPRANGE dipr;
+
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_SLIDER(data->sliderCount);
+ else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_X;
+ else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_Y;
+ else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_Z;
+ else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RX;
+ else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RY;
+ else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
+ object->offset = DIJOFS_RZ;
+ else
+ return DIENUM_CONTINUE;
+
+ ZeroMemory(&dipr, sizeof(dipr));
+ dipr.diph.dwSize = sizeof(dipr);
+ dipr.diph.dwHeaderSize = sizeof(dipr.diph);
+ dipr.diph.dwObj = doi->dwType;
+ dipr.diph.dwHow = DIPH_BYID;
+ dipr.lMin = -32768;
+ dipr.lMax = 32767;
+
+ if (FAILED(IDirectInputDevice8_SetProperty(data->device,
+ DIPROP_RANGE,
+ &dipr.diph)))
+ {
+ return DIENUM_CONTINUE;
+ }
+
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
+ {
+ object->type = _GLFW_TYPE_SLIDER;
+ data->sliderCount++;
+ }
+ else
+ {
+ object->type = _GLFW_TYPE_AXIS;
+ data->axisCount++;
+ }
+ }
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
+ {
+ object->offset = DIJOFS_BUTTON(data->buttonCount);
+ object->type = _GLFW_TYPE_BUTTON;
+ data->buttonCount++;
+ }
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
+ {
+ object->offset = DIJOFS_POV(data->povCount);
+ object->type = _GLFW_TYPE_POV;
+ data->povCount++;
+ }
+
+ data->objectCount++;
+ return DIENUM_CONTINUE;
+}
+
+// DirectInput device enumeration callback
+//
+static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
+{
+ int joy = 0;
+ DIDEVCAPS dc;
+ DIPROPDWORD dipd;
+ IDirectInputDevice8* device;
+ _GLFWobjenumWin32 data;
+ _GLFWjoystickWin32* js;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (memcmp(&_glfw.win32_js[joy].guid, &di->guidInstance, sizeof(GUID)) == 0)
+ return DIENUM_CONTINUE;
+ }
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.win32_js[joy].present)
+ break;
+ }
+
+ if (joy > GLFW_JOYSTICK_LAST)
+ return DIENUM_STOP;
+
+ if (supportsXInput(&di->guidProduct))
+ return DIENUM_CONTINUE;
+
+ if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
+ &di->guidInstance,
+ &device,
+ NULL)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "DI: Failed to create device");
+ return DIENUM_CONTINUE;
+ }
+
+ if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "DI: Failed to set device data format");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ ZeroMemory(&dc, sizeof(dc));
+ dc.dwSize = sizeof(dc);
+
+ if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "DI: Failed to query device capabilities");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ ZeroMemory(&dipd, sizeof(dipd));
+ dipd.diph.dwSize = sizeof(dipd);
+ dipd.diph.dwHeaderSize = sizeof(dipd.diph);
+ dipd.diph.dwHow = DIPH_DEVICE;
+ dipd.dwData = DIPROPAXISMODE_ABS;
+
+ if (FAILED(IDirectInputDevice8_SetProperty(device,
+ DIPROP_AXISMODE,
+ &dipd.diph)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "DI: Failed to set device axis mode");
+
+ IDirectInputDevice8_Release(device);
+ return DIENUM_CONTINUE;
+ }
+
+ memset(&data, 0, sizeof(data));
+ data.device = device;
+ data.objects = calloc(dc.dwAxes + dc.dwButtons + dc.dwPOVs,
+ sizeof(_GLFWjoyobjectWin32));
+
+ if (FAILED(IDirectInputDevice8_EnumObjects(device,
+ deviceObjectCallback,
+ &data,
+ DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "DI: Failed to enumerate device objects");
+
+ IDirectInputDevice8_Release(device);
+ free(data.objects);
+ return DIENUM_CONTINUE;
+ }
+
+ qsort(data.objects, data.objectCount,
+ sizeof(_GLFWjoyobjectWin32),
+ compareJoystickObjects);
+
+ js = _glfw.win32_js + joy;
+ js->device = device;
+ js->guid = di->guidInstance;
+ js->axisCount = data.axisCount + data.sliderCount;
+ js->axes = calloc(js->axisCount, sizeof(float));
+ js->buttonCount += data.buttonCount + data.povCount * 4;
+ js->buttons = calloc(js->buttonCount, 1);
+ js->objects = data.objects;
+ js->objectCount = data.objectCount;
+ js->name = _glfwCreateUTF8FromWideStringWin32(di->tszInstanceName);
+ js->present = GLFW_TRUE;
+
+ _glfwInputJoystickChange(joy, GLFW_CONNECTED);
+ return DIENUM_CONTINUE;
+}
+
+// Attempt to open the specified joystick device
+// TODO: Pack state arrays for non-gamepad devices
+//
+static GLFWbool openXinputDevice(DWORD index)
+{
+ int joy;
+ XINPUT_CAPABILITIES xic;
+ _GLFWjoystickWin32* js;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (_glfw.win32_js[joy].present &&
+ _glfw.win32_js[joy].device == NULL &&
+ _glfw.win32_js[joy].index == index)
+ {
+ return GLFW_FALSE;
+ }
+ }
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ {
+ if (!_glfw.win32_js[joy].present)
+ break;
+ }
+
+ if (joy > GLFW_JOYSTICK_LAST)
+ return GLFW_FALSE;
+
+ if (_glfw_XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
+ return GLFW_FALSE;
+
+ js = _glfw.win32_js + joy;
+ js->axisCount = 6;
+ js->axes = calloc(js->axisCount, sizeof(float));
+ js->buttonCount = 14;
+ js->buttons = calloc(js->buttonCount, 1);
+ js->present = GLFW_TRUE;
+ js->name = strdup(getDeviceDescription(&xic));
+ js->index = index;
+
+ _glfwInputJoystickChange(joy, GLFW_CONNECTED);
+
+ return GLFW_TRUE;
+}
+
+// Polls for and processes events the specified joystick
+//
+static GLFWbool pollJoystickState(_GLFWjoystickWin32* js, int mode)
+{
+ if (!js->present)
+ return GLFW_FALSE;
+
+ if (js->device)
+ {
+ int i, j, ai = 0, bi = 0;
+ HRESULT result;
+ DIJOYSTATE state;
+
+ IDirectInputDevice8_Poll(js->device);
+ result = IDirectInputDevice8_GetDeviceState(js->device,
+ sizeof(state),
+ &state);
+ if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
+ {
+ IDirectInputDevice8_Acquire(js->device);
+ IDirectInputDevice8_Poll(js->device);
+ result = IDirectInputDevice8_GetDeviceState(js->device,
+ sizeof(state),
+ &state);
+ }
+
+ if (FAILED(result))
+ {
+ closeJoystick(js);
+ return GLFW_FALSE;
+ }
+
+ if (mode == _GLFW_PRESENCE_ONLY)
+ return GLFW_TRUE;
+
+ for (i = 0; i < js->objectCount; i++)
+ {
+ const void* data = (char*) &state + js->objects[i].offset;
+
+ switch (js->objects[i].type)
+ {
+ case _GLFW_TYPE_AXIS:
+ case _GLFW_TYPE_SLIDER:
+ {
+ js->axes[ai++] = (*((LONG*) data) + 0.5f) / 32767.5f;
+ break;
+ }
+
+ case _GLFW_TYPE_BUTTON:
+ {
+ if (*((BYTE*) data) & 0x80)
+ js->buttons[bi++] = GLFW_PRESS;
+ else
+ js->buttons[bi++] = GLFW_RELEASE;
+
+ break;
+ }
+
+ case _GLFW_TYPE_POV:
+ {
+ const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 };
+ // Screams of horror are appropriate at this point
+ int value = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
+ if (value < 0 || value > 8)
+ value = 8;
+
+ for (j = 0; j < 4; j++)
+ {
+ if (directions[value] & (1 << j))
+ js->buttons[bi++] = GLFW_PRESS;
+ else
+ js->buttons[bi++] = GLFW_RELEASE;
+ }
+
+ break;
+ }
+ }
+ }
+
+ return GLFW_TRUE;
+ }
+ else
+ {
+ int i;
+ DWORD result;
+ XINPUT_STATE xis;
+ const WORD buttons[14] =
+ {
+ XINPUT_GAMEPAD_A,
+ XINPUT_GAMEPAD_B,
+ XINPUT_GAMEPAD_X,
+ XINPUT_GAMEPAD_Y,
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
+ XINPUT_GAMEPAD_BACK,
+ XINPUT_GAMEPAD_START,
+ XINPUT_GAMEPAD_LEFT_THUMB,
+ XINPUT_GAMEPAD_RIGHT_THUMB,
+ XINPUT_GAMEPAD_DPAD_UP,
+ XINPUT_GAMEPAD_DPAD_RIGHT,
+ XINPUT_GAMEPAD_DPAD_DOWN,
+ XINPUT_GAMEPAD_DPAD_LEFT
+ };
+
+ result = _glfw_XInputGetState(js->index, &xis);
+ if (result != ERROR_SUCCESS)
+ {
+ if (result == ERROR_DEVICE_NOT_CONNECTED)
+ closeJoystick(js);
+
+ return GLFW_FALSE;
+ }
+
+ if (mode == _GLFW_PRESENCE_ONLY)
+ return GLFW_TRUE;
+
+ if (sqrt((double) (xis.Gamepad.sThumbLX * xis.Gamepad.sThumbLX +
+ xis.Gamepad.sThumbLY * xis.Gamepad.sThumbLY)) >
+ (double) XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE)
+ {
+ js->axes[0] = (xis.Gamepad.sThumbLX + 0.5f) / 32767.f;
+ js->axes[1] = (xis.Gamepad.sThumbLY + 0.5f) / 32767.f;
+ }
+ else
+ {
+ js->axes[0] = 0.f;
+ js->axes[1] = 0.f;
+ }
+
+ if (sqrt((double) (xis.Gamepad.sThumbRX * xis.Gamepad.sThumbRX +
+ xis.Gamepad.sThumbRY * xis.Gamepad.sThumbRY)) >
+ (double) XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE)
+ {
+ js->axes[2] = (xis.Gamepad.sThumbRX + 0.5f) / 32767.f;
+ js->axes[3] = (xis.Gamepad.sThumbRY + 0.5f) / 32767.f;
+ }
+ else
+ {
+ js->axes[2] = 0.f;
+ js->axes[3] = 0.f;
+ }
+
+ if (xis.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
+ js->axes[4] = xis.Gamepad.bLeftTrigger / 127.5f - 1.f;
+ else
+ js->axes[4] = -1.f;
+
+ if (xis.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
+ js->axes[5] = xis.Gamepad.bRightTrigger / 127.5f - 1.f;
+ else
+ js->axes[5] = -1.f;
+
+ for (i = 0; i < 14; i++)
+ js->buttons[i] = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
+
+ return GLFW_TRUE;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialize joystick interface
+//
+void _glfwInitJoysticksWin32(void)
+{
+ if (_glfw.win32.dinput8.instance)
+ {
+ if (FAILED(_glfw_DirectInput8Create(GetModuleHandle(NULL),
+ DIRECTINPUT_VERSION,
+ &IID_IDirectInput8W,
+ (void**) &_glfw.win32.dinput8.api,
+ NULL)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "DI: Failed to create interface");
+ }
+ }
+
+ _glfwDetectJoystickConnectionWin32();
+}
+
+// Close all opened joystick handles
+//
+void _glfwTerminateJoysticksWin32(void)
+{
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ closeJoystick(_glfw.win32_js + joy);
+
+ if (_glfw.win32.dinput8.api)
+ IDirectInput8_Release(_glfw.win32.dinput8.api);
+}
+
+// Checks for new joysticks after DBT_DEVICEARRIVAL
+//
+void _glfwDetectJoystickConnectionWin32(void)
+{
+ if (_glfw.win32.xinput.instance)
+ {
+ DWORD i;
+
+ for (i = 0; i < XUSER_MAX_COUNT; i++)
+ openXinputDevice(i);
+ }
+
+ if (_glfw.win32.dinput8.api)
+ {
+ if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
+ DI8DEVCLASS_GAMECTRL,
+ deviceCallback,
+ NULL,
+ DIEDFL_ALLDEVICES)))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Failed to enumerate DirectInput8 devices");
+ return;
+ }
+ }
+}
+
+// Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
+//
+void _glfwDetectJoystickDisconnectionWin32(void)
+{
+ int joy;
+
+ for (joy = GLFW_JOYSTICK_1; joy <= GLFW_JOYSTICK_LAST; joy++)
+ pollJoystickState(_glfw.win32_js + joy, _GLFW_PRESENCE_ONLY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformJoystickPresent(int joy)
+{
+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;
+ return pollJoystickState(js, _GLFW_PRESENCE_ONLY);
+}
+
+const float* _glfwPlatformGetJoystickAxes(int joy, int* count)
+{
+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;
+ if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
+ return NULL;
+
+ *count = js->axisCount;
+ return js->axes;
+}
+
+const unsigned char* _glfwPlatformGetJoystickButtons(int joy, int* count)
+{
+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;
+ if (!pollJoystickState(js, _GLFW_UPDATE_STATE))
+ return NULL;
+
+ *count = js->buttonCount;
+ return js->buttons;
+}
+
+const char* _glfwPlatformGetJoystickName(int joy)
+{
+ _GLFWjoystickWin32* js = _glfw.win32_js + joy;
+ if (!pollJoystickState(js, _GLFW_PRESENCE_ONLY))
+ return NULL;
+
+ return js->name;
+}
+
diff --git a/glfw-3.2.1/src/win32_joystick.h b/glfw-3.2.1/src/win32_joystick.h
new file mode 100644
index 0000000..6a75b41
--- /dev/null
+++ b/glfw-3.2.1/src/win32_joystick.h
@@ -0,0 +1,64 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_win32_joystick_h_
+#define _glfw3_win32_joystick_h_
+
+#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
+ _GLFWjoystickWin32 win32_js[GLFW_JOYSTICK_LAST + 1]
+
+// Joystick element (axis, button or slider)
+//
+typedef struct _GLFWjoyobjectWin32
+{
+ int offset;
+ int type;
+} _GLFWjoyobjectWin32;
+
+// Win32-specific per-joystick data
+//
+typedef struct _GLFWjoystickWin32
+{
+ GLFWbool present;
+ float* axes;
+ int axisCount;
+ unsigned char* buttons;
+ int buttonCount;
+ _GLFWjoyobjectWin32* objects;
+ int objectCount;
+ char* name;
+ IDirectInputDevice8W* device;
+ DWORD index;
+ GUID guid;
+} _GLFWjoystickWin32;
+
+
+void _glfwInitJoysticksWin32(void);
+void _glfwTerminateJoysticksWin32(void);
+void _glfwDetectJoystickConnectionWin32(void);
+void _glfwDetectJoystickDisconnectionWin32(void);
+
+#endif // _glfw3_win32_joystick_h_
diff --git a/glfw-3.2.1/src/win32_monitor.c b/glfw-3.2.1/src/win32_monitor.c
new file mode 100644
index 0000000..e55c9a7
--- /dev/null
+++ b/glfw-3.2.1/src/win32_monitor.c
@@ -0,0 +1,401 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <malloc.h>
+
+
+// Create monitor from an adapter and (optionally) a display
+//
+static _GLFWmonitor* createMonitor(DISPLAY_DEVICEW* adapter,
+ DISPLAY_DEVICEW* display)
+{
+ _GLFWmonitor* monitor;
+ char* name;
+ HDC dc;
+
+ if (display)
+ name = _glfwCreateUTF8FromWideStringWin32(display->DeviceString);
+ else
+ name = _glfwCreateUTF8FromWideStringWin32(adapter->DeviceString);
+ if (!name)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string to UTF-8");
+ return NULL;
+ }
+
+ dc = CreateDCW(L"DISPLAY", adapter->DeviceName, NULL, NULL);
+
+ monitor = _glfwAllocMonitor(name,
+ GetDeviceCaps(dc, HORZSIZE),
+ GetDeviceCaps(dc, VERTSIZE));
+
+ DeleteDC(dc);
+ free(name);
+
+ if (adapter->StateFlags & DISPLAY_DEVICE_MODESPRUNED)
+ monitor->win32.modesPruned = GLFW_TRUE;
+
+ wcscpy(monitor->win32.adapterName, adapter->DeviceName);
+ WideCharToMultiByte(CP_UTF8, 0,
+ adapter->DeviceName, -1,
+ monitor->win32.publicAdapterName,
+ sizeof(monitor->win32.publicAdapterName),
+ NULL, NULL);
+
+ if (display)
+ {
+ wcscpy(monitor->win32.displayName, display->DeviceName);
+ WideCharToMultiByte(CP_UTF8, 0,
+ display->DeviceName, -1,
+ monitor->win32.publicDisplayName,
+ sizeof(monitor->win32.publicDisplayName),
+ NULL, NULL);
+ }
+
+ return monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Change the current video mode
+//
+GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+ DEVMODEW dm;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return GLFW_TRUE;
+
+ ZeroMemory(&dm, sizeof(dm));
+ dm.dmSize = sizeof(DEVMODEW);
+ 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;
+
+ if (ChangeDisplaySettingsExW(monitor->win32.adapterName,
+ &dm,
+ NULL,
+ CDS_FULLSCREEN,
+ NULL) != DISP_CHANGE_SUCCESSFUL)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to set video mode");
+ return GLFW_FALSE;
+ }
+
+ monitor->win32.modeChanged = GLFW_TRUE;
+ return GLFW_TRUE;
+}
+
+// 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;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ int found = 0;
+ DWORD adapterIndex, displayIndex, primaryIndex = 0;
+ DISPLAY_DEVICEW adapter, display;
+ GLFWbool hasDisplays = GLFW_FALSE;
+ _GLFWmonitor** monitors = NULL;
+
+ *count = 0;
+
+ // HACK: Check if any active adapters have connected displays
+ // If not, this is a headless system or a VMware guest
+
+ for (adapterIndex = 0; ; adapterIndex++)
+ {
+ ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
+ adapter.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
+ break;
+
+ if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
+ continue;
+
+ ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
+ display.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (EnumDisplayDevicesW(adapter.DeviceName, 0, &display, 0))
+ {
+ hasDisplays = GLFW_TRUE;
+ break;
+ }
+ }
+
+ for (adapterIndex = 0; ; adapterIndex++)
+ {
+ ZeroMemory(&adapter, sizeof(DISPLAY_DEVICEW));
+ adapter.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (!EnumDisplayDevicesW(NULL, adapterIndex, &adapter, 0))
+ break;
+
+ if (!(adapter.StateFlags & DISPLAY_DEVICE_ACTIVE))
+ continue;
+
+ if (adapter.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
+ primaryIndex = found;
+
+ if (hasDisplays)
+ {
+ for (displayIndex = 0; ; displayIndex++)
+ {
+ ZeroMemory(&display, sizeof(DISPLAY_DEVICEW));
+ display.cb = sizeof(DISPLAY_DEVICEW);
+
+ if (!EnumDisplayDevicesW(adapter.DeviceName, displayIndex, &display, 0))
+ break;
+
+ found++;
+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
+ monitors[found - 1] = createMonitor(&adapter, &display);
+ }
+ }
+ else
+ {
+ found++;
+ monitors = realloc(monitors, sizeof(_GLFWmonitor*) * found);
+ monitors[found - 1] = createMonitor(&adapter, NULL);
+ }
+ }
+
+ _GLFW_SWAP_POINTERS(monitors[0], monitors[primaryIndex]);
+
+ *count = found;
+ return monitors;
+}
+
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ if (wcslen(first->win32.displayName))
+ return wcscmp(first->win32.displayName, second->win32.displayName) == 0;
+ else
+ return wcscmp(first->win32.adapterName, second->win32.adapterName) == 0;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ DEVMODEW settings;
+ ZeroMemory(&settings, sizeof(DEVMODEW));
+ settings.dmSize = sizeof(DEVMODEW);
+
+ EnumDisplaySettingsExW(monitor->win32.adapterName,
+ ENUM_CURRENT_SETTINGS,
+ &settings,
+ EDS_ROTATEDMODE);
+
+ if (xpos)
+ *xpos = settings.dmPosition.x;
+ if (ypos)
+ *ypos = settings.dmPosition.y;
+}
+
+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(DEVMODEW));
+ dm.dmSize = sizeof(DEVMODEW);
+
+ 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(DEVMODEW));
+ dm.dmSize = sizeof(DEVMODEW);
+
+ 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);
+}
+
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ HDC dc;
+ WORD values[768];
+
+ dc = CreateDCW(L"DISPLAY", monitor->win32.adapterName, NULL, NULL);
+ GetDeviceGammaRamp(dc, values);
+ DeleteDC(dc);
+
+ _glfwAllocGammaArrays(ramp, 256);
+
+ memcpy(ramp->red, values + 0, 256 * sizeof(unsigned short));
+ memcpy(ramp->green, values + 256, 256 * sizeof(unsigned short));
+ memcpy(ramp->blue, values + 512, 256 * sizeof(unsigned short));
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ HDC dc;
+ WORD values[768];
+
+ if (ramp->size != 256)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Gamma ramp size must be 256");
+ return;
+ }
+
+ memcpy(values + 0, ramp->red, 256 * sizeof(unsigned short));
+ memcpy(values + 256, ramp->green, 256 * sizeof(unsigned short));
+ memcpy(values + 512, ramp->blue, 256 * sizeof(unsigned short));
+
+ 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-3.2.1/src/win32_platform.h b/glfw-3.2.1/src/win32_platform.h
new file mode 100644
index 0000000..c0dcff1
--- /dev/null
+++ b/glfw-3.2.1/src/win32_platform.h
@@ -0,0 +1,350 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_win32_platform_h_
+#define _glfw3_win32_platform_h_
+
+// 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
+
+#include <wctype.h>
+#include <windows.h>
+#include <mmsystem.h>
+#include <dinput.h>
+#include <xinput.h>
+#include <dbt.h>
+
+#if defined(_MSC_VER)
+ #include <malloc.h>
+ #define strdup _strdup
+#endif
+
+// 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
+
+#if WINVER < 0x0601
+typedef struct tagCHANGEFILTERSTRUCT
+{
+ DWORD cbSize;
+ DWORD ExtStatus;
+
+} CHANGEFILTERSTRUCT, *PCHANGEFILTERSTRUCT;
+#ifndef MSGFLT_ALLOW
+ #define MSGFLT_ALLOW 1
+#endif
+#endif /*Windows 7*/
+
+#ifndef DPI_ENUMS_DECLARED
+typedef enum PROCESS_DPI_AWARENESS
+{
+ PROCESS_DPI_UNAWARE = 0,
+ PROCESS_SYSTEM_DPI_AWARE = 1,
+ PROCESS_PER_MONITOR_DPI_AWARE = 2
+} PROCESS_DPI_AWARENESS;
+#endif /*DPI_ENUMS_DECLARED*/
+
+// HACK: Define macros that some xinput.h variants don't
+#ifndef XINPUT_CAPS_WIRELESS
+ #define XINPUT_CAPS_WIRELESS 0x0002
+#endif
+#ifndef XINPUT_DEVSUBTYPE_WHEEL
+ #define XINPUT_DEVSUBTYPE_WHEEL 0x02
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
+ #define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
+#endif
+#ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
+ #define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
+ #define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
+#endif
+#ifndef XINPUT_DEVSUBTYPE_GUITAR
+ #define XINPUT_DEVSUBTYPE_GUITAR 0x06
+#endif
+#ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
+ #define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
+#endif
+#ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
+ #define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
+#endif
+#ifndef XUSER_MAX_COUNT
+ #define XUSER_MAX_COUNT 4
+#endif
+
+// HACK: Define macros that some dinput.h variants don't
+#ifndef DIDFT_OPTIONAL
+ #define DIDFT_OPTIONAL 0x80000000
+#endif
+
+// winmm.dll function pointer typedefs
+typedef DWORD (WINAPI * TIMEGETTIME_T)(void);
+#define _glfw_timeGetTime _glfw.win32.winmm.timeGetTime
+
+// xinput.dll function pointer typedefs
+typedef DWORD (WINAPI * XINPUTGETCAPABILITIES_T)(DWORD,DWORD,XINPUT_CAPABILITIES*);
+typedef DWORD (WINAPI * XINPUTGETSTATE_T)(DWORD,XINPUT_STATE*);
+#define _glfw_XInputGetCapabilities _glfw.win32.xinput.XInputGetCapabilities
+#define _glfw_XInputGetState _glfw.win32.xinput.XInputGetState
+
+// dinput8.dll function pointer typedefs
+typedef HRESULT (WINAPI * DIRECTINPUT8CREATE_T)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
+#define _glfw_DirectInput8Create _glfw.win32.dinput8.DirectInput8Create
+
+// user32.dll function pointer typedefs
+typedef BOOL (WINAPI * SETPROCESSDPIAWARE_T)(void);
+typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFILTERSTRUCT);
+#define _glfw_SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware
+#define _glfw_ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx
+
+// dwmapi.dll function pointer typedefs
+typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
+typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
+#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
+#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
+
+// shcore.dll function pointer typedefs
+typedef HRESULT (WINAPI * SETPROCESSDPIAWARENESS_T)(PROCESS_DPI_AWARENESS);
+#define _glfw_SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness
+
+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"
+
+#define _GLFW_WNDCLASSNAME L"GLFW30"
+
+#define _glfw_dlopen(name) LoadLibraryA(name)
+#define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
+#define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->win32.handle)
+#define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
+#define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time
+#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32
+
+
+// Win32-specific per-window data
+//
+typedef struct _GLFWwindowWin32
+{
+ HWND handle;
+ HICON bigIcon;
+ HICON smallIcon;
+
+ GLFWbool cursorTracked;
+ GLFWbool iconified;
+
+ // The last received cursor position, regardless of source
+ int lastCursorPosX, lastCursorPosY;
+
+} _GLFWwindowWin32;
+
+// Win32-specific global data
+//
+typedef struct _GLFWlibraryWin32
+{
+ HWND helperWindowHandle;
+ DWORD foregroundLockTimeout;
+ char* clipboardString;
+ char keyName[64];
+ short int publicKeys[512];
+ short int nativeKeys[GLFW_KEY_LAST + 1];
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+
+ struct {
+ HINSTANCE instance;
+ TIMEGETTIME_T timeGetTime;
+ } winmm;
+
+ struct {
+ HINSTANCE instance;
+ DIRECTINPUT8CREATE_T DirectInput8Create;
+ IDirectInput8W* api;
+ } dinput8;
+
+ struct {
+ HINSTANCE instance;
+ XINPUTGETCAPABILITIES_T XInputGetCapabilities;
+ XINPUTGETSTATE_T XInputGetState;
+ } xinput;
+
+ struct {
+ HINSTANCE instance;
+ SETPROCESSDPIAWARE_T SetProcessDPIAware;
+ CHANGEWINDOWMESSAGEFILTEREX_T ChangeWindowMessageFilterEx;
+ } user32;
+
+ struct {
+ HINSTANCE instance;
+ DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
+ DWMFLUSH_T DwmFlush;
+ } dwmapi;
+
+ struct {
+ HINSTANCE instance;
+ SETPROCESSDPIAWARENESS_T SetProcessDpiAwareness;
+ } shcore;
+
+} _GLFWlibraryWin32;
+
+// Win32-specific per-monitor data
+//
+typedef struct _GLFWmonitorWin32
+{
+ // This size matches the static size of DISPLAY_DEVICE.DeviceName
+ WCHAR adapterName[32];
+ WCHAR displayName[32];
+ char publicAdapterName[64];
+ char publicDisplayName[64];
+ GLFWbool modesPruned;
+ GLFWbool modeChanged;
+
+} _GLFWmonitorWin32;
+
+// Win32-specific per-cursor data
+//
+typedef struct _GLFWcursorWin32
+{
+ HCURSOR handle;
+
+} _GLFWcursorWin32;
+
+// Win32-specific global timer data
+//
+typedef struct _GLFWtimeWin32
+{
+ GLFWbool hasPC;
+ uint64_t frequency;
+
+} _GLFWtimeWin32;
+
+// Win32-specific global TLS data
+//
+typedef struct _GLFWtlsWin32
+{
+ GLFWbool allocated;
+ DWORD context;
+
+} _GLFWtlsWin32;
+
+
+GLFWbool _glfwRegisterWindowClassWin32(void);
+void _glfwUnregisterWindowClassWin32(void);
+
+GLFWbool _glfwInitThreadLocalStorageWin32(void);
+void _glfwTerminateThreadLocalStorageWin32(void);
+
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
+
+void _glfwInitTimerWin32(void);
+
+GLFWbool _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
+void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
+
+#endif // _glfw3_win32_platform_h_
diff --git a/glfw-3.2.1/src/win32_time.c b/glfw-3.2.1/src/win32_time.c
new file mode 100644
index 0000000..d972f56
--- /dev/null
+++ b/glfw-3.2.1/src/win32_time.c
@@ -0,0 +1,74 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Initialise timer
+//
+void _glfwInitTimerWin32(void)
+{
+ uint64_t frequency;
+
+ if (QueryPerformanceFrequency((LARGE_INTEGER*) &frequency))
+ {
+ _glfw.win32_time.hasPC = GLFW_TRUE;
+ _glfw.win32_time.frequency = frequency;
+ }
+ else
+ {
+ _glfw.win32_time.hasPC = GLFW_FALSE;
+ _glfw.win32_time.frequency = 1000;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+uint64_t _glfwPlatformGetTimerValue(void)
+{
+ if (_glfw.win32_time.hasPC)
+ {
+ uint64_t value;
+ QueryPerformanceCounter((LARGE_INTEGER*) &value);
+ return value;
+ }
+ else
+ return (uint64_t) _glfw_timeGetTime();
+}
+
+uint64_t _glfwPlatformGetTimerFrequency(void)
+{
+ return _glfw.win32_time.frequency;
+}
+
diff --git a/glfw-3.2.1/src/win32_tls.c b/glfw-3.2.1/src/win32_tls.c
new file mode 100644
index 0000000..ab79fcc
--- /dev/null
+++ b/glfw-3.2.1/src/win32_tls.c
@@ -0,0 +1,69 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWbool _glfwInitThreadLocalStorageWin32(void)
+{
+ _glfw.win32_tls.context = TlsAlloc();
+ if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to allocate TLS index");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32_tls.allocated = GLFW_TRUE;
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateThreadLocalStorageWin32(void)
+{
+ if (_glfw.win32_tls.allocated)
+ TlsFree(_glfw.win32_tls.context);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwPlatformSetCurrentContext(_GLFWwindow* context)
+{
+ TlsSetValue(_glfw.win32_tls.context, context);
+}
+
+_GLFWwindow* _glfwPlatformGetCurrentContext(void)
+{
+ return TlsGetValue(_glfw.win32_tls.context);
+}
+
diff --git a/glfw-3.2.1/src/win32_window.c b/glfw-3.2.1/src/win32_window.c
new file mode 100644
index 0000000..8e30eb6
--- /dev/null
+++ b/glfw-3.2.1/src/win32_window.c
@@ -0,0 +1,1724 @@
+//========================================================================
+// GLFW 3.2 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <windowsx.h>
+#include <shellapi.h>
+
+#define _GLFW_KEY_INVALID -2
+
+// Returns the window style for the specified window
+//
+static DWORD getWindowStyle(const _GLFWwindow* window)
+{
+ DWORD style = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+
+ if (window->monitor)
+ style |= WS_POPUP;
+ else
+ {
+ if (window->decorated)
+ {
+ style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
+
+ if (window->resizable)
+ style |= WS_MAXIMIZEBOX | WS_THICKFRAME;
+ }
+ else
+ style |= WS_POPUP;
+ }
+
+ return style;
+}
+
+// Returns the extended window style for the specified window
+//
+static DWORD getWindowExStyle(const _GLFWwindow* window)
+{
+ DWORD style = WS_EX_APPWINDOW;
+
+ if (window->monitor || window->floating)
+ style |= WS_EX_TOPMOST;
+
+ return style;
+}
+
+// Returns the image whose area most closely matches the desired one
+//
+static const GLFWimage* chooseImage(int count, const GLFWimage* images,
+ int width, int height)
+{
+ int i, leastDiff = INT_MAX;
+ const GLFWimage* closest = NULL;
+
+ for (i = 0; i < count; i++)
+ {
+ const int currDiff = abs(images[i].width * images[i].height -
+ width * height);
+ if (currDiff < leastDiff)
+ {
+ closest = images + i;
+ leastDiff = currDiff;
+ }
+ }
+
+ return closest;
+}
+
+// Creates an RGBA icon or cursor
+//
+static HICON createIcon(const GLFWimage* image,
+ int xhot, int yhot, GLFWbool icon)
+{
+ int i;
+ HDC dc;
+ HICON handle;
+ HBITMAP color, mask;
+ BITMAPV5HEADER bi;
+ ICONINFO ii;
+ unsigned char* target = NULL;
+ unsigned char* source = image->pixels;
+
+ ZeroMemory(&bi, sizeof(bi));
+ bi.bV5Size = sizeof(BITMAPV5HEADER);
+ bi.bV5Width = image->width;
+ bi.bV5Height = -image->height;
+ bi.bV5Planes = 1;
+ bi.bV5BitCount = 32;
+ bi.bV5Compression = BI_BITFIELDS;
+ bi.bV5RedMask = 0x00ff0000;
+ bi.bV5GreenMask = 0x0000ff00;
+ bi.bV5BlueMask = 0x000000ff;
+ bi.bV5AlphaMask = 0xff000000;
+
+ dc = GetDC(NULL);
+ color = CreateDIBSection(dc,
+ (BITMAPINFO*) &bi,
+ DIB_RGB_COLORS,
+ (void**) &target,
+ NULL,
+ (DWORD) 0);
+ ReleaseDC(NULL, dc);
+
+ if (!color)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create RGBA bitmap");
+ return NULL;
+ }
+
+ mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
+ if (!mask)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create mask bitmap");
+ DeleteObject(color);
+ return NULL;
+ }
+
+ for (i = 0; i < image->width * image->height; i++)
+ {
+ target[0] = source[2];
+ target[1] = source[1];
+ target[2] = source[0];
+ target[3] = source[3];
+ target += 4;
+ source += 4;
+ }
+
+ ZeroMemory(&ii, sizeof(ii));
+ ii.fIcon = icon;
+ ii.xHotspot = xhot;
+ ii.yHotspot = yhot;
+ ii.hbmMask = mask;
+ ii.hbmColor = color;
+
+ handle = CreateIconIndirect(&ii);
+
+ DeleteObject(color);
+ DeleteObject(mask);
+
+ if (!handle)
+ {
+ if (icon)
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");
+ else
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");
+ }
+
+ return handle;
+}
+
+// Translate client window size to full window size according to styles
+//
+static void getFullWindowSize(DWORD style, DWORD exStyle,
+ int clientWidth, int clientHeight,
+ int* fullWidth, int* fullHeight)
+{
+ RECT rect = { 0, 0, clientWidth, clientHeight };
+ AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+ *fullWidth = rect.right - rect.left;
+ *fullHeight = rect.bottom - rect.top;
+}
+
+// Enforce the client rect aspect ratio based on which edge is being dragged
+//
+static void applyAspectRatio(_GLFWwindow* window, int edge, RECT* area)
+{
+ int xoff, yoff;
+ const float ratio = (float) window->numer / (float) window->denom;
+
+ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+ 0, 0, &xoff, &yoff);
+
+ if (edge == WMSZ_LEFT || edge == WMSZ_BOTTOMLEFT ||
+ edge == WMSZ_RIGHT || edge == WMSZ_BOTTOMRIGHT)
+ {
+ area->bottom = area->top + yoff +
+ (int) ((area->right - area->left - xoff) / ratio);
+ }
+ else if (edge == WMSZ_TOPLEFT || edge == WMSZ_TOPRIGHT)
+ {
+ area->top = area->bottom - yoff -
+ (int) ((area->right - area->left - xoff) / ratio);
+ }
+ else if (edge == WMSZ_TOP || edge == WMSZ_BOTTOM)
+ {
+ area->right = area->left + xoff +
+ (int) ((area->bottom - area->top - yoff) * ratio);
+ }
+}
+
+// Centers the cursor over the window client area
+//
+static void centerCursor(_GLFWwindow* window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Returns whether the cursor is in the client area of the specified window
+//
+static GLFWbool cursorInClientArea(_GLFWwindow* window)
+{
+ RECT area;
+ POINT pos;
+
+ if (!GetCursorPos(&pos))
+ return GLFW_FALSE;
+
+ if (WindowFromPoint(pos) != window->win32.handle)
+ return GLFW_FALSE;
+
+ GetClientRect(window->win32.handle, &area);
+ ClientToScreen(window->win32.handle, (POINT*) &area.left);
+ ClientToScreen(window->win32.handle, (POINT*) &area.right);
+
+ return PtInRect(&area, pos);
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (window->cursor)
+ SetCursor(window->cursor->win32.handle);
+ else
+ SetCursor(LoadCursorW(NULL, IDC_ARROW));
+ }
+ else
+ SetCursor(NULL);
+}
+
+// Updates the cursor clip rect
+//
+static void updateClipRect(_GLFWwindow* window)
+{
+ if (window)
+ {
+ RECT clipRect;
+ GetClientRect(window->win32.handle, &clipRect);
+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.left);
+ ClientToScreen(window->win32.handle, (POINT*) &clipRect.right);
+ ClipCursor(&clipRect);
+ }
+ else
+ ClipCursor(NULL);
+}
+
+// Translates a GLFW standard cursor to a resource ID
+//
+static LPWSTR translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return IDC_ARROW;
+ case GLFW_IBEAM_CURSOR:
+ return IDC_IBEAM;
+ case GLFW_CROSSHAIR_CURSOR:
+ return IDC_CROSS;
+ case GLFW_HAND_CURSOR:
+ return IDC_HAND;
+ case GLFW_HRESIZE_CURSOR:
+ return IDC_SIZEWE;
+ case GLFW_VRESIZE_CURSOR:
+ return IDC_SIZENS;
+ }
+
+ return NULL;
+}
+
+// Retrieves and translates modifier keys
+//
+static int getKeyMods(void)
+{
+ int mods = 0;
+
+ if (GetKeyState(VK_SHIFT) & (1 << 31))
+ mods |= GLFW_MOD_SHIFT;
+ if (GetKeyState(VK_CONTROL) & (1 << 31))
+ mods |= GLFW_MOD_CONTROL;
+ if (GetKeyState(VK_MENU) & (1 << 31))
+ mods |= GLFW_MOD_ALT;
+ if ((GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN)) & (1 << 31))
+ mods |= GLFW_MOD_SUPER;
+
+ return mods;
+}
+
+// Retrieves and translates modifier keys
+//
+static int getAsyncKeyMods(void)
+{
+ int mods = 0;
+
+ if (GetAsyncKeyState(VK_SHIFT) & (1 << 31))
+ mods |= GLFW_MOD_SHIFT;
+ if (GetAsyncKeyState(VK_CONTROL) & (1 << 31))
+ mods |= GLFW_MOD_CONTROL;
+ if (GetAsyncKeyState(VK_MENU) & (1 << 31))
+ mods |= GLFW_MOD_ALT;
+ if ((GetAsyncKeyState(VK_LWIN) | GetAsyncKeyState(VK_RWIN)) & (1 << 31))
+ mods |= GLFW_MOD_SUPER;
+
+ return mods;
+}
+
+// Translates a Windows key to the corresponding GLFW key
+//
+static int translateKey(WPARAM wParam, LPARAM lParam)
+{
+ if (wParam == VK_CONTROL)
+ {
+ // The CTRL keys require special handling
+
+ MSG next;
+ DWORD time;
+
+ // Is this an extended key (i.e. right key)?
+ if (lParam & 0x01000000)
+ return GLFW_KEY_RIGHT_CONTROL;
+
+ // Here is a trick: "Alt Gr" sends LCTRL, then RALT. We only
+ // want the RALT message, so we try to see if the next message
+ // is a RALT message. In that case, this is a false LCTRL!
+ time = GetMessageTime();
+
+ if (PeekMessageW(&next, NULL, 0, 0, PM_NOREMOVE))
+ {
+ if (next.message == WM_KEYDOWN ||
+ next.message == WM_SYSKEYDOWN ||
+ next.message == WM_KEYUP ||
+ next.message == WM_SYSKEYUP)
+ {
+ if (next.wParam == VK_MENU &&
+ (next.lParam & 0x01000000) &&
+ next.time == time)
+ {
+ // Next message is a RALT down message, which
+ // means that this is not a proper LCTRL message
+ return _GLFW_KEY_INVALID;
+ }
+ }
+ }
+
+ return GLFW_KEY_LEFT_CONTROL;
+ }
+
+ if (wParam == VK_PROCESSKEY)
+ {
+ // IME notifies that keys have been filtered by setting the virtual
+ // key-code to VK_PROCESSKEY
+ return _GLFW_KEY_INVALID;
+ }
+
+ return _glfw.win32.publicKeys[HIWORD(lParam) & 0x1FF];
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static GLFWbool acquireMonitor(_GLFWwindow* window)
+{
+ GLFWvidmode mode;
+ GLFWbool status;
+ int xpos, ypos;
+
+ status = _glfwSetVideoModeWin32(window->monitor, &window->videoMode);
+
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+
+ SetWindowPos(window->win32.handle, HWND_TOPMOST,
+ xpos, ypos, mode.width, mode.height,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS);
+
+ _glfwInputMonitorWindowChange(window->monitor, window);
+ return status;
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfwInputMonitorWindowChange(window->monitor, NULL);
+ _glfwRestoreVideoModeWin32(window->monitor);
+}
+
+// Window callback function (handles window messages)
+//
+static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+{
+ _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
+ if (!window)
+ {
+ // This is the message handling for the hidden helper window
+
+ switch (uMsg)
+ {
+ case WM_DEVICECHANGE:
+ {
+ if (wParam == DBT_DEVNODES_CHANGED)
+ {
+ _glfwInputMonitorChange();
+ return TRUE;
+ }
+ else if (wParam == DBT_DEVICEARRIVAL)
+ {
+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+ if (dbh)
+ {
+ if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ _glfwDetectJoystickConnectionWin32();
+ }
+ }
+ else if (wParam == DBT_DEVICEREMOVECOMPLETE)
+ {
+ DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
+ if (dbh)
+ {
+ if (dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+ _glfwDetectJoystickDisconnectionWin32();
+ }
+ }
+
+ break;
+ }
+ }
+
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+ }
+
+ switch (uMsg)
+ {
+ case WM_SETFOCUS:
+ {
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
+
+ return 0;
+ }
+
+ case WM_KILLFOCUS:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
+
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+ return 0;
+ }
+
+ case WM_SYSCOMMAND:
+ {
+ switch (wParam & 0xfff0)
+ {
+ case SC_SCREENSAVE:
+ case SC_MONITORPOWER:
+ {
+ if (window->monitor)
+ {
+ // We are running in full screen mode, so disallow
+ // screen saver and screen blanking
+ return 0;
+ }
+ else
+ break;
+ }
+
+ // User trying to access application menu using ALT?
+ case SC_KEYMENU:
+ return 0;
+ }
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ _glfwInputWindowCloseRequest(window);
+ return 0;
+ }
+
+ case WM_CHAR:
+ case WM_SYSCHAR:
+ case WM_UNICHAR:
+ {
+ const GLFWbool plain = (uMsg != WM_SYSCHAR);
+
+ if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR)
+ {
+ // WM_UNICHAR is not sent by Windows, but is sent by some
+ // third-party input method engine
+ // Returning TRUE here announces support for this message
+ return TRUE;
+ }
+
+ _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain);
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ {
+ const int key = translateKey(wParam, lParam);
+ const int scancode = (lParam >> 16) & 0x1ff;
+ const int action = ((lParam >> 31) & 1) ? GLFW_RELEASE : GLFW_PRESS;
+ const int mods = getKeyMods();
+
+ if (key == _GLFW_KEY_INVALID)
+ break;
+
+ if (action == GLFW_RELEASE && wParam == VK_SHIFT)
+ {
+ // Release both Shift keys on Shift up event, as only one event
+ // is sent even if both keys are released
+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, scancode, action, mods);
+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, scancode, action, mods);
+ }
+ else if (wParam == VK_SNAPSHOT)
+ {
+ // Key down is not reported for the Print Screen key
+ _glfwInputKey(window, key, scancode, GLFW_PRESS, mods);
+ _glfwInputKey(window, key, scancode, GLFW_RELEASE, mods);
+ }
+ else
+ _glfwInputKey(window, key, scancode, action, mods);
+
+ break;
+ }
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case WM_XBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_XBUTTONUP:
+ {
+ int button, action;
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_LEFT;
+ else if (uMsg == WM_RBUTTONDOWN || uMsg == WM_RBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_RIGHT;
+ else if (uMsg == WM_MBUTTONDOWN || uMsg == WM_MBUTTONUP)
+ button = GLFW_MOUSE_BUTTON_MIDDLE;
+ else if (GET_XBUTTON_WPARAM(wParam) == XBUTTON1)
+ button = GLFW_MOUSE_BUTTON_4;
+ else
+ button = GLFW_MOUSE_BUTTON_5;
+
+ if (uMsg == WM_LBUTTONDOWN || uMsg == WM_RBUTTONDOWN ||
+ uMsg == WM_MBUTTONDOWN || uMsg == WM_XBUTTONDOWN)
+ {
+ action = GLFW_PRESS;
+ SetCapture(hWnd);
+ }
+ else
+ {
+ action = GLFW_RELEASE;
+ ReleaseCapture();
+ }
+
+ _glfwInputMouseClick(window, button, action, getKeyMods());
+
+ if (uMsg == WM_XBUTTONDOWN || uMsg == WM_XBUTTONUP)
+ return TRUE;
+
+ return 0;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ const int x = GET_X_LPARAM(lParam);
+ const int y = GET_Y_LPARAM(lParam);
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ const int dx = x - window->win32.lastCursorPosX;
+ const int dy = y - window->win32.lastCursorPosY;
+
+ if (_glfw.win32.disabledCursorWindow != window)
+ break;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + dx,
+ window->virtualCursorPosY + dy);
+ }
+ else
+ _glfwInputCursorPos(window, x, y);
+
+ window->win32.lastCursorPosX = x;
+ window->win32.lastCursorPosY = y;
+
+ if (!window->win32.cursorTracked)
+ {
+ TRACKMOUSEEVENT tme;
+ ZeroMemory(&tme, sizeof(tme));
+ tme.cbSize = sizeof(tme);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = window->win32.handle;
+ TrackMouseEvent(&tme);
+
+ window->win32.cursorTracked = GLFW_TRUE;
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+ }
+
+ return 0;
+ }
+
+ case WM_MOUSELEAVE:
+ {
+ window->win32.cursorTracked = GLFW_FALSE;
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+ return 0;
+ }
+
+ case WM_MOUSEWHEEL:
+ {
+ _glfwInputScroll(window, 0.0, (SHORT) HIWORD(wParam) / (double) WHEEL_DELTA);
+ return 0;
+ }
+
+ case WM_MOUSEHWHEEL:
+ {
+ // This message is only sent on Windows Vista and later
+ // NOTE: The X-axis is inverted for consistency with OS X and X11.
+ _glfwInputScroll(window, -((SHORT) HIWORD(wParam) / (double) WHEEL_DELTA), 0.0);
+ return 0;
+ }
+
+ case WM_ENTERSIZEMOVE:
+ case WM_ENTERMENULOOP:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
+
+ break;
+ }
+
+ case WM_EXITSIZEMOVE:
+ case WM_EXITMENULOOP:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
+
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ const GLFWbool iconified =
+ !window->win32.iconified && wParam == SIZE_MINIMIZED;
+ const GLFWbool restored =
+ window->win32.iconified &&
+ (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED);
+
+ if (_glfw.win32.disabledCursorWindow == window)
+ updateClipRect(window);
+
+ if (iconified)
+ _glfwInputWindowIconify(window, GLFW_TRUE);
+ else if (restored)
+ _glfwInputWindowIconify(window, GLFW_FALSE);
+
+ _glfwInputFramebufferSize(window, LOWORD(lParam), HIWORD(lParam));
+ _glfwInputWindowSize(window, LOWORD(lParam), HIWORD(lParam));
+
+ if (iconified)
+ {
+ window->win32.iconified = GLFW_TRUE;
+ if (window->monitor)
+ releaseMonitor(window);
+ }
+ else if (restored)
+ {
+ window->win32.iconified = GLFW_FALSE;
+ if (window->monitor)
+ acquireMonitor(window);
+ }
+
+ return 0;
+ }
+
+ case WM_MOVE:
+ {
+ if (_glfw.win32.disabledCursorWindow == window)
+ updateClipRect(window);
+
+ // NOTE: This cannot use LOWORD/HIWORD recommended by MSDN, as
+ // those macros do not handle negative window positions correctly
+ _glfwInputWindowPos(window,
+ GET_X_LPARAM(lParam),
+ GET_Y_LPARAM(lParam));
+ return 0;
+ }
+
+ case WM_SIZING:
+ {
+ if (window->numer == GLFW_DONT_CARE ||
+ window->denom == GLFW_DONT_CARE)
+ {
+ break;
+ }
+
+ applyAspectRatio(window, (int) wParam, (RECT*) lParam);
+ return TRUE;
+ }
+
+ case WM_GETMINMAXINFO:
+ {
+ int xoff, yoff;
+ MINMAXINFO* mmi = (MINMAXINFO*) lParam;
+
+ if (window->monitor)
+ break;
+
+ getFullWindowSize(getWindowStyle(window), getWindowExStyle(window),
+ 0, 0, &xoff, &yoff);
+
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ mmi->ptMinTrackSize.x = window->minwidth + xoff;
+ mmi->ptMinTrackSize.y = window->minheight + yoff;
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ mmi->ptMaxTrackSize.x = window->maxwidth + xoff;
+ mmi->ptMaxTrackSize.y = window->maxheight + yoff;
+ }
+
+ return 0;
+ }
+
+ case WM_PAINT:
+ {
+ _glfwInputWindowDamage(window);
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ return TRUE;
+ }
+
+ case WM_SETCURSOR:
+ {
+ if (LOWORD(lParam) == HTCLIENT)
+ {
+ updateCursorImage(window);
+ return TRUE;
+ }
+
+ break;
+ }
+
+ case WM_DPICHANGED:
+ {
+ RECT* rect = (RECT*) lParam;
+ SetWindowPos(window->win32.handle,
+ HWND_TOP,
+ rect->left,
+ rect->top,
+ rect->right - rect->left,
+ rect->bottom - rect->top,
+ SWP_NOACTIVATE | SWP_NOZORDER);
+ break;
+ }
+
+ case WM_DROPFILES:
+ {
+ HDROP drop = (HDROP) wParam;
+ POINT pt;
+ int i;
+
+ const int count = DragQueryFileW(drop, 0xffffffff, NULL, 0);
+ char** paths = calloc(count, sizeof(char*));
+
+ // Move the mouse to the position of the drop
+ DragQueryPoint(drop, &pt);
+ _glfwInputCursorPos(window, pt.x, pt.y);
+
+ for (i = 0; i < count; i++)
+ {
+ const UINT length = DragQueryFileW(drop, i, NULL, 0);
+ WCHAR* buffer = calloc(length + 1, sizeof(WCHAR));
+
+ DragQueryFileW(drop, i, buffer, length + 1);
+ paths[i] = _glfwCreateUTF8FromWideStringWin32(buffer);
+
+ free(buffer);
+ }
+
+ _glfwInputDrop(window, count, (const char**) paths);
+
+ for (i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+
+ DragFinish(drop);
+ return 0;
+ }
+ }
+
+ return DefWindowProcW(hWnd, uMsg, wParam, lParam);
+}
+
+// Creates the GLFW window
+//
+static int createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig)
+{
+ int xpos, ypos, fullWidth, fullHeight;
+ WCHAR* wideTitle;
+ DWORD style = getWindowStyle(window);
+ DWORD exStyle = getWindowExStyle(window);
+
+ if (window->monitor)
+ {
+ GLFWvidmode mode;
+
+ // NOTE: This window placement is temporary and approximate, as the
+ // correct position and size cannot be known until the monitor
+ // video mode has been set
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+ fullWidth = mode.width;
+ fullHeight = mode.height;
+ }
+ else
+ {
+ xpos = CW_USEDEFAULT;
+ ypos = CW_USEDEFAULT;
+
+ if (wndconfig->maximized)
+ style |= WS_MAXIMIZE;
+
+ getFullWindowSize(style, exStyle,
+ wndconfig->width, wndconfig->height,
+ &fullWidth, &fullHeight);
+ }
+
+ wideTitle = _glfwCreateWideStringFromUTF8Win32(wndconfig->title);
+ if (!wideTitle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert window title to UTF-16");
+ return GLFW_FALSE;
+ }
+
+ window->win32.handle = CreateWindowExW(exStyle,
+ _GLFW_WNDCLASSNAME,
+ wideTitle,
+ style,
+ xpos, ypos,
+ fullWidth, fullHeight,
+ NULL, // No parent window
+ NULL, // No window menu
+ GetModuleHandleW(NULL),
+ NULL);
+
+ free(wideTitle);
+
+ if (!window->win32.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ SetPropW(window->win32.handle, L"GLFW", window);
+
+ if (_glfw_ChangeWindowMessageFilterEx)
+ {
+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_DROPFILES, MSGFLT_ALLOW, NULL);
+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_COPYDATA, MSGFLT_ALLOW, NULL);
+ _glfw_ChangeWindowMessageFilterEx(window->win32.handle,
+ WM_COPYGLOBALDATA, MSGFLT_ALLOW, NULL);
+ }
+
+ DragAcceptFiles(window->win32.handle, TRUE);
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Registers the GLFW window class
+//
+GLFWbool _glfwRegisterWindowClassWin32(void)
+{
+ WNDCLASSEXW wc;
+
+ ZeroMemory(&wc, sizeof(wc));
+ wc.cbSize = sizeof(wc);
+ wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+ wc.lpfnWndProc = (WNDPROC) windowProc;
+ wc.hInstance = GetModuleHandleW(NULL);
+ wc.hCursor = LoadCursorW(NULL, IDC_ARROW);
+ wc.lpszClassName = _GLFW_WNDCLASSNAME;
+
+ // Load user-provided icon if available
+ wc.hIcon = LoadImageW(GetModuleHandleW(NULL),
+ L"GLFW_ICON", IMAGE_ICON,
+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ if (!wc.hIcon)
+ {
+ // No user-provided icon found, load default icon
+ wc.hIcon = LoadImageW(NULL,
+ IDI_APPLICATION, IMAGE_ICON,
+ 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ }
+
+ if (!RegisterClassExW(&wc))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to register window class");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Unregisters the GLFW window class
+//
+void _glfwUnregisterWindowClassWin32(void)
+{
+ UnregisterClassW(_GLFW_WNDCLASSNAME, GetModuleHandleW(NULL));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!createNativeWindow(window, wndconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitWGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextWGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ _glfwPlatformFocusWindow(window);
+ if (!acquireMonitor(window))
+ return GLFW_FALSE;
+
+ centerCursor(window);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (window->monitor)
+ releaseMonitor(window);
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ if (_glfw.win32.disabledCursorWindow == window)
+ _glfw.win32.disabledCursorWindow = NULL;
+
+ if (window->win32.handle)
+ {
+ RemovePropW(window->win32.handle, L"GLFW");
+ DestroyWindow(window->win32.handle);
+ window->win32.handle = NULL;
+ }
+
+ if (window->win32.bigIcon)
+ DestroyIcon(window->win32.bigIcon);
+
+ if (window->win32.smallIcon)
+ DestroyIcon(window->win32.smallIcon);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+ WCHAR* wideTitle = _glfwCreateWideStringFromUTF8Win32(title);
+ if (!wideTitle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert window title to UTF-16");
+ return;
+ }
+
+ SetWindowTextW(window->win32.handle, wideTitle);
+ free(wideTitle);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ HICON bigIcon = NULL, smallIcon = NULL;
+
+ if (count)
+ {
+ const GLFWimage* bigImage = chooseImage(count, images,
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON));
+ const GLFWimage* smallImage = chooseImage(count, images,
+ GetSystemMetrics(SM_CXSMICON),
+ GetSystemMetrics(SM_CYSMICON));
+
+ bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
+ smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
+ }
+ else
+ {
+ bigIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICON);
+ smallIcon = (HICON) GetClassLongPtrW(window->win32.handle, GCLP_HICONSM);
+ }
+
+ SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
+ SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
+
+ if (window->win32.bigIcon)
+ DestroyIcon(window->win32.bigIcon);
+
+ if (window->win32.smallIcon)
+ DestroyIcon(window->win32.smallIcon);
+
+ if (count)
+ {
+ window->win32.bigIcon = bigIcon;
+ window->win32.smallIcon = smallIcon;
+ }
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ POINT pos = { 0, 0 };
+ ClientToScreen(window->win32.handle, &pos);
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = pos.y;
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ RECT rect = { xpos, ypos, xpos, ypos };
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ SetWindowPos(window->win32.handle, NULL, rect.left, rect.top, 0, 0,
+ SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ RECT area;
+ GetClientRect(window->win32.handle, &area);
+
+ if (width)
+ *width = area.right;
+ if (height)
+ *height = area.bottom;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ RECT rect = { 0, 0, width, height };
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ 0, 0, rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOZORDER);
+ }
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ RECT area;
+
+ if ((minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) &&
+ (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE))
+ {
+ return;
+ }
+
+ GetWindowRect(window->win32.handle, &area);
+ MoveWindow(window->win32.handle,
+ area.left, area.top,
+ area.right - area.left,
+ area.bottom - area.top, TRUE);
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ RECT area;
+
+ if (numer == GLFW_DONT_CARE || denom == GLFW_DONT_CARE)
+ return;
+
+ GetWindowRect(window->win32.handle, &area);
+ applyAspectRatio(window, WMSZ_BOTTOMRIGHT, &area);
+ MoveWindow(window->win32.handle,
+ area.left, area.top,
+ area.right - area.left,
+ area.bottom - area.top, TRUE);
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ RECT rect;
+ int width, height;
+
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ SetRect(&rect, 0, 0, width, height);
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+
+ if (left)
+ *left = -rect.left;
+ if (top)
+ *top = -rect.top;
+ if (right)
+ *right = rect.right - width;
+ if (bottom)
+ *bottom = rect.bottom - height;
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_MINIMIZE);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_RESTORE);
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_MAXIMIZE);
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_SHOW);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->win32.handle, SW_HIDE);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ BringWindowToTop(window->win32.handle);
+ SetForegroundWindow(window->win32.handle);
+ SetFocus(window->win32.handle);
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (window->monitor == monitor)
+ {
+ if (monitor)
+ {
+ if (monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ RECT rect = { xpos, ypos, xpos + width, ypos + height };
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ SetWindowPos(window->win32.handle, HWND_TOP,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ SWP_NOCOPYBITS | SWP_NOACTIVATE | SWP_NOZORDER);
+ }
+
+ return;
+ }
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowMonitorChange(window, monitor);
+
+ if (monitor)
+ {
+ GLFWvidmode mode;
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+ UINT flags = SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOCOPYBITS;
+
+ if (window->decorated)
+ {
+ style &= ~WS_OVERLAPPEDWINDOW;
+ style |= getWindowStyle(window);
+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+
+ flags |= SWP_FRAMECHANGED;
+ }
+
+ _glfwPlatformGetVideoMode(monitor, &mode);
+ _glfwPlatformGetMonitorPos(monitor, &xpos, &ypos);
+
+ SetWindowPos(window->win32.handle, HWND_TOPMOST,
+ xpos, ypos, mode.width, mode.height,
+ flags);
+
+ acquireMonitor(window);
+ }
+ else
+ {
+ HWND after;
+ RECT rect = { xpos, ypos, xpos + width, ypos + height };
+ DWORD style = GetWindowLongW(window->win32.handle, GWL_STYLE);
+ UINT flags = SWP_NOACTIVATE | SWP_NOCOPYBITS;
+
+ if (window->decorated)
+ {
+ style &= ~WS_POPUP;
+ style |= getWindowStyle(window);
+ SetWindowLongW(window->win32.handle, GWL_STYLE, style);
+
+ flags |= SWP_FRAMECHANGED;
+ }
+
+ if (window->floating)
+ after = HWND_TOPMOST;
+ else
+ after = HWND_NOTOPMOST;
+
+ AdjustWindowRectEx(&rect, getWindowStyle(window),
+ FALSE, getWindowExStyle(window));
+ SetWindowPos(window->win32.handle, after,
+ rect.left, rect.top,
+ rect.right - rect.left, rect.bottom - rect.top,
+ flags);
+ }
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return window->win32.handle == GetActiveWindow();
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return IsIconic(window->win32.handle);
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return IsWindowVisible(window->win32.handle);
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return IsZoomed(window->win32.handle);
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ MSG msg;
+ HWND handle;
+ _GLFWwindow* window;
+
+ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ if (msg.message == WM_QUIT)
+ {
+ // Treat WM_QUIT as a close on all windows
+ // While GLFW does not itself post WM_QUIT, other processes may post
+ // it to this one, for example Task Manager
+
+ window = _glfw.windowListHead;
+ while (window)
+ {
+ _glfwInputWindowCloseRequest(window);
+ window = window->next;
+ }
+ }
+ else
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ }
+
+ handle = GetActiveWindow();
+ if (handle)
+ {
+ // LSHIFT/RSHIFT fixup (keys tend to "stick" without this fix)
+ // This is the only async event handling in GLFW, but it solves some
+ // nasty problems
+ window = GetPropW(handle, L"GLFW");
+ if (window)
+ {
+ const int mods = getAsyncKeyMods();
+
+ // Get current state of left and right shift keys
+ const int lshiftDown = (GetAsyncKeyState(VK_LSHIFT) >> 15) & 1;
+ const int rshiftDown = (GetAsyncKeyState(VK_RSHIFT) >> 15) & 1;
+
+ // See if this differs from our belief of what has happened
+ // (we only have to check for lost key up events)
+ if (!lshiftDown && window->keys[GLFW_KEY_LEFT_SHIFT] == 1)
+ _glfwInputKey(window, GLFW_KEY_LEFT_SHIFT, 0, GLFW_RELEASE, mods);
+
+ if (!rshiftDown && window->keys[GLFW_KEY_RIGHT_SHIFT] == 1)
+ _glfwInputKey(window, GLFW_KEY_RIGHT_SHIFT, 0, GLFW_RELEASE, mods);
+ }
+ }
+
+ window = _glfw.win32.disabledCursorWindow;
+ if (window)
+ {
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+
+ // NOTE: Re-center the cursor only if it has moved since the last call,
+ // to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
+ if (window->win32.lastCursorPosX != width / 2 ||
+ window->win32.lastCursorPosY != height / 2)
+ {
+ _glfwPlatformSetCursorPos(window, width / 2, height / 2);
+ }
+ }
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ WaitMessage();
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ MsgWaitForMultipleObjects(0, NULL, FALSE, (DWORD) (timeout * 1e3), QS_ALLEVENTS);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ _GLFWwindow* window = _glfw.windowListHead;
+ PostMessage(window->win32.handle, WM_NULL, 0, 0);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ POINT pos;
+
+ if (GetCursorPos(&pos))
+ {
+ ScreenToClient(window->win32.handle, &pos);
+
+ if (xpos)
+ *xpos = pos.x;
+ if (ypos)
+ *ypos = pos.y;
+ }
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double xpos, double ypos)
+{
+ POINT pos = { (int) xpos, (int) ypos };
+
+ // Store the new position so it can be recognized later
+ window->win32.lastCursorPosX = pos.x;
+ window->win32.lastCursorPosY = pos.y;
+
+ ClientToScreen(window->win32.handle, &pos);
+ SetCursorPos(pos.x, pos.y);
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (mode == GLFW_CURSOR_DISABLED)
+ {
+ _glfw.win32.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.win32.restoreCursorPosX,
+ &_glfw.win32.restoreCursorPosY);
+ centerCursor(window);
+ updateClipRect(window);
+ }
+ else if (_glfw.win32.disabledCursorWindow == window)
+ {
+ _glfw.win32.disabledCursorWindow = NULL;
+ updateClipRect(NULL);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.win32.restoreCursorPosX,
+ _glfw.win32.restoreCursorPosY);
+ }
+
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+const char* _glfwPlatformGetKeyName(int key, int scancode)
+{
+ WCHAR name[16];
+
+ if (key != GLFW_KEY_UNKNOWN)
+ scancode = _glfw.win32.nativeKeys[key];
+
+ if (!_glfwIsPrintable(_glfw.win32.publicKeys[scancode]))
+ return NULL;
+
+ if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR)))
+ return NULL;
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, name, -1,
+ _glfw.win32.keyName,
+ sizeof(_glfw.win32.keyName),
+ NULL, NULL))
+ {
+ return NULL;
+ }
+
+ return _glfw.win32.keyName;
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
+ if (!cursor->win32.handle)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ cursor->win32.handle =
+ CopyCursor(LoadCursorW(NULL, translateCursorShape(shape)));
+ if (!cursor->win32.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create standard cursor");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->win32.handle)
+ DestroyIcon((HICON) cursor->win32.handle);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (cursorInClientArea(window))
+ updateCursorImage(window);
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ int characterCount;
+ HANDLE object;
+ WCHAR* buffer;
+
+ characterCount = MultiByteToWideChar(CP_UTF8, 0, string, -1, NULL, 0);
+ if (!characterCount)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert clipboard string to UTF-16");
+ return;
+ }
+
+ object = GlobalAlloc(GMEM_MOVEABLE, characterCount * sizeof(WCHAR));
+ if (!object)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to allocate global handle for clipboard");
+ return;
+ }
+
+ buffer = GlobalLock(object);
+ if (!buffer)
+ {
+ GlobalFree(object);
+
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");
+ return;
+ }
+
+ MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
+ GlobalUnlock(object);
+
+ if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+ {
+ GlobalFree(object);
+
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
+ return;
+ }
+
+ EmptyClipboard();
+ SetClipboardData(CF_UNICODETEXT, object);
+ CloseClipboard();
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ HANDLE object;
+ WCHAR* buffer;
+
+ if (!OpenClipboard(_glfw.win32.helperWindowHandle))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to open clipboard");
+ return NULL;
+ }
+
+ object = GetClipboardData(CF_UNICODETEXT);
+ if (!object)
+ {
+ CloseClipboard();
+
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "Win32: Failed to convert clipboard to string");
+ return NULL;
+ }
+
+ buffer = GlobalLock(object);
+ if (!buffer)
+ {
+ CloseClipboard();
+
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to lock global handle");
+ return NULL;
+ }
+
+ free(_glfw.win32.clipboardString);
+ _glfw.win32.clipboardString =
+ _glfwCreateUTF8FromWideStringWin32(buffer);
+
+ GlobalUnlock(object);
+ CloseClipboard();
+
+ if (!_glfw.win32.clipboardString)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert wide string to UTF-8");
+ return NULL;
+ }
+
+ return _glfw.win32.clipboardString;
+}
+
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
+{
+ char** extensions;
+
+ *count = 0;
+
+ if (!_glfw.vk.KHR_win32_surface)
+ return NULL;
+
+ extensions = calloc(2, sizeof(char*));
+ extensions[0] = strdup("VK_KHR_surface");
+ extensions[1] = strdup("VK_KHR_win32_surface");
+
+ *count = 2;
+ return extensions;
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR vkGetPhysicalDeviceWin32PresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWin32PresentationSupportKHR");
+ if (!vkGetPhysicalDeviceWin32PresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceWin32PresentationSupportKHR(device, queuefamily);
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ VkResult err;
+ VkWin32SurfaceCreateInfoKHR sci;
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR;
+
+ vkCreateWin32SurfaceKHR = (PFN_vkCreateWin32SurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateWin32SurfaceKHR");
+ if (!vkCreateWin32SurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Win32: Vulkan instance missing VK_KHR_win32_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ sci.hinstance = GetModuleHandle(NULL);
+ sci.hwnd = window->win32.handle;
+
+ err = vkCreateWin32SurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW 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-3.2.1/src/window.c b/glfw-3.2.1/src/window.c
new file mode 100644
index 0000000..5e74e6e
--- /dev/null
+++ b/glfw-3.2.1/src/window.c
@@ -0,0 +1,904 @@
+//========================================================================
+// GLFW 3.2 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <float.h>
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW event API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused)
+{
+ if (focused)
+ {
+ if (window->callbacks.focus)
+ window->callbacks.focus((GLFWwindow*) window, focused);
+ }
+ else
+ {
+ int i;
+
+ if (window->callbacks.focus)
+ window->callbacks.focus((GLFWwindow*) window, focused);
+
+ // Release all pressed keyboard keys
+ for (i = 0; i <= GLFW_KEY_LAST; i++)
+ {
+ if (window->keys[i] == GLFW_PRESS)
+ _glfwInputKey(window, i, 0, GLFW_RELEASE, 0);
+ }
+
+ // Release all pressed mouse buttons
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
+ {
+ if (window->mouseButtons[i] == GLFW_PRESS)
+ _glfwInputMouseClick(window, i, GLFW_RELEASE, 0);
+ }
+ }
+}
+
+void _glfwInputWindowPos(_GLFWwindow* window, int x, int y)
+{
+ if (window->callbacks.pos)
+ window->callbacks.pos((GLFWwindow*) window, x, y);
+}
+
+void _glfwInputWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->callbacks.size)
+ window->callbacks.size((GLFWwindow*) window, width, height);
+}
+
+void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified)
+{
+ if (window->callbacks.iconify)
+ window->callbacks.iconify((GLFWwindow*) window, iconified);
+}
+
+void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->callbacks.fbsize)
+ window->callbacks.fbsize((GLFWwindow*) window, width, height);
+}
+
+void _glfwInputWindowDamage(_GLFWwindow* window)
+{
+ if (window->callbacks.refresh)
+ window->callbacks.refresh((GLFWwindow*) window);
+}
+
+void _glfwInputWindowCloseRequest(_GLFWwindow* window)
+{
+ window->closed = GLFW_TRUE;
+
+ if (window->callbacks.close)
+ window->callbacks.close((GLFWwindow*) window);
+}
+
+void _glfwInputWindowMonitorChange(_GLFWwindow* window, _GLFWmonitor* monitor)
+{
+ window->monitor = monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW public API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height,
+ const char* title,
+ GLFWmonitor* monitor,
+ GLFWwindow* share)
+{
+ _GLFWfbconfig fbconfig;
+ _GLFWctxconfig ctxconfig;
+ _GLFWwndconfig wndconfig;
+ _GLFWwindow* window;
+ _GLFWwindow* previous;
+
+ assert(title != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+
+ if (width <= 0 || height <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window size %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 (ctxconfig.share)
+ {
+ if (ctxconfig.client == GLFW_NO_API ||
+ ctxconfig.share->context.client == GLFW_NO_API)
+ {
+ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
+ return NULL;
+ }
+ }
+
+ 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->cursorMode = GLFW_CURSOR_NORMAL;
+
+ window->minwidth = GLFW_DONT_CARE;
+ window->minheight = GLFW_DONT_CARE;
+ window->maxwidth = GLFW_DONT_CARE;
+ window->maxheight = GLFW_DONT_CARE;
+ window->numer = GLFW_DONT_CARE;
+ window->denom = GLFW_DONT_CARE;
+
+ // Save the currently current context so it can be restored later
+ previous = _glfwPlatformGetCurrentContext();
+ if (ctxconfig.client != GLFW_NO_API)
+ glfwMakeContextCurrent(NULL);
+
+ // Open the actual window and create its context
+ if (!_glfwPlatformCreateWindow(window, &wndconfig, &ctxconfig, &fbconfig))
+ {
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ glfwDestroyWindow((GLFWwindow*) window);
+ return NULL;
+ }
+
+ if (ctxconfig.client != GLFW_NO_API)
+ {
+ window->context.makeCurrent(window);
+
+ // Retrieve the actual (as opposed to requested) context attributes
+ if (!_glfwRefreshContextAttribs(&ctxconfig))
+ {
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ glfwDestroyWindow((GLFWwindow*) window);
+ return NULL;
+ }
+
+ // Restore the previously current context (or NULL)
+ glfwMakeContextCurrent((GLFWwindow*) previous);
+ }
+
+ if (!window->monitor)
+ {
+ if (wndconfig.visible)
+ {
+ _glfwPlatformShowWindow(window);
+ if (wndconfig.focused)
+ _glfwPlatformFocusWindow(window);
+ }
+ }
+
+ return (GLFWwindow*) window;
+}
+
+void glfwDefaultWindowHints(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ memset(&_glfw.hints, 0, sizeof(_glfw.hints));
+
+ // The default is OpenGL with minimum version 1.0
+ _glfw.hints.context.client = GLFW_OPENGL_API;
+ _glfw.hints.context.source = GLFW_NATIVE_CONTEXT_API;
+ _glfw.hints.context.major = 1;
+ _glfw.hints.context.minor = 0;
+
+ // The default is a focused, visible, resizable window with decorations
+ _glfw.hints.window.resizable = GLFW_TRUE;
+ _glfw.hints.window.visible = GLFW_TRUE;
+ _glfw.hints.window.decorated = GLFW_TRUE;
+ _glfw.hints.window.focused = GLFW_TRUE;
+ _glfw.hints.window.autoIconify = GLFW_TRUE;
+
+ // The default is 24 bits of color, 24 bits of depth and 8 bits of stencil,
+ // double buffered
+ _glfw.hints.framebuffer.redBits = 8;
+ _glfw.hints.framebuffer.greenBits = 8;
+ _glfw.hints.framebuffer.blueBits = 8;
+ _glfw.hints.framebuffer.alphaBits = 8;
+ _glfw.hints.framebuffer.depthBits = 24;
+ _glfw.hints.framebuffer.stencilBits = 8;
+ _glfw.hints.framebuffer.doublebuffer = GLFW_TRUE;
+
+ // The default is to select the highest available refresh rate
+ _glfw.hints.refreshRate = GLFW_DONT_CARE;
+}
+
+GLFWAPI void glfwWindowHint(int hint, int value)
+{
+ _GLFW_REQUIRE_INIT();
+
+ switch (hint)
+ {
+ case GLFW_RED_BITS:
+ _glfw.hints.framebuffer.redBits = value;
+ break;
+ case GLFW_GREEN_BITS:
+ _glfw.hints.framebuffer.greenBits = value;
+ break;
+ case GLFW_BLUE_BITS:
+ _glfw.hints.framebuffer.blueBits = value;
+ break;
+ case GLFW_ALPHA_BITS:
+ _glfw.hints.framebuffer.alphaBits = value;
+ break;
+ case GLFW_DEPTH_BITS:
+ _glfw.hints.framebuffer.depthBits = value;
+ break;
+ case GLFW_STENCIL_BITS:
+ _glfw.hints.framebuffer.stencilBits = value;
+ break;
+ case GLFW_ACCUM_RED_BITS:
+ _glfw.hints.framebuffer.accumRedBits = value;
+ break;
+ case GLFW_ACCUM_GREEN_BITS:
+ _glfw.hints.framebuffer.accumGreenBits = value;
+ break;
+ case GLFW_ACCUM_BLUE_BITS:
+ _glfw.hints.framebuffer.accumBlueBits = value;
+ break;
+ case GLFW_ACCUM_ALPHA_BITS:
+ _glfw.hints.framebuffer.accumAlphaBits = value;
+ break;
+ case GLFW_AUX_BUFFERS:
+ _glfw.hints.framebuffer.auxBuffers = value;
+ break;
+ case GLFW_STEREO:
+ _glfw.hints.framebuffer.stereo = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_DOUBLEBUFFER:
+ _glfw.hints.framebuffer.doublebuffer = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_SAMPLES:
+ _glfw.hints.framebuffer.samples = value;
+ break;
+ case GLFW_SRGB_CAPABLE:
+ _glfw.hints.framebuffer.sRGB = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_RESIZABLE:
+ _glfw.hints.window.resizable = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_DECORATED:
+ _glfw.hints.window.decorated = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_FOCUSED:
+ _glfw.hints.window.focused = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_AUTO_ICONIFY:
+ _glfw.hints.window.autoIconify = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_FLOATING:
+ _glfw.hints.window.floating = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_MAXIMIZED:
+ _glfw.hints.window.maximized = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_VISIBLE:
+ _glfw.hints.window.visible = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_CLIENT_API:
+ _glfw.hints.context.client = value;
+ break;
+ case GLFW_CONTEXT_CREATION_API:
+ _glfw.hints.context.source = value;
+ break;
+ case GLFW_CONTEXT_VERSION_MAJOR:
+ _glfw.hints.context.major = value;
+ break;
+ case GLFW_CONTEXT_VERSION_MINOR:
+ _glfw.hints.context.minor = value;
+ break;
+ case GLFW_CONTEXT_ROBUSTNESS:
+ _glfw.hints.context.robustness = value;
+ break;
+ case GLFW_OPENGL_FORWARD_COMPAT:
+ _glfw.hints.context.forward = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_OPENGL_DEBUG_CONTEXT:
+ _glfw.hints.context.debug = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_CONTEXT_NO_ERROR:
+ _glfw.hints.context.noerror = value ? GLFW_TRUE : GLFW_FALSE;
+ break;
+ case GLFW_OPENGL_PROFILE:
+ _glfw.hints.context.profile = value;
+ break;
+ case GLFW_CONTEXT_RELEASE_BEHAVIOR:
+ _glfw.hints.context.release = value;
+ break;
+ case GLFW_REFRESH_RATE:
+ _glfw.hints.refreshRate = value;
+ break;
+ default:
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid window hint %i", hint);
+ break;
+ }
+}
+
+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 == _glfwPlatformGetCurrentContext())
+ 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->closed;
+}
+
+GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* handle, int value)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ window->closed = 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);
+
+ _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);
+
+ _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 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();
+ _glfwPlatformMaximizeWindow(window);
+}
+
+GLFWAPI void glfwShowWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (window->monitor)
+ return;
+
+ _glfwPlatformShowWindow(window);
+ _glfwPlatformFocusWindow(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_RESIZABLE:
+ return window->resizable;
+ case GLFW_DECORATED:
+ return window->decorated;
+ case GLFW_FLOATING:
+ return window->floating;
+ 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 %i", attrib);
+ return 0;
+}
+
+GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return (GLFWmonitor*) window->monitor;
+}
+
+GLFWAPI void glfwSetWindowMonitor(GLFWwindow* wh,
+ GLFWmonitor* mh,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ _GLFWwindow* window = (_GLFWwindow*) wh;
+ _GLFWmonitor* monitor = (_GLFWmonitor*) mh;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+
+ if (width <= 0 || height <= 0)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid window size %ix%i",
+ width, height);
+ return;
+ }
+
+ if (refreshRate < 0 && refreshRate != GLFW_DONT_CARE)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE,
+ "Invalid refresh rate %i",
+ refreshRate);
+ return;
+ }
+
+ window->videoMode.width = width;
+ window->videoMode.height = height;
+ window->videoMode.refreshRate = refreshRate;
+
+ _glfwPlatformSetWindowMonitor(window, monitor,
+ xpos, ypos, width, height,
+ refreshRate);
+}
+
+GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* handle, void* pointer)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ assert(window != NULL);
+
+ _GLFW_REQUIRE_INIT();
+ window->userPointer = pointer;
+}
+
+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 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 void glfwPollEvents(void)
+{
+ _GLFW_REQUIRE_INIT();
+ _glfwPlatformPollEvents();
+}
+
+GLFWAPI void glfwWaitEvents(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (!_glfw.windowListHead)
+ return;
+
+ _glfwPlatformWaitEvents();
+}
+
+GLFWAPI void glfwWaitEventsTimeout(double timeout)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (timeout != timeout || timeout < 0.0 || timeout > DBL_MAX)
+ {
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", timeout);
+ return;
+ }
+
+ _glfwPlatformWaitEventsTimeout(timeout);
+}
+
+GLFWAPI void glfwPostEmptyEvent(void)
+{
+ _GLFW_REQUIRE_INIT();
+
+ if (!_glfw.windowListHead)
+ return;
+
+ _glfwPlatformPostEmptyEvent();
+}
+
diff --git a/glfw-3.2.1/src/wl_init.c b/glfw-3.2.1/src/wl_init.c
new file mode 100644
index 0000000..44f7d0c
--- /dev/null
+++ b/glfw-3.2.1/src/wl_init.c
@@ -0,0 +1,658 @@
+//========================================================================
+// GLFW 3.2 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 "internal.h"
+
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <wayland-client.h>
+#include <wayland-cursor.h>
+
+
+static inline int min(int n1, int n2)
+{
+ return n1 < n2 ? n1 : n2;
+}
+
+static void pointerHandleEnter(void* data,
+ struct wl_pointer* pointer,
+ uint32_t serial,
+ struct wl_surface* surface,
+ wl_fixed_t sx,
+ wl_fixed_t sy)
+{
+ _GLFWwindow* window = wl_surface_get_user_data(surface);
+
+ _glfw.wl.pointerSerial = serial;
+ _glfw.wl.pointerFocus = window;
+
+ _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;
+
+ _glfw.wl.pointerSerial = serial;
+ _glfw.wl.pointerFocus = NULL;
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+}
+
+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;
+
+ if (!window)
+ return;
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ return;
+ else
+ {
+ window->wl.cursorPosX = wl_fixed_to_double(sx);
+ window->wl.cursorPosY = wl_fixed_to_double(sy);
+ }
+
+ _glfwInputCursorPos(window,
+ wl_fixed_to_double(sx),
+ wl_fixed_to_double(sy));
+}
+
+static void pointerHandleButton(void* data,
+ struct wl_pointer* wl_pointer,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+ int glfwButton;
+
+ if (!window)
+ return;
+
+ /* 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* wl_pointer,
+ uint32_t time,
+ uint32_t axis,
+ wl_fixed_t value)
+{
+ _GLFWwindow* window = _glfw.wl.pointerFocus;
+ double scroll_factor;
+ double x, y;
+
+ if (!window)
+ return;
+
+ /* 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. */
+ scroll_factor = 1.0/10.0;
+
+ switch (axis)
+ {
+ case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+ x = wl_fixed_to_double(value) * scroll_factor;
+ y = 0.0;
+ break;
+ case WL_POINTER_AXIS_VERTICAL_SCROLL:
+ x = 0.0;
+ y = wl_fixed_to_double(value) * scroll_factor;
+ break;
+ default:
+ break;
+ }
+
+ _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;
+ char* mapStr;
+
+ 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_map_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_map_unref(keymap);
+ return;
+ }
+
+ 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.control_mask =
+ 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Control");
+ _glfw.wl.xkb.alt_mask =
+ 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
+ _glfw.wl.xkb.shift_mask =
+ 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
+ _glfw.wl.xkb.super_mask =
+ 1 << xkb_map_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
+}
+
+static void keyboardHandleEnter(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ struct wl_surface* surface,
+ struct wl_array* keys)
+{
+ _GLFWwindow* window = wl_surface_get_user_data(surface);
+
+ _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.keyboardFocus = NULL;
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+}
+
+static int toGLFWKeyCode(uint32_t key)
+{
+ if (key < sizeof(_glfw.wl.publicKeys) / sizeof(_glfw.wl.publicKeys[0]))
+ return _glfw.wl.publicKeys[key];
+
+ return GLFW_KEY_UNKNOWN;
+}
+
+static void keyboardHandleKey(void* data,
+ struct wl_keyboard* keyboard,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state)
+{
+ uint32_t code, num_syms;
+ long cp;
+ int keyCode;
+ int action;
+ const xkb_keysym_t *syms;
+ _GLFWwindow* window = _glfw.wl.keyboardFocus;
+
+ if (!window)
+ return;
+
+ keyCode = toGLFWKeyCode(key);
+ action = state == WL_KEYBOARD_KEY_STATE_PRESSED
+ ? GLFW_PRESS : GLFW_RELEASE;
+
+ _glfwInputKey(window, keyCode, key, action,
+ _glfw.wl.xkb.modifiers);
+
+ code = key + 8;
+ num_syms = xkb_key_get_syms(_glfw.wl.xkb.state, code, &syms);
+
+ if (num_syms == 1)
+ {
+ cp = _glfwKeySym2Unicode(syms[0]);
+ 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);
+ }
+ }
+}
+
+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;
+
+ 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_DEPRESSED |
+ XKB_STATE_LATCHED);
+ if (mask & _glfw.wl.xkb.control_mask)
+ modifiers |= GLFW_MOD_CONTROL;
+ if (mask & _glfw.wl.xkb.alt_mask)
+ modifiers |= GLFW_MOD_ALT;
+ if (mask & _glfw.wl.xkb.shift_mask)
+ modifiers |= GLFW_MOD_SHIFT;
+ if (mask & _glfw.wl.xkb.super_mask)
+ modifiers |= GLFW_MOD_SUPER;
+ _glfw.wl.xkb.modifiers = modifiers;
+}
+
+static const struct wl_keyboard_listener keyboardListener = {
+ keyboardHandleKeymap,
+ keyboardHandleEnter,
+ keyboardHandleLeave,
+ keyboardHandleKey,
+ keyboardHandleModifiers,
+};
+
+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 const struct wl_seat_listener seatListener = {
+ seatHandleCapabilities
+};
+
+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.wl_compositor_version = min(3, version);
+ _glfw.wl.compositor =
+ wl_registry_bind(registry, name, &wl_compositor_interface,
+ _glfw.wl.wl_compositor_version);
+ }
+ 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.seat =
+ wl_registry_bind(registry, name, &wl_seat_interface, 1);
+ wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL);
+ }
+ }
+ else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0)
+ {
+ _glfw.wl.relativePointerManager =
+ wl_registry_bind(registry, name,
+ &zwp_relative_pointer_manager_v1_interface,
+ 1);
+ }
+ else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0)
+ {
+ _glfw.wl.pointerConstraints =
+ wl_registry_bind(registry, name,
+ &zwp_pointer_constraints_v1_interface,
+ 1);
+ }
+}
+
+static void registryHandleGlobalRemove(void *data,
+ struct wl_registry *registry,
+ uint32_t name)
+{
+}
+
+
+static const struct wl_registry_listener registryListener = {
+ registryHandleGlobal,
+ registryHandleGlobalRemove
+};
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ memset(_glfw.wl.publicKeys, -1, sizeof(_glfw.wl.publicKeys));
+
+ _glfw.wl.publicKeys[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
+ _glfw.wl.publicKeys[KEY_1] = GLFW_KEY_1;
+ _glfw.wl.publicKeys[KEY_2] = GLFW_KEY_2;
+ _glfw.wl.publicKeys[KEY_3] = GLFW_KEY_3;
+ _glfw.wl.publicKeys[KEY_4] = GLFW_KEY_4;
+ _glfw.wl.publicKeys[KEY_5] = GLFW_KEY_5;
+ _glfw.wl.publicKeys[KEY_6] = GLFW_KEY_6;
+ _glfw.wl.publicKeys[KEY_7] = GLFW_KEY_7;
+ _glfw.wl.publicKeys[KEY_8] = GLFW_KEY_8;
+ _glfw.wl.publicKeys[KEY_9] = GLFW_KEY_9;
+ _glfw.wl.publicKeys[KEY_0] = GLFW_KEY_0;
+ _glfw.wl.publicKeys[KEY_MINUS] = GLFW_KEY_MINUS;
+ _glfw.wl.publicKeys[KEY_EQUAL] = GLFW_KEY_EQUAL;
+ _glfw.wl.publicKeys[KEY_Q] = GLFW_KEY_Q;
+ _glfw.wl.publicKeys[KEY_W] = GLFW_KEY_W;
+ _glfw.wl.publicKeys[KEY_E] = GLFW_KEY_E;
+ _glfw.wl.publicKeys[KEY_R] = GLFW_KEY_R;
+ _glfw.wl.publicKeys[KEY_T] = GLFW_KEY_T;
+ _glfw.wl.publicKeys[KEY_Y] = GLFW_KEY_Y;
+ _glfw.wl.publicKeys[KEY_U] = GLFW_KEY_U;
+ _glfw.wl.publicKeys[KEY_I] = GLFW_KEY_I;
+ _glfw.wl.publicKeys[KEY_O] = GLFW_KEY_O;
+ _glfw.wl.publicKeys[KEY_P] = GLFW_KEY_P;
+ _glfw.wl.publicKeys[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
+ _glfw.wl.publicKeys[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
+ _glfw.wl.publicKeys[KEY_A] = GLFW_KEY_A;
+ _glfw.wl.publicKeys[KEY_S] = GLFW_KEY_S;
+ _glfw.wl.publicKeys[KEY_D] = GLFW_KEY_D;
+ _glfw.wl.publicKeys[KEY_F] = GLFW_KEY_F;
+ _glfw.wl.publicKeys[KEY_G] = GLFW_KEY_G;
+ _glfw.wl.publicKeys[KEY_H] = GLFW_KEY_H;
+ _glfw.wl.publicKeys[KEY_J] = GLFW_KEY_J;
+ _glfw.wl.publicKeys[KEY_K] = GLFW_KEY_K;
+ _glfw.wl.publicKeys[KEY_L] = GLFW_KEY_L;
+ _glfw.wl.publicKeys[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
+ _glfw.wl.publicKeys[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
+ _glfw.wl.publicKeys[KEY_Z] = GLFW_KEY_Z;
+ _glfw.wl.publicKeys[KEY_X] = GLFW_KEY_X;
+ _glfw.wl.publicKeys[KEY_C] = GLFW_KEY_C;
+ _glfw.wl.publicKeys[KEY_V] = GLFW_KEY_V;
+ _glfw.wl.publicKeys[KEY_B] = GLFW_KEY_B;
+ _glfw.wl.publicKeys[KEY_N] = GLFW_KEY_N;
+ _glfw.wl.publicKeys[KEY_M] = GLFW_KEY_M;
+ _glfw.wl.publicKeys[KEY_COMMA] = GLFW_KEY_COMMA;
+ _glfw.wl.publicKeys[KEY_DOT] = GLFW_KEY_PERIOD;
+ _glfw.wl.publicKeys[KEY_SLASH] = GLFW_KEY_SLASH;
+ _glfw.wl.publicKeys[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
+ _glfw.wl.publicKeys[KEY_ESC] = GLFW_KEY_ESCAPE;
+ _glfw.wl.publicKeys[KEY_TAB] = GLFW_KEY_TAB;
+ _glfw.wl.publicKeys[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
+ _glfw.wl.publicKeys[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
+ _glfw.wl.publicKeys[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
+ _glfw.wl.publicKeys[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
+ _glfw.wl.publicKeys[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
+ _glfw.wl.publicKeys[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
+ _glfw.wl.publicKeys[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
+ _glfw.wl.publicKeys[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
+ _glfw.wl.publicKeys[KEY_MENU] = GLFW_KEY_MENU;
+ _glfw.wl.publicKeys[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
+ _glfw.wl.publicKeys[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
+ _glfw.wl.publicKeys[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
+ _glfw.wl.publicKeys[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
+ _glfw.wl.publicKeys[KEY_PAUSE] = GLFW_KEY_PAUSE;
+ _glfw.wl.publicKeys[KEY_DELETE] = GLFW_KEY_DELETE;
+ _glfw.wl.publicKeys[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
+ _glfw.wl.publicKeys[KEY_ENTER] = GLFW_KEY_ENTER;
+ _glfw.wl.publicKeys[KEY_HOME] = GLFW_KEY_HOME;
+ _glfw.wl.publicKeys[KEY_END] = GLFW_KEY_END;
+ _glfw.wl.publicKeys[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
+ _glfw.wl.publicKeys[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
+ _glfw.wl.publicKeys[KEY_INSERT] = GLFW_KEY_INSERT;
+ _glfw.wl.publicKeys[KEY_LEFT] = GLFW_KEY_LEFT;
+ _glfw.wl.publicKeys[KEY_RIGHT] = GLFW_KEY_RIGHT;
+ _glfw.wl.publicKeys[KEY_DOWN] = GLFW_KEY_DOWN;
+ _glfw.wl.publicKeys[KEY_UP] = GLFW_KEY_UP;
+ _glfw.wl.publicKeys[KEY_F1] = GLFW_KEY_F1;
+ _glfw.wl.publicKeys[KEY_F2] = GLFW_KEY_F2;
+ _glfw.wl.publicKeys[KEY_F3] = GLFW_KEY_F3;
+ _glfw.wl.publicKeys[KEY_F4] = GLFW_KEY_F4;
+ _glfw.wl.publicKeys[KEY_F5] = GLFW_KEY_F5;
+ _glfw.wl.publicKeys[KEY_F6] = GLFW_KEY_F6;
+ _glfw.wl.publicKeys[KEY_F7] = GLFW_KEY_F7;
+ _glfw.wl.publicKeys[KEY_F8] = GLFW_KEY_F8;
+ _glfw.wl.publicKeys[KEY_F9] = GLFW_KEY_F9;
+ _glfw.wl.publicKeys[KEY_F10] = GLFW_KEY_F10;
+ _glfw.wl.publicKeys[KEY_F11] = GLFW_KEY_F11;
+ _glfw.wl.publicKeys[KEY_F12] = GLFW_KEY_F12;
+ _glfw.wl.publicKeys[KEY_F13] = GLFW_KEY_F13;
+ _glfw.wl.publicKeys[KEY_F14] = GLFW_KEY_F14;
+ _glfw.wl.publicKeys[KEY_F15] = GLFW_KEY_F15;
+ _glfw.wl.publicKeys[KEY_F16] = GLFW_KEY_F16;
+ _glfw.wl.publicKeys[KEY_F17] = GLFW_KEY_F17;
+ _glfw.wl.publicKeys[KEY_F18] = GLFW_KEY_F18;
+ _glfw.wl.publicKeys[KEY_F19] = GLFW_KEY_F19;
+ _glfw.wl.publicKeys[KEY_F20] = GLFW_KEY_F20;
+ _glfw.wl.publicKeys[KEY_F21] = GLFW_KEY_F21;
+ _glfw.wl.publicKeys[KEY_F22] = GLFW_KEY_F22;
+ _glfw.wl.publicKeys[KEY_F23] = GLFW_KEY_F23;
+ _glfw.wl.publicKeys[KEY_F24] = GLFW_KEY_F24;
+ _glfw.wl.publicKeys[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
+ _glfw.wl.publicKeys[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
+ _glfw.wl.publicKeys[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
+ _glfw.wl.publicKeys[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
+ _glfw.wl.publicKeys[KEY_KP0] = GLFW_KEY_KP_0;
+ _glfw.wl.publicKeys[KEY_KP1] = GLFW_KEY_KP_1;
+ _glfw.wl.publicKeys[KEY_KP2] = GLFW_KEY_KP_2;
+ _glfw.wl.publicKeys[KEY_KP3] = GLFW_KEY_KP_3;
+ _glfw.wl.publicKeys[KEY_KP4] = GLFW_KEY_KP_4;
+ _glfw.wl.publicKeys[KEY_KP5] = GLFW_KEY_KP_5;
+ _glfw.wl.publicKeys[KEY_KP6] = GLFW_KEY_KP_6;
+ _glfw.wl.publicKeys[KEY_KP7] = GLFW_KEY_KP_7;
+ _glfw.wl.publicKeys[KEY_KP8] = GLFW_KEY_KP_8;
+ _glfw.wl.publicKeys[KEY_KP9] = GLFW_KEY_KP_9;
+ _glfw.wl.publicKeys[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
+ _glfw.wl.publicKeys[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
+ _glfw.wl.publicKeys[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformInit(void)
+{
+ _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);
+
+ _glfw.wl.monitors = calloc(4, sizeof(_GLFWmonitor*));
+ _glfw.wl.monitorsSize = 4;
+
+ createKeyTables();
+
+ _glfw.wl.xkb.context = xkb_context_new(0);
+ if (!_glfw.wl.xkb.context)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to initialize xkb context");
+ return 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);
+
+ if (!_glfwInitThreadLocalStoragePOSIX())
+ return GLFW_FALSE;
+
+ if (!_glfwInitJoysticksLinux())
+ return GLFW_FALSE;
+
+ _glfwInitTimerPOSIX();
+
+ if (_glfw.wl.pointer && _glfw.wl.shm)
+ {
+ _glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
+ if (!_glfw.wl.cursorTheme)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unable to load default cursor theme\n");
+ return GLFW_FALSE;
+ }
+ _glfw.wl.cursorSurface =
+ wl_compositor_create_surface(_glfw.wl.compositor);
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ _glfwTerminateEGL();
+ _glfwTerminateJoysticksLinux();
+ _glfwTerminateThreadLocalStoragePOSIX();
+
+ if (_glfw.wl.cursorTheme)
+ wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
+ if (_glfw.wl.cursorSurface)
+ wl_surface_destroy(_glfw.wl.cursorSurface);
+ if (_glfw.wl.registry)
+ wl_registry_destroy(_glfw.wl.registry);
+ if (_glfw.wl.display)
+ wl_display_flush(_glfw.wl.display);
+ if (_glfw.wl.display)
+ wl_display_disconnect(_glfw.wl.display);
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " Wayland EGL"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#else
+ " gettimeofday"
+#endif
+#if defined(__linux__)
+ " /dev/js"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+}
+
diff --git a/glfw-3.2.1/src/wl_monitor.c b/glfw-3.2.1/src/wl_monitor.c
new file mode 100644
index 0000000..27731c2
--- /dev/null
+++ b/glfw-3.2.1/src/wl_monitor.c
@@ -0,0 +1,269 @@
+//========================================================================
+// GLFW 3.2 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 "internal.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+
+struct _GLFWvidmodeWayland
+{
+ GLFWvidmode base;
+ uint32_t flags;
+};
+
+static void geometry(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;
+
+ monitor->wl.x = x;
+ monitor->wl.y = y;
+ monitor->widthMM = physicalWidth;
+ monitor->heightMM = physicalHeight;
+}
+
+static void mode(void* data,
+ struct wl_output* output,
+ uint32_t flags,
+ int32_t width,
+ int32_t height,
+ int32_t refresh)
+{
+ struct _GLFWmonitor *monitor = data;
+ _GLFWvidmodeWayland mode = { { 0 }, };
+
+ mode.base.width = width;
+ mode.base.height = height;
+ mode.base.refreshRate = refresh / 1000;
+ mode.flags = flags;
+
+ if (monitor->wl.modesCount + 1 >= monitor->wl.modesSize)
+ {
+ int size = monitor->wl.modesSize * 2;
+ _GLFWvidmodeWayland* modes =
+ realloc(monitor->wl.modes,
+ size * sizeof(_GLFWvidmodeWayland));
+ monitor->wl.modes = modes;
+ monitor->wl.modesSize = size;
+ }
+
+ monitor->wl.modes[monitor->wl.modesCount++] = mode;
+}
+
+static void done(void* data,
+ struct wl_output* output)
+{
+ struct _GLFWmonitor *monitor = data;
+
+ monitor->wl.done = GLFW_TRUE;
+}
+
+static void scale(void* data,
+ struct wl_output* output,
+ int32_t factor)
+{
+ struct _GLFWmonitor *monitor = data;
+
+ monitor->wl.scale = factor;
+}
+
+static const struct wl_output_listener output_listener = {
+ geometry,
+ mode,
+ done,
+ scale,
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version)
+{
+ _GLFWmonitor *monitor;
+ struct wl_output *output;
+ char name_str[80];
+
+ memset(name_str, 0, sizeof(name_str));
+ snprintf(name_str, 79, "wl_output@%u", name);
+
+ if (version < 2)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Unsupported output interface version");
+ return;
+ }
+
+ monitor = _glfwAllocMonitor(name_str, 0, 0);
+
+ output = wl_registry_bind(_glfw.wl.registry,
+ name,
+ &wl_output_interface,
+ 2);
+ if (!output)
+ {
+ _glfwFreeMonitor(monitor);
+ return;
+ }
+
+ monitor->wl.modes = calloc(4, sizeof(_GLFWvidmodeWayland));
+ monitor->wl.modesSize = 4;
+
+ monitor->wl.scale = 1;
+
+ monitor->wl.output = output;
+ wl_output_add_listener(output, &output_listener, monitor);
+
+ if (_glfw.wl.monitorsCount + 1 >= _glfw.wl.monitorsSize)
+ {
+ _GLFWmonitor** monitors = _glfw.wl.monitors;
+ int size = _glfw.wl.monitorsSize * 2;
+
+ monitors = realloc(monitors, size * sizeof(_GLFWmonitor*));
+
+ _glfw.wl.monitors = monitors;
+ _glfw.wl.monitorsSize = size;
+ }
+
+ _glfw.wl.monitors[_glfw.wl.monitorsCount++] = monitor;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ _GLFWmonitor** monitors;
+ _GLFWmonitor* monitor;
+ int i, monitorsCount = _glfw.wl.monitorsCount;
+
+ if (_glfw.wl.monitorsCount == 0)
+ goto err;
+
+ monitors = calloc(monitorsCount, sizeof(_GLFWmonitor*));
+
+ for (i = 0; i < monitorsCount; i++)
+ {
+ _GLFWmonitor* origMonitor = _glfw.wl.monitors[i];
+ monitor = calloc(1, sizeof(_GLFWmonitor));
+
+ monitor->modes =
+ _glfwPlatformGetVideoModes(origMonitor,
+ &origMonitor->wl.modesCount);
+ *monitor = *_glfw.wl.monitors[i];
+ monitors[i] = monitor;
+ }
+
+ *count = monitorsCount;
+ return monitors;
+
+err:
+ *count = 0;
+ return NULL;
+}
+
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ return first->wl.output == second->wl.output;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (xpos)
+ *xpos = monitor->wl.x;
+ if (ypos)
+ *ypos = monitor->wl.y;
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* found)
+{
+ GLFWvidmode *modes;
+ int i, modesCount = monitor->wl.modesCount;
+
+ modes = calloc(modesCount, sizeof(GLFWvidmode));
+
+ for (i = 0; i < modesCount; i++)
+ modes[i] = monitor->wl.modes[i].base;
+
+ *found = modesCount;
+ return modes;
+}
+
+void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
+{
+ int i;
+
+ for (i = 0; i < monitor->wl.modesCount; i++)
+ {
+ if (monitor->wl.modes[i].flags & WL_OUTPUT_MODE_CURRENT)
+ {
+ *mode = monitor->wl.modes[i].base;
+ return;
+ }
+ }
+}
+
+void _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Gamma ramp getting not supported yet");
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Gamma ramp setting not supported yet");
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* handle)
+{
+ _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return monitor->wl.output;
+}
+
diff --git a/glfw-3.2.1/src/wl_platform.h b/glfw-3.2.1/src/wl_platform.h
new file mode 100644
index 0000000..9e42b36
--- /dev/null
+++ b/glfw-3.2.1/src/wl_platform.h
@@ -0,0 +1,179 @@
+//========================================================================
+// GLFW 3.2 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.
+//
+//========================================================================
+
+#ifndef _glfw3_wayland_platform_h_
+#define _glfw3_wayland_platform_h_
+
+#include <wayland-client.h>
+#include <xkbcommon/xkbcommon.h>
+#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_tls.h"
+#include "posix_time.h"
+#include "linux_joystick.h"
+#include "xkb_unicode.h"
+#include "egl_context.h"
+
+#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
+#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->wl.native)
+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.wl.display)
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWayland wl
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWayland wl
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWayland wl
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWayland wl
+
+#define _GLFW_PLATFORM_CONTEXT_STATE
+#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
+
+
+// Wayland-specific video mode data
+//
+typedef struct _GLFWvidmodeWayland _GLFWvidmodeWayland;
+
+// Wayland-specific per-window data
+//
+typedef struct _GLFWwindowWayland
+{
+ int width, height;
+ GLFWbool visible;
+ GLFWbool maximized;
+ struct wl_surface* surface;
+ struct wl_egl_window* native;
+ struct wl_shell_surface* shell_surface;
+ struct wl_callback* callback;
+
+ _GLFWcursor* currentCursor;
+ double cursorPosX, cursorPosY;
+
+ char* title;
+
+ // We need to track the monitors the window spans on to calculate the
+ // optimal scaling factor.
+ int scale;
+ _GLFWmonitor** monitors;
+ int monitorsCount;
+ int monitorsSize;
+
+ struct {
+ struct zwp_relative_pointer_v1* relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer;
+ } pointerLock;
+} _GLFWwindowWayland;
+
+// Wayland-specific global data
+//
+typedef struct _GLFWlibraryWayland
+{
+ struct wl_display* display;
+ struct wl_registry* registry;
+ struct wl_compositor* compositor;
+ struct wl_shell* shell;
+ struct wl_shm* shm;
+ struct wl_seat* seat;
+ struct wl_pointer* pointer;
+ struct wl_keyboard* keyboard;
+ struct zwp_relative_pointer_manager_v1* relativePointerManager;
+ struct zwp_pointer_constraints_v1* pointerConstraints;
+
+ int wl_compositor_version;
+
+ struct wl_cursor_theme* cursorTheme;
+ struct wl_surface* cursorSurface;
+ uint32_t pointerSerial;
+
+ _GLFWmonitor** monitors;
+ int monitorsCount;
+ int monitorsSize;
+
+ short int publicKeys[256];
+
+ struct {
+ struct xkb_context* context;
+ struct xkb_keymap* keymap;
+ struct xkb_state* state;
+ xkb_mod_mask_t control_mask;
+ xkb_mod_mask_t alt_mask;
+ xkb_mod_mask_t shift_mask;
+ xkb_mod_mask_t super_mask;
+ unsigned int modifiers;
+ } xkb;
+
+ _GLFWwindow* pointerFocus;
+ _GLFWwindow* keyboardFocus;
+
+} _GLFWlibraryWayland;
+
+// Wayland-specific per-monitor data
+//
+typedef struct _GLFWmonitorWayland
+{
+ struct wl_output* output;
+
+ _GLFWvidmodeWayland* modes;
+ int modesCount;
+ int modesSize;
+ GLFWbool done;
+
+ int x;
+ int y;
+ int scale;
+} _GLFWmonitorWayland;
+
+// Wayland-specific per-cursor data
+//
+typedef struct _GLFWcursorWayland
+{
+ struct wl_cursor_image* image;
+ struct wl_buffer* buffer;
+ int width, height;
+ int xhot, yhot;
+} _GLFWcursorWayland;
+
+
+void _glfwAddOutputWayland(uint32_t name, uint32_t version);
+
+#endif // _glfw3_wayland_platform_h_
diff --git a/glfw-3.2.1/src/wl_window.c b/glfw-3.2.1/src/wl_window.c
new file mode 100644
index 0000000..cf75ec8
--- /dev/null
+++ b/glfw-3.2.1/src/wl_window.c
@@ -0,0 +1,1050 @@
+//========================================================================
+// GLFW 3.2 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.
+//
+//========================================================================
+
+#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 <poll.h>
+
+#include <wayland-egl.h>
+#include <wayland-cursor.h>
+
+
+static void handlePing(void* data,
+ struct wl_shell_surface* shellSurface,
+ uint32_t serial)
+{
+ wl_shell_surface_pong(shellSurface, serial);
+}
+
+static void handleConfigure(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 (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 handlePopupDone(void* data,
+ struct wl_shell_surface* shellSurface)
+{
+}
+
+static const struct wl_shell_surface_listener shellSurfaceListener = {
+ handlePing,
+ handleConfigure,
+ handlePopupDone
+};
+
+static void checkScaleChange(_GLFWwindow* window)
+{
+ int scaledWidth, scaledHeight;
+ int scale = 1;
+ int i;
+ int monitorScale;
+
+ // Check if we will be able to set the buffer scale or not.
+ if (_glfw.wl.wl_compositor_version < 3)
+ return;
+
+ // Get the scale factor from the highest scale monitor.
+ for (i = 0; i < window->wl.monitorsCount; ++i)
+ {
+ monitorScale = window->wl.monitors[i]->wl.scale;
+ if (scale < monitorScale)
+ scale = monitorScale;
+ }
+
+ // Only change the framebuffer size if the scale changed.
+ if (scale != window->wl.scale)
+ {
+ window->wl.scale = scale;
+ scaledWidth = window->wl.width * scale;
+ scaledHeight = window->wl.height * scale;
+ wl_surface_set_buffer_scale(window->wl.surface, scale);
+ wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
+ _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
+ }
+}
+
+static void handleEnter(void *data,
+ struct wl_surface *surface,
+ struct wl_output *output)
+{
+ _GLFWwindow* window = data;
+ _GLFWmonitor* monitor = wl_output_get_user_data(output);
+
+ if (window->wl.monitorsCount + 1 > window->wl.monitorsSize)
+ {
+ ++window->wl.monitorsSize;
+ window->wl.monitors =
+ realloc(window->wl.monitors,
+ window->wl.monitorsSize * sizeof(_GLFWmonitor*));
+ }
+
+ window->wl.monitors[window->wl.monitorsCount++] = monitor;
+
+ checkScaleChange(window);
+}
+
+static void handleLeave(void *data,
+ struct wl_surface *surface,
+ struct wl_output *output)
+{
+ _GLFWwindow* window = data;
+ _GLFWmonitor* monitor = wl_output_get_user_data(output);
+ GLFWbool found;
+ int i;
+
+ for (i = 0, found = GLFW_FALSE; i < window->wl.monitorsCount - 1; ++i)
+ {
+ if (monitor == window->wl.monitors[i])
+ found = GLFW_TRUE;
+ if (found)
+ window->wl.monitors[i] = window->wl.monitors[i + 1];
+ }
+ window->wl.monitors[--window->wl.monitorsCount] = NULL;
+
+ checkScaleChange(window);
+}
+
+static const struct wl_surface_listener surfaceListener = {
+ handleEnter,
+ handleLeave
+};
+
+// Makes the surface considered as XRGB instead of ARGB.
+static void setOpaqueRegion(_GLFWwindow* window)
+{
+ struct wl_region* region;
+
+ region = wl_compositor_create_region(_glfw.wl.compositor);
+ if (!region)
+ return;
+
+ wl_region_add(region, 0, 0, window->wl.width, window->wl.height);
+ wl_surface_set_opaque_region(window->wl.surface, region);
+ wl_surface_commit(window->wl.surface);
+ wl_region_destroy(region);
+}
+
+static GLFWbool createSurface(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig)
+{
+ window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor);
+ if (!window->wl.surface)
+ return 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;
+
+ // TODO: make this optional once issue #197 is fixed.
+ setOpaqueRegion(window);
+
+ return GLFW_TRUE;
+}
+
+static GLFWbool createShellSurface(_GLFWwindow* window)
+{
+ window->wl.shell_surface = wl_shell_get_shell_surface(_glfw.wl.shell,
+ window->wl.surface);
+ if (!window->wl.shell_surface)
+ return GLFW_FALSE;
+
+ wl_shell_surface_add_listener(window->wl.shell_surface,
+ &shellSurfaceListener,
+ window);
+
+ if (window->wl.title)
+ wl_shell_surface_set_title(window->wl.shell_surface, window->wl.title);
+
+ if (window->monitor)
+ {
+ wl_shell_surface_set_fullscreen(
+ window->wl.shell_surface,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ 0,
+ window->monitor->wl.output);
+ }
+ else if (window->wl.maximized)
+ {
+ wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
+ }
+ else
+ {
+ wl_shell_surface_set_toplevel(window->wl.shell_surface);
+ }
+
+ return GLFW_TRUE;
+}
+
+static int
+createTmpfileCloexec(char* tmpname)
+{
+ int fd;
+
+ fd = mkostemp(tmpname, O_CLOEXEC);
+ if (fd >= 0)
+ unlink(tmpname);
+
+ return fd;
+}
+
+static void
+handleEvents(int timeout)
+{
+ struct wl_display* display = _glfw.wl.display;
+ struct pollfd fds[] = {
+ { wl_display_get_fd(display), POLLIN },
+ };
+
+ while (wl_display_prepare_read(display) != 0)
+ wl_display_dispatch_pending(display);
+
+ // If an error different from EAGAIN happens, we have likely been
+ // disconnected from the Wayland session, try to handle that the best we
+ // can.
+ if (wl_display_flush(display) < 0 && errno != EAGAIN)
+ {
+ _GLFWwindow* window = _glfw.windowListHead;
+ while (window)
+ {
+ _glfwInputWindowCloseRequest(window);
+ window = window->next;
+ }
+ wl_display_cancel_read(display);
+ return;
+ }
+
+ if (poll(fds, 1, timeout) > 0)
+ {
+ wl_display_read_events(display);
+ wl_display_dispatch_pending(display);
+ }
+ else
+ {
+ wl_display_cancel_read(display);
+ }
+}
+
+/*
+ * Create a new, unique, anonymous file of the given size, and
+ * return the file descriptor for it. The file descriptor is set
+ * 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 insufficent, errno
+ * is set to ENOSPC. If posix_fallocate() is not supported, program may
+ * receive SIGBUS on accessing mmap()'ed file contents instead.
+ */
+int
+createAnonymousFile(off_t size)
+{
+ static const char template[] = "/glfw-shared-XXXXXX";
+ const char* path;
+ char* name;
+ int fd;
+ int ret;
+
+ 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;
+ ret = posix_fallocate(fd, 0, size);
+ if (ret != 0)
+ {
+ close(fd);
+ errno = ret;
+ return -1;
+ }
+ return fd;
+}
+
+// Translates a GLFW standard cursor to a theme cursor name
+//
+static char *translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return "left_ptr";
+ case GLFW_IBEAM_CURSOR:
+ return "xterm";
+ case GLFW_CROSSHAIR_CURSOR:
+ return "crosshair";
+ case GLFW_HAND_CURSOR:
+ return "grabbing";
+ case GLFW_HRESIZE_CURSOR:
+ return "sb_h_double_arrow";
+ case GLFW_VRESIZE_CURSOR:
+ return "sb_v_double_arrow";
+ }
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ if (!createSurface(window, wndconfig))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+
+ if (wndconfig->title)
+ window->wl.title = strdup(wndconfig->title);
+
+ if (wndconfig->visible)
+ {
+ if (!createShellSurface(window))
+ return GLFW_FALSE;
+
+ window->wl.visible = GLFW_TRUE;
+ }
+ else
+ {
+ window->wl.shell_surface = 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->context.destroy)
+ window->context.destroy(window);
+
+ if (window->wl.native)
+ wl_egl_window_destroy(window->wl.native);
+
+ if (window->wl.shell_surface)
+ wl_shell_surface_destroy(window->wl.shell_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 = strdup(title);
+ if (window->wl.shell_surface)
+ wl_shell_surface_set_title(window->wl.shell_surface, title);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Setting window icon not supported");
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ // A Wayland client is not aware of its position, so just warn and leave it
+ // 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)
+{
+ int scaledWidth = width * window->wl.scale;
+ int scaledHeight = height * window->wl.scale;
+ window->wl.width = width;
+ window->wl.height = height;
+ wl_egl_window_resize(window->wl.native, scaledWidth, scaledHeight, 0, 0);
+ setOpaqueRegion(window);
+ _glfwInputFramebufferSize(window, scaledWidth, scaledHeight);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ // TODO: find out how to trigger a resize.
+ // The actual limits are checked in the wl_shell_surface::configure handler.
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ // TODO: find out how to trigger a resize.
+ // The actual limits are checked in the wl_shell_surface::configure handler.
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+ *width *= window->wl.scale;
+ *height *= window->wl.scale;
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ // TODO: will need a proper implementation once decorations are
+ // implemented, but for now just leave everything as 0.
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ // TODO: move to xdg_shell instead of wl_shell.
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Iconify window not supported");
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ // TODO: also do the same for iconified.
+ if (window->monitor || window->wl.maximized)
+ {
+ if (window->wl.shell_surface)
+ wl_shell_surface_set_toplevel(window->wl.shell_surface);
+
+ window->wl.maximized = GLFW_FALSE;
+ }
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (!window->monitor && !window->wl.maximized)
+ {
+ if (window->wl.shell_surface)
+ {
+ // Let the compositor select the best output.
+ wl_shell_surface_set_maximized(window->wl.shell_surface, NULL);
+ }
+ window->wl.maximized = GLFW_TRUE;
+ }
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ if (!window->monitor)
+ {
+ if (!window->wl.shell_surface)
+ createShellSurface(window);
+ window->wl.visible = GLFW_TRUE;
+ }
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ if (!window->monitor)
+ {
+ if (window->wl.shell_surface)
+ wl_shell_surface_destroy(window->wl.shell_surface);
+ window->wl.visible = GLFW_FALSE;
+ }
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Focusing a window requires user interaction");
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (monitor)
+ {
+ wl_shell_surface_set_fullscreen(
+ window->wl.shell_surface,
+ WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
+ refreshRate * 1000, // Convert Hz to mHz.
+ monitor->wl.output);
+ }
+ else
+ {
+ wl_shell_surface_set_toplevel(window->wl.shell_surface);
+ }
+ _glfwInputWindowMonitorChange(window, monitor);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ return _glfw.wl.keyboardFocus == window;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ // TODO: move to xdg_shell, wl_shell doesn't have any iconified concept.
+ return GLFW_FALSE;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ return window->wl.visible;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ return window->wl.maximized;
+}
+
+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* _glfwPlatformGetKeyName(int key, int scancode)
+{
+ // TODO
+ return NULL;
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ struct wl_shm_pool* pool;
+ 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 GLFW_FALSE;
+ }
+
+ data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Cursor mmap failed: %m");
+ close(fd);
+ return GLFW_FALSE;
+ }
+
+ 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;
+ }
+
+ cursor->wl.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);
+
+ 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.image = standardCursor->images[0];
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ // If it's a standard cursor we don't need to do anything here
+ if (cursor->wl.image)
+ return;
+
+ if (cursor->wl.buffer)
+ wl_buffer_destroy(cursor->wl.buffer);
+}
+
+static void handleRelativeMotion(void* data,
+ struct zwp_relative_pointer_v1* pointer,
+ uint32_t timeHi,
+ uint32_t timeLo,
+ wl_fixed_t dx,
+ wl_fixed_t dy,
+ wl_fixed_t dxUnaccel,
+ wl_fixed_t dyUnaccel)
+{
+ _GLFWwindow* window = data;
+
+ if (window->cursorMode != GLFW_CURSOR_DISABLED)
+ return;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + wl_fixed_to_double(dxUnaccel),
+ window->virtualCursorPosY + wl_fixed_to_double(dyUnaccel));
+}
+
+static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
+ handleRelativeMotion
+};
+
+static void handleLocked(void* data,
+ struct zwp_locked_pointer_v1* lockedPointer)
+{
+}
+
+static void unlockPointer(_GLFWwindow* window)
+{
+ struct zwp_relative_pointer_v1* relativePointer =
+ window->wl.pointerLock.relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer =
+ window->wl.pointerLock.lockedPointer;
+
+ zwp_relative_pointer_v1_destroy(relativePointer);
+ zwp_locked_pointer_v1_destroy(lockedPointer);
+
+ window->wl.pointerLock.relativePointer = NULL;
+ window->wl.pointerLock.lockedPointer = NULL;
+}
+
+static void lockPointer(_GLFWwindow* window);
+
+static void handleUnlocked(void* data,
+ struct zwp_locked_pointer_v1* lockedPointer)
+{
+}
+
+static const struct zwp_locked_pointer_v1_listener lockedPointerListener = {
+ handleLocked,
+ handleUnlocked
+};
+
+static void lockPointer(_GLFWwindow* window)
+{
+ struct zwp_relative_pointer_v1* relativePointer;
+ struct zwp_locked_pointer_v1* lockedPointer;
+
+ if (!_glfw.wl.relativePointerManager)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: no relative pointer manager");
+ return;
+ }
+
+ relativePointer =
+ zwp_relative_pointer_manager_v1_get_relative_pointer(
+ _glfw.wl.relativePointerManager,
+ _glfw.wl.pointer);
+ zwp_relative_pointer_v1_add_listener(relativePointer,
+ &relativePointerListener,
+ window);
+
+ lockedPointer =
+ zwp_pointer_constraints_v1_lock_pointer(
+ _glfw.wl.pointerConstraints,
+ window->wl.surface,
+ _glfw.wl.pointer,
+ NULL,
+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ zwp_locked_pointer_v1_add_listener(lockedPointer,
+ &lockedPointerListener,
+ window);
+
+ window->wl.pointerLock.relativePointer = relativePointer;
+ window->wl.pointerLock.lockedPointer = lockedPointer;
+
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
+ NULL, 0, 0);
+}
+
+static GLFWbool isPointerLocked(_GLFWwindow* window)
+{
+ return window->wl.pointerLock.lockedPointer != NULL;
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ struct wl_buffer* buffer;
+ struct wl_cursor* defaultCursor;
+ struct wl_cursor_image* image;
+ struct wl_surface* surface = _glfw.wl.cursorSurface;
+
+ 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)
+ 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)
+ image = cursor->wl.image;
+ else
+ {
+ defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
+ "left_ptr");
+ if (!defaultCursor)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Standard cursor not found");
+ return;
+ }
+ image = defaultCursor->images[0];
+ }
+
+ if (image)
+ {
+ buffer = wl_cursor_image_get_buffer(image);
+ if (!buffer)
+ return;
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
+ surface,
+ image->hotspot_x,
+ image->hotspot_y);
+ wl_surface_attach(surface, buffer, 0, 0);
+ wl_surface_damage(surface, 0, 0,
+ image->width, image->height);
+ wl_surface_commit(surface);
+ }
+ else
+ {
+ wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
+ surface,
+ cursor->wl.xhot,
+ cursor->wl.yhot);
+ wl_surface_attach(surface, cursor->wl.buffer, 0, 0);
+ wl_surface_damage(surface, 0, 0,
+ cursor->wl.width, cursor->wl.height);
+ wl_surface_commit(surface);
+ }
+ }
+ 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.pointerSerial,
+ NULL, 0, 0);
+ }
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Clipboard setting not implemented yet");
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ // TODO
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Clipboard getting not implemented yet");
+ return NULL;
+}
+
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
+{
+ char** extensions;
+
+ *count = 0;
+
+ if (!_glfw.vk.KHR_wayland_surface)
+ return NULL;
+
+ extensions = calloc(2, sizeof(char*));
+ extensions[0] = strdup("VK_KHR_surface");
+ extensions[1] = strdup("VK_KHR_wayland_surface");
+
+ *count = 2;
+ return extensions;
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR vkGetPhysicalDeviceWaylandPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceWaylandPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceWaylandPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
+ return VK_NULL_HANDLE;
+ }
+
+ return vkGetPhysicalDeviceWaylandPresentationSupportKHR(device,
+ queuefamily,
+ _glfw.wl.display);
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ VkResult err;
+ VkWaylandSurfaceCreateInfoKHR sci;
+ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR;
+
+ vkCreateWaylandSurfaceKHR = (PFN_vkCreateWaylandSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR");
+ if (!vkCreateWaylandSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "Wayland: Vulkan instance missing VK_KHR_wayland_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
+ sci.display = _glfw.wl.display;
+ sci.surface = window->wl.surface;
+
+ err = vkCreateWaylandSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Failed to create Vulkan surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW native API //////
+//////////////////////////////////////////////////////////////////////////
+
+GLFWAPI struct wl_display* glfwGetWaylandDisplay(void)
+{
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return _glfw.wl.display;
+}
+
+GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
+ return window->wl.surface;
+}
+
diff --git a/glfw-3.2.1/src/x11_init.c b/glfw-3.2.1/src/x11_init.c
new file mode 100644
index 0000000..f7a06c1
--- /dev/null
+++ b/glfw-3.2.1/src/x11_init.c
@@ -0,0 +1,833 @@
+//========================================================================
+// GLFW 3.2 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <X11/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, 0, 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, 0, 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.publicKeys, -1, sizeof(_glfw.x11.publicKeys));
+ memset(_glfw.x11.nativeKeys, -1, sizeof(_glfw.x11.nativeKeys));
+
+ 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.publicKeys[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.publicKeys[scancode] < 0)
+ _glfw.x11.publicKeys[scancode] = translateKeyCode(scancode);
+
+ // Store the reverse translation for faster key name lookup
+ if (_glfw.x11.publicKeys[scancode] > 0)
+ _glfw.x11.nativeKeys[_glfw.x11.publicKeys[scancode]] = scancode;
+ }
+}
+
+// Check whether the IM has a usable style
+//
+static GLFWbool hasUsableInputMethodStyle(void)
+{
+ unsigned int i;
+ GLFWbool found = GLFW_FALSE;
+ XIMStyles* styles = NULL;
+
+ if (XGetIMValues(_glfw.x11.im, XNQueryInputStyle, &styles, NULL) != NULL)
+ return GLFW_FALSE;
+
+ for (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)
+{
+ unsigned long i;
+ const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
+
+ for (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)
+{
+ Window* windowFromRoot = NULL;
+ Window* windowFromChild = NULL;
+
+ // First we need a couple of atoms
+ const Atom supportingWmCheck =
+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
+ const Atom wmSupported =
+ XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
+
+ // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
+ if (_glfwGetWindowPropertyX11(_glfw.x11.root,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromRoot) != 1)
+ {
+ if (windowFromRoot)
+ XFree(windowFromRoot);
+ return;
+ }
+
+ _glfwGrabErrorHandlerX11();
+
+ // It should be the ID of a child window (of the root)
+ // Then we look for the same property on the child window
+ if (_glfwGetWindowPropertyX11(*windowFromRoot,
+ supportingWmCheck,
+ XA_WINDOW,
+ (unsigned char**) &windowFromChild) != 1)
+ {
+ XFree(windowFromRoot);
+ if (windowFromChild)
+ XFree(windowFromChild);
+ return;
+ }
+
+ _glfwReleaseErrorHandlerX11();
+
+ // It should be the ID of that same child window
+ if (*windowFromRoot != *windowFromChild)
+ {
+ XFree(windowFromRoot);
+ XFree(windowFromChild);
+ return;
+ }
+
+ XFree(windowFromRoot);
+ XFree(windowFromChild);
+
+ // We are now fairly sure that an EWMH-compliant window manager is running
+
+ Atom* supportedAtoms;
+ unsigned long atomCount;
+
+ // Now we need to check the _NET_SUPPORTED property of the root window
+ // It should be a list of supported WM protocol and state atoms
+ atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
+ wmSupported,
+ XA_ATOM,
+ (unsigned char**) &supportedAtoms);
+
+ // See which of the atoms we support that are supported by the WM
+ _glfw.x11.NET_WM_STATE =
+ 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_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_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");
+
+ XFree(supportedAtoms);
+}
+
+// Initialize X11 display and look for supported X11 extensions
+//
+static GLFWbool initExtensions(void)
+{
+#if defined(_GLFW_HAS_XF86VM)
+ // Check for XF86VidMode extension
+ _glfw.x11.vidmode.available =
+ XF86VidModeQueryExtension(_glfw.x11.display,
+ &_glfw.x11.vidmode.eventBase,
+ &_glfw.x11.vidmode.errorBase);
+#endif /*_GLFW_HAS_XF86VM*/
+
+ // Check for RandR extension
+ 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 = XRRGetScreenResources(_glfw.x11.display,
+ _glfw.x11.root);
+
+ if (!sr->ncrtc || !XRRGetCrtcGammaSize(_glfw.x11.display, sr->crtcs[0]))
+ {
+ // This is either a headless system or an older Nvidia binary driver
+ // with broken gamma support
+ // Flag it as useless and fall back to Xf86VidMode gamma, if
+ // available
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: RandR gamma ramp support seems broken");
+ _glfw.x11.randr.gammaBroken = GLFW_TRUE;
+ }
+
+ XRRFreeScreenResources(sr);
+
+ XRRSelectInput(_glfw.x11.display, _glfw.x11.root,
+ RROutputChangeNotifyMask);
+ }
+
+ if (XineramaQueryExtension(_glfw.x11.display,
+ &_glfw.x11.xinerama.major,
+ &_glfw.x11.xinerama.minor))
+ {
+ if (XineramaIsActive(_glfw.x11.display))
+ _glfw.x11.xinerama.available = GLFW_TRUE;
+ }
+
+ // Check if Xkb is supported on this display
+ _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.x11xcb.handle = dlopen("libX11-xcb.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (_glfw.x11.x11xcb.handle)
+ {
+ _glfw.x11.x11xcb.XGetXCBConnection = (XGETXCBCONNECTION_T)
+ dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection");
+ }
+
+ // Update the key code LUT
+ // FIXME: We should listen to XkbMapNotify events to track changes to
+ // the keyboard mapping.
+ createKeyTables();
+
+ // Detect whether an EWMH-conformant window manager is running
+ detectEWMH();
+
+ // 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.COMPOUND_STRING =
+ XInternAtom(_glfw.x11.display, "COMPOUND_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.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.XdndLeave = XInternAtom(_glfw.x11.display, "XdndLeave", False);
+ _glfw.x11.XdndFinished = XInternAtom(_glfw.x11.display, "XdndFinished", False);
+ _glfw.x11.XdndSelection = XInternAtom(_glfw.x11.display, "XdndSelection", False);
+
+ // ICCCM, EWMH and Motif window property atoms
+ // These can be set safely even without WM support
+ // The EWMH atoms that require WM support are handled in detectEWMH
+ _glfw.x11.WM_PROTOCOLS =
+ XInternAtom(_glfw.x11.display, "WM_PROTOCOLS", False);
+ _glfw.x11.WM_STATE =
+ XInternAtom(_glfw.x11.display, "WM_STATE", False);
+ _glfw.x11.WM_DELETE_WINDOW =
+ XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
+ _glfw.x11.NET_WM_ICON =
+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
+ _glfw.x11.NET_WM_PING =
+ XInternAtom(_glfw.x11.display, "_NET_WM_PING", False);
+ _glfw.x11.NET_WM_PID =
+ XInternAtom(_glfw.x11.display, "_NET_WM_PID", False);
+ _glfw.x11.NET_WM_NAME =
+ XInternAtom(_glfw.x11.display, "_NET_WM_NAME", False);
+ _glfw.x11.NET_WM_ICON_NAME =
+ XInternAtom(_glfw.x11.display, "_NET_WM_ICON_NAME", False);
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR =
+ XInternAtom(_glfw.x11.display, "_NET_WM_BYPASS_COMPOSITOR", False);
+ _glfw.x11.MOTIF_WM_HINTS =
+ XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False);
+
+ return GLFW_TRUE;
+}
+
+// Create a blank cursor for hidden and disabled cursor modes
+//
+static Cursor createHiddenCursor(void)
+{
+ unsigned char pixels[16 * 16 * 4];
+ GLFWimage image = { 16, 16, pixels };
+
+ memset(pixels, 0, sizeof(pixels));
+
+ return _glfwCreateCursorX11(&image, 0, 0);
+}
+
+// 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[8192];
+ 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;
+
+ 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, apply the environment's locale
+ // This is done because the C locale breaks wide character input
+ if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0)
+ setlocale(LC_CTYPE, "");
+#endif
+
+ XInitThreads();
+
+ _glfw.x11.display = XOpenDisplay(NULL);
+ if (!_glfw.x11.display)
+ {
+ 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();
+
+ if (!initExtensions())
+ return GLFW_FALSE;
+
+ _glfw.x11.cursor = 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 (!_glfwInitThreadLocalStoragePOSIX())
+ return GLFW_FALSE;
+
+ if (!_glfwInitJoysticksLinux())
+ return GLFW_FALSE;
+
+ _glfwInitTimerPOSIX();
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformTerminate(void)
+{
+ if (_glfw.x11.x11xcb.handle)
+ {
+ dlclose(_glfw.x11.x11xcb.handle);
+ _glfw.x11.x11xcb.handle = NULL;
+ }
+
+ if (_glfw.x11.cursor)
+ {
+ XFreeCursor(_glfw.x11.display, _glfw.x11.cursor);
+ _glfw.x11.cursor = (Cursor) 0;
+ }
+
+ free(_glfw.x11.clipboardString);
+
+ if (_glfw.x11.im)
+ {
+ XCloseIM(_glfw.x11.im);
+ _glfw.x11.im = NULL;
+ }
+
+ _glfwTerminateEGL();
+
+ if (_glfw.x11.display)
+ {
+ XCloseDisplay(_glfw.x11.display);
+ _glfw.x11.display = NULL;
+ }
+
+ // NOTE: This needs to be done after XCloseDisplay, as libGL registers
+ // cleanup callbacks that get called by it
+ _glfwTerminateGLX();
+
+ _glfwTerminateJoysticksLinux();
+ _glfwTerminateThreadLocalStoragePOSIX();
+}
+
+const char* _glfwPlatformGetVersionString(void)
+{
+ return _GLFW_VERSION_NUMBER " X11 GLX EGL"
+#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
+ " clock_gettime"
+#else
+ " gettimeofday"
+#endif
+#if defined(__linux__)
+ " /dev/js"
+#endif
+#if defined(_GLFW_HAS_XF86VM)
+ " Xf86vm"
+#endif
+#if defined(_GLFW_BUILD_DLL)
+ " shared"
+#endif
+ ;
+}
+
diff --git a/glfw-3.2.1/src/x11_monitor.c b/glfw-3.2.1/src/x11_monitor.c
new file mode 100644
index 0000000..2cec791
--- /dev/null
+++ b/glfw-3.2.1/src/x11_monitor.c
@@ -0,0 +1,491 @@
+//========================================================================
+// GLFW 3.2 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.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) ((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)
+{
+ int i;
+
+ for (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 //////
+//////////////////////////////////////////////////////////////////////////
+
+// Set the current video mode for the specified monitor
+//
+GLFWbool _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+ XRROutputInfo* oi;
+ GLFWvidmode current;
+ const GLFWvidmode* best;
+ RRMode native = None;
+ int i;
+
+ best = _glfwChooseVideoMode(monitor, desired);
+ _glfwPlatformGetVideoMode(monitor, &current);
+ if (_glfwCompareVideoModes(&current, best) == 0)
+ return GLFW_TRUE;
+
+ sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+ oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+ for (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);
+
+ if (!native)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Monitor mode list changed");
+ return GLFW_FALSE;
+ }
+ }
+
+ return GLFW_TRUE;
+}
+
+// Restore the saved (original) video mode for the specified monitor
+//
+void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+
+ if (monitor->x11.oldMode == None)
+ return;
+
+ sr = XRRGetScreenResources(_glfw.x11.display, _glfw.x11.root);
+ 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 //////
+//////////////////////////////////////////////////////////////////////////
+
+_GLFWmonitor** _glfwPlatformGetMonitors(int* count)
+{
+ int i, j, k, found = 0;
+ _GLFWmonitor** monitors = NULL;
+
+ *count = 0;
+
+ if (_glfw.x11.randr.available)
+ {
+ int screenCount = 0;
+ XineramaScreenInfo* screens = NULL;
+ XRRScreenResources* sr = XRRGetScreenResources(_glfw.x11.display,
+ _glfw.x11.root);
+ RROutput primary = XRRGetOutputPrimary(_glfw.x11.display,
+ _glfw.x11.root);
+
+ monitors = calloc(sr->noutput, sizeof(_GLFWmonitor*));
+
+ if (_glfw.x11.xinerama.available)
+ screens = XineramaQueryScreens(_glfw.x11.display, &screenCount);
+
+ for (i = 0; i < sr->ncrtc; i++)
+ {
+ XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display,
+ sr, sr->crtcs[i]);
+
+ for (j = 0; j < ci->noutput; j++)
+ {
+ int widthMM, heightMM;
+ _GLFWmonitor* monitor;
+ XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display,
+ sr, ci->outputs[j]);
+ if (oi->connection != RR_Connected)
+ {
+ XRRFreeOutputInfo(oi);
+ continue;
+ }
+
+ 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;
+ }
+
+ monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
+ monitor->x11.output = ci->outputs[j];
+ monitor->x11.crtc = oi->crtc;
+
+ for (k = 0; k < screenCount; k++)
+ {
+ if (screens[k].x_org == ci->x &&
+ screens[k].y_org == ci->y &&
+ screens[k].width == ci->width &&
+ screens[k].height == ci->height)
+ {
+ monitor->x11.index = k;
+ break;
+ }
+ }
+
+ XRRFreeOutputInfo(oi);
+
+ found++;
+ monitors[found - 1] = monitor;
+
+ if (ci->outputs[j] == primary)
+ _GLFW_SWAP_POINTERS(monitors[0], monitors[found - 1]);
+ }
+
+ XRRFreeCrtcInfo(ci);
+ }
+
+ XRRFreeScreenResources(sr);
+
+ if (screens)
+ XFree(screens);
+
+ if (found == 0)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: RandR monitor support seems broken");
+
+ _glfw.x11.randr.monitorBroken = GLFW_TRUE;
+ free(monitors);
+ monitors = NULL;
+ }
+ }
+
+ if (!monitors)
+ {
+ monitors = calloc(1, sizeof(_GLFWmonitor*));
+ monitors[0] = _glfwAllocMonitor("Display",
+ DisplayWidthMM(_glfw.x11.display,
+ _glfw.x11.screen),
+ DisplayHeightMM(_glfw.x11.display,
+ _glfw.x11.screen));
+ found = 1;
+ }
+
+ *count = found;
+ return monitors;
+}
+
+GLFWbool _glfwPlatformIsSameMonitor(_GLFWmonitor* first, _GLFWmonitor* second)
+{
+ return first->x11.crtc == second->x11.crtc;
+}
+
+void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+
+ if (xpos)
+ *xpos = ci->x;
+ if (ypos)
+ *ypos = ci->y;
+
+ XRRFreeCrtcInfo(ci);
+ XRRFreeScreenResources(sr);
+ }
+}
+
+GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
+{
+ GLFWvidmode* result;
+
+ *count = 0;
+
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
+ {
+ int i, j;
+ XRRScreenResources* sr;
+ XRRCrtcInfo* ci;
+ XRROutputInfo* oi;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
+ oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
+
+ result = calloc(oi->nmode, sizeof(GLFWvidmode));
+
+ for (i = 0; i < oi->nmode; i++)
+ {
+ const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
+ if (!modeIsGood(mi))
+ continue;
+
+ const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
+
+ 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;
+ XRRCrtcInfo* ci;
+
+ sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
+ 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);
+ }
+}
+
+void _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);
+ }
+#if defined(_GLFW_HAS_XF86VM)
+ 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);
+ }
+#endif /*_GLFW_HAS_XF86VM*/
+}
+
+void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
+{
+ if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
+ {
+ 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);
+ }
+#if defined(_GLFW_HAS_XF86VM)
+ 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);
+ }
+#endif /*_GLFW_HAS_XF86VM*/
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// 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-3.2.1/src/x11_platform.h b/glfw-3.2.1/src/x11_platform.h
new file mode 100644
index 0000000..3304306
--- /dev/null
+++ b/glfw-3.2.1/src/x11_platform.h
@@ -0,0 +1,296 @@
+//========================================================================
+// GLFW 3.2 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#ifndef _glfw3_x11_platform_h_
+#define _glfw3_x11_platform_h_
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdint.h>
+#include <dlfcn.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#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>
+
+#if defined(_GLFW_HAS_XF86VM)
+ // The Xf86VidMode extension provides fallback gamma control
+ #include <X11/extensions/xf86vmode.h>
+#endif
+
+typedef XID xcb_window_t;
+typedef XID xcb_visualid_t;
+typedef struct xcb_connection_t xcb_connection_t;
+typedef xcb_connection_t* (* XGETXCBCONNECTION_T)(Display*);
+
+typedef VkFlags VkXlibSurfaceCreateFlagsKHR;
+typedef VkFlags VkXcbSurfaceCreateFlagsKHR;
+
+typedef struct VkXlibSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkXlibSurfaceCreateFlagsKHR flags;
+ Display* dpy;
+ Window window;
+} VkXlibSurfaceCreateInfoKHR;
+
+typedef struct VkXcbSurfaceCreateInfoKHR
+{
+ VkStructureType sType;
+ const void* pNext;
+ VkXcbSurfaceCreateFlagsKHR flags;
+ xcb_connection_t* connection;
+ xcb_window_t window;
+} VkXcbSurfaceCreateInfoKHR;
+
+typedef VkResult (APIENTRY *PFN_vkCreateXlibSurfaceKHR)(VkInstance,const VkXlibSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)(VkPhysicalDevice,uint32_t,Display*,VisualID);
+typedef VkResult (APIENTRY *PFN_vkCreateXcbSurfaceKHR)(VkInstance,const VkXcbSurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
+typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)(VkPhysicalDevice,uint32_t,xcb_connection_t*,xcb_visualid_t);
+
+#include "posix_tls.h"
+#include "posix_time.h"
+#include "linux_joystick.h"
+#include "xkb_unicode.h"
+#include "glx_context.h"
+#include "egl_context.h"
+
+#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
+#define _glfw_dlclose(handle) dlclose(handle)
+#define _glfw_dlsym(handle, name) dlsym(handle, name)
+
+#define _GLFW_EGL_NATIVE_WINDOW ((EGLNativeWindowType) window->x11.handle)
+#define _GLFW_EGL_NATIVE_DISPLAY ((EGLNativeDisplayType) _glfw.x11.display)
+
+#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 x11
+#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 x11
+#define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorX11 x11
+#define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorX11 x11
+
+
+// X11-specific per-window data
+//
+typedef struct _GLFWwindowX11
+{
+ Colormap colormap;
+ Window handle;
+ XIC ic;
+
+ GLFWbool overrideRedirect;
+
+ // Cached position and size used to filter out duplicate events
+ int width, height;
+ int xpos, ypos;
+
+ // The last received cursor position, regardless of source
+ int lastCursorPosX, lastCursorPosY;
+ // The last position the cursor was warped to by GLFW
+ int warpCursorPosX, warpCursorPosY;
+
+ // The information from the last KeyPress event
+ unsigned int lastKeyCode;
+ Time lastKeyTime;
+
+} _GLFWwindowX11;
+
+// X11-specific global data
+//
+typedef struct _GLFWlibraryX11
+{
+ Display* display;
+ int screen;
+ Window root;
+
+ // Invisible cursor for hidden cursor mode
+ Cursor cursor;
+ // 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;
+ // Clipboard string (while the selection is owned)
+ char* clipboardString;
+ // Key name string
+ char keyName[64];
+ // X11 keycode to GLFW key LUT
+ short int publicKeys[256];
+ // GLFW key to X11 keycode LUT
+ short int nativeKeys[GLFW_KEY_LAST + 1];
+ // Where to place the cursor when re-enabled
+ double restoreCursorPosX, restoreCursorPosY;
+ // The window whose disabled cursor mode is active
+ _GLFWwindow* disabledCursorWindow;
+
+ // Window manager atoms
+ Atom WM_PROTOCOLS;
+ 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_BYPASS_COMPOSITOR;
+ Atom NET_WM_FULLSCREEN_MONITORS;
+ 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 XdndLeave;
+ Atom XdndFinished;
+ Atom XdndSelection;
+
+ // Selection (clipboard) atoms
+ Atom TARGETS;
+ Atom MULTIPLE;
+ Atom CLIPBOARD;
+ Atom CLIPBOARD_MANAGER;
+ Atom SAVE_TARGETS;
+ Atom NULL_;
+ Atom UTF8_STRING;
+ Atom COMPOUND_STRING;
+ Atom ATOM_PAIR;
+ Atom GLFW_SELECTION;
+
+ struct {
+ GLFWbool available;
+ int eventBase;
+ int errorBase;
+ int major;
+ int minor;
+ GLFWbool gammaBroken;
+ GLFWbool monitorBroken;
+ } randr;
+
+ struct {
+ GLFWbool available;
+ GLFWbool detectable;
+ int majorOpcode;
+ int eventBase;
+ int errorBase;
+ int major;
+ int minor;
+ } xkb;
+
+ struct {
+ int count;
+ int timeout;
+ int interval;
+ int blanking;
+ int exposure;
+ } saver;
+
+ struct {
+ Window source;
+ } xdnd;
+
+ struct {
+ GLFWbool available;
+ int major;
+ int minor;
+ } xinerama;
+
+ struct {
+ void* handle;
+ XGETXCBCONNECTION_T XGetXCBConnection;
+ } x11xcb;
+
+#if defined(_GLFW_HAS_XF86VM)
+ struct {
+ GLFWbool available;
+ int eventBase;
+ int errorBase;
+ } vidmode;
+#endif /*_GLFW_HAS_XF86VM*/
+
+} _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;
+
+
+GLFWbool _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);
+
+void _glfwGrabErrorHandlerX11(void);
+void _glfwReleaseErrorHandlerX11(void);
+void _glfwInputErrorX11(int error, const char* message);
+
+#endif // _glfw3_x11_platform_h_
diff --git a/glfw-3.2.1/src/x11_window.c b/glfw-3.2.1/src/x11_window.c
new file mode 100644
index 0000000..077eebb
--- /dev/null
+++ b/glfw-3.2.1/src/x11_window.c
@@ -0,0 +1,2475 @@
+//========================================================================
+// GLFW 3.2 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+#include <X11/cursorfont.h>
+#include <X11/Xmd.h>
+
+#include <sys/select.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+
+// Action for EWMH client messages
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
+#define _NET_WM_STATE_TOGGLE 2
+
+// Additional mouse button names for XButtonEvent
+#define Button6 6
+#define Button7 7
+
+
+// Wait for data to arrive using select
+// This avoids blocking other threads via the per-display Xlib lock that also
+// covers GLX functions
+//
+static GLFWbool waitForEvent(double* timeout)
+{
+ fd_set fds;
+ const int fd = ConnectionNumber(_glfw.x11.display);
+ int count = fd + 1;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+#if defined(__linux__)
+ FD_SET(_glfw.linux_js.inotify, &fds);
+
+ if (fd < _glfw.linux_js.inotify)
+ count = _glfw.linux_js.inotify + 1;
+#endif
+ for (;;)
+ {
+ if (timeout)
+ {
+ const long seconds = (long) *timeout;
+ const long microseconds = (long) ((*timeout - seconds) * 1e6);
+ struct timeval tv = { seconds, microseconds };
+ const uint64_t base = _glfwPlatformGetTimerValue();
+
+ const int result = select(count, &fds, NULL, NULL, &tv);
+ const int error = errno;
+
+ *timeout -= (_glfwPlatformGetTimerValue() - base) /
+ (double) _glfwPlatformGetTimerFrequency();
+
+ if (result > 0)
+ return GLFW_TRUE;
+ if ((result == -1 && error == EINTR) || *timeout <= 0.0)
+ return GLFW_FALSE;
+ }
+ else if (select(count, &fds, NULL, NULL, NULL) != -1 || errno != EINTR)
+ return GLFW_TRUE;
+ }
+}
+
+// Waits until a VisibilityNotify event arrives for the specified window or the
+// timeout period elapses (ICCCM section 4.2.2)
+//
+static GLFWbool waitForVisibilityNotify(_GLFWwindow* window)
+{
+ XEvent dummy;
+ double timeout = 0.1;
+
+ while (!XCheckTypedWindowEvent(_glfw.x11.display,
+ window->x11.handle,
+ VisibilityNotify,
+ &dummy))
+ {
+ if (!waitForEvent(&timeout))
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+// Returns whether the window is iconified
+//
+static int getWindowState(_GLFWwindow* window)
+{
+ int result = WithdrawnState;
+ struct {
+ CARD32 state;
+ Window icon;
+ } *state = NULL;
+
+ if (_glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.WM_STATE,
+ _glfw.x11.WM_STATE,
+ (unsigned char**) &state) >= 2)
+ {
+ result = state->state;
+ }
+
+ XFree(state);
+ return result;
+}
+
+// Returns whether the event is a selection event
+//
+static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
+{
+ return event->type == SelectionRequest ||
+ event->type == SelectionNotify ||
+ event->type == SelectionClear;
+}
+
+// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window
+//
+static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer)
+{
+ _GLFWwindow* window = (_GLFWwindow*) pointer;
+ return event->type == PropertyNotify &&
+ event->xproperty.state == PropertyNewValue &&
+ event->xproperty.window == window->x11.handle &&
+ event->xproperty.atom == _glfw.x11.NET_FRAME_EXTENTS;
+}
+
+// Translates a GLFW standard cursor to a font cursor shape
+//
+static int translateCursorShape(int shape)
+{
+ switch (shape)
+ {
+ case GLFW_ARROW_CURSOR:
+ return XC_left_ptr;
+ case GLFW_IBEAM_CURSOR:
+ return XC_xterm;
+ case GLFW_CROSSHAIR_CURSOR:
+ return XC_crosshair;
+ case GLFW_HAND_CURSOR:
+ return XC_hand1;
+ case GLFW_HRESIZE_CURSOR:
+ return XC_sb_h_double_arrow;
+ case GLFW_VRESIZE_CURSOR:
+ return XC_sb_v_double_arrow;
+ }
+
+ return 0;
+}
+
+// Translates an X event modifier state mask
+//
+static int translateState(int state)
+{
+ int mods = 0;
+
+ if (state & ShiftMask)
+ mods |= GLFW_MOD_SHIFT;
+ if (state & ControlMask)
+ mods |= GLFW_MOD_CONTROL;
+ if (state & Mod1Mask)
+ mods |= GLFW_MOD_ALT;
+ if (state & Mod4Mask)
+ mods |= GLFW_MOD_SUPER;
+
+ return mods;
+}
+
+// Translates an X11 key code to a GLFW key token
+//
+static int translateKey(int scancode)
+{
+ // Use the pre-filled LUT (see createKeyTables() in x11_init.c)
+ if (scancode < 0 || scancode > 255)
+ return GLFW_KEY_UNKNOWN;
+
+ return _glfw.x11.publicKeys[scancode];
+}
+
+// Return the GLFW window corresponding to the specified X11 window
+//
+static _GLFWwindow* findWindowByHandle(Window handle)
+{
+ _GLFWwindow* window;
+
+ if (XFindContext(_glfw.x11.display,
+ handle,
+ _glfw.x11.context,
+ (XPointer*) &window) != 0)
+ {
+ return NULL;
+ }
+
+ return window;
+}
+
+// Sends an EWMH or ICCCM event to the window manager
+//
+static void sendEventToWM(_GLFWwindow* window, Atom type,
+ long a, long b, long c, long d, long e)
+{
+ XEvent event;
+ memset(&event, 0, sizeof(event));
+
+ event.type = ClientMessage;
+ event.xclient.window = window->x11.handle;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = type;
+ event.xclient.data.l[0] = a;
+ event.xclient.data.l[1] = b;
+ event.xclient.data.l[2] = c;
+ event.xclient.data.l[3] = d;
+ event.xclient.data.l[4] = e;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &event);
+}
+
+// Updates the normal hints according to the window settings
+//
+static void updateNormalHints(_GLFWwindow* window, int width, int height)
+{
+ XSizeHints* hints = XAllocSizeHints();
+
+ if (!window->monitor)
+ {
+ if (window->resizable)
+ {
+ if (window->minwidth != GLFW_DONT_CARE &&
+ window->minheight != GLFW_DONT_CARE)
+ {
+ hints->flags |= PMinSize;
+ hints->min_width = window->minwidth;
+ hints->min_height = window->minheight;
+ }
+
+ if (window->maxwidth != GLFW_DONT_CARE &&
+ window->maxheight != GLFW_DONT_CARE)
+ {
+ hints->flags |= PMaxSize;
+ hints->max_width = window->maxwidth;
+ hints->max_height = window->maxheight;
+ }
+
+ if (window->numer != GLFW_DONT_CARE &&
+ window->denom != GLFW_DONT_CARE)
+ {
+ hints->flags |= PAspect;
+ hints->min_aspect.x = hints->max_aspect.x = window->numer;
+ hints->min_aspect.y = hints->max_aspect.y = window->denom;
+ }
+ }
+ else
+ {
+ hints->flags |= (PMinSize | PMaxSize);
+ hints->min_width = hints->max_width = width;
+ hints->min_height = hints->max_height = height;
+ }
+ }
+
+ hints->flags |= PWinGravity;
+ hints->win_gravity = StaticGravity;
+
+ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
+ XFree(hints);
+}
+
+// Updates the full screen status of the window
+//
+static void updateWindowMode(_GLFWwindow* window)
+{
+ if (window->monitor)
+ {
+ if (_glfw.x11.xinerama.available &&
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ window->monitor->x11.index,
+ 0);
+ }
+
+ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_ADD,
+ _glfw.x11.NET_WM_STATE_FULLSCREEN,
+ 0, 1, 0);
+ }
+ else
+ {
+ // This is the butcher's way of removing window decorations
+ // Setting the override-redirect attribute on a window makes the
+ // window manager ignore the window completely (ICCCM, section 4)
+ // The good thing is that this makes undecorated full screen windows
+ // easy to do; the bad thing is that we have to do everything
+ // manually and some things (like iconify/restore) won't work at
+ // all, as those are tasks usually performed by the window manager
+
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = True;
+ XChangeWindowAttributes(_glfw.x11.display,
+ window->x11.handle,
+ CWOverrideRedirect,
+ &attributes);
+
+ window->x11.overrideRedirect = GLFW_TRUE;
+ }
+
+ // Enable compositor bypass
+ {
+ const unsigned long value = 1;
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*) &value, 1);
+ }
+ }
+ else
+ {
+ if (_glfw.x11.xinerama.available &&
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS)
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_FULLSCREEN_MONITORS);
+ }
+
+ if (_glfw.x11.NET_WM_STATE && _glfw.x11.NET_WM_STATE_FULLSCREEN)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_REMOVE,
+ _glfw.x11.NET_WM_STATE_FULLSCREEN,
+ 0, 1, 0);
+ }
+ else
+ {
+ XSetWindowAttributes attributes;
+ attributes.override_redirect = False;
+ XChangeWindowAttributes(_glfw.x11.display,
+ window->x11.handle,
+ CWOverrideRedirect,
+ &attributes);
+
+ window->x11.overrideRedirect = GLFW_FALSE;
+ }
+
+ // Disable compositor bypass
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_BYPASS_COMPOSITOR);
+ }
+ }
+}
+
+// Splits and translates a text/uri-list into separate file paths
+// NOTE: This function destroys the provided string
+//
+static char** parseUriList(char* text, int* count)
+{
+ const char* prefix = "file://";
+ char** paths = NULL;
+ char* line;
+
+ *count = 0;
+
+ while ((line = strtok(text, "\r\n")))
+ {
+ text = NULL;
+
+ if (line[0] == '#')
+ continue;
+
+ if (strncmp(line, prefix, strlen(prefix)) == 0)
+ line += strlen(prefix);
+
+ (*count)++;
+
+ char* path = calloc(strlen(line) + 1, 1);
+ paths = realloc(paths, *count * sizeof(char*));
+ paths[*count - 1] = path;
+
+ while (*line)
+ {
+ if (line[0] == '%' && line[1] && line[2])
+ {
+ const char digits[3] = { line[1], line[2], '\0' };
+ *path = strtol(digits, NULL, 16);
+ line += 2;
+ }
+ else
+ *path = *line;
+
+ path++;
+ line++;
+ }
+ }
+
+ return paths;
+}
+
+// Centers the cursor over the window client area
+//
+static void centerCursor(_GLFWwindow* window)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
+}
+
+// Updates the cursor image according to its cursor mode
+//
+static void updateCursorImage(_GLFWwindow* window)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ if (window->cursor)
+ {
+ XDefineCursor(_glfw.x11.display, window->x11.handle,
+ window->cursor->x11.handle);
+ }
+ else
+ XUndefineCursor(_glfw.x11.display, window->x11.handle);
+ }
+ else
+ XDefineCursor(_glfw.x11.display, window->x11.handle, _glfw.x11.cursor);
+}
+
+// Create the X11 window (and its colormap)
+//
+static GLFWbool createNativeWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ Visual* visual, int depth)
+{
+ // Create a colormap based on the visual used by the current context
+ window->x11.colormap = XCreateColormap(_glfw.x11.display,
+ _glfw.x11.root,
+ visual,
+ AllocNone);
+
+ // Create the actual window
+ {
+ XSetWindowAttributes wa;
+ const unsigned long wamask = CWBorderPixel | CWColormap | CWEventMask;
+
+ wa.colormap = window->x11.colormap;
+ wa.border_pixel = 0;
+ wa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | ButtonPressMask | ButtonReleaseMask |
+ ExposureMask | FocusChangeMask | VisibilityChangeMask |
+ EnterWindowMask | LeaveWindowMask | PropertyChangeMask;
+
+ _glfwGrabErrorHandlerX11();
+
+ window->x11.handle = XCreateWindow(_glfw.x11.display,
+ _glfw.x11.root,
+ 0, 0,
+ wndconfig->width, wndconfig->height,
+ 0, // Border width
+ depth, // Color depth
+ InputOutput,
+ visual,
+ wamask,
+ &wa);
+
+ _glfwReleaseErrorHandlerX11();
+
+ if (!window->x11.handle)
+ {
+ _glfwInputErrorX11(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create window");
+ return GLFW_FALSE;
+ }
+
+ XSaveContext(_glfw.x11.display,
+ window->x11.handle,
+ _glfw.x11.context,
+ (XPointer) window);
+ }
+
+ if (!wndconfig->decorated)
+ {
+ struct
+ {
+ unsigned long flags;
+ unsigned long functions;
+ unsigned long decorations;
+ long input_mode;
+ unsigned long status;
+ } hints;
+
+ hints.flags = 2; // Set decorations
+ hints.decorations = 0; // No decorations
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.MOTIF_WM_HINTS,
+ _glfw.x11.MOTIF_WM_HINTS, 32,
+ PropModeReplace,
+ (unsigned char*) &hints,
+ sizeof(hints) / sizeof(long));
+ }
+
+ if (_glfw.x11.NET_WM_STATE && !window->monitor)
+ {
+ Atom states[3];
+ int count = 0;
+
+ if (wndconfig->floating)
+ {
+ if (_glfw.x11.NET_WM_STATE_ABOVE)
+ states[count++] = _glfw.x11.NET_WM_STATE_ABOVE;
+ }
+
+ if (wndconfig->maximized)
+ {
+ if (_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT;
+ states[count++] = _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ;
+ }
+ }
+
+ if (count)
+ {
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_STATE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &states, count);
+ }
+ }
+
+ // Declare the WM protocols supported by GLFW
+ {
+ Atom protocols[] =
+ {
+ _glfw.x11.WM_DELETE_WINDOW,
+ _glfw.x11.NET_WM_PING
+ };
+
+ XSetWMProtocols(_glfw.x11.display, window->x11.handle,
+ protocols, sizeof(protocols) / sizeof(Atom));
+ }
+
+ // Declare our PID
+ {
+ const pid_t pid = getpid();
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_PID, XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char*) &pid, 1);
+ }
+
+ if (_glfw.x11.NET_WM_WINDOW_TYPE && _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL)
+ {
+ Atom type = _glfw.x11.NET_WM_WINDOW_TYPE_NORMAL;
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_WINDOW_TYPE, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &type, 1);
+ }
+
+ // Set ICCCM WM_HINTS property
+ {
+ XWMHints* hints = XAllocWMHints();
+ if (!hints)
+ {
+ _glfwInputError(GLFW_OUT_OF_MEMORY,
+ "X11: Failed to allocate WM hints");
+ return GLFW_FALSE;
+ }
+
+ hints->flags = StateHint;
+ hints->initial_state = NormalState;
+
+ XSetWMHints(_glfw.x11.display, window->x11.handle, hints);
+ XFree(hints);
+ }
+
+ updateNormalHints(window, wndconfig->width, wndconfig->height);
+
+ // Set ICCCM WM_CLASS property
+ // HACK: Until a mechanism for specifying the application name is added, the
+ // initial window title is used as the window class name
+ if (strlen(wndconfig->title))
+ {
+ XClassHint* hint = XAllocClassHint();
+ hint->res_name = (char*) wndconfig->title;
+ hint->res_class = (char*) wndconfig->title;
+
+ XSetClassHint(_glfw.x11.display, window->x11.handle, hint);
+ XFree(hint);
+ }
+
+ if (_glfw.x11.XdndAware)
+ {
+ // Announce support for Xdnd (drag and drop)
+ const Atom version = 5;
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.XdndAware, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*) &version, 1);
+ }
+
+ _glfwPlatformSetWindowTitle(window, wndconfig->title);
+
+ if (_glfw.x11.im)
+ {
+ window->x11.ic = XCreateIC(_glfw.x11.im,
+ XNInputStyle,
+ XIMPreeditNothing | XIMStatusNothing,
+ XNClientWindow,
+ window->x11.handle,
+ XNFocusWindow,
+ window->x11.handle,
+ NULL);
+ }
+
+ _glfwPlatformGetWindowPos(window, &window->x11.xpos, &window->x11.ypos);
+ _glfwPlatformGetWindowSize(window, &window->x11.width, &window->x11.height);
+
+ return GLFW_TRUE;
+}
+
+// Set the specified property to the selection converted to the requested target
+//
+static Atom writeTargetToProperty(const XSelectionRequestEvent* request)
+{
+ int i;
+ const Atom formats[] = { _glfw.x11.UTF8_STRING,
+ _glfw.x11.COMPOUND_STRING,
+ XA_STRING };
+ const int formatCount = sizeof(formats) / sizeof(formats[0]);
+
+ if (request->property == None)
+ {
+ // The requester is a legacy client (ICCCM section 2.2)
+ // We don't support legacy clients, so fail here
+ return None;
+ }
+
+ if (request->target == _glfw.x11.TARGETS)
+ {
+ // The list of supported targets was requested
+
+ const Atom targets[] = { _glfw.x11.TARGETS,
+ _glfw.x11.MULTIPLE,
+ _glfw.x11.UTF8_STRING,
+ _glfw.x11.COMPOUND_STRING,
+ XA_STRING };
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ (unsigned char*) targets,
+ sizeof(targets) / sizeof(targets[0]));
+
+ return request->property;
+ }
+
+ if (request->target == _glfw.x11.MULTIPLE)
+ {
+ // Multiple conversions were requested
+
+ Atom* targets;
+ unsigned long i, count;
+
+ count = _glfwGetWindowPropertyX11(request->requestor,
+ request->property,
+ _glfw.x11.ATOM_PAIR,
+ (unsigned char**) &targets);
+
+ for (i = 0; i < count; i += 2)
+ {
+ int j;
+
+ for (j = 0; j < formatCount; j++)
+ {
+ if (targets[i] == formats[j])
+ break;
+ }
+
+ if (j < formatCount)
+ {
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ targets[i + 1],
+ targets[i],
+ 8,
+ PropModeReplace,
+ (unsigned char*) _glfw.x11.clipboardString,
+ strlen(_glfw.x11.clipboardString));
+ }
+ else
+ targets[i + 1] = None;
+ }
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ _glfw.x11.ATOM_PAIR,
+ 32,
+ PropModeReplace,
+ (unsigned char*) targets,
+ count);
+
+ XFree(targets);
+
+ return request->property;
+ }
+
+ if (request->target == _glfw.x11.SAVE_TARGETS)
+ {
+ // The request is a check whether we support SAVE_TARGETS
+ // It should be handled as a no-op side effect target
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ _glfw.x11.NULL_,
+ 32,
+ PropModeReplace,
+ NULL,
+ 0);
+
+ return request->property;
+ }
+
+ // Conversion to a data target was requested
+
+ for (i = 0; i < formatCount; i++)
+ {
+ if (request->target == formats[i])
+ {
+ // The requested target is one we support
+
+ XChangeProperty(_glfw.x11.display,
+ request->requestor,
+ request->property,
+ request->target,
+ 8,
+ PropModeReplace,
+ (unsigned char*) _glfw.x11.clipboardString,
+ strlen(_glfw.x11.clipboardString));
+
+ return request->property;
+ }
+ }
+
+ // The requested target is not supported
+
+ return None;
+}
+
+static void handleSelectionClear(XEvent* event)
+{
+ free(_glfw.x11.clipboardString);
+ _glfw.x11.clipboardString = NULL;
+}
+
+static void handleSelectionRequest(XEvent* event)
+{
+ const XSelectionRequestEvent* request = &event->xselectionrequest;
+
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.xselection.property = writeTargetToProperty(request);
+ reply.xselection.type = SelectionNotify;
+ reply.xselection.display = request->display;
+ reply.xselection.requestor = request->requestor;
+ reply.xselection.selection = request->selection;
+ reply.xselection.target = request->target;
+ reply.xselection.time = request->time;
+
+ XSendEvent(_glfw.x11.display, request->requestor, False, 0, &reply);
+}
+
+static void pushSelectionToManager(_GLFWwindow* window)
+{
+ XConvertSelection(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD_MANAGER,
+ _glfw.x11.SAVE_TARGETS,
+ None,
+ window->x11.handle,
+ CurrentTime);
+
+ for (;;)
+ {
+ XEvent event;
+
+ while (XCheckIfEvent(_glfw.x11.display, &event, isSelectionEvent, NULL))
+ {
+ switch (event.type)
+ {
+ case SelectionRequest:
+ handleSelectionRequest(&event);
+ break;
+
+ case SelectionClear:
+ handleSelectionClear(&event);
+ break;
+
+ case SelectionNotify:
+ {
+ if (event.xselection.target == _glfw.x11.SAVE_TARGETS)
+ {
+ // This means one of two things; either the selection was
+ // not owned, which means there is no clipboard manager, or
+ // the transfer to the clipboard manager has completed
+ // In either case, it means we are done here
+ return;
+ }
+
+ break;
+ }
+ }
+ }
+
+ waitForEvent(NULL);
+ }
+}
+
+// Make the specified window and its video mode active on its monitor
+//
+static GLFWbool acquireMonitor(_GLFWwindow* window)
+{
+ GLFWbool status;
+
+ if (_glfw.x11.saver.count == 0)
+ {
+ // Remember old screen saver settings
+ XGetScreenSaver(_glfw.x11.display,
+ &_glfw.x11.saver.timeout,
+ &_glfw.x11.saver.interval,
+ &_glfw.x11.saver.blanking,
+ &_glfw.x11.saver.exposure);
+
+ // Disable screen saver
+ XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking,
+ DefaultExposures);
+ }
+
+ if (!window->monitor->window)
+ _glfw.x11.saver.count++;
+
+ status = _glfwSetVideoModeX11(window->monitor, &window->videoMode);
+
+ if (window->x11.overrideRedirect)
+ {
+ int xpos, ypos;
+ GLFWvidmode mode;
+
+ // Manually position the window over its monitor
+ _glfwPlatformGetMonitorPos(window->monitor, &xpos, &ypos);
+ _glfwPlatformGetVideoMode(window->monitor, &mode);
+
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, mode.width, mode.height);
+ }
+
+ _glfwInputMonitorWindowChange(window->monitor, window);
+ return status;
+}
+
+// Remove the window and restore the original video mode
+//
+static void releaseMonitor(_GLFWwindow* window)
+{
+ if (window->monitor->window != window)
+ return;
+
+ _glfwInputMonitorWindowChange(window->monitor, NULL);
+ _glfwRestoreVideoModeX11(window->monitor);
+
+ _glfw.x11.saver.count--;
+
+ if (_glfw.x11.saver.count == 0)
+ {
+ // Restore old screen saver settings
+ XSetScreenSaver(_glfw.x11.display,
+ _glfw.x11.saver.timeout,
+ _glfw.x11.saver.interval,
+ _glfw.x11.saver.blanking,
+ _glfw.x11.saver.exposure);
+ }
+}
+
+// Decode a Unicode code point from a UTF-8 stream
+// Based on cutef8 by Jeff Bezanson (Public Domain)
+//
+#if defined(X_HAVE_UTF8_STRING)
+static unsigned int decodeUTF8(const char** s)
+{
+ unsigned int ch = 0, count = 0;
+ static const unsigned int offsets[] =
+ {
+ 0x00000000u, 0x00003080u, 0x000e2080u,
+ 0x03c82080u, 0xfa082080u, 0x82082080u
+ };
+
+ do
+ {
+ ch = (ch << 6) + (unsigned char) **s;
+ (*s)++;
+ count++;
+ } while ((**s & 0xc0) == 0x80);
+
+ assert(count <= 6);
+ return ch - offsets[count - 1];
+}
+#endif /*X_HAVE_UTF8_STRING*/
+
+// Process the specified X event
+//
+static void processEvent(XEvent *event)
+{
+ _GLFWwindow* window = NULL;
+ int keycode = 0;
+ Bool filtered = False;
+
+ // HACK: Save scancode as some IMs clear the field in XFilterEvent
+ if (event->type == KeyPress || event->type == KeyRelease)
+ keycode = event->xkey.keycode;
+
+ if (_glfw.x11.im)
+ filtered = XFilterEvent(event, None);
+
+ if (_glfw.x11.randr.available)
+ {
+ if (event->type == _glfw.x11.randr.eventBase + RRNotify)
+ {
+ XRRUpdateConfiguration(event);
+ _glfwInputMonitorChange();
+ return;
+ }
+ }
+
+ if (event->type != GenericEvent)
+ {
+ window = findWindowByHandle(event->xany.window);
+ if (window == NULL)
+ {
+ // This is an event for a window that has already been destroyed
+ return;
+ }
+ }
+
+ switch (event->type)
+ {
+ case KeyPress:
+ {
+ const int key = translateKey(keycode);
+ const int mods = translateState(event->xkey.state);
+ const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
+
+ if (window->x11.ic)
+ {
+ // HACK: Ignore duplicate key press events generated by ibus
+ // Corresponding release events are filtered out by the
+ // GLFW key repeat logic
+ if (window->x11.lastKeyCode != keycode ||
+ window->x11.lastKeyTime != event->xkey.time)
+ {
+ if (keycode)
+ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
+ }
+
+ window->x11.lastKeyCode = keycode;
+ window->x11.lastKeyTime = event->xkey.time;
+
+ if (!filtered)
+ {
+ int count;
+ Status status;
+#if defined(X_HAVE_UTF8_STRING)
+ char buffer[100];
+ char* chars = buffer;
+
+ count = Xutf8LookupString(window->x11.ic,
+ &event->xkey,
+ buffer, sizeof(buffer) - 1,
+ NULL, &status);
+
+ if (status == XBufferOverflow)
+ {
+ chars = calloc(count + 1, 1);
+ count = Xutf8LookupString(window->x11.ic,
+ &event->xkey,
+ chars, count,
+ NULL, &status);
+ }
+
+ if (status == XLookupChars || status == XLookupBoth)
+ {
+ const char* c = chars;
+ chars[count] = '\0';
+ while (c - chars < count)
+ _glfwInputChar(window, decodeUTF8(&c), mods, plain);
+ }
+#else /*X_HAVE_UTF8_STRING*/
+ wchar_t buffer[16];
+ wchar_t* chars = buffer;
+
+ count = XwcLookupString(window->x11.ic,
+ &event->xkey,
+ buffer, sizeof(buffer) / sizeof(wchar_t),
+ NULL, &status);
+
+ if (status == XBufferOverflow)
+ {
+ chars = calloc(count, sizeof(wchar_t));
+ count = XwcLookupString(window->x11.ic,
+ &event->xkey,
+ chars, count,
+ NULL, &status);
+ }
+
+ if (status == XLookupChars || status == XLookupBoth)
+ {
+ int i;
+ for (i = 0; i < count; i++)
+ _glfwInputChar(window, chars[i], mods, plain);
+ }
+#endif /*X_HAVE_UTF8_STRING*/
+
+ if (chars != buffer)
+ free(chars);
+ }
+ }
+ else
+ {
+ KeySym keysym;
+ XLookupString(&event->xkey, NULL, 0, &keysym, NULL);
+
+ _glfwInputKey(window, key, keycode, GLFW_PRESS, mods);
+
+ const long character = _glfwKeySym2Unicode(keysym);
+ if (character != -1)
+ _glfwInputChar(window, character, mods, plain);
+ }
+
+ return;
+ }
+
+ case KeyRelease:
+ {
+ const int key = translateKey(keycode);
+ const int mods = translateState(event->xkey.state);
+
+ if (!_glfw.x11.xkb.detectable)
+ {
+ // HACK: Key repeat events will arrive as KeyRelease/KeyPress
+ // pairs with similar or identical time stamps
+ // The key repeat logic in _glfwInputKey expects only key
+ // presses to repeat, so detect and discard release events
+ if (XEventsQueued(_glfw.x11.display, QueuedAfterReading))
+ {
+ XEvent next;
+ XPeekEvent(_glfw.x11.display, &next);
+
+ if (next.type == KeyPress &&
+ next.xkey.window == event->xkey.window &&
+ next.xkey.keycode == keycode)
+ {
+ // HACK: The time of repeat events sometimes doesn't
+ // match that of the press event, so add an
+ // epsilon
+ // Toshiyuki Takahashi can press a button
+ // 16 times per second so it's fairly safe to
+ // assume that no human is pressing the key 50
+ // times per second (value is ms)
+ if ((next.xkey.time - event->xkey.time) < 20)
+ {
+ // This is very likely a server-generated key repeat
+ // event, so ignore it
+ return;
+ }
+ }
+ }
+ }
+
+ _glfwInputKey(window, key, keycode, GLFW_RELEASE, mods);
+ return;
+ }
+
+ case ButtonPress:
+ {
+ const int mods = translateState(event->xbutton.state);
+
+ if (event->xbutton.button == Button1)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS, mods);
+ else if (event->xbutton.button == Button2)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS, mods);
+ else if (event->xbutton.button == Button3)
+ _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS, mods);
+
+ // Modern X provides scroll events as mouse button presses
+ else if (event->xbutton.button == Button4)
+ _glfwInputScroll(window, 0.0, 1.0);
+ else if (event->xbutton.button == Button5)
+ _glfwInputScroll(window, 0.0, -1.0);
+ else if (event->xbutton.button == Button6)
+ _glfwInputScroll(window, 1.0, 0.0);
+ else if (event->xbutton.button == Button7)
+ _glfwInputScroll(window, -1.0, 0.0);
+
+ else
+ {
+ // Additional buttons after 7 are treated as regular buttons
+ // We subtract 4 to fill the gap left by scroll input above
+ _glfwInputMouseClick(window,
+ event->xbutton.button - Button1 - 4,
+ GLFW_PRESS,
+ mods);
+ }
+
+ return;
+ }
+
+ case ButtonRelease:
+ {
+ const int mods = translateState(event->xbutton.state);
+
+ if (event->xbutton.button == Button1)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_LEFT,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button == Button2)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_MIDDLE,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button == Button3)
+ {
+ _glfwInputMouseClick(window,
+ GLFW_MOUSE_BUTTON_RIGHT,
+ GLFW_RELEASE,
+ mods);
+ }
+ else if (event->xbutton.button > Button7)
+ {
+ // Additional buttons after 7 are treated as regular buttons
+ // We subtract 4 to fill the gap left by scroll input above
+ _glfwInputMouseClick(window,
+ event->xbutton.button - Button1 - 4,
+ GLFW_RELEASE,
+ mods);
+ }
+
+ return;
+ }
+
+ case EnterNotify:
+ {
+ // HACK: This is a workaround for WMs (KWM, Fluxbox) that otherwise
+ // ignore the defined cursor for hidden cursor mode
+ if (window->cursorMode == GLFW_CURSOR_HIDDEN)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_HIDDEN);
+
+ _glfwInputCursorEnter(window, GLFW_TRUE);
+ return;
+ }
+
+ case LeaveNotify:
+ {
+ _glfwInputCursorEnter(window, GLFW_FALSE);
+ return;
+ }
+
+ case MotionNotify:
+ {
+ const int x = event->xmotion.x;
+ const int y = event->xmotion.y;
+
+ if (x != window->x11.warpCursorPosX || y != window->x11.warpCursorPosY)
+ {
+ // The cursor was moved by something other than GLFW
+
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ {
+ if (_glfw.x11.disabledCursorWindow != window)
+ return;
+
+ const int dx = x - window->x11.lastCursorPosX;
+ const int dy = y - window->x11.lastCursorPosY;
+
+ _glfwInputCursorPos(window,
+ window->virtualCursorPosX + dx,
+ window->virtualCursorPosY + dy);
+ }
+ else
+ _glfwInputCursorPos(window, x, y);
+ }
+
+ window->x11.lastCursorPosX = x;
+ window->x11.lastCursorPosY = y;
+ return;
+ }
+
+ case ConfigureNotify:
+ {
+ if (event->xconfigure.width != window->x11.width ||
+ event->xconfigure.height != window->x11.height)
+ {
+ _glfwInputFramebufferSize(window,
+ event->xconfigure.width,
+ event->xconfigure.height);
+
+ _glfwInputWindowSize(window,
+ event->xconfigure.width,
+ event->xconfigure.height);
+
+ window->x11.width = event->xconfigure.width;
+ window->x11.height = event->xconfigure.height;
+ }
+
+ if (event->xconfigure.x != window->x11.xpos ||
+ event->xconfigure.y != window->x11.ypos)
+ {
+ if (window->x11.overrideRedirect || event->xany.send_event)
+ {
+ _glfwInputWindowPos(window,
+ event->xconfigure.x,
+ event->xconfigure.y);
+
+ window->x11.xpos = event->xconfigure.x;
+ window->x11.ypos = event->xconfigure.y;
+ }
+ }
+
+ return;
+ }
+
+ case ClientMessage:
+ {
+ // Custom client message, probably from the window manager
+
+ if (filtered)
+ return;
+
+ if (event->xclient.message_type == None)
+ return;
+
+ if (event->xclient.message_type == _glfw.x11.WM_PROTOCOLS)
+ {
+ const Atom protocol = event->xclient.data.l[0];
+ if (protocol == None)
+ return;
+
+ if (protocol == _glfw.x11.WM_DELETE_WINDOW)
+ {
+ // The window manager was asked to close the window, for example by
+ // the user pressing a 'close' window decoration button
+ _glfwInputWindowCloseRequest(window);
+ }
+ else if (protocol == _glfw.x11.NET_WM_PING)
+ {
+ // The window manager is pinging the application to ensure it's
+ // still responding to events
+
+ XEvent reply = *event;
+ reply.xclient.window = _glfw.x11.root;
+
+ XSendEvent(_glfw.x11.display, _glfw.x11.root,
+ False,
+ SubstructureNotifyMask | SubstructureRedirectMask,
+ &reply);
+ }
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndEnter)
+ {
+ // A drag operation has entered the window
+ // TODO: Check if UTF-8 string is supported by the source
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndDrop)
+ {
+ // The drag operation has finished dropping on
+ // the window, ask to convert it to a UTF-8 string
+ _glfw.x11.xdnd.source = event->xclient.data.l[0];
+ XConvertSelection(_glfw.x11.display,
+ _glfw.x11.XdndSelection,
+ _glfw.x11.UTF8_STRING,
+ _glfw.x11.XdndSelection,
+ window->x11.handle, CurrentTime);
+ }
+ else if (event->xclient.message_type == _glfw.x11.XdndPosition)
+ {
+ // The drag operation has moved over the window
+ const int absX = (event->xclient.data.l[2] >> 16) & 0xFFFF;
+ const int absY = (event->xclient.data.l[2]) & 0xFFFF;
+ int x, y;
+
+ _glfwPlatformGetWindowPos(window, &x, &y);
+ _glfwInputCursorPos(window, absX - x, absY - y);
+
+ // Reply that we are ready to copy the dragged data
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = event->xclient.data.l[0];
+ reply.xclient.message_type = _glfw.x11.XdndStatus;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = window->x11.handle;
+ reply.xclient.data.l[1] = 1; // Always accept the dnd with no rectangle
+ reply.xclient.data.l[2] = 0; // Specify an empty rectangle
+ reply.xclient.data.l[3] = 0;
+ reply.xclient.data.l[4] = _glfw.x11.XdndActionCopy;
+
+ XSendEvent(_glfw.x11.display, event->xclient.data.l[0],
+ False, NoEventMask, &reply);
+ XFlush(_glfw.x11.display);
+ }
+
+ return;
+ }
+
+ case SelectionNotify:
+ {
+ if (event->xselection.property)
+ {
+ // The converted data from the drag operation has arrived
+ char* data;
+ const int result =
+ _glfwGetWindowPropertyX11(event->xselection.requestor,
+ event->xselection.property,
+ event->xselection.target,
+ (unsigned char**) &data);
+
+ if (result)
+ {
+ int i, count;
+ char** paths = parseUriList(data, &count);
+
+ _glfwInputDrop(window, count, (const char**) paths);
+
+ for (i = 0; i < count; i++)
+ free(paths[i]);
+ free(paths);
+ }
+
+ XFree(data);
+
+ XEvent reply;
+ memset(&reply, 0, sizeof(reply));
+
+ reply.type = ClientMessage;
+ reply.xclient.window = _glfw.x11.xdnd.source;
+ reply.xclient.message_type = _glfw.x11.XdndFinished;
+ reply.xclient.format = 32;
+ reply.xclient.data.l[0] = window->x11.handle;
+ reply.xclient.data.l[1] = result;
+ reply.xclient.data.l[2] = _glfw.x11.XdndActionCopy;
+
+ // Reply that all is well
+ XSendEvent(_glfw.x11.display, _glfw.x11.xdnd.source,
+ False, NoEventMask, &reply);
+ XFlush(_glfw.x11.display);
+ }
+
+ return;
+ }
+
+ case FocusIn:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_DISABLED);
+
+ if (event->xfocus.mode == NotifyGrab ||
+ event->xfocus.mode == NotifyUngrab)
+ {
+ // Ignore focus events from popup indicator windows, window menu
+ // key chords and window dragging
+ return;
+ }
+
+ if (window->x11.ic)
+ XSetICFocus(window->x11.ic);
+
+ _glfwInputWindowFocus(window, GLFW_TRUE);
+ return;
+ }
+
+ case FocusOut:
+ {
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
+ _glfwPlatformSetCursorMode(window, GLFW_CURSOR_NORMAL);
+
+ if (event->xfocus.mode == NotifyGrab ||
+ event->xfocus.mode == NotifyUngrab)
+ {
+ // Ignore focus events from popup indicator windows, window menu
+ // key chords and window dragging
+ return;
+ }
+
+ if (window->x11.ic)
+ XUnsetICFocus(window->x11.ic);
+
+ if (window->monitor && window->autoIconify)
+ _glfwPlatformIconifyWindow(window);
+
+ _glfwInputWindowFocus(window, GLFW_FALSE);
+ return;
+ }
+
+ case Expose:
+ {
+ _glfwInputWindowDamage(window);
+ return;
+ }
+
+ case PropertyNotify:
+ {
+ if (event->xproperty.atom == _glfw.x11.WM_STATE &&
+ event->xproperty.state == PropertyNewValue)
+ {
+ const int state = getWindowState(window);
+ if (state == IconicState)
+ {
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowIconify(window, GLFW_TRUE);
+ }
+ else if (state == NormalState)
+ {
+ if (window->monitor)
+ acquireMonitor(window);
+
+ _glfwInputWindowIconify(window, GLFW_FALSE);
+ }
+ }
+
+ return;
+ }
+
+ case SelectionClear:
+ {
+ handleSelectionClear(event);
+ return;
+ }
+
+ case SelectionRequest:
+ {
+ handleSelectionRequest(event);
+ return;
+ }
+
+ case DestroyNotify:
+ return;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Retrieve a single window property of the specified type
+// Inspired by fghGetWindowProperty from freeglut
+//
+unsigned long _glfwGetWindowPropertyX11(Window window,
+ Atom property,
+ Atom type,
+ unsigned char** value)
+{
+ Atom actualType;
+ int actualFormat;
+ unsigned long itemCount, bytesAfter;
+
+ XGetWindowProperty(_glfw.x11.display,
+ window,
+ property,
+ 0,
+ LONG_MAX,
+ False,
+ type,
+ &actualType,
+ &actualFormat,
+ &itemCount,
+ &bytesAfter,
+ value);
+
+ if (type != AnyPropertyType && actualType != type)
+ return 0;
+
+ return itemCount;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
+int _glfwPlatformCreateWindow(_GLFWwindow* window,
+ const _GLFWwndconfig* wndconfig,
+ const _GLFWctxconfig* ctxconfig,
+ const _GLFWfbconfig* fbconfig)
+{
+ Visual* visual;
+ int depth;
+
+ if (ctxconfig->client == GLFW_NO_API)
+ {
+ visual = DefaultVisual(_glfw.x11.display, _glfw.x11.screen);
+ depth = DefaultDepth(_glfw.x11.display, _glfw.x11.screen);
+ }
+ else
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwInitGLX())
+ return GLFW_FALSE;
+ if (!_glfwChooseVisualGLX(ctxconfig, fbconfig, &visual, &depth))
+ return GLFW_FALSE;
+ }
+ else
+ {
+ if (!_glfwInitEGL())
+ return GLFW_FALSE;
+ if (!_glfwChooseVisualEGL(ctxconfig, fbconfig, &visual, &depth))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (!createNativeWindow(window, wndconfig, visual, depth))
+ return GLFW_FALSE;
+
+ if (ctxconfig->client != GLFW_NO_API)
+ {
+ if (ctxconfig->source == GLFW_NATIVE_CONTEXT_API)
+ {
+ if (!_glfwCreateContextGLX(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ else
+ {
+ if (!_glfwCreateContextEGL(window, ctxconfig, fbconfig))
+ return GLFW_FALSE;
+ }
+ }
+
+ if (window->monitor)
+ {
+ _glfwPlatformShowWindow(window);
+ updateWindowMode(window);
+ if (!acquireMonitor(window))
+ return GLFW_FALSE;
+
+ centerCursor(window);
+ }
+
+ XFlush(_glfw.x11.display);
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.disabledCursorWindow == window)
+ _glfw.x11.disabledCursorWindow = NULL;
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ if (window->x11.ic)
+ {
+ XDestroyIC(window->x11.ic);
+ window->x11.ic = NULL;
+ }
+
+ if (window->context.destroy)
+ window->context.destroy(window);
+
+ if (window->x11.handle)
+ {
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) ==
+ window->x11.handle)
+ {
+ pushSelectionToManager(window);
+ }
+
+ XDeleteContext(_glfw.x11.display, window->x11.handle, _glfw.x11.context);
+ XUnmapWindow(_glfw.x11.display, window->x11.handle);
+ XDestroyWindow(_glfw.x11.display, window->x11.handle);
+ window->x11.handle = (Window) 0;
+ }
+
+ if (window->x11.colormap)
+ {
+ XFreeColormap(_glfw.x11.display, window->x11.colormap);
+ window->x11.colormap = (Colormap) 0;
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
+{
+#if defined(X_HAVE_UTF8_STRING)
+ Xutf8SetWMProperties(_glfw.x11.display,
+ window->x11.handle,
+ title, title,
+ NULL, 0,
+ NULL, NULL, NULL);
+#else
+ // This may be a slightly better fallback than using XStoreName and
+ // XSetIconName, which always store their arguments using STRING
+ XmbSetWMProperties(_glfw.x11.display,
+ window->x11.handle,
+ title, title,
+ NULL, 0,
+ NULL, NULL, NULL);
+#endif
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_NAME, _glfw.x11.UTF8_STRING, 8,
+ PropModeReplace,
+ (unsigned char*) title, strlen(title));
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON_NAME, _glfw.x11.UTF8_STRING, 8,
+ PropModeReplace,
+ (unsigned char*) title, strlen(title));
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
+ int count, const GLFWimage* images)
+{
+ if (count)
+ {
+ int i, j, longCount = 0;
+
+ for (i = 0; i < count; i++)
+ longCount += 2 + images[i].width * images[i].height;
+
+ long* icon = calloc(longCount, sizeof(long));
+ long* target = icon;
+
+ for (i = 0; i < count; i++)
+ {
+ *target++ = images[i].width;
+ *target++ = images[i].height;
+
+ for (j = 0; j < images[i].width * images[i].height; j++)
+ {
+ *target++ = (images[i].pixels[j * 4 + 0] << 16) |
+ (images[i].pixels[j * 4 + 1] << 8) |
+ (images[i].pixels[j * 4 + 2] << 0) |
+ (images[i].pixels[j * 4 + 3] << 24);
+ }
+ }
+
+ XChangeProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON,
+ XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char*) icon,
+ longCount);
+
+ free(icon);
+ }
+ else
+ {
+ XDeleteProperty(_glfw.x11.display, window->x11.handle,
+ _glfw.x11.NET_WM_ICON);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
+{
+ Window dummy;
+ int x, y;
+
+ XTranslateCoordinates(_glfw.x11.display, window->x11.handle, _glfw.x11.root,
+ 0, 0, &x, &y, &dummy);
+
+ if (xpos)
+ *xpos = x;
+ if (ypos)
+ *ypos = y;
+}
+
+void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos)
+{
+ // HACK: Explicitly setting PPosition to any value causes some WMs, notably
+ // Compiz and Metacity, to honor the position of unmapped windows
+ if (!_glfwPlatformWindowVisible(window))
+ {
+ long supplied;
+ XSizeHints* hints = XAllocSizeHints();
+
+ if (XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied))
+ {
+ hints->flags |= PPosition;
+ hints->x = hints->y = 0;
+
+ XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints);
+ }
+
+ XFree(hints);
+ }
+
+ XMoveWindow(_glfw.x11.display, window->x11.handle, xpos, ypos);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetWindowSize(_GLFWwindow* window, int* width, int* height)
+{
+ XWindowAttributes attribs;
+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &attribs);
+
+ if (width)
+ *width = attribs.width;
+ if (height)
+ *height = attribs.height;
+}
+
+void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
+{
+ if (window->monitor)
+ {
+ if (window->monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ if (!window->resizable)
+ updateNormalHints(window, width, height);
+
+ XResizeWindow(_glfw.x11.display, window->x11.handle, width, height);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
+ int minwidth, int minheight,
+ int maxwidth, int maxheight)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ updateNormalHints(window, width, height);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom)
+{
+ int width, height;
+ _glfwPlatformGetWindowSize(window, &width, &height);
+ updateNormalHints(window, width, height);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height)
+{
+ _glfwPlatformGetWindowSize(window, width, height);
+}
+
+void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
+ int* left, int* top,
+ int* right, int* bottom)
+{
+ long* extents = NULL;
+
+ if (window->monitor || !window->decorated)
+ return;
+
+ if (_glfw.x11.NET_FRAME_EXTENTS == None)
+ return;
+
+ if (!_glfwPlatformWindowVisible(window) &&
+ _glfw.x11.NET_REQUEST_FRAME_EXTENTS)
+ {
+ XEvent event;
+ double timeout = 0.5;
+
+ // Ensure _NET_FRAME_EXTENTS is set, allowing glfwGetWindowFrameSize to
+ // function before the window is mapped
+ sendEventToWM(window, _glfw.x11.NET_REQUEST_FRAME_EXTENTS,
+ 0, 0, 0, 0, 0);
+
+ // HACK: Use a timeout because earlier versions of some window managers
+ // (at least Unity, Fluxbox and Xfwm) failed to send the reply
+ // They have been fixed but broken versions are still in the wild
+ // If you are affected by this and your window manager is NOT
+ // listed above, PLEASE report it to their and our issue trackers
+ while (!XCheckIfEvent(_glfw.x11.display,
+ &event,
+ isFrameExtentsEvent,
+ (XPointer) window))
+ {
+ if (!waitForEvent(&timeout))
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: The window manager has a broken _NET_REQUEST_FRAME_EXTENTS implementation; please report this issue");
+ return;
+ }
+ }
+ }
+
+ if (_glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_FRAME_EXTENTS,
+ XA_CARDINAL,
+ (unsigned char**) &extents) == 4)
+ {
+ if (left)
+ *left = extents[0];
+ if (top)
+ *top = extents[2];
+ if (right)
+ *right = extents[1];
+ if (bottom)
+ *bottom = extents[3];
+ }
+
+ if (extents)
+ XFree(extents);
+}
+
+void _glfwPlatformIconifyWindow(_GLFWwindow* window)
+{
+ if (window->x11.overrideRedirect)
+ {
+ // Override-redirect windows cannot be iconified or restored, as those
+ // tasks are performed by the window manager
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
+ return;
+ }
+
+ XIconifyWindow(_glfw.x11.display, window->x11.handle, _glfw.x11.screen);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformRestoreWindow(_GLFWwindow* window)
+{
+ if (window->x11.overrideRedirect)
+ {
+ // Override-redirect windows cannot be iconified or restored, as those
+ // tasks are performed by the window manager
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Iconification of full screen windows requires a WM that supports EWMH full screen");
+ return;
+ }
+
+ if (_glfwPlatformWindowIconified(window))
+ {
+ XMapWindow(_glfw.x11.display, window->x11.handle);
+ waitForVisibilityNotify(window);
+ }
+ else if (_glfwPlatformWindowVisible(window))
+ {
+ if (_glfw.x11.NET_WM_STATE &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_REMOVE,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
+ 1, 0);
+ }
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.NET_WM_STATE &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT &&
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ sendEventToWM(window,
+ _glfw.x11.NET_WM_STATE,
+ _NET_WM_STATE_ADD,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT,
+ _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ,
+ 1, 0);
+ XFlush(_glfw.x11.display);
+ }
+}
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ if (_glfwPlatformWindowVisible(window))
+ return;
+
+ XMapWindow(_glfw.x11.display, window->x11.handle);
+ waitForVisibilityNotify(window);
+}
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ XUnmapWindow(_glfw.x11.display, window->x11.handle);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformFocusWindow(_GLFWwindow* window)
+{
+ if (_glfw.x11.NET_ACTIVE_WINDOW)
+ sendEventToWM(window, _glfw.x11.NET_ACTIVE_WINDOW, 1, 0, 0, 0, 0);
+ else
+ {
+ XRaiseWindow(_glfw.x11.display, window->x11.handle);
+ XSetInputFocus(_glfw.x11.display, window->x11.handle,
+ RevertToParent, CurrentTime);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
+ _GLFWmonitor* monitor,
+ int xpos, int ypos,
+ int width, int height,
+ int refreshRate)
+{
+ if (window->monitor == monitor)
+ {
+ if (monitor)
+ {
+ if (monitor->window == window)
+ acquireMonitor(window);
+ }
+ else
+ {
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, width, height);
+ }
+
+ return;
+ }
+
+ if (window->monitor)
+ releaseMonitor(window);
+
+ _glfwInputWindowMonitorChange(window, monitor);
+ updateNormalHints(window, width, height);
+ updateWindowMode(window);
+
+ if (window->monitor)
+ {
+ XMapRaised(_glfw.x11.display, window->x11.handle);
+ if (waitForVisibilityNotify(window))
+ acquireMonitor(window);
+ }
+ else
+ {
+ XMoveResizeWindow(_glfw.x11.display, window->x11.handle,
+ xpos, ypos, width, height);
+ }
+
+ XFlush(_glfw.x11.display);
+}
+
+int _glfwPlatformWindowFocused(_GLFWwindow* window)
+{
+ Window focused;
+ int state;
+
+ XGetInputFocus(_glfw.x11.display, &focused, &state);
+ return window->x11.handle == focused;
+}
+
+int _glfwPlatformWindowIconified(_GLFWwindow* window)
+{
+ return getWindowState(window) == IconicState;
+}
+
+int _glfwPlatformWindowVisible(_GLFWwindow* window)
+{
+ XWindowAttributes wa;
+ XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa);
+ return wa.map_state == IsViewable;
+}
+
+int _glfwPlatformWindowMaximized(_GLFWwindow* window)
+{
+ Atom* states;
+ unsigned long i;
+ GLFWbool maximized = GLFW_FALSE;
+ const unsigned long count =
+ _glfwGetWindowPropertyX11(window->x11.handle,
+ _glfw.x11.NET_WM_STATE,
+ XA_ATOM,
+ (unsigned char**) &states);
+
+ for (i = 0; i < count; i++)
+ {
+ if (states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
+ states[i] == _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
+ {
+ maximized = GLFW_TRUE;
+ break;
+ }
+ }
+
+ XFree(states);
+ return maximized;
+}
+
+void _glfwPlatformPollEvents(void)
+{
+ _glfwPollJoystickEvents();
+
+ int count = XPending(_glfw.x11.display);
+ while (count--)
+ {
+ XEvent event;
+ XNextEvent(_glfw.x11.display, &event);
+ processEvent(&event);
+ }
+
+ if (_glfw.x11.disabledCursorWindow)
+ centerCursor(_glfw.x11.disabledCursorWindow);
+
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformWaitEvents(void)
+{
+ while (!XPending(_glfw.x11.display))
+ waitForEvent(NULL);
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformWaitEventsTimeout(double timeout)
+{
+ while (!XPending(_glfw.x11.display))
+ {
+ if (!waitForEvent(&timeout))
+ break;
+ }
+
+ _glfwPlatformPollEvents();
+}
+
+void _glfwPlatformPostEmptyEvent(void)
+{
+ XEvent event;
+ _GLFWwindow* window = _glfw.windowListHead;
+
+ memset(&event, 0, sizeof(event));
+ event.type = ClientMessage;
+ event.xclient.window = window->x11.handle;
+ event.xclient.format = 32; // Data is 32-bit longs
+ event.xclient.message_type = _glfw.x11.NULL_;
+
+ XSendEvent(_glfw.x11.display, window->x11.handle, False, 0, &event);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
+{
+ Window root, child;
+ int rootX, rootY, childX, childY;
+ unsigned int mask;
+
+ XQueryPointer(_glfw.x11.display, window->x11.handle,
+ &root, &child,
+ &rootX, &rootY, &childX, &childY,
+ &mask);
+
+ if (xpos)
+ *xpos = childX;
+ if (ypos)
+ *ypos = childY;
+}
+
+void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
+{
+ // Store the new position so it can be recognized later
+ window->x11.warpCursorPosX = (int) x;
+ window->x11.warpCursorPosY = (int) y;
+
+ XWarpPointer(_glfw.x11.display, None, window->x11.handle,
+ 0,0,0,0, (int) x, (int) y);
+ XFlush(_glfw.x11.display);
+}
+
+void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode)
+{
+ if (mode == GLFW_CURSOR_DISABLED)
+ {
+ _glfw.x11.disabledCursorWindow = window;
+ _glfwPlatformGetCursorPos(window,
+ &_glfw.x11.restoreCursorPosX,
+ &_glfw.x11.restoreCursorPosY);
+ centerCursor(window);
+ XGrabPointer(_glfw.x11.display, window->x11.handle, True,
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+ GrabModeAsync, GrabModeAsync,
+ window->x11.handle, _glfw.x11.cursor, CurrentTime);
+ }
+ else if (_glfw.x11.disabledCursorWindow == window)
+ {
+ _glfw.x11.disabledCursorWindow = NULL;
+ XUngrabPointer(_glfw.x11.display, CurrentTime);
+ _glfwPlatformSetCursorPos(window,
+ _glfw.x11.restoreCursorPosX,
+ _glfw.x11.restoreCursorPosY);
+ }
+
+ updateCursorImage(window);
+ XFlush(_glfw.x11.display);
+}
+
+const char* _glfwPlatformGetKeyName(int key, int scancode)
+{
+ KeySym keysym;
+ int extra;
+
+ if (!_glfw.x11.xkb.available)
+ return NULL;
+
+ if (key != GLFW_KEY_UNKNOWN)
+ scancode = _glfw.x11.nativeKeys[key];
+
+ if (!_glfwIsPrintable(_glfw.x11.publicKeys[scancode]))
+ return NULL;
+
+ keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0);
+ if (keysym == NoSymbol)
+ return NULL;
+
+ XkbTranslateKeySym(_glfw.x11.display, &keysym, 0,
+ _glfw.x11.keyName, sizeof(_glfw.x11.keyName),
+ &extra);
+
+ if (!strlen(_glfw.x11.keyName))
+ return NULL;
+
+ return _glfw.x11.keyName;
+}
+
+int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
+ const GLFWimage* image,
+ int xhot, int yhot)
+{
+ cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
+ if (!cursor->x11.handle)
+ return GLFW_FALSE;
+
+ return GLFW_TRUE;
+}
+
+int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
+{
+ cursor->x11.handle = XCreateFontCursor(_glfw.x11.display,
+ translateCursorShape(shape));
+ if (!cursor->x11.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create standard cursor");
+ return GLFW_FALSE;
+ }
+
+ return GLFW_TRUE;
+}
+
+void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
+{
+ if (cursor->x11.handle)
+ XFreeCursor(_glfw.x11.display, cursor->x11.handle);
+}
+
+void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
+{
+ if (window->cursorMode == GLFW_CURSOR_NORMAL)
+ {
+ updateCursorImage(window);
+ XFlush(_glfw.x11.display);
+ }
+}
+
+void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string)
+{
+ free(_glfw.x11.clipboardString);
+ _glfw.x11.clipboardString = strdup(string);
+
+ XSetSelectionOwner(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD,
+ window->x11.handle, CurrentTime);
+
+ if (XGetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD) !=
+ window->x11.handle)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to become owner of clipboard selection");
+ }
+}
+
+const char* _glfwPlatformGetClipboardString(_GLFWwindow* window)
+{
+ size_t i;
+ const Atom formats[] = { _glfw.x11.UTF8_STRING,
+ _glfw.x11.COMPOUND_STRING,
+ XA_STRING };
+ const size_t formatCount = sizeof(formats) / sizeof(formats[0]);
+
+ if (findWindowByHandle(XGetSelectionOwner(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD)))
+ {
+ // Instead of doing a large number of X round-trips just to put this
+ // string into a window property and then read it back, just return it
+ return _glfw.x11.clipboardString;
+ }
+
+ free(_glfw.x11.clipboardString);
+ _glfw.x11.clipboardString = NULL;
+
+ for (i = 0; i < formatCount; i++)
+ {
+ char* data;
+ XEvent event;
+
+ XConvertSelection(_glfw.x11.display,
+ _glfw.x11.CLIPBOARD,
+ formats[i],
+ _glfw.x11.GLFW_SELECTION,
+ window->x11.handle, CurrentTime);
+
+ while (!XCheckTypedEvent(_glfw.x11.display, SelectionNotify, &event))
+ waitForEvent(NULL);
+
+ if (event.xselection.property == None)
+ continue;
+
+ if (_glfwGetWindowPropertyX11(event.xselection.requestor,
+ event.xselection.property,
+ event.xselection.target,
+ (unsigned char**) &data))
+ {
+ _glfw.x11.clipboardString = strdup(data);
+ }
+
+ XFree(data);
+
+ XDeleteProperty(_glfw.x11.display,
+ event.xselection.requestor,
+ event.xselection.property);
+
+ if (_glfw.x11.clipboardString)
+ break;
+ }
+
+ if (_glfw.x11.clipboardString == NULL)
+ {
+ _glfwInputError(GLFW_FORMAT_UNAVAILABLE,
+ "X11: Failed to convert clipboard to string");
+ }
+
+ return _glfw.x11.clipboardString;
+}
+
+char** _glfwPlatformGetRequiredInstanceExtensions(uint32_t* count)
+{
+ char** extensions;
+
+ *count = 0;
+
+ if (!_glfw.vk.KHR_xcb_surface || !_glfw.x11.x11xcb.handle)
+ {
+ if (!_glfw.vk.KHR_xlib_surface)
+ return NULL;
+ }
+
+ extensions = calloc(2, sizeof(char*));
+ extensions[0] = strdup("VK_KHR_surface");
+
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ extensions[1] = strdup("VK_KHR_xcb_surface");
+ else
+ extensions[1] = strdup("VK_KHR_xlib_surface");
+
+ *count = 2;
+ return extensions;
+}
+
+int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,
+ VkPhysicalDevice device,
+ uint32_t queuefamily)
+{
+ VisualID visualID = XVisualIDFromVisual(DefaultVisual(_glfw.x11.display,
+ _glfw.x11.screen));
+
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ {
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR vkGetPhysicalDeviceXcbPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXcbPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceXcbPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");
+ return GLFW_FALSE;
+ }
+
+ xcb_connection_t* connection =
+ _glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
+ if (!connection)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to retrieve XCB connection");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceXcbPresentationSupportKHR(device,
+ queuefamily,
+ connection,
+ visualID);
+ }
+ else
+ {
+ PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR vkGetPhysicalDeviceXlibPresentationSupportKHR =
+ (PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR)
+ vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceXlibPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceXlibPresentationSupportKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");
+ return GLFW_FALSE;
+ }
+
+ return vkGetPhysicalDeviceXlibPresentationSupportKHR(device,
+ queuefamily,
+ _glfw.x11.display,
+ visualID);
+ }
+}
+
+VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
+ _GLFWwindow* window,
+ const VkAllocationCallbacks* allocator,
+ VkSurfaceKHR* surface)
+{
+ if (_glfw.vk.KHR_xcb_surface && _glfw.x11.x11xcb.handle)
+ {
+ VkResult err;
+ VkXcbSurfaceCreateInfoKHR sci;
+ PFN_vkCreateXcbSurfaceKHR vkCreateXcbSurfaceKHR;
+
+ xcb_connection_t* connection =
+ _glfw.x11.x11xcb.XGetXCBConnection(_glfw.x11.display);
+ if (!connection)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to retrieve XCB connection");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ vkCreateXcbSurfaceKHR = (PFN_vkCreateXcbSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateXcbSurfaceKHR");
+ if (!vkCreateXcbSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xcb_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ sci.connection = connection;
+ sci.window = window->x11.handle;
+
+ err = vkCreateXcbSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create Vulkan XCB surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+ }
+ else
+ {
+ VkResult err;
+ VkXlibSurfaceCreateInfoKHR sci;
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR;
+
+ vkCreateXlibSurfaceKHR = (PFN_vkCreateXlibSurfaceKHR)
+ vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR");
+ if (!vkCreateXlibSurfaceKHR)
+ {
+ _glfwInputError(GLFW_API_UNAVAILABLE,
+ "X11: Vulkan instance missing VK_KHR_xlib_surface extension");
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
+ }
+
+ memset(&sci, 0, sizeof(sci));
+ sci.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+ sci.dpy = _glfw.x11.display;
+ sci.window = window->x11.handle;
+
+ err = vkCreateXlibSurfaceKHR(instance, &sci, allocator, surface);
+ if (err)
+ {
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "X11: Failed to create Vulkan X11 surface: %s",
+ _glfwGetVulkanResultString(err));
+ }
+
+ return err;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW 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;
+}
+
diff --git a/glfw-3.2.1/src/xkb_unicode.c b/glfw-3.2.1/src/xkb_unicode.c
new file mode 100644
index 0000000..3223335
--- /dev/null
+++ b/glfw-3.2.1/src/xkb_unicode.c
@@ -0,0 +1,889 @@
+//========================================================================
+// GLFW 3.2 X11 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2016 Camilla Berglund <elmindreda@glfw.org>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+
+#include "internal.h"
+
+
+/*
+ * 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 },
+ // Numeric keypad with numlock on
+ { 0xff80 /*XKB_KEY_KP_Space*/, ' ' },
+ { 0xffbd /*XKB_KEY_KP_Equal*/, '=' },
+ { 0xffaa /*XKB_KEY_KP_Multiply*/, '*' },
+ { 0xffab /*XKB_KEY_KP_Add*/, '+' },
+ { 0xffac /*XKB_KEY_KP_Separator*/, ',' },
+ { 0xffad /*XKB_KEY_KP_Subtract*/, '-' },
+ { 0xffae /*XKB_KEY_KP_Decimal*/, '.' },
+ { 0xffaf /*XKB_KEY_KP_Divide*/, '/' },
+ { 0xffb0 /*XKB_KEY_KP_0*/, 0x0030 },
+ { 0xffb1 /*XKB_KEY_KP_1*/, 0x0031 },
+ { 0xffb2 /*XKB_KEY_KP_2*/, 0x0032 },
+ { 0xffb3 /*XKB_KEY_KP_3*/, 0x0033 },
+ { 0xffb4 /*XKB_KEY_KP_4*/, 0x0034 },
+ { 0xffb5 /*XKB_KEY_KP_5*/, 0x0035 },
+ { 0xffb6 /*XKB_KEY_KP_6*/, 0x0036 },
+ { 0xffb7 /*XKB_KEY_KP_7*/, 0x0037 },
+ { 0xffb8 /*XKB_KEY_KP_8*/, 0x0038 },
+ { 0xffb9 /*XKB_KEY_KP_9*/, 0x0039 }
+};
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW 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;
+}
+
diff --git a/glfw-3.2.1/src/xkb_unicode.h b/glfw-3.2.1/src/xkb_unicode.h
new file mode 100644
index 0000000..688374d
--- /dev/null
+++ b/glfw-3.2.1/src/xkb_unicode.h
@@ -0,0 +1,33 @@
+//========================================================================
+// GLFW 3.2 Linux - 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.
+//
+//========================================================================
+
+#ifndef _glfw3_xkb_unicode_h_
+#define _glfw3_xkb_unicode_h_
+
+
+long _glfwKeySym2Unicode(unsigned int keysym);
+
+#endif // _glfw3_xkb_unicode_h_