aboutsummaryrefslogtreecommitdiff
path: root/3rdparty/glfw/source/src/win32_init.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/glfw/source/src/win32_init.c')
-rw-r--r--3rdparty/glfw/source/src/win32_init.c713
1 files changed, 713 insertions, 0 deletions
diff --git a/3rdparty/glfw/source/src/win32_init.c b/3rdparty/glfw/source/src/win32_init.c
new file mode 100644
index 0000000..ae00b05
--- /dev/null
+++ b/3rdparty/glfw/source/src/win32_init.c
@@ -0,0 +1,713 @@
+//========================================================================
+// GLFW 3.4 Win32 - www.glfw.org
+//------------------------------------------------------------------------
+// Copyright (c) 2002-2006 Marcus Geelnard
+// Copyright (c) 2006-2019 Camilla Löwy <[email protected]>
+//
+// This software is provided 'as-is', without any express or implied
+// warranty. In no event will the authors be held liable for any damages
+// arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose,
+// including commercial applications, and to alter it and redistribute it
+// freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not
+// claim that you wrote the original software. If you use this software
+// in a product, an acknowledgment in the product documentation would
+// be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not
+// be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source
+// distribution.
+//
+//========================================================================
+// Please use C89 style variable declarations in this file because VS 2010
+//========================================================================
+
+#include "internal.h"
+
+#include <stdlib.h>
+
+static const GUID _glfw_GUID_DEVINTERFACE_HID =
+ {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
+
+#define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
+
+#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
+
+#if defined(_GLFW_BUILD_DLL)
+ #pragma message("These symbols must be exported by the executable and have no effect in a DLL")
+#endif
+
+// Executables (but not DLLs) exporting this symbol with this value will be
+// automatically directed to the high-performance GPU on Nvidia Optimus systems
+// with up-to-date drivers
+//
+__declspec(dllexport) DWORD NvOptimusEnablement = 1;
+
+// Executables (but not DLLs) exporting this symbol with this value will be
+// automatically directed to the high-performance GPU on AMD PowerXpress systems
+// with up-to-date drivers
+//
+__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
+
+#endif // _GLFW_USE_HYBRID_HPG
+
+#if defined(_GLFW_BUILD_DLL)
+
+// GLFW DLL entry point
+//
+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
+{
+ return TRUE;
+}
+
+#endif // _GLFW_BUILD_DLL
+
+// Load necessary libraries (DLLs)
+//
+static GLFWbool loadLibraries(void)
+{
+ if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ (const WCHAR*) &_glfw,
+ (HMODULE*) &_glfw.win32.instance))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to retrieve own module handle");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll");
+ if (!_glfw.win32.user32.instance)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to load user32.dll");
+ return GLFW_FALSE;
+ }
+
+ _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDPIAware");
+ _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
+ _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
+ _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
+ _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow");
+ _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
+ _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
+
+ _glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll");
+ if (_glfw.win32.dinput8.instance)
+ {
+ _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
+ _glfwPlatformGetModuleSymbol(_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 = _glfwPlatformLoadModule(names[i]);
+ if (_glfw.win32.xinput.instance)
+ {
+ _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetCapabilities");
+ _glfw.win32.xinput.GetState = (PFN_XInputGetState)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetState");
+
+ break;
+ }
+ }
+ }
+
+ _glfw.win32.dwmapi.instance = _glfwPlatformLoadModule("dwmapi.dll");
+ if (_glfw.win32.dwmapi.instance)
+ {
+ _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
+ _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmFlush");
+ _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
+ _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
+ }
+
+ _glfw.win32.shcore.instance = _glfwPlatformLoadModule("shcore.dll");
+ if (_glfw.win32.shcore.instance)
+ {
+ _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
+ _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "GetDpiForMonitor");
+ }
+
+ _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll");
+ if (_glfw.win32.ntdll.instance)
+ {
+ _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
+ _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
+ }
+
+ return GLFW_TRUE;
+}
+
+// Unload used libraries (DLLs)
+//
+static void freeLibraries(void)
+{
+ if (_glfw.win32.xinput.instance)
+ _glfwPlatformFreeModule(_glfw.win32.xinput.instance);
+
+ if (_glfw.win32.dinput8.instance)
+ _glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
+
+ if (_glfw.win32.user32.instance)
+ _glfwPlatformFreeModule(_glfw.win32.user32.instance);
+
+ if (_glfw.win32.dwmapi.instance)
+ _glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
+
+ if (_glfw.win32.shcore.instance)
+ _glfwPlatformFreeModule(_glfw.win32.shcore.instance);
+
+ if (_glfw.win32.ntdll.instance)
+ _glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
+}
+
+// Create key code translation tables
+//
+static void createKeyTables(void)
+{
+ int scancode;
+
+ memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
+ memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
+
+ // See https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf
+ // PS/2 set 1 make
+#pragma push_macro("INDEX")
+#undef INDEX
+#define INDEX(makeCode, e0, e1) GLFW_WIN32_CALC_KEYMAP(makeCode, e0, e1)
+
+ short int* keycodes = _glfw.win32.keycodes;
+
+ // E0 bit-v v-E1 bit
+ keycodes[INDEX(0x0B, 0, 0)] = GLFW_KEY_0;
+ keycodes[INDEX(0x02, 0, 0)] = GLFW_KEY_1;
+ keycodes[INDEX(0x03, 0, 0)] = GLFW_KEY_2;
+ keycodes[INDEX(0x04, 0, 0)] = GLFW_KEY_3;
+ keycodes[INDEX(0x05, 0, 0)] = GLFW_KEY_4;
+ keycodes[INDEX(0x06, 0, 0)] = GLFW_KEY_5;
+ keycodes[INDEX(0x07, 0, 0)] = GLFW_KEY_6;
+ keycodes[INDEX(0x08, 0, 0)] = GLFW_KEY_7;
+ keycodes[INDEX(0x09, 0, 0)] = GLFW_KEY_8;
+ keycodes[INDEX(0x0A, 0, 0)] = GLFW_KEY_9;
+ keycodes[INDEX(0x1E, 0, 0)] = GLFW_KEY_A;
+ keycodes[INDEX(0x30, 0, 0)] = GLFW_KEY_B;
+ keycodes[INDEX(0x2E, 0, 0)] = GLFW_KEY_C;
+ keycodes[INDEX(0x20, 0, 0)] = GLFW_KEY_D;
+ keycodes[INDEX(0x12, 0, 0)] = GLFW_KEY_E;
+ keycodes[INDEX(0x21, 0, 0)] = GLFW_KEY_F;
+ keycodes[INDEX(0x22, 0, 0)] = GLFW_KEY_G;
+ keycodes[INDEX(0x23, 0, 0)] = GLFW_KEY_H;
+ keycodes[INDEX(0x17, 0, 0)] = GLFW_KEY_I;
+ keycodes[INDEX(0x24, 0, 0)] = GLFW_KEY_J;
+ keycodes[INDEX(0x25, 0, 0)] = GLFW_KEY_K;
+ keycodes[INDEX(0x26, 0, 0)] = GLFW_KEY_L;
+ keycodes[INDEX(0x32, 0, 0)] = GLFW_KEY_M;
+ keycodes[INDEX(0x31, 0, 0)] = GLFW_KEY_N;
+ keycodes[INDEX(0x18, 0, 0)] = GLFW_KEY_O;
+ keycodes[INDEX(0x19, 0, 0)] = GLFW_KEY_P;
+ keycodes[INDEX(0x10, 0, 0)] = GLFW_KEY_Q;
+ keycodes[INDEX(0x13, 0, 0)] = GLFW_KEY_R;
+ keycodes[INDEX(0x1F, 0, 0)] = GLFW_KEY_S;
+ keycodes[INDEX(0x14, 0, 0)] = GLFW_KEY_T;
+ keycodes[INDEX(0x16, 0, 0)] = GLFW_KEY_U;
+ keycodes[INDEX(0x2F, 0, 0)] = GLFW_KEY_V;
+ keycodes[INDEX(0x11, 0, 0)] = GLFW_KEY_W;
+ keycodes[INDEX(0x2D, 0, 0)] = GLFW_KEY_X;
+ keycodes[INDEX(0x15, 0, 0)] = GLFW_KEY_Y;
+ keycodes[INDEX(0x2C, 0, 0)] = GLFW_KEY_Z;
+
+ keycodes[INDEX(0x28, 0, 0)] = GLFW_KEY_APOSTROPHE;
+ keycodes[INDEX(0x2B, 0, 0)] = GLFW_KEY_BACKSLASH;
+ keycodes[INDEX(0x33, 0, 0)] = GLFW_KEY_COMMA;
+ keycodes[INDEX(0x0D, 0, 0)] = GLFW_KEY_EQUAL;
+ keycodes[INDEX(0x29, 0, 0)] = GLFW_KEY_GRAVE_ACCENT;
+ keycodes[INDEX(0x1A, 0, 0)] = GLFW_KEY_LEFT_BRACKET;
+ keycodes[INDEX(0x0C, 0, 0)] = GLFW_KEY_MINUS;
+ keycodes[INDEX(0x34, 0, 0)] = GLFW_KEY_PERIOD;
+ keycodes[INDEX(0x1B, 0, 0)] = GLFW_KEY_RIGHT_BRACKET;
+ keycodes[INDEX(0x27, 0, 0)] = GLFW_KEY_SEMICOLON;
+ keycodes[INDEX(0x35, 0, 0)] = GLFW_KEY_SLASH;
+ keycodes[INDEX(0x56, 0, 0)] = GLFW_KEY_WORLD_2;
+
+ keycodes[INDEX(0x0E, 0, 0)] = GLFW_KEY_BACKSPACE;
+ keycodes[INDEX(0x53, 1, 0)] = GLFW_KEY_DELETE;
+ keycodes[INDEX(0x4F, 1, 0)] = GLFW_KEY_END;
+ keycodes[INDEX(0x1C, 0, 0)] = GLFW_KEY_ENTER;
+ keycodes[INDEX(0x01, 0, 0)] = GLFW_KEY_ESCAPE;
+ keycodes[INDEX(0x47, 1, 0)] = GLFW_KEY_HOME;
+ keycodes[INDEX(0x52, 1, 0)] = GLFW_KEY_INSERT;
+ keycodes[INDEX(0x5D, 1, 0)] = GLFW_KEY_MENU;
+ keycodes[INDEX(0x51, 1, 0)] = GLFW_KEY_PAGE_DOWN;
+ keycodes[INDEX(0x49, 1, 0)] = GLFW_KEY_PAGE_UP;
+ keycodes[INDEX(0x46, 1, 0)] = GLFW_KEY_PAUSE; // Ctrl+Pause
+ keycodes[INDEX(0x1D, 0, 1)] = GLFW_KEY_PAUSE; // Pause
+ keycodes[INDEX(0x39, 0, 0)] = GLFW_KEY_SPACE;
+ keycodes[INDEX(0x0F, 0, 0)] = GLFW_KEY_TAB;
+ keycodes[INDEX(0x3A, 0, 0)] = GLFW_KEY_CAPS_LOCK;
+ keycodes[INDEX(0x45, 1, 0)] = GLFW_KEY_NUM_LOCK;
+ keycodes[INDEX(0x46, 0, 0)] = GLFW_KEY_SCROLL_LOCK;
+ keycodes[INDEX(0x3B, 0, 0)] = GLFW_KEY_F1;
+ keycodes[INDEX(0x3C, 0, 0)] = GLFW_KEY_F2;
+ keycodes[INDEX(0x3D, 0, 0)] = GLFW_KEY_F3;
+ keycodes[INDEX(0x3E, 0, 0)] = GLFW_KEY_F4;
+ keycodes[INDEX(0x3F, 0, 0)] = GLFW_KEY_F5;
+ keycodes[INDEX(0x40, 0, 0)] = GLFW_KEY_F6;
+ keycodes[INDEX(0x41, 0, 0)] = GLFW_KEY_F7;
+ keycodes[INDEX(0x42, 0, 0)] = GLFW_KEY_F8;
+ keycodes[INDEX(0x43, 0, 0)] = GLFW_KEY_F9;
+ keycodes[INDEX(0x44, 0, 0)] = GLFW_KEY_F10;
+ keycodes[INDEX(0x57, 0, 0)] = GLFW_KEY_F11;
+ keycodes[INDEX(0x58, 0, 0)] = GLFW_KEY_F12;
+ keycodes[INDEX(0x64, 0, 0)] = GLFW_KEY_F13;
+ keycodes[INDEX(0x65, 0, 0)] = GLFW_KEY_F14;
+ keycodes[INDEX(0x66, 0, 0)] = GLFW_KEY_F15;
+ keycodes[INDEX(0x67, 0, 0)] = GLFW_KEY_F16;
+ keycodes[INDEX(0x68, 0, 0)] = GLFW_KEY_F17;
+ keycodes[INDEX(0x69, 0, 0)] = GLFW_KEY_F18;
+ keycodes[INDEX(0x6A, 0, 0)] = GLFW_KEY_F19;
+ keycodes[INDEX(0x6B, 0, 0)] = GLFW_KEY_F20;
+ keycodes[INDEX(0x6C, 0, 0)] = GLFW_KEY_F21;
+ keycodes[INDEX(0x6D, 0, 0)] = GLFW_KEY_F22;
+ keycodes[INDEX(0x6E, 0, 0)] = GLFW_KEY_F23;
+ keycodes[INDEX(0x76, 0, 0)] = GLFW_KEY_F24;
+ keycodes[INDEX(0x38, 0, 0)] = GLFW_KEY_LEFT_ALT;
+ keycodes[INDEX(0x1D, 0, 0)] = GLFW_KEY_LEFT_CONTROL;
+ keycodes[INDEX(0x2A, 0, 0)] = GLFW_KEY_LEFT_SHIFT;
+ keycodes[INDEX(0x5B, 1, 0)] = GLFW_KEY_LEFT_SUPER;
+ keycodes[INDEX(0x37, 1, 0)] = GLFW_KEY_PRINT_SCREEN;
+ keycodes[INDEX(0x38, 1, 0)] = GLFW_KEY_RIGHT_ALT;
+ keycodes[INDEX(0x1D, 1, 0)] = GLFW_KEY_RIGHT_CONTROL;
+ keycodes[INDEX(0x36, 0, 0)] = GLFW_KEY_RIGHT_SHIFT;
+ keycodes[INDEX(0x5C, 1, 0)] = GLFW_KEY_RIGHT_SUPER;
+ keycodes[INDEX(0x50, 1, 0)] = GLFW_KEY_DOWN;
+ keycodes[INDEX(0x4B, 1, 0)] = GLFW_KEY_LEFT;
+ keycodes[INDEX(0x4D, 1, 0)] = GLFW_KEY_RIGHT;
+ keycodes[INDEX(0x48, 1, 0)] = GLFW_KEY_UP;
+
+ keycodes[INDEX(0x52, 0, 0)] = GLFW_KEY_KP_0;
+ keycodes[INDEX(0x4F, 0, 0)] = GLFW_KEY_KP_1;
+ keycodes[INDEX(0x50, 0, 0)] = GLFW_KEY_KP_2;
+ keycodes[INDEX(0x51, 0, 0)] = GLFW_KEY_KP_3;
+ keycodes[INDEX(0x4B, 0, 0)] = GLFW_KEY_KP_4;
+ keycodes[INDEX(0x4C, 0, 0)] = GLFW_KEY_KP_5;
+ keycodes[INDEX(0x4D, 0, 0)] = GLFW_KEY_KP_6;
+ keycodes[INDEX(0x47, 0, 0)] = GLFW_KEY_KP_7;
+ keycodes[INDEX(0x48, 0, 0)] = GLFW_KEY_KP_8;
+ keycodes[INDEX(0x49, 0, 0)] = GLFW_KEY_KP_9;
+ keycodes[INDEX(0x4E, 0, 0)] = GLFW_KEY_KP_ADD;
+ keycodes[INDEX(0x53, 0, 0)] = GLFW_KEY_KP_DECIMAL;
+ keycodes[INDEX(0x35, 1, 0)] = GLFW_KEY_KP_DIVIDE;
+ keycodes[INDEX(0x1C, 1, 0)] = GLFW_KEY_KP_ENTER;
+ keycodes[INDEX(0x59, 0, 0)] = GLFW_KEY_KP_EQUAL;
+ keycodes[INDEX(0x37, 0, 0)] = GLFW_KEY_KP_MULTIPLY;
+ keycodes[INDEX(0x4A, 0, 0)] = GLFW_KEY_KP_SUBTRACT;
+#pragma pop_macro("INDEX")
+
+ for (scancode = 0; scancode < (sizeof(_glfw.win32.keycodes) / sizeof(_glfw.win32.keycodes[0])); scancode++)
+ {
+ int keycode = _glfw.win32.keycodes[scancode];
+ if (keycode > 0)
+ {
+ int e0 = scancode & (1 << GLFW_WIN32_KEYMAP_E0_BIT);
+ int e1 = scancode & (1 << GLFW_WIN32_KEYMAP_E1_BIT);
+ // NOTE: operator || outputs 0 or 1 regardless the value of the operands
+ GLFWbool extended = e0 || e1;
+ // Old scancode format:
+ // Xkkkkkkkk <- 8 bit index
+ // ^-- Extended bit
+ int compatScancode = (scancode & 0xFF) | (extended & 0x01) << 8;
+
+ _glfw.win32.scancodes[keycode] = compatScancode;
+ }
+ }
+}
+
+// Creates a dummy window for behind-the-scenes work
+//
+static GLFWbool createHelperWindow(void)
+{
+ MSG msg;
+
+ _glfw.win32.helperWindowHandle =
+ CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
+ _GLFW_WNDCLASSNAME,
+ L"GLFW message window",
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
+ 0, 0, 1, 1,
+ NULL, NULL,
+ _glfw.win32.instance,
+ NULL);
+
+ if (!_glfw.win32.helperWindowHandle)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to create helper window");
+ return GLFW_FALSE;
+ }
+
+ // HACK: The command to the first ShowWindow call is ignored if the parent
+ // process passed along a STARTUPINFO, so clear that with a no-op call
+ ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
+
+ // Register for HID device notifications
+ {
+ DEV_BROADCAST_DEVICEINTERFACE_W dbi;
+ ZeroMemory(&dbi, sizeof(dbi));
+ dbi.dbcc_size = sizeof(dbi);
+ dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
+ dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
+
+ _glfw.win32.deviceNotificationHandle =
+ RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
+ (DEV_BROADCAST_HDR*) &dbi,
+ DEVICE_NOTIFY_WINDOW_HANDLE);
+ }
+
+ while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+
+ return GLFW_TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+////// GLFW internal API //////
+//////////////////////////////////////////////////////////////////////////
+
+// Returns a wide string version of the specified UTF-8 string
+//
+WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source)
+{
+ WCHAR* target;
+ int count;
+
+ count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0);
+ if (!count)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string from UTF-8");
+ return NULL;
+ }
+
+ target = _glfw_calloc(count, sizeof(WCHAR));
+
+ if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string from UTF-8");
+ _glfw_free(target);
+ return NULL;
+ }
+
+ return target;
+}
+
+// Returns a UTF-8 string version of the specified wide string
+//
+char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source)
+{
+ char* target;
+ int size;
+
+ size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL);
+ if (!size)
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string to UTF-8");
+ return NULL;
+ }
+
+ target = _glfw_calloc(size, 1);
+
+ if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL))
+ {
+ _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
+ "Win32: Failed to convert string to UTF-8");
+ _glfw_free(target);
+ return NULL;
+ }
+
+ return target;
+}
+
+// Reports the specified error, appending information about the last Win32 error
+//
+void _glfwInputErrorWin32(int error, const char* description)
+{
+ WCHAR buffer[_GLFW_MESSAGE_SIZE] = L"";
+ char message[_GLFW_MESSAGE_SIZE] = "";
+
+ FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL,
+ GetLastError() & 0xffff,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ buffer,
+ sizeof(buffer) / sizeof(WCHAR),
+ NULL);
+ WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL);
+
+ _glfwInputError(error, "%s: %s", description, message);
+}
+
+// Updates key names according to the current keyboard layout
+//
+void _glfwUpdateKeyNamesWin32(void)
+{
+ int key;
+ BYTE state[256] = {0};
+
+ memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames));
+
+ for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++)
+ {
+ UINT vk;
+ int scancode, length;
+ WCHAR chars[16];
+
+ scancode = _glfw.win32.scancodes[key];
+ if (scancode == -1)
+ continue;
+
+ if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD)
+ {
+ const UINT vks[] = {
+ VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,
+ VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
+ VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE,
+ VK_MULTIPLY, VK_SUBTRACT, VK_ADD
+ };
+
+ vk = vks[key - GLFW_KEY_KP_0];
+ }
+ else
+ vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK);
+
+ length = ToUnicode(vk, scancode, state,
+ chars, sizeof(chars) / sizeof(WCHAR),
+ 0);
+
+ if (length == -1)
+ {
+ length = ToUnicode(vk, scancode, state,
+ chars, sizeof(chars) / sizeof(WCHAR),
+ 0);
+ }
+
+ if (length < 1)
+ continue;
+
+ WideCharToMultiByte(CP_UTF8, 0, chars, 1,
+ _glfw.win32.keynames[key],
+ sizeof(_glfw.win32.keynames[key]),
+ NULL, NULL);
+ }
+}
+
+// Replacement for IsWindowsVersionOrGreater, as we cannot rely on the
+// application having a correct embedded manifest
+//
+BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp)
+{
+ OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp };
+ DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR;
+ ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
+ // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+ // latter lies unless the user knew to embed a non-default manifest
+ // announcing support for Windows 10 via supportedOS GUID
+ return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+// Checks whether we are on at least the specified build of Windows 10
+//
+BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build)
+{
+ OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build };
+ DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER;
+ ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL);
+ cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL);
+ // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the
+ // latter lies unless the user knew to embed a non-default manifest
+ // announcing support for Windows 10 via supportedOS GUID
+ return RtlVerifyVersionInfo(&osvi, mask, cond) == 0;
+}
+
+GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform)
+{
+ const _GLFWplatform win32 =
+ {
+ GLFW_PLATFORM_WIN32,
+ _glfwInitWin32,
+ _glfwTerminateWin32,
+ _glfwGetCursorPosWin32,
+ _glfwSetCursorPosWin32,
+ _glfwSetCursorModeWin32,
+ _glfwSetRawMouseMotionWin32,
+ _glfwRawMouseMotionSupportedWin32,
+ _glfwKeyboardsSupportedWin32,
+ _glfwCreateCursorWin32,
+ _glfwCreateStandardCursorWin32,
+ _glfwDestroyCursorWin32,
+ _glfwSetCursorWin32,
+ _glfwGetScancodeNameWin32,
+ _glfwGetKeyScancodeWin32,
+ _glfwSetClipboardStringWin32,
+ _glfwGetClipboardStringWin32,
+ _glfwInitJoysticksWin32,
+ _glfwTerminateJoysticksWin32,
+ _glfwPollJoystickWin32,
+ _glfwGetMappingNameWin32,
+ _glfwUpdateGamepadGUIDWin32,
+ _glfwFreeMonitorWin32,
+ _glfwGetMonitorPosWin32,
+ _glfwGetMonitorContentScaleWin32,
+ _glfwGetMonitorWorkareaWin32,
+ _glfwGetVideoModesWin32,
+ _glfwGetVideoModeWin32,
+ _glfwGetGammaRampWin32,
+ _glfwSetGammaRampWin32,
+ _glfwCreateWindowWin32,
+ _glfwDestroyWindowWin32,
+ _glfwSetWindowTitleWin32,
+ _glfwSetWindowIconWin32,
+ _glfwGetWindowPosWin32,
+ _glfwSetWindowPosWin32,
+ _glfwGetWindowSizeWin32,
+ _glfwSetWindowSizeWin32,
+ _glfwSetWindowSizeLimitsWin32,
+ _glfwSetWindowAspectRatioWin32,
+ _glfwGetFramebufferSizeWin32,
+ _glfwGetWindowFrameSizeWin32,
+ _glfwGetWindowContentScaleWin32,
+ _glfwIconifyWindowWin32,
+ _glfwRestoreWindowWin32,
+ _glfwMaximizeWindowWin32,
+ _glfwShowWindowWin32,
+ _glfwHideWindowWin32,
+ _glfwRequestWindowAttentionWin32,
+ _glfwFocusWindowWin32,
+ _glfwSetWindowMonitorWin32,
+ _glfwWindowFocusedWin32,
+ _glfwWindowIconifiedWin32,
+ _glfwWindowVisibleWin32,
+ _glfwWindowMaximizedWin32,
+ _glfwWindowHoveredWin32,
+ _glfwFramebufferTransparentWin32,
+ _glfwGetWindowOpacityWin32,
+ _glfwSetWindowResizableWin32,
+ _glfwSetWindowDecoratedWin32,
+ _glfwSetWindowFloatingWin32,
+ _glfwSetWindowOpacityWin32,
+ _glfwSetWindowMousePassthroughWin32,
+ _glfwPollEventsWin32,
+ _glfwWaitEventsWin32,
+ _glfwWaitEventsTimeoutWin32,
+ _glfwPostEmptyEventWin32,
+ _glfwGetEGLPlatformWin32,
+ _glfwGetEGLNativeDisplayWin32,
+ _glfwGetEGLNativeWindowWin32,
+ _glfwGetRequiredInstanceExtensionsWin32,
+ _glfwGetPhysicalDevicePresentationSupportWin32,
+ _glfwCreateWindowSurfaceWin32,
+ };
+
+ *platform = win32;
+ return GLFW_TRUE;
+}
+
+int _glfwInitWin32(void)
+{
+ if (!loadLibraries())
+ return GLFW_FALSE;
+
+ createKeyTables();
+ _glfwUpdateKeyNamesWin32();
+
+ if (_glfwIsWindows10Version1703OrGreaterWin32())
+ SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ else if (IsWindows8Point1OrGreater())
+ SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
+ else if (IsWindowsVistaOrGreater())
+ SetProcessDPIAware();
+
+ if (!_glfwRegisterWindowClassWin32())
+ return GLFW_FALSE;
+
+ if (!createHelperWindow())
+ return GLFW_FALSE;
+
+ // Register that we want to receive WM_INPUT for keyboards
+ {
+ RAWINPUTDEVICE rid;
+ rid.usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC
+ rid.usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD
+ rid.dwFlags = 0;
+ rid.hwndTarget = 0; // Message delivered to focused window
+
+ if (RegisterRawInputDevices(&rid, 1, sizeof(RAWINPUTDEVICE)) == FALSE)
+ return GLFW_FALSE;
+ }
+
+ _glfwPollMonitorsWin32();
+ _glfwPollKeyboardsWin32();
+ return GLFW_TRUE;
+}
+
+void _glfwTerminateWin32(void)
+{
+ if (_glfw.win32.deviceNotificationHandle)
+ UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
+
+ if (_glfw.win32.helperWindowHandle)
+ DestroyWindow(_glfw.win32.helperWindowHandle);
+
+ _glfwUnregisterWindowClassWin32();
+
+ _glfw_free(_glfw.win32.clipboardString);
+ _glfw_free(_glfw.win32.rawInput);
+
+ _glfwTerminateWGL();
+ _glfwTerminateEGL();
+
+ freeLibraries();
+}
+