volviewer

Volumetric Data Toy Viewer
git clone anongit@rnpnr.xyz:volviewer.git
Log | Files | Refs | Feed | LICENSE

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