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