1 /// Translated from C to D 2 module glfw3.win32_init; 3 4 extern(C): @nogc: nothrow: __gshared: 5 6 //======================================================================== 7 // GLFW 3.3 Win32 - www.glfw.org 8 //------------------------------------------------------------------------ 9 // Copyright (c) 2002-2006 Marcus Geelnard 10 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 11 // 12 // This software is provided 'as-is', without any express or implied 13 // warranty. In no event will the authors be held liable for any damages 14 // arising from the use of this software. 15 // 16 // Permission is granted to anyone to use this software for any purpose, 17 // including commercial applications, and to alter it and redistribute it 18 // freely, subject to the following restrictions: 19 // 20 // 1. The origin of this software must not be misrepresented; you must not 21 // claim that you wrote the original software. If you use this software 22 // in a product, an acknowledgment in the product documentation would 23 // be appreciated but is not required. 24 // 25 // 2. Altered source versions must be plainly marked as such, and must not 26 // be misrepresented as being the original software. 27 // 28 // 3. This notice may not be removed or altered from any source 29 // distribution. 30 // 31 //======================================================================== 32 // Please use C89 style variable declarations in this file because VS 2010 33 //======================================================================== 34 35 import glfw3.internal; 36 37 import core.stdc.stdlib; 38 import core.stdc.string; 39 40 private const(GUID) _glfw_GUID_DEVINTERFACE_HID = GUID(0x4d1e55b2,0xf16f,0x11cf,[0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30]); 41 42 package: 43 44 enum GUID_DEVINTERFACE_HID = _glfw_GUID_DEVINTERFACE_HID; 45 46 version(_GLFW_USE_HYBRID_HPG) version = _GLFW_USE_HPG; 47 version(_GLFW_USE_OPTIMUS_HPG) version = _GLFW_USE_HPG; 48 49 version(_GLFW_USE_HPG) { 50 51 // Executables (but not DLLs) exporting this symbol with this value will be 52 // automatically directed to the high-performance GPU on Nvidia Optimus systems 53 // with up-to-date drivers 54 // 55 DWORD NvOptimusEnablement = 1; 56 57 // Executables (but not DLLs) exporting this symbol with this value will be 58 // automatically directed to the high-performance GPU on AMD PowerXpress systems 59 // with up-to-date drivers 60 // 61 int AmdPowerXpressRequestHighPerformance = 1; 62 63 } 64 65 version (_GLFW_BUILD_DLL) { 66 67 // GLFW DLL entry point 68 // 69 extern(Windows) BOOL DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { 70 return TRUE; 71 } 72 73 } 74 75 // Load necessary libraries (DLLs) 76 // 77 private GLFWbool loadLibraries() { 78 _glfw.win32.winmm.instance = LoadLibraryA("winmm.dll"); 79 if (!_glfw.win32.winmm.instance) 80 { 81 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 82 "Win32: Failed to load winmm.dll"); 83 return GLFW_FALSE; 84 } 85 86 _glfw.win32.winmm.GetTime = cast(PFN_timeGetTime) 87 GetProcAddress(_glfw.win32.winmm.instance, "timeGetTime"); 88 89 _glfw.win32.user32.instance = LoadLibraryA("user32.dll"); 90 if (!_glfw.win32.user32.instance) 91 { 92 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 93 "Win32: Failed to load user32.dll"); 94 return GLFW_FALSE; 95 } 96 97 _glfw.win32.user32.SetProcessDPIAware_ = cast(PFN_SetProcessDPIAware) 98 GetProcAddress(_glfw.win32.user32.instance, "SetProcessDPIAware"); 99 _glfw.win32.user32.ChangeWindowMessageFilterEx_ = cast(PFN_ChangeWindowMessageFilterEx) 100 GetProcAddress(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); 101 _glfw.win32.user32.EnableNonClientDpiScaling_ = cast(PFN_EnableNonClientDpiScaling) 102 GetProcAddress(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); 103 _glfw.win32.user32.SetProcessDpiAwarenessContext_ = cast(PFN_SetProcessDpiAwarenessContext) 104 GetProcAddress(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext"); 105 _glfw.win32.user32.GetDpiForWindow_ = cast(PFN_GetDpiForWindow) 106 GetProcAddress(_glfw.win32.user32.instance, "GetDpiForWindow"); 107 _glfw.win32.user32.AdjustWindowRectExForDpi_ = cast(PFN_AdjustWindowRectExForDpi) 108 GetProcAddress(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); 109 110 _glfw.win32.dinput8.instance = LoadLibraryA("dinput8.dll"); 111 if (_glfw.win32.dinput8.instance) 112 { 113 _glfw.win32.dinput8.Create = cast(PFN_DirectInput8Create) 114 GetProcAddress(_glfw.win32.dinput8.instance, "DirectInput8Create"); 115 } 116 117 { 118 int i; 119 const(char)*[6] names = [ 120 "xinput1_4.dll".ptr, 121 "xinput1_3.dll".ptr, 122 "xinput9_1_0.dll".ptr, 123 "xinput1_2.dll".ptr, 124 "xinput1_1.dll".ptr, 125 null 126 ]; 127 128 for (i = 0; names[i]; i++) 129 { 130 _glfw.win32.xinput.instance = LoadLibraryA(names[i]); 131 if (_glfw.win32.xinput.instance) 132 { 133 _glfw.win32.xinput.GetCapabilities = cast(PFN_XInputGetCapabilities) 134 GetProcAddress(_glfw.win32.xinput.instance, "XInputGetCapabilities"); 135 _glfw.win32.xinput.GetState = cast(PFN_XInputGetState) 136 GetProcAddress(_glfw.win32.xinput.instance, "XInputGetState"); 137 _glfw.win32.xinput.SetState = cast(PFN_XInputSetState) 138 GetProcAddress(_glfw.win32.xinput.instance, "XInputSetState"); 139 140 break; 141 } 142 } 143 } 144 145 _glfw.win32.dwmapi.instance = LoadLibraryA("dwmapi.dll"); 146 if (_glfw.win32.dwmapi.instance) 147 { 148 _glfw.win32.dwmapi.IsCompositionEnabled = cast(PFN_DwmIsCompositionEnabled) 149 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); 150 _glfw.win32.dwmapi.Flush = cast(PFN_DwmFlush) 151 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); 152 _glfw.win32.dwmapi.EnableBlurBehindWindow = cast(PFN_DwmEnableBlurBehindWindow) 153 GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); 154 } 155 156 _glfw.win32.shcore.instance = LoadLibraryA("shcore.dll"); 157 if (_glfw.win32.shcore.instance) 158 { 159 _glfw.win32.shcore.SetProcessDpiAwareness_ = cast(PFN_SetProcessDpiAwareness) 160 GetProcAddress(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); 161 _glfw.win32.shcore.GetDpiForMonitor_ = cast(PFN_GetDpiForMonitor) 162 GetProcAddress(_glfw.win32.shcore.instance, "GetDpiForMonitor"); 163 } 164 165 _glfw.win32.ntdll.instance = LoadLibraryA("ntdll.dll"); 166 if (_glfw.win32.ntdll.instance) 167 { 168 _glfw.win32.ntdll.RtlVerifyVersionInfo_ = cast(PFN_RtlVerifyVersionInfo) 169 GetProcAddress(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); 170 } 171 172 return GLFW_TRUE; 173 } 174 175 // Unload used libraries (DLLs) 176 // 177 private extern(D) void freeLibraries() { 178 if (_glfw.win32.xinput.instance) 179 FreeLibrary(_glfw.win32.xinput.instance); 180 181 if (_glfw.win32.dinput8.instance) 182 FreeLibrary(_glfw.win32.dinput8.instance); 183 184 if (_glfw.win32.winmm.instance) 185 FreeLibrary(_glfw.win32.winmm.instance); 186 187 if (_glfw.win32.user32.instance) 188 FreeLibrary(_glfw.win32.user32.instance); 189 190 if (_glfw.win32.dwmapi.instance) 191 FreeLibrary(_glfw.win32.dwmapi.instance); 192 193 if (_glfw.win32.shcore.instance) 194 FreeLibrary(_glfw.win32.shcore.instance); 195 196 if (_glfw.win32.ntdll.instance) 197 FreeLibrary(_glfw.win32.ntdll.instance); 198 } 199 200 // Create key code translation tables 201 // 202 private extern(D) void createKeyTables() { 203 int scancode; 204 205 memset(_glfw.win32.keycodes.ptr, -1, typeof(_glfw.win32.keycodes).sizeof); 206 memset(_glfw.win32.scancodes.ptr, -1, typeof(_glfw.win32.scancodes).sizeof); 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 private GLFWbool createHelperWindow() { 341 MSG msg; 342 343 _glfw.win32.helperWindowHandle = 344 CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, 345 _GLFW_WNDCLASSNAME.ptr, 346 "GLFW message window"w.ptr, 347 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 348 0, 0, 1, 1, 349 null, null, 350 GetModuleHandleW(null), 351 null); 352 353 if (!_glfw.win32.helperWindowHandle) 354 { 355 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 356 "Win32: Failed to create helper window"); 357 return GLFW_FALSE; 358 } 359 360 // HACK: The command to the first ShowWindow call is ignored if the parent 361 // process passed along a STARTUPINFO, so clear that with a no-op call 362 ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE); 363 364 // Register for HID device notifications 365 { 366 DEV_BROADCAST_DEVICEINTERFACE_W dbi; 367 memset(&dbi, 0, typeof(dbi).sizeof); //ZeroMemory(&dbi, typeof(dbi).sizeof); 368 dbi.dbcc_size = typeof(dbi).sizeof; 369 dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 370 dbi.dbcc_classguid = GUID_DEVINTERFACE_HID; 371 372 _glfw.win32.deviceNotificationHandle = 373 RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle, 374 cast(DEV_BROADCAST_HDR*) &dbi, 375 DEVICE_NOTIFY_WINDOW_HANDLE); 376 } 377 378 while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) 379 { 380 TranslateMessage(&msg); 381 DispatchMessageW(&msg); 382 } 383 384 return GLFW_TRUE; 385 } 386 387 388 ////////////////////////////////////////////////////////////////////////// 389 ////// GLFW internal API ////// 390 ////////////////////////////////////////////////////////////////////////// 391 392 // Returns a wide string version of the specified UTF-8 string 393 // 394 WCHAR* _glfwCreateWideStringFromUTF8Win32(const(char)* source) { 395 WCHAR* target; 396 int count; 397 398 count = MultiByteToWideChar(CP_UTF8, 0, source, -1, null, 0); 399 if (!count) 400 { 401 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 402 "Win32: Failed to convert string from UTF-8"); 403 return null; 404 } 405 406 target = cast(WCHAR*) calloc(count, WCHAR.sizeof); 407 408 if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count)) 409 { 410 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 411 "Win32: Failed to convert string from UTF-8"); 412 free(target); 413 return null; 414 } 415 416 return target; 417 } 418 419 // Returns a UTF-8 string version of the specified wide string 420 // 421 char* _glfwCreateUTF8FromWideStringWin32(const(WCHAR)* source) { 422 char* target; 423 int size; 424 425 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, null, 0, null, null); 426 if (!size) 427 { 428 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 429 "Win32: Failed to convert string to UTF-8"); 430 return null; 431 } 432 433 target = cast(char*) calloc(size, 1); 434 435 if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, null, null)) 436 { 437 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 438 "Win32: Failed to convert string to UTF-8"); 439 free(target); 440 return null; 441 } 442 443 return target; 444 } 445 446 // Reports the specified error, appending information about the last Win32 error 447 // 448 void _glfwInputErrorWin32(int error, const(char)* description) { 449 WCHAR[_GLFW_MESSAGE_SIZE] buffer = ""w; 450 char[_GLFW_MESSAGE_SIZE] message = ""; 451 452 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | 453 FORMAT_MESSAGE_IGNORE_INSERTS | 454 FORMAT_MESSAGE_MAX_WIDTH_MASK, 455 null, 456 GetLastError() & 0xffff, 457 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 458 buffer.ptr, 459 buffer.sizeof / WCHAR.sizeof, 460 null); 461 WideCharToMultiByte(CP_UTF8, 0, buffer.ptr, -1, message.ptr, typeof(message).sizeof, null, null); 462 463 _glfwInputError(error, "%s: %s", description, message.ptr); 464 } 465 466 // Updates key names according to the current keyboard layout 467 // 468 void _glfwUpdateKeyNamesWin32() { 469 int key; 470 BYTE[256] state = 0; 471 472 memset(_glfw.win32.keynames.ptr, 0, typeof(_glfw.win32.keynames).sizeof); 473 474 for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++) 475 { 476 UINT vk; 477 int scancode;int length; 478 WCHAR[16] chars; 479 480 scancode = _glfw.win32.scancodes[key]; 481 if (scancode == -1) 482 continue; 483 484 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) 485 { 486 const(UINT)[15] vks = [ 487 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, 488 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, 489 VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, 490 VK_MULTIPLY, VK_SUBTRACT, VK_ADD 491 ]; 492 493 vk = vks[key - GLFW_KEY_KP_0]; 494 } 495 else 496 vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK); 497 498 length = ToUnicode(vk, scancode, state.ptr, 499 chars.ptr, chars.sizeof / WCHAR.sizeof, 500 0); 501 502 if (length == -1) 503 { 504 length = ToUnicode(vk, scancode, state.ptr, 505 chars.ptr, chars.sizeof / WCHAR.sizeof, 506 0); 507 } 508 509 if (length < 1) 510 continue; 511 512 WideCharToMultiByte(CP_UTF8, 0, chars.ptr, 1, 513 _glfw.win32.keynames[key].ptr, 514 typeof(_glfw.win32.keynames[key]).sizeof, 515 null, null); 516 } 517 } 518 519 // Replacement for IsWindowsVersionOrGreater as MinGW lacks versionhelpers.h 520 // 521 BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) { 522 OSVERSIONINFOEXW osvi = OSVERSIONINFOEXW(OSVERSIONINFOEXW.sizeof, major, minor, 0, 0, (wchar[128]).init, sp); 523 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR; 524 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 525 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 526 cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 527 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 528 // latter lies unless the user knew to embed a non-default manifest 529 // announcing support for Windows 10 via supportedOS GUID 530 return _glfw.win32.ntdll.RtlVerifyVersionInfo_(&osvi, mask, cond) == 0; 531 } 532 533 // Checks whether we are on at least the specified build of Windows 10 534 // 535 BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build) { 536 OSVERSIONINFOEXW osvi = OSVERSIONINFOEXW(OSVERSIONINFOEXW.sizeof, 10, 0, build); 537 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER; 538 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 539 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 540 cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL); 541 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 542 // latter lies unless the user knew to embed a non-default manifest 543 // announcing support for Windows 10 via supportedOS GUID 544 return _glfw.win32.ntdll.RtlVerifyVersionInfo_(&osvi, mask, cond) == 0; 545 } 546 547 548 ////////////////////////////////////////////////////////////////////////// 549 ////// GLFW platform API ////// 550 ////////////////////////////////////////////////////////////////////////// 551 552 int _glfwPlatformInit() { 553 // To make SetForegroundWindow work as we want, we need to fiddle 554 // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early 555 // as possible in the hope of still being the foreground process) 556 SystemParametersInfoW(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, 557 &_glfw.win32.foregroundLockTimeout, 0); 558 SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, null /*UIntToPtr(0)*/, 559 SPIF_SENDCHANGE); 560 561 if (!loadLibraries()) 562 return GLFW_FALSE; 563 564 createKeyTables(); 565 _glfwUpdateKeyNamesWin32(); 566 567 if (_glfwIsWindows10CreatorsUpdateOrGreaterWin32()) 568 _glfw.win32.user32.SetProcessDpiAwarenessContext_(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 569 else if (IsWindows8Point1OrGreater()) 570 _glfw.win32.shcore.SetProcessDpiAwareness_(PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE); 571 else if (IsWindowsVistaOrGreater()) 572 _glfw.win32.user32.SetProcessDPIAware_(); 573 574 if (!_glfwRegisterWindowClassWin32()) 575 return GLFW_FALSE; 576 577 if (!createHelperWindow()) 578 return GLFW_FALSE; 579 580 _glfwInitTimerWin32(); 581 _glfwInitJoysticksWin32(); 582 583 _glfwPollMonitorsWin32(); 584 return GLFW_TRUE; 585 } 586 587 void _glfwPlatformTerminate() { 588 if (_glfw.win32.deviceNotificationHandle) 589 UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle); 590 591 if (_glfw.win32.helperWindowHandle) 592 DestroyWindow(_glfw.win32.helperWindowHandle); 593 594 _glfwUnregisterWindowClassWin32(); 595 596 // Restore previous foreground lock timeout system setting 597 SystemParametersInfoW(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, 598 cast(void*) cast(UINT_PTR) _glfw.win32.foregroundLockTimeout, 599 SPIF_SENDCHANGE); 600 601 free(_glfw.win32.clipboardString); 602 free(_glfw.win32.rawInput); 603 604 _glfwTerminateWGL(); 605 _glfwTerminateEGL(); 606 607 _glfwTerminateJoysticksWin32(); 608 609 freeLibraries(); 610 } 611 612 const(char)* _glfwPlatformGetVersionString() { 613 version (MinGW) { 614 enum clibPart = " MinGW"; 615 } else version (CRuntime_Microsoft) { 616 enum clibPart = " VisualC"; 617 } else { 618 enum clibPart = ""; 619 } 620 621 version(_GLFW_USE_HYBRID_HPG) { 622 enum optimusPart = " hybrid-GPU"; 623 } else version(_GLFW_USE_OPTIMUS_HPG) { 624 enum optimusPart = " hybrid-GPU"; 625 } else { 626 enum optimusPart = ""; 627 } 628 version (_GLFW_BUILD_DLL) { 629 enum dllPart = " DLL"; 630 } else { 631 enum dllPart = ""; 632 } 633 634 return _GLFW_VERSION_NUMBER ~ " Win32 WGL EGL OSMesa" ~ clibPart ~ optimusPart ~ dllPart; 635 }