win32_init.c (28564B)
1 //======================================================================== 2 // GLFW 3.4 Win32 (modified for raylib) - www.glfw.org; www.raylib.com 3 //------------------------------------------------------------------------ 4 // Copyright (c) 2002-2006 Marcus Geelnard 5 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 6 // Copyright (c) 2024 M374LX <wilsalx@gmail.com> 7 // 8 // This software is provided 'as-is', without any express or implied 9 // warranty. In no event will the authors be held liable for any damages 10 // arising from the use of this software. 11 // 12 // Permission is granted to anyone to use this software for any purpose, 13 // including commercial applications, and to alter it and redistribute it 14 // freely, subject to the following restrictions: 15 // 16 // 1. The origin of this software must not be misrepresented; you must not 17 // claim that you wrote the original software. If you use this software 18 // in a product, an acknowledgment in the product documentation would 19 // be appreciated but is not required. 20 // 21 // 2. Altered source versions must be plainly marked as such, and must not 22 // be misrepresented as being the original software. 23 // 24 // 3. This notice may not be removed or altered from any source 25 // distribution. 26 // 27 //======================================================================== 28 29 #include "internal.h" 30 31 #if defined(_GLFW_WIN32) 32 33 #include <stdlib.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 #pragma message("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 if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | 76 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 77 (const WCHAR*) &_glfw, 78 (HMODULE*) &_glfw.win32.instance)) 79 { 80 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 81 "Win32: Failed to retrieve own module handle"); 82 return GLFW_FALSE; 83 } 84 85 _glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll"); 86 if (!_glfw.win32.user32.instance) 87 { 88 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 89 "Win32: Failed to load user32.dll"); 90 return GLFW_FALSE; 91 } 92 93 _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware) 94 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDPIAware"); 95 _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx) 96 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx"); 97 _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling) 98 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling"); 99 _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext) 100 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext"); 101 _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow) 102 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow"); 103 _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi) 104 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi"); 105 _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi) 106 _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi"); 107 108 _glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll"); 109 if (_glfw.win32.dinput8.instance) 110 { 111 _glfw.win32.dinput8.Create = (PFN_DirectInput8Create) 112 _glfwPlatformGetModuleSymbol(_glfw.win32.dinput8.instance, "DirectInput8Create"); 113 } 114 115 { 116 int i; 117 const char* names[] = 118 { 119 "xinput1_4.dll", 120 "xinput1_3.dll", 121 "xinput9_1_0.dll", 122 "xinput1_2.dll", 123 "xinput1_1.dll", 124 NULL 125 }; 126 127 for (i = 0; names[i]; i++) 128 { 129 _glfw.win32.xinput.instance = _glfwPlatformLoadModule(names[i]); 130 if (_glfw.win32.xinput.instance) 131 { 132 _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities) 133 _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetCapabilities"); 134 _glfw.win32.xinput.GetState = (PFN_XInputGetState) 135 _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetState"); 136 137 break; 138 } 139 } 140 } 141 142 _glfw.win32.dwmapi.instance = _glfwPlatformLoadModule("dwmapi.dll"); 143 if (_glfw.win32.dwmapi.instance) 144 { 145 _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled) 146 _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); 147 _glfw.win32.dwmapi.Flush = (PFN_DwmFlush) 148 _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmFlush"); 149 _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow) 150 _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow"); 151 _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor) 152 _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor"); 153 } 154 155 _glfw.win32.shcore.instance = _glfwPlatformLoadModule("shcore.dll"); 156 if (_glfw.win32.shcore.instance) 157 { 158 _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness) 159 _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "SetProcessDpiAwareness"); 160 _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor) 161 _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "GetDpiForMonitor"); 162 } 163 164 _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll"); 165 if (_glfw.win32.ntdll.instance) 166 { 167 _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo) 168 _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo"); 169 } 170 171 return GLFW_TRUE; 172 } 173 174 // Unload used libraries (DLLs) 175 // 176 static void freeLibraries(void) 177 { 178 if (_glfw.win32.xinput.instance) 179 _glfwPlatformFreeModule(_glfw.win32.xinput.instance); 180 181 if (_glfw.win32.dinput8.instance) 182 _glfwPlatformFreeModule(_glfw.win32.dinput8.instance); 183 184 if (_glfw.win32.user32.instance) 185 _glfwPlatformFreeModule(_glfw.win32.user32.instance); 186 187 if (_glfw.win32.dwmapi.instance) 188 _glfwPlatformFreeModule(_glfw.win32.dwmapi.instance); 189 190 if (_glfw.win32.shcore.instance) 191 _glfwPlatformFreeModule(_glfw.win32.shcore.instance); 192 193 if (_glfw.win32.ntdll.instance) 194 _glfwPlatformFreeModule(_glfw.win32.ntdll.instance); 195 } 196 197 // Create key code translation tables 198 // 199 static void createKeyTablesWin32(void) 200 { 201 int scancode; 202 203 memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes)); 204 memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes)); 205 206 _glfw.win32.keycodes[0x00B] = GLFW_KEY_0; 207 _glfw.win32.keycodes[0x002] = GLFW_KEY_1; 208 _glfw.win32.keycodes[0x003] = GLFW_KEY_2; 209 _glfw.win32.keycodes[0x004] = GLFW_KEY_3; 210 _glfw.win32.keycodes[0x005] = GLFW_KEY_4; 211 _glfw.win32.keycodes[0x006] = GLFW_KEY_5; 212 _glfw.win32.keycodes[0x007] = GLFW_KEY_6; 213 _glfw.win32.keycodes[0x008] = GLFW_KEY_7; 214 _glfw.win32.keycodes[0x009] = GLFW_KEY_8; 215 _glfw.win32.keycodes[0x00A] = GLFW_KEY_9; 216 _glfw.win32.keycodes[0x01E] = GLFW_KEY_A; 217 _glfw.win32.keycodes[0x030] = GLFW_KEY_B; 218 _glfw.win32.keycodes[0x02E] = GLFW_KEY_C; 219 _glfw.win32.keycodes[0x020] = GLFW_KEY_D; 220 _glfw.win32.keycodes[0x012] = GLFW_KEY_E; 221 _glfw.win32.keycodes[0x021] = GLFW_KEY_F; 222 _glfw.win32.keycodes[0x022] = GLFW_KEY_G; 223 _glfw.win32.keycodes[0x023] = GLFW_KEY_H; 224 _glfw.win32.keycodes[0x017] = GLFW_KEY_I; 225 _glfw.win32.keycodes[0x024] = GLFW_KEY_J; 226 _glfw.win32.keycodes[0x025] = GLFW_KEY_K; 227 _glfw.win32.keycodes[0x026] = GLFW_KEY_L; 228 _glfw.win32.keycodes[0x032] = GLFW_KEY_M; 229 _glfw.win32.keycodes[0x031] = GLFW_KEY_N; 230 _glfw.win32.keycodes[0x018] = GLFW_KEY_O; 231 _glfw.win32.keycodes[0x019] = GLFW_KEY_P; 232 _glfw.win32.keycodes[0x010] = GLFW_KEY_Q; 233 _glfw.win32.keycodes[0x013] = GLFW_KEY_R; 234 _glfw.win32.keycodes[0x01F] = GLFW_KEY_S; 235 _glfw.win32.keycodes[0x014] = GLFW_KEY_T; 236 _glfw.win32.keycodes[0x016] = GLFW_KEY_U; 237 _glfw.win32.keycodes[0x02F] = GLFW_KEY_V; 238 _glfw.win32.keycodes[0x011] = GLFW_KEY_W; 239 _glfw.win32.keycodes[0x02D] = GLFW_KEY_X; 240 _glfw.win32.keycodes[0x015] = GLFW_KEY_Y; 241 _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z; 242 243 _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE; 244 _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH; 245 _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA; 246 _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL; 247 _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT; 248 _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET; 249 _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS; 250 _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD; 251 _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET; 252 _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON; 253 _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH; 254 _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2; 255 256 _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE; 257 _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE; 258 _glfw.win32.keycodes[0x14F] = GLFW_KEY_END; 259 _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER; 260 _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE; 261 _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME; 262 _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT; 263 _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU; 264 _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN; 265 _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP; 266 _glfw.win32.keycodes[0x045] = GLFW_KEY_PAUSE; 267 _glfw.win32.keycodes[0x039] = GLFW_KEY_SPACE; 268 _glfw.win32.keycodes[0x00F] = GLFW_KEY_TAB; 269 _glfw.win32.keycodes[0x03A] = GLFW_KEY_CAPS_LOCK; 270 _glfw.win32.keycodes[0x145] = GLFW_KEY_NUM_LOCK; 271 _glfw.win32.keycodes[0x046] = GLFW_KEY_SCROLL_LOCK; 272 _glfw.win32.keycodes[0x03B] = GLFW_KEY_F1; 273 _glfw.win32.keycodes[0x03C] = GLFW_KEY_F2; 274 _glfw.win32.keycodes[0x03D] = GLFW_KEY_F3; 275 _glfw.win32.keycodes[0x03E] = GLFW_KEY_F4; 276 _glfw.win32.keycodes[0x03F] = GLFW_KEY_F5; 277 _glfw.win32.keycodes[0x040] = GLFW_KEY_F6; 278 _glfw.win32.keycodes[0x041] = GLFW_KEY_F7; 279 _glfw.win32.keycodes[0x042] = GLFW_KEY_F8; 280 _glfw.win32.keycodes[0x043] = GLFW_KEY_F9; 281 _glfw.win32.keycodes[0x044] = GLFW_KEY_F10; 282 _glfw.win32.keycodes[0x057] = GLFW_KEY_F11; 283 _glfw.win32.keycodes[0x058] = GLFW_KEY_F12; 284 _glfw.win32.keycodes[0x064] = GLFW_KEY_F13; 285 _glfw.win32.keycodes[0x065] = GLFW_KEY_F14; 286 _glfw.win32.keycodes[0x066] = GLFW_KEY_F15; 287 _glfw.win32.keycodes[0x067] = GLFW_KEY_F16; 288 _glfw.win32.keycodes[0x068] = GLFW_KEY_F17; 289 _glfw.win32.keycodes[0x069] = GLFW_KEY_F18; 290 _glfw.win32.keycodes[0x06A] = GLFW_KEY_F19; 291 _glfw.win32.keycodes[0x06B] = GLFW_KEY_F20; 292 _glfw.win32.keycodes[0x06C] = GLFW_KEY_F21; 293 _glfw.win32.keycodes[0x06D] = GLFW_KEY_F22; 294 _glfw.win32.keycodes[0x06E] = GLFW_KEY_F23; 295 _glfw.win32.keycodes[0x076] = GLFW_KEY_F24; 296 _glfw.win32.keycodes[0x038] = GLFW_KEY_LEFT_ALT; 297 _glfw.win32.keycodes[0x01D] = GLFW_KEY_LEFT_CONTROL; 298 _glfw.win32.keycodes[0x02A] = GLFW_KEY_LEFT_SHIFT; 299 _glfw.win32.keycodes[0x15B] = GLFW_KEY_LEFT_SUPER; 300 _glfw.win32.keycodes[0x137] = GLFW_KEY_PRINT_SCREEN; 301 _glfw.win32.keycodes[0x138] = GLFW_KEY_RIGHT_ALT; 302 _glfw.win32.keycodes[0x11D] = GLFW_KEY_RIGHT_CONTROL; 303 _glfw.win32.keycodes[0x036] = GLFW_KEY_RIGHT_SHIFT; 304 _glfw.win32.keycodes[0x15C] = GLFW_KEY_RIGHT_SUPER; 305 _glfw.win32.keycodes[0x150] = GLFW_KEY_DOWN; 306 _glfw.win32.keycodes[0x14B] = GLFW_KEY_LEFT; 307 _glfw.win32.keycodes[0x14D] = GLFW_KEY_RIGHT; 308 _glfw.win32.keycodes[0x148] = GLFW_KEY_UP; 309 310 _glfw.win32.keycodes[0x052] = GLFW_KEY_KP_0; 311 _glfw.win32.keycodes[0x04F] = GLFW_KEY_KP_1; 312 _glfw.win32.keycodes[0x050] = GLFW_KEY_KP_2; 313 _glfw.win32.keycodes[0x051] = GLFW_KEY_KP_3; 314 _glfw.win32.keycodes[0x04B] = GLFW_KEY_KP_4; 315 _glfw.win32.keycodes[0x04C] = GLFW_KEY_KP_5; 316 _glfw.win32.keycodes[0x04D] = GLFW_KEY_KP_6; 317 _glfw.win32.keycodes[0x047] = GLFW_KEY_KP_7; 318 _glfw.win32.keycodes[0x048] = GLFW_KEY_KP_8; 319 _glfw.win32.keycodes[0x049] = GLFW_KEY_KP_9; 320 _glfw.win32.keycodes[0x04E] = GLFW_KEY_KP_ADD; 321 _glfw.win32.keycodes[0x053] = GLFW_KEY_KP_DECIMAL; 322 _glfw.win32.keycodes[0x135] = GLFW_KEY_KP_DIVIDE; 323 _glfw.win32.keycodes[0x11C] = GLFW_KEY_KP_ENTER; 324 _glfw.win32.keycodes[0x059] = GLFW_KEY_KP_EQUAL; 325 _glfw.win32.keycodes[0x037] = GLFW_KEY_KP_MULTIPLY; 326 _glfw.win32.keycodes[0x04A] = GLFW_KEY_KP_SUBTRACT; 327 328 for (scancode = 0; scancode < 512; scancode++) 329 { 330 if (_glfw.win32.keycodes[scancode] > 0) 331 _glfw.win32.scancodes[_glfw.win32.keycodes[scancode]] = scancode; 332 } 333 } 334 335 // Window procedure for the hidden helper window 336 // 337 static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 338 { 339 switch (uMsg) 340 { 341 case WM_DISPLAYCHANGE: 342 _glfwPollMonitorsWin32(); 343 break; 344 345 case WM_DEVICECHANGE: 346 { 347 if (!_glfw.joysticksInitialized) 348 break; 349 350 if (wParam == DBT_DEVICEARRIVAL) 351 { 352 DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; 353 if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 354 _glfwDetectJoystickConnectionWin32(); 355 } 356 else if (wParam == DBT_DEVICEREMOVECOMPLETE) 357 { 358 DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam; 359 if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) 360 _glfwDetectJoystickDisconnectionWin32(); 361 } 362 363 break; 364 } 365 } 366 367 return DefWindowProcW(hWnd, uMsg, wParam, lParam); 368 } 369 370 // Creates a dummy window for behind-the-scenes work 371 // 372 static GLFWbool createHelperWindow(void) 373 { 374 MSG msg; 375 WNDCLASSEXW wc = { sizeof(wc) }; 376 377 wc.style = CS_OWNDC; 378 wc.lpfnWndProc = (WNDPROC) helperWindowProc; 379 wc.hInstance = _glfw.win32.instance; 380 wc.lpszClassName = L"GLFW3 Helper"; 381 382 _glfw.win32.helperWindowClass = RegisterClassExW(&wc); 383 if (!_glfw.win32.helperWindowClass) 384 { 385 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 386 "Win32: Failed to register helper window class"); 387 return GLFW_FALSE; 388 } 389 390 _glfw.win32.helperWindowHandle = 391 CreateWindowExW(WS_EX_OVERLAPPEDWINDOW, 392 MAKEINTATOM(_glfw.win32.helperWindowClass), 393 L"GLFW message window", 394 WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 395 0, 0, 1, 1, 396 NULL, NULL, 397 _glfw.win32.instance, 398 NULL); 399 400 if (!_glfw.win32.helperWindowHandle) 401 { 402 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 403 "Win32: Failed to create helper window"); 404 return GLFW_FALSE; 405 } 406 407 // HACK: The command to the first ShowWindow call is ignored if the parent 408 // process passed along a STARTUPINFO, so clear that with a no-op call 409 ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE); 410 411 // Register for HID device notifications 412 { 413 DEV_BROADCAST_DEVICEINTERFACE_W dbi; 414 ZeroMemory(&dbi, sizeof(dbi)); 415 dbi.dbcc_size = sizeof(dbi); 416 dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; 417 dbi.dbcc_classguid = GUID_DEVINTERFACE_HID; 418 419 _glfw.win32.deviceNotificationHandle = 420 RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle, 421 (DEV_BROADCAST_HDR*) &dbi, 422 DEVICE_NOTIFY_WINDOW_HANDLE); 423 } 424 425 while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE)) 426 { 427 TranslateMessage(&msg); 428 DispatchMessageW(&msg); 429 } 430 431 return GLFW_TRUE; 432 } 433 434 ////////////////////////////////////////////////////////////////////////// 435 ////// GLFW internal API ////// 436 ////////////////////////////////////////////////////////////////////////// 437 438 // Returns a wide string version of the specified UTF-8 string 439 // 440 WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source) 441 { 442 WCHAR* target; 443 int count; 444 445 count = MultiByteToWideChar(CP_UTF8, 0, source, -1, NULL, 0); 446 if (!count) 447 { 448 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 449 "Win32: Failed to convert string from UTF-8"); 450 return NULL; 451 } 452 453 target = _glfw_calloc(count, sizeof(WCHAR)); 454 455 if (!MultiByteToWideChar(CP_UTF8, 0, source, -1, target, count)) 456 { 457 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 458 "Win32: Failed to convert string from UTF-8"); 459 _glfw_free(target); 460 return NULL; 461 } 462 463 return target; 464 } 465 466 // Returns a UTF-8 string version of the specified wide string 467 // 468 char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source) 469 { 470 char* target; 471 int size; 472 473 size = WideCharToMultiByte(CP_UTF8, 0, source, -1, NULL, 0, NULL, NULL); 474 if (!size) 475 { 476 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 477 "Win32: Failed to convert string to UTF-8"); 478 return NULL; 479 } 480 481 target = _glfw_calloc(size, 1); 482 483 if (!WideCharToMultiByte(CP_UTF8, 0, source, -1, target, size, NULL, NULL)) 484 { 485 _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, 486 "Win32: Failed to convert string to UTF-8"); 487 _glfw_free(target); 488 return NULL; 489 } 490 491 return target; 492 } 493 494 // Reports the specified error, appending information about the last Win32 error 495 // 496 void _glfwInputErrorWin32(int error, const char* description) 497 { 498 WCHAR buffer[_GLFW_MESSAGE_SIZE] = L""; 499 char message[_GLFW_MESSAGE_SIZE] = ""; 500 501 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | 502 FORMAT_MESSAGE_IGNORE_INSERTS | 503 FORMAT_MESSAGE_MAX_WIDTH_MASK, 504 NULL, 505 GetLastError() & 0xffff, 506 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 507 buffer, 508 sizeof(buffer) / sizeof(WCHAR), 509 NULL); 510 WideCharToMultiByte(CP_UTF8, 0, buffer, -1, message, sizeof(message), NULL, NULL); 511 512 _glfwInputError(error, "%s: %s", description, message); 513 } 514 515 // Updates key names according to the current keyboard layout 516 // 517 void _glfwUpdateKeyNamesWin32(void) 518 { 519 int key; 520 BYTE state[256] = {0}; 521 522 memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames)); 523 524 for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++) 525 { 526 UINT vk; 527 int scancode, length; 528 WCHAR chars[16]; 529 530 scancode = _glfw.win32.scancodes[key]; 531 if (scancode == -1) 532 continue; 533 534 if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) 535 { 536 const UINT vks[] = { 537 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, 538 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, 539 VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, 540 VK_MULTIPLY, VK_SUBTRACT, VK_ADD 541 }; 542 543 vk = vks[key - GLFW_KEY_KP_0]; 544 } 545 else 546 vk = MapVirtualKeyW(scancode, MAPVK_VSC_TO_VK); 547 548 length = ToUnicode(vk, scancode, state, 549 chars, sizeof(chars) / sizeof(WCHAR), 550 0); 551 552 if (length == -1) 553 { 554 // This is a dead key, so we need a second simulated key press 555 // to make it output its own character (usually a diacritic) 556 length = ToUnicode(vk, scancode, state, 557 chars, sizeof(chars) / sizeof(WCHAR), 558 0); 559 } 560 561 if (length < 1) 562 continue; 563 564 WideCharToMultiByte(CP_UTF8, 0, chars, 1, 565 _glfw.win32.keynames[key], 566 sizeof(_glfw.win32.keynames[key]), 567 NULL, NULL); 568 } 569 } 570 571 // Replacement for IsWindowsVersionOrGreater, as we cannot rely on the 572 // application having a correct embedded manifest 573 // 574 BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp) 575 { 576 OSVERSIONINFOEXW osvi = { sizeof(osvi), major, minor, 0, 0, {0}, sp }; 577 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR; 578 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 579 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 580 cond = VerSetConditionMask(cond, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); 581 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 582 // latter lies unless the user knew to embed a non-default manifest 583 // announcing support for Windows 10 via supportedOS GUID 584 return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; 585 } 586 587 // Checks whether we are on at least the specified build of Windows 10 588 // 589 BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build) 590 { 591 OSVERSIONINFOEXW osvi = { sizeof(osvi), 10, 0, build }; 592 DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER; 593 ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); 594 cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); 595 cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL); 596 // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the 597 // latter lies unless the user knew to embed a non-default manifest 598 // announcing support for Windows 10 via supportedOS GUID 599 return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; 600 } 601 602 GLFWbool _glfwConnectWin32(int platformID, _GLFWplatform* platform) 603 { 604 const _GLFWplatform win32 = 605 { 606 .platformID = GLFW_PLATFORM_WIN32, 607 .init = _glfwInitWin32, 608 .terminate = _glfwTerminateWin32, 609 .getCursorPos = _glfwGetCursorPosWin32, 610 .setCursorPos = _glfwSetCursorPosWin32, 611 .setCursorMode = _glfwSetCursorModeWin32, 612 .setRawMouseMotion = _glfwSetRawMouseMotionWin32, 613 .rawMouseMotionSupported = _glfwRawMouseMotionSupportedWin32, 614 .createCursor = _glfwCreateCursorWin32, 615 .createStandardCursor = _glfwCreateStandardCursorWin32, 616 .destroyCursor = _glfwDestroyCursorWin32, 617 .setCursor = _glfwSetCursorWin32, 618 .getScancodeName = _glfwGetScancodeNameWin32, 619 .getKeyScancode = _glfwGetKeyScancodeWin32, 620 .setClipboardString = _glfwSetClipboardStringWin32, 621 .getClipboardString = _glfwGetClipboardStringWin32, 622 .initJoysticks = _glfwInitJoysticksWin32, 623 .terminateJoysticks = _glfwTerminateJoysticksWin32, 624 .pollJoystick = _glfwPollJoystickWin32, 625 .getMappingName = _glfwGetMappingNameWin32, 626 .updateGamepadGUID = _glfwUpdateGamepadGUIDWin32, 627 .freeMonitor = _glfwFreeMonitorWin32, 628 .getMonitorPos = _glfwGetMonitorPosWin32, 629 .getMonitorContentScale = _glfwGetMonitorContentScaleWin32, 630 .getMonitorWorkarea = _glfwGetMonitorWorkareaWin32, 631 .getVideoModes = _glfwGetVideoModesWin32, 632 .getVideoMode = _glfwGetVideoModeWin32, 633 .getGammaRamp = _glfwGetGammaRampWin32, 634 .setGammaRamp = _glfwSetGammaRampWin32, 635 .createWindow = _glfwCreateWindowWin32, 636 .destroyWindow = _glfwDestroyWindowWin32, 637 .setWindowTitle = _glfwSetWindowTitleWin32, 638 .setWindowIcon = _glfwSetWindowIconWin32, 639 .getWindowPos = _glfwGetWindowPosWin32, 640 .setWindowPos = _glfwSetWindowPosWin32, 641 .getWindowSize = _glfwGetWindowSizeWin32, 642 .setWindowSize = _glfwSetWindowSizeWin32, 643 .setWindowSizeLimits = _glfwSetWindowSizeLimitsWin32, 644 .setWindowAspectRatio = _glfwSetWindowAspectRatioWin32, 645 .getFramebufferSize = _glfwGetFramebufferSizeWin32, 646 .getWindowFrameSize = _glfwGetWindowFrameSizeWin32, 647 .getWindowContentScale = _glfwGetWindowContentScaleWin32, 648 .iconifyWindow = _glfwIconifyWindowWin32, 649 .restoreWindow = _glfwRestoreWindowWin32, 650 .maximizeWindow = _glfwMaximizeWindowWin32, 651 .showWindow = _glfwShowWindowWin32, 652 .hideWindow = _glfwHideWindowWin32, 653 .requestWindowAttention = _glfwRequestWindowAttentionWin32, 654 .focusWindow = _glfwFocusWindowWin32, 655 .setWindowMonitor = _glfwSetWindowMonitorWin32, 656 .windowFocused = _glfwWindowFocusedWin32, 657 .windowIconified = _glfwWindowIconifiedWin32, 658 .windowVisible = _glfwWindowVisibleWin32, 659 .windowMaximized = _glfwWindowMaximizedWin32, 660 .windowHovered = _glfwWindowHoveredWin32, 661 .framebufferTransparent = _glfwFramebufferTransparentWin32, 662 .getWindowOpacity = _glfwGetWindowOpacityWin32, 663 .setWindowResizable = _glfwSetWindowResizableWin32, 664 .setWindowDecorated = _glfwSetWindowDecoratedWin32, 665 .setWindowFloating = _glfwSetWindowFloatingWin32, 666 .setWindowOpacity = _glfwSetWindowOpacityWin32, 667 .setWindowMousePassthrough = _glfwSetWindowMousePassthroughWin32, 668 .pollEvents = _glfwPollEventsWin32, 669 .waitEvents = _glfwWaitEventsWin32, 670 .waitEventsTimeout = _glfwWaitEventsTimeoutWin32, 671 .postEmptyEvent = _glfwPostEmptyEventWin32, 672 .getEGLPlatform = _glfwGetEGLPlatformWin32, 673 .getEGLNativeDisplay = _glfwGetEGLNativeDisplayWin32, 674 .getEGLNativeWindow = _glfwGetEGLNativeWindowWin32, 675 .getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsWin32, 676 .getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportWin32, 677 .createWindowSurface = _glfwCreateWindowSurfaceWin32 678 }; 679 680 *platform = win32; 681 return GLFW_TRUE; 682 } 683 684 int _glfwInitWin32(void) 685 { 686 if (!loadLibraries()) 687 return GLFW_FALSE; 688 689 createKeyTablesWin32(); 690 _glfwUpdateKeyNamesWin32(); 691 692 if (_glfwIsWindows10Version1703OrGreaterWin32()) 693 SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); 694 else if (IsWindows8Point1OrGreater()) 695 SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); 696 else if (IsWindowsVistaOrGreater()) 697 SetProcessDPIAware(); 698 699 if (!createHelperWindow()) 700 return GLFW_FALSE; 701 702 _glfwPollMonitorsWin32(); 703 return GLFW_TRUE; 704 } 705 706 void _glfwTerminateWin32(void) 707 { 708 if (_glfw.win32.blankCursor) 709 DestroyIcon((HICON) _glfw.win32.blankCursor); 710 711 if (_glfw.win32.deviceNotificationHandle) 712 UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle); 713 714 if (_glfw.win32.helperWindowHandle) 715 DestroyWindow(_glfw.win32.helperWindowHandle); 716 if (_glfw.win32.helperWindowClass) 717 UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance); 718 if (_glfw.win32.mainWindowClass) 719 UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance); 720 721 _glfw_free(_glfw.win32.clipboardString); 722 _glfw_free(_glfw.win32.rawInput); 723 724 _glfwTerminateWGL(); 725 _glfwTerminateEGL(); 726 _glfwTerminateOSMesa(); 727 728 freeLibraries(); 729 } 730 731 #endif // _GLFW_WIN32 732