win32_init.c (23394B)
1 //======================================================================== 2 // GLFW 3.3 Win32 - www.glfw.org 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 6 // 7 // This software is provided 'as-is', without any express or implied 8 // warranty. In no event will the authors be held liable for any damages 9 // arising from the use of this software. 10 // 11 // Permission is granted to anyone to use this software for any purpose, 12 // including commercial applications, and to alter it and redistribute it 13 // freely, subject to the following restrictions: 14 // 15 // 1. The origin of this software must not be misrepresented; you must not 16 // claim that you wrote the original software. If you use this software 17 // in a product, an acknowledgment in the product documentation would 18 // be appreciated but is not required. 19 // 20 // 2. Altered source versions must be plainly marked as such, and must not 21 // be misrepresented as being the original software. 22 // 23 // 3. This notice may not be removed or altered from any source 24 // distribution. 25 // 26 //======================================================================== 27 // Please use C89 style variable declarations in this file because VS 2010 28 //======================================================================== 29 30 #include "internal.h" 31 32 #include <stdlib.h> 33 #include <malloc.h> 34 35 static const GUID _glfw_GUID_DEVINTERFACE_HID = 36 {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}}; 37 38 #define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID 39 40 #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) 41 42 #if defined(_GLFW_BUILD_DLL) 43 #warning "These symbols must be exported by the executable and have no effect in a DLL" 44 #endif 45 46 // Executables (but not DLLs) exporting this symbol with this value will be 47 // automatically directed to the high-performance GPU on Nvidia Optimus systems 48 // with up-to-date drivers 49 // 50 __declspec(dllexport) DWORD NvOptimusEnablement = 1; 51 52 // Executables (but not DLLs) exporting this symbol with this value will be 53 // automatically directed to the high-performance GPU on AMD PowerXpress systems 54 // with up-to-date drivers 55 // 56 __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; 57 58 #endif // _GLFW_USE_HYBRID_HPG 59 60 #if defined(_GLFW_BUILD_DLL) 61 62 // GLFW DLL entry point 63 // 64 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) 65 { 66 return TRUE; 67 } 68 69 #endif // _GLFW_BUILD_DLL 70 71 // Load necessary libraries (DLLs) 72 // 73 static GLFWbool loadLibraries(void) 74 { 75 _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); 76 if (!_glfw.win32.winmm.instance) 77 { 78 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 79 "Win32: Failed to load winmm.dll"); 80 return GLFW_FALSE; 81 } 82 83 _glfw.win32.winmm.GetTime = (PFN_timeGetTime) 84 GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); 85 86 _glfw.win32.user32.instance = LoadLibraryA("user32.dll"); 87 if (!_glfw.win32.user32.instance) 88 { 89 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 90 "Win32: Failed to load user32.dll"); 91 return GLFW_FALSE; 92 } 93 94 _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware) 95 GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); 96 _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx) 97 GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); 98 _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling) 99 GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); 100 _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext) 101 GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext"); 102 _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow) 103 GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow"); 104 _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi) 105 GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); 106 107 _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); 108 if (_glfw.win32.dinput8.instance) 109 { 110 _glfw.win32.dinput8.Create = (PFN_DirectInput8Create) 111 GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create"); 112 } 113 114 { 115 int i; 116 const char* names[] = 117 { 118 "xinput1_4.dll", 119 "xinput1_3.dll", 120 "xinput9_1_0.dll", 121 "xinput1_2.dll", 122 "xinput1_1.dll", 123 NULL 124 }; 125 126 for (i = 0; names[i]; i++) 127 { 128 _glfw.win32.xinput.instance = LoadLibraryA(names[i]); 129 if (_glfw.win32.xinput.instance) 130 { 131 _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities) 132 GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities"); 133 _glfw.win32.xinput.GetState = (PFN_XInputGetState) 134 GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState"); 135 136 break; 137 } 138 } 139 } 140 141 _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); 142 if (_glfw.win32.dwmapi.instance) 143 { 144 _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled) 145 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); 146 _glfw.win32.dwmapi.Flush = (PFN_DwmFlush) 147 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); 148 _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) 149 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); 150 _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) 151 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); 152 } 153 154 _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); 155 if (_glfw.win32.shcore.instance) 156 { 157 _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness) 158 GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); 159 _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor) 160 GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); 161 } 162 163 _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll"); 164 if (_glfw.win32.ntdll.instance) 165 { 166 _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) 167 GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); 168 } 169 170 return GLFW_TRUE; 171 } 172 173 // Unload used libraries (DLLs) 174 // 175 static void freeLibraries(void) 176 { 177 if (_glfw.win32.xinput.instance) 178 FreeLibrary(_glfw.win32.xinput.instance); 179 180 if (_glfw.win32.dinput8.instance) 181 FreeLibrary(_glfw.win32.dinput8.instance); 182 183 if (_glfw.win32.winmm.instance) 184 FreeLibrary(_glfw.win32.winmm.instance); 185 186 if (_glfw.win32.user32.instance) 187 FreeLibrary(_glfw.win32.user32.instance); 188 189 if (_glfw.win32.dwmapi.instance) 190 FreeLibrary(_glfw.win32.dwmapi.instance); 191 192 if (_glfw.win32.shcore.instance) 193 FreeLibrary(_glfw.win32.shcore.instance); 194 195 if (_glfw.win32.ntdll.instance) 196 FreeLibrary(_glfw.win32.ntdll.instance); 197 } 198 199 // Create key code translation tables 200 // 201 static void createKeyTables(void) 202 { 203 int scancode; 204 205 memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes)); 206 memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes)); 207 208 _glfw.win32.keycodes[0x00B] = GLFW_KEY_0; 209 _glfw.win32.keycodes[0x002] = GLFW_KEY_1; 210 _glfw.win32.keycodes[0x003] = GLFW_KEY_2; 211 _glfw.win32.keycodes[0x004] = GLFW_KEY_3; 212 _glfw.win32.keycodes[0x005] = GLFW_KEY_4; 213 _glfw.win32.keycodes[0x006] = GLFW_KEY_5; 214 _glfw.win32.keycodes[0x007] = GLFW_KEY_6; 215 _glfw.win32.keycodes[0x008] = GLFW_KEY_7; 216 _glfw.win32.keycodes[0x009] = GLFW_KEY_8; 217 _glfw.win32.keycodes[0x00A] = GLFW_KEY_9; 218 _glfw.win32.keycodes[0x01E] = GLFW_KEY_A; 219 _glfw.win32.keycodes[0x030] = GLFW_KEY_B; 220 _glfw.win32.keycodes[0x02E] = GLFW_KEY_C; 221 _glfw.win32.keycodes[0x020] = GLFW_KEY_D; 222 _glfw.win32.keycodes[0x012] = GLFW_KEY_E; 223 _glfw.win32.keycodes[0x021] = GLFW_KEY_F; 224 _glfw.win32.keycodes[0x022] = GLFW_KEY_G; 225 _glfw.win32.keycodes[0x023] = GLFW_KEY_H; 226 _glfw.win32.keycodes[0x017] = GLFW_KEY_I; 227 _glfw.win32.keycodes[0x024] = GLFW_KEY_J; 228 _glfw.win32.keycodes[0x025] = GLFW_KEY_K; 229 _glfw.win32.keycodes[0x026] = GLFW_KEY_L; 230 _glfw.win32.keycodes[0x032] = GLFW_KEY_M; 231 _glfw.win32.keycodes[0x031] = GLFW_KEY_N; 232 _glfw.win32.keycodes[0x018] = GLFW_KEY_O; 233 _glfw.win32.keycodes[0x019] = GLFW_KEY_P; 234 _glfw.win32.keycodes[0x010] = GLFW_KEY_Q; 235 _glfw.win32.keycodes[0x013] = GLFW_KEY_R; 236 _glfw.win32.keycodes[0x01F] = GLFW_KEY_S; 237 _glfw.win32.keycodes[0x014] = GLFW_KEY_T; 238 _glfw.win32.keycodes[0x016] = GLFW_KEY_U; 239 _glfw.win32.keycodes[0x02F] = GLFW_KEY_V; 240 _glfw.win32.keycodes[0x011] = GLFW_KEY_W; 241 _glfw.win32.keycodes[0x02D] = GLFW_KEY_X; 242 _glfw.win32.keycodes[0x015] = GLFW_KEY_Y; 243 _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z; 244 245 _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE; 246 _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH; 247 _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA; 248 _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL; 249 _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT; 250 _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET; 251 _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS; 252 _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD; 253 _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET; 254 _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON; 255 _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH; 256 _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2; 257 258 _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE; 259 _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE; 260 _glfw.win32.keycodes[0x14F] = GLFW_KEY_END; 261 _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER; 262 _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE; 263 _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME; 264 _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT; 265 _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU; 266 _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN; 267 _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP; 268 _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE; 269 _glfw.win32.keycodes[0x146] = GLFW_KEY_PAUSE; 270 _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE; 271 _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB; 272 _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK; 273 _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK; 274 _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK; 275 _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1; 276 _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2; 277 _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3; 278 _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4; 279 _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5; 280 _glfw.win32.keycodes[0x040] = GLFW_KEY_F6; 281 _glfw.win32.keycodes[0x041] = GLFW_KEY_F7; 282 _glfw.win32.keycodes[0x042] = GLFW_KEY_F8; 283 _glfw.win32.keycodes[0x043] = GLFW_KEY_F9; 284 _glfw.win32.keycodes[0x044] = GLFW_KEY_F10; 285 _glfw.win32.keycodes[0x057] = GLFW_KEY_F11; 286 _glfw.win32.keycodes[0x058] = GLFW_KEY_F12; 287 _glfw.win32.keycodes[0x064] = GLFW_KEY_F13; 288 _glfw.win32.keycodes[0x065] = GLFW_KEY_F14; 289 _glfw.win32.keycodes[0x066] = GLFW_KEY_F15; 290 _glfw.win32.keycodes[0x067] = GLFW_KEY_F16; 291 _glfw.win32.keycodes[0x068] = GLFW_KEY_F17; 292 _glfw.win32.keycodes[0x069] = GLFW_KEY_F18; 293 _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19; 294 _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20; 295 _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21; 296 _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22; 297 _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23; 298 _glfw.win32.keycodes[0x076] = GLFW_KEY_F24; 299 _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT; 300 _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL; 301 _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT; 302 _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER; 303 _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN; 304 _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT; 305 _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL; 306 _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT; 307 _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER; 308 _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN; 309 _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT; 310 _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT; 311 _glfw.win32.keycodes[0x148] = GLFW_KEY_UP; 312 313 _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0; 314 _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1; 315 _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2; 316 _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3; 317 _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4; 318 _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5; 319 _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6; 320 _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7; 321 _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8; 322 _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9; 323 _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD; 324 _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL; 325 _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE; 326 _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER; 327 _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL; 328 _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY; 329 _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT; 330 331 for (scancode = 0; scancode < 512; scancode++) 332 { 333 if (_glfw.win32.keycodes[scancode] > 0) 334 _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode; 335 } 336 } 337 338 // Creates a dummy window for behind-the-scenes work 339 // 340 static GLFWbool createHelperWindow(void) 341 { 342 MSG msg; 343 344 _glfw.win32.helperWindowHandle = 345 CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, 346 _GLFW_WNDCLASSNAME, 347 L"GLFW message window", 348 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 349 0, 0, 1, 1, 350 NULL, NULL, 351 GetModuleHandleW(NULL), 352 NULL); 353 354 if (!_glfw.win32.helperWindowHandle) 355 { 356 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 357 "Win32: Failed to create helper window"); 358 return GLFW_FALSE; 359 } 360 361 // HACK: The command to the first ShowWindow call is ignored if the parent 362 // process passed along a STARTUPINFO, so clear that with a no-op call 363 ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE); 364 365 // Register for HID device notifications 366 { 367 DEV_BROADCAST_DEVICEINTERFACE_W dbi; 368 ZeroMemory(&dbi, sizeof(dbi)); 369 dbi.dbcc_size = sizeof(dbi); 370 dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 371 dbi.dbcc_classguid = GUID_DEVINTERFACE_HID; 372 373 _glfw.win32.deviceNotificationHandle = 374 RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle, 375 (DEV_BROADCAST_HDR*) &dbi, 376 DEVICE_NOTIFY_WINDOW_HANDLE); 377 } 378 379 while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) 380 { 381 TranslateMessage(&msg); 382 DispatchMessageW(&msg); 383 } 384 385 return GLFW_TRUE; 386 } 387 388 389 ////////////////////////////////////////////////////////////////////////// 390 ////// GLFW internal API ////// 391 ////////////////////////////////////////////////////////////////////////// 392 393 // Returns a wide string version of the specified UTF-8 string 394 // 395 WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source) 396 { 397 WCHAR* target; 398 int count; 399 400 count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); 401 if (!count) 402 { 403 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 404 "Win32: Failed to convert string from UTF-8"); 405 return NULL; 406 } 407 408 target = calloc(count, sizeof(WCHAR)); 409 410 if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count)) 411 { 412 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 413 "Win32: Failed to convert string from UTF-8"); 414 free(target); 415 return NULL; 416 } 417 418 return target; 419 } 420 421 // Returns a UTF-8 string version of the specified wide string 422 // 423 char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) 424 { 425 char* target; 426 int size; 427 428 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); 429 if (!size) 430 { 431 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 432 "Win32: Failed to convert string to UTF-8"); 433 return NULL; 434 } 435 436 target = calloc(size, 1); 437 438 if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) 439 { 440 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 441 "Win32: Failed to convert string to UTF-8"); 442 free(target); 443 return NULL; 444 } 445 446 return target; 447 } 448 449 // Reports the specified error, appending information about the last Win32 error 450 // 451 void _glfwInputErrorWin32(int error, const char* description) 452 { 453 WCHAR buffer[_GLFW_MESSAGE_SIZE] = L""; 454 char message[_GLFW_MESSAGE_SIZE] = ""; 455 456 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | 457 FORMAT_MESSAGE_IGNORE_INSERTS | 458 FORMAT_MESSAGE_MAX_WIDTH_MASK, 459 NULL, 460 GetLastError() & 0xffff, 461 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 462 buffer, 463 sizeof(buffer) / sizeof(WCHAR), 464 NULL); 465 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL); 466 467 _glfwInputError(error, "%s: %s", description, message); 468 } 469 470 // Updates key names according to the current keyboard layout 471 // 472 void _glfwUpdateKeyNamesWin32(void) 473 { 474 int key; 475 BYTE state[256] = {0}; 476 477 memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames)); 478 479 for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++) 480 { 481 UINT vk; 482 int scancode, length; 483 WCHAR chars[16]; 484 485 scancode = _glfw.win32.scancodes[key]; 486 if (scancode == -1) 487 continue; 488 489 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) 490 { 491 const UINT vks[] = { 492 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, 493 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, 494 VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, 495 VK_MULTIPLY, VK_SUBTRACT, VK_ADD 496 }; 497 498 vk = vks[key - GLFW_KEY_KP_0]; 499 } 500 else 501 vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK); 502 503 length = ToUnicode(vk, scancode, state, 504 chars, sizeof(chars) / sizeof(WCHAR), 505 0); 506 507 if (length == -1) 508 { 509 length = ToUnicode(vk, scancode, state, 510 chars, sizeof(chars) / sizeof(WCHAR), 511 0); 512 } 513 514 if (length < 1) 515 continue; 516 517 WideCharToMultiByte(CP_UTF8, 0, chars, 1, 518 _glfw.win32.keynames[key], 519 sizeof(_glfw.win32.keynames[key]), 520 NULL, NULL); 521 } 522 } 523 524 // Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h 525 // 526 BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) 527 { 528 OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp }; 529 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR; 530 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 531 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 532 cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 533 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 534 // latter lies unless the user knew to embed a non-default manifest 535 // announcing support for Windows 10 via supportedOS GUID 536 return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; 537 } 538 539 // Checks whether we are on at least the specified build of Windows 10 540 // 541 BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build) 542 { 543 OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build }; 544 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER; 545 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 546 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 547 cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL); 548 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 549 // latter lies unless the user knew to embed a non-default manifest 550 // announcing support for Windows 10 via supportedOS GUID 551 return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; 552 } 553 554 555 ////////////////////////////////////////////////////////////////////////// 556 ////// GLFW platform API ////// 557 ////////////////////////////////////////////////////////////////////////// 558 559 int _glfwPlatformInit(void) 560 { 561 // To make SetForegroundWindow work as we want, we need to fiddle 562 // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early 563 // as possible in the hope of still being the foreground process) 564 SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, 565 &_glfw.win32.foregroundLockTimeout, 0); 566 SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, UIntToPtr(0), 567 SPIF_SENDCHANGE); 568 569 if (!loadLibraries()) 570 return GLFW_FALSE; 571 572 createKeyTables(); 573 _glfwUpdateKeyNamesWin32(); 574 575 if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32()) 576 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 577 else if (IsWindows8Point1OrGreater()) 578 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 579 else if (IsWindowsVistaOrGreater()) 580 SetProcessDPIAware(); 581 582 if (!_glfwRegisterWindowClassWin32()) 583 return GLFW_FALSE; 584 585 if (!createHelperWindow()) 586 return GLFW_FALSE; 587 588 _glfwInitTimerWin32(); 589 _glfwInitJoysticksWin32(); 590 591 _glfwPollMonitorsWin32(); 592 return GLFW_TRUE; 593 } 594 595 void _glfwPlatformTerminate(void) 596 { 597 if (_glfw.win32.deviceNotificationHandle) 598 UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle); 599 600 if (_glfw.win32.helperWindowHandle) 601 DestroyWindow(_glfw.win32.helperWindowHandle); 602 603 _glfwUnregisterWindowClassWin32(); 604 605 // Restore previous foreground lock timeout system setting 606 SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 607 UIntToPtr(_glfw.win32.foregroundLockTimeout), 608 SPIF_SENDCHANGE); 609 610 free(_glfw.win32.clipboardString); 611 free(_glfw.win32.rawInput); 612 613 _glfwTerminateWGL(); 614 _glfwTerminateEGL(); 615 616 _glfwTerminateJoysticksWin32(); 617 618 freeLibraries(); 619 } 620 621 const char* _glfwPlatformGetVersionString(void) 622 { 623 return _GLFW_VERSION_NUMBER " Win32 WGL EGL OSMesa" 624 #if defined(__MINGW32__) 625 " MinGW" 626 #elif defined(_MSC_VER) 627 " VisualC" 628 #endif 629 #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG) 630 " hybrid-GPU" 631 #endif 632 #if defined(_GLFW_BUILD_DLL) 633 " DLL" 634 #endif 635 ; 636 } 637