github.com/Konstantin8105/c4go@v0.0.0-20240505174241-768bb1c65a51/tests/raylib/external/glfw/src/win32_init.c (about)

     1  //========================================================================
     2  // GLFW 3.4 Win32 - www.glfw.org
     3  //------------------------------------------------------------------------
     4  // Copyright (c) 2002-2006 Marcus Geelnard
     5  // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
     6  //
     7  // This software is provided 'as-is', without any express or implied
     8  // warranty. In no event will the authors be held liable for any damages
     9  // arising from the use of this software.
    10  //
    11  // Permission is granted to anyone to use this software for any purpose,
    12  // including commercial applications, and to alter it and redistribute it
    13  // freely, subject to the following restrictions:
    14  //
    15  // 1. The origin of this software must not be misrepresented; you must not
    16  //    claim that you wrote the original software. If you use this software
    17  //    in a product, an acknowledgment in the product documentation would
    18  //    be appreciated but is not required.
    19  //
    20  // 2. Altered source versions must be plainly marked as such, and must not
    21  //    be misrepresented as being the original software.
    22  //
    23  // 3. This notice may not be removed or altered from any source
    24  //    distribution.
    25  //
    26  //========================================================================
    27  // Please use C89 style variable declarations in this file because VS 2010
    28  //========================================================================
    29  
    30  #include "internal.h"
    31  
    32  #include <stdlib.h>
    33  
    34  static const GUID _glfw_GUID_DEVINTERFACE_HID =
    35      {0x4d1e55b2,0xf16f,0x11cf,{0x88,0xcb,0x00,0x11,0x11,0x00,0x00,0x30}};
    36  
    37  #define GUID_DEVINTERFACE_HID _glfw_GUID_DEVINTERFACE_HID
    38  
    39  #if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
    40  
    41  #if defined(_GLFW_BUILD_DLL)
    42   #pragma message("These symbols must be exported by the executable and have no effect in a DLL")
    43  #endif
    44  
    45  // Executables (but not DLLs) exporting this symbol with this value will be
    46  // automatically directed to the high-performance GPU on Nvidia Optimus systems
    47  // with up-to-date drivers
    48  //
    49  __declspec(dllexport) DWORD NvOptimusEnablement = 1;
    50  
    51  // Executables (but not DLLs) exporting this symbol with this value will be
    52  // automatically directed to the high-performance GPU on AMD PowerXpress systems
    53  // with up-to-date drivers
    54  //
    55  __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
    56  
    57  #endif // _GLFW_USE_HYBRID_HPG
    58  
    59  #if defined(_GLFW_BUILD_DLL)
    60  
    61  // GLFW DLL entry point
    62  //
    63  BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
    64  {
    65      return TRUE;
    66  }
    67  
    68  #endif // _GLFW_BUILD_DLL
    69  
    70  // Load necessary libraries (DLLs)
    71  //
    72  static GLFWbool loadLibraries(void)
    73  {
    74      if (!GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
    75                                  GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
    76                              (const WCHAR*) &_glfw,
    77                              (HMODULE*) &_glfw.win32.instance))
    78      {
    79          _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    80                               "Win32: Failed to retrieve own module handle");
    81          return GLFW_FALSE;
    82      }
    83  
    84      _glfw.win32.user32.instance = _glfwPlatformLoadModule("user32.dll");
    85      if (!_glfw.win32.user32.instance)
    86      {
    87          _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
    88                               "Win32: Failed to load user32.dll");
    89          return GLFW_FALSE;
    90      }
    91  
    92      _glfw.win32.user32.SetProcessDPIAware_ = (PFN_SetProcessDPIAware)
    93          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDPIAware");
    94      _glfw.win32.user32.ChangeWindowMessageFilterEx_ = (PFN_ChangeWindowMessageFilterEx)
    95          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "ChangeWindowMessageFilterEx");
    96      _glfw.win32.user32.EnableNonClientDpiScaling_ = (PFN_EnableNonClientDpiScaling)
    97          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "EnableNonClientDpiScaling");
    98      _glfw.win32.user32.SetProcessDpiAwarenessContext_ = (PFN_SetProcessDpiAwarenessContext)
    99          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "SetProcessDpiAwarenessContext");
   100      _glfw.win32.user32.GetDpiForWindow_ = (PFN_GetDpiForWindow)
   101          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetDpiForWindow");
   102      _glfw.win32.user32.AdjustWindowRectExForDpi_ = (PFN_AdjustWindowRectExForDpi)
   103          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "AdjustWindowRectExForDpi");
   104      _glfw.win32.user32.GetSystemMetricsForDpi_ = (PFN_GetSystemMetricsForDpi)
   105          _glfwPlatformGetModuleSymbol(_glfw.win32.user32.instance, "GetSystemMetricsForDpi");
   106  
   107      _glfw.win32.dinput8.instance = _glfwPlatformLoadModule("dinput8.dll");
   108      if (_glfw.win32.dinput8.instance)
   109      {
   110          _glfw.win32.dinput8.Create = (PFN_DirectInput8Create)
   111              _glfwPlatformGetModuleSymbol(_glfw.win32.dinput8.instance, "DirectInput8Create");
   112      }
   113  
   114      {
   115          int i;
   116          const char* names[] =
   117          {
   118              "xinput1_4.dll",
   119              "xinput1_3.dll",
   120              "xinput9_1_0.dll",
   121              "xinput1_2.dll",
   122              "xinput1_1.dll",
   123              NULL
   124          };
   125  
   126          for (i = 0;  names[i];  i++)
   127          {
   128              _glfw.win32.xinput.instance = _glfwPlatformLoadModule(names[i]);
   129              if (_glfw.win32.xinput.instance)
   130              {
   131                  _glfw.win32.xinput.GetCapabilities = (PFN_XInputGetCapabilities)
   132                      _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetCapabilities");
   133                  _glfw.win32.xinput.GetState = (PFN_XInputGetState)
   134                      _glfwPlatformGetModuleSymbol(_glfw.win32.xinput.instance, "XInputGetState");
   135  
   136                  break;
   137              }
   138          }
   139      }
   140  
   141      _glfw.win32.dwmapi.instance = _glfwPlatformLoadModule("dwmapi.dll");
   142      if (_glfw.win32.dwmapi.instance)
   143      {
   144          _glfw.win32.dwmapi.IsCompositionEnabled = (PFN_DwmIsCompositionEnabled)
   145              _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
   146          _glfw.win32.dwmapi.Flush = (PFN_DwmFlush)
   147              _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmFlush");
   148          _glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
   149              _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
   150          _glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
   151              _glfwPlatformGetModuleSymbol(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
   152      }
   153  
   154      _glfw.win32.shcore.instance = _glfwPlatformLoadModule("shcore.dll");
   155      if (_glfw.win32.shcore.instance)
   156      {
   157          _glfw.win32.shcore.SetProcessDpiAwareness_ = (PFN_SetProcessDpiAwareness)
   158              _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "SetProcessDpiAwareness");
   159          _glfw.win32.shcore.GetDpiForMonitor_ = (PFN_GetDpiForMonitor)
   160              _glfwPlatformGetModuleSymbol(_glfw.win32.shcore.instance, "GetDpiForMonitor");
   161      }
   162  
   163      _glfw.win32.ntdll.instance = _glfwPlatformLoadModule("ntdll.dll");
   164      if (_glfw.win32.ntdll.instance)
   165      {
   166          _glfw.win32.ntdll.RtlVerifyVersionInfo_ = (PFN_RtlVerifyVersionInfo)
   167              _glfwPlatformGetModuleSymbol(_glfw.win32.ntdll.instance, "RtlVerifyVersionInfo");
   168      }
   169  
   170      return GLFW_TRUE;
   171  }
   172  
   173  // Unload used libraries (DLLs)
   174  //
   175  static void freeLibraries(void)
   176  {
   177      if (_glfw.win32.xinput.instance)
   178          _glfwPlatformFreeModule(_glfw.win32.xinput.instance);
   179  
   180      if (_glfw.win32.dinput8.instance)
   181          _glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
   182  
   183      if (_glfw.win32.user32.instance)
   184          _glfwPlatformFreeModule(_glfw.win32.user32.instance);
   185  
   186      if (_glfw.win32.dwmapi.instance)
   187          _glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
   188  
   189      if (_glfw.win32.shcore.instance)
   190          _glfwPlatformFreeModule(_glfw.win32.shcore.instance);
   191  
   192      if (_glfw.win32.ntdll.instance)
   193          _glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
   194  }
   195  
   196  // Create key code translation tables
   197  //
   198  static void createKeyTables(void)
   199  {
   200      int scancode;
   201  
   202      memset(_glfw.win32.keycodes, -1, sizeof(_glfw.win32.keycodes));
   203      memset(_glfw.win32.scancodes, -1, sizeof(_glfw.win32.scancodes));
   204  
   205      _glfw.win32.keycodes[0x00B] = GLFW_KEY_0;
   206      _glfw.win32.keycodes[0x002] = GLFW_KEY_1;
   207      _glfw.win32.keycodes[0x003] = GLFW_KEY_2;
   208      _glfw.win32.keycodes[0x004] = GLFW_KEY_3;
   209      _glfw.win32.keycodes[0x005] = GLFW_KEY_4;
   210      _glfw.win32.keycodes[0x006] = GLFW_KEY_5;
   211      _glfw.win32.keycodes[0x007] = GLFW_KEY_6;
   212      _glfw.win32.keycodes[0x008] = GLFW_KEY_7;
   213      _glfw.win32.keycodes[0x009] = GLFW_KEY_8;
   214      _glfw.win32.keycodes[0x00A] = GLFW_KEY_9;
   215      _glfw.win32.keycodes[0x01E] = GLFW_KEY_A;
   216      _glfw.win32.keycodes[0x030] = GLFW_KEY_B;
   217      _glfw.win32.keycodes[0x02E] = GLFW_KEY_C;
   218      _glfw.win32.keycodes[0x020] = GLFW_KEY_D;
   219      _glfw.win32.keycodes[0x012] = GLFW_KEY_E;
   220      _glfw.win32.keycodes[0x021] = GLFW_KEY_F;
   221      _glfw.win32.keycodes[0x022] = GLFW_KEY_G;
   222      _glfw.win32.keycodes[0x023] = GLFW_KEY_H;
   223      _glfw.win32.keycodes[0x017] = GLFW_KEY_I;
   224      _glfw.win32.keycodes[0x024] = GLFW_KEY_J;
   225      _glfw.win32.keycodes[0x025] = GLFW_KEY_K;
   226      _glfw.win32.keycodes[0x026] = GLFW_KEY_L;
   227      _glfw.win32.keycodes[0x032] = GLFW_KEY_M;
   228      _glfw.win32.keycodes[0x031] = GLFW_KEY_N;
   229      _glfw.win32.keycodes[0x018] = GLFW_KEY_O;
   230      _glfw.win32.keycodes[0x019] = GLFW_KEY_P;
   231      _glfw.win32.keycodes[0x010] = GLFW_KEY_Q;
   232      _glfw.win32.keycodes[0x013] = GLFW_KEY_R;
   233      _glfw.win32.keycodes[0x01F] = GLFW_KEY_S;
   234      _glfw.win32.keycodes[0x014] = GLFW_KEY_T;
   235      _glfw.win32.keycodes[0x016] = GLFW_KEY_U;
   236      _glfw.win32.keycodes[0x02F] = GLFW_KEY_V;
   237      _glfw.win32.keycodes[0x011] = GLFW_KEY_W;
   238      _glfw.win32.keycodes[0x02D] = GLFW_KEY_X;
   239      _glfw.win32.keycodes[0x015] = GLFW_KEY_Y;
   240      _glfw.win32.keycodes[0x02C] = GLFW_KEY_Z;
   241  
   242      _glfw.win32.keycodes[0x028] = GLFW_KEY_APOSTROPHE;
   243      _glfw.win32.keycodes[0x02B] = GLFW_KEY_BACKSLASH;
   244      _glfw.win32.keycodes[0x033] = GLFW_KEY_COMMA;
   245      _glfw.win32.keycodes[0x00D] = GLFW_KEY_EQUAL;
   246      _glfw.win32.keycodes[0x029] = GLFW_KEY_GRAVE_ACCENT;
   247      _glfw.win32.keycodes[0x01A] = GLFW_KEY_LEFT_BRACKET;
   248      _glfw.win32.keycodes[0x00C] = GLFW_KEY_MINUS;
   249      _glfw.win32.keycodes[0x034] = GLFW_KEY_PERIOD;
   250      _glfw.win32.keycodes[0x01B] = GLFW_KEY_RIGHT_BRACKET;
   251      _glfw.win32.keycodes[0x027] = GLFW_KEY_SEMICOLON;
   252      _glfw.win32.keycodes[0x035] = GLFW_KEY_SLASH;
   253      _glfw.win32.keycodes[0x056] = GLFW_KEY_WORLD_2;
   254  
   255      _glfw.win32.keycodes[0x00E] = GLFW_KEY_BACKSPACE;
   256      _glfw.win32.keycodes[0x153] = GLFW_KEY_DELETE;
   257      _glfw.win32.keycodes[0x14F] = GLFW_KEY_END;
   258      _glfw.win32.keycodes[0x01C] = GLFW_KEY_ENTER;
   259      _glfw.win32.keycodes[0x001] = GLFW_KEY_ESCAPE;
   260      _glfw.win32.keycodes[0x147] = GLFW_KEY_HOME;
   261      _glfw.win32.keycodes[0x152] = GLFW_KEY_INSERT;
   262      _glfw.win32.keycodes[0x15D] = GLFW_KEY_MENU;
   263      _glfw.win32.keycodes[0x151] = GLFW_KEY_PAGE_DOWN;
   264      _glfw.win32.keycodes[0x149] = GLFW_KEY_PAGE_UP;
   265      _glfw.win32.keycodes[0x045] = 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  // Window procedure for the hidden helper window
   335  //
   336  static LRESULT CALLBACK helperWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
   337  {
   338      switch (uMsg)
   339      {
   340          case WM_DISPLAYCHANGE:
   341              _glfwPollMonitorsWin32();
   342              break;
   343  
   344          case WM_DEVICECHANGE:
   345          {
   346              if (!_glfw.joysticksInitialized)
   347                  break;
   348  
   349              if (wParam == DBT_DEVICEARRIVAL)
   350              {
   351                  DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
   352                  if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
   353                      _glfwDetectJoystickConnectionWin32();
   354              }
   355              else if (wParam == DBT_DEVICEREMOVECOMPLETE)
   356              {
   357                  DEV_BROADCAST_HDR* dbh = (DEV_BROADCAST_HDR*) lParam;
   358                  if (dbh && dbh->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
   359                      _glfwDetectJoystickDisconnectionWin32();
   360              }
   361  
   362              break;
   363          }
   364      }
   365  
   366      return DefWindowProcW(hWnd, uMsg, wParam, lParam);
   367  }
   368  
   369  // Creates a dummy window for behind-the-scenes work
   370  //
   371  static GLFWbool createHelperWindow(void)
   372  {
   373      MSG msg;
   374      WNDCLASSEXW wc = { sizeof(wc) };
   375  
   376      wc.style         = CS_OWNDC;
   377      wc.lpfnWndProc   = (WNDPROC) helperWindowProc;
   378      wc.hInstance     = _glfw.win32.instance;
   379      wc.lpszClassName = L"GLFW3 Helper";
   380  
   381      _glfw.win32.helperWindowClass = RegisterClassExW(&wc);
   382      if (!_glfw.win32.helperWindowClass)
   383      {
   384          _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
   385                               "WIn32: Failed to register helper window class");
   386          return GLFW_FALSE;
   387      }
   388  
   389      _glfw.win32.helperWindowHandle =
   390          CreateWindowExW(WS_EX_OVERLAPPEDWINDOW,
   391                          MAKEINTATOM(_glfw.win32.helperWindowClass),
   392                          L"GLFW message window",
   393                          WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
   394                          0, 0, 1, 1,
   395                          NULL, NULL,
   396                          _glfw.win32.instance,
   397                          NULL);
   398  
   399      if (!_glfw.win32.helperWindowHandle)
   400      {
   401          _glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
   402                               "Win32: Failed to create helper window");
   403          return GLFW_FALSE;
   404      }
   405  
   406      // HACK: The command to the first ShowWindow call is ignored if the parent
   407      //       process passed along a STARTUPINFO, so clear that with a no-op call
   408      ShowWindow(_glfw.win32.helperWindowHandle, SW_HIDE);
   409  
   410      // Register for HID device notifications
   411      {
   412          DEV_BROADCAST_DEVICEINTERFACE_W dbi;
   413          ZeroMemory(&dbi, sizeof(dbi));
   414          dbi.dbcc_size = sizeof(dbi);
   415          dbi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
   416          dbi.dbcc_classguid = GUID_DEVINTERFACE_HID;
   417  
   418          _glfw.win32.deviceNotificationHandle =
   419              RegisterDeviceNotificationW(_glfw.win32.helperWindowHandle,
   420                                          (DEV_BROADCAST_HDR*) &dbi,
   421                                          DEVICE_NOTIFY_WINDOW_HANDLE);
   422      }
   423  
   424      while (PeekMessageW(&msg, _glfw.win32.helperWindowHandle, 0, 0, PM_REMOVE))
   425      {
   426          TranslateMessage(&msg);
   427          DispatchMessageW(&msg);
   428      }
   429  
   430     return GLFW_TRUE;
   431  }
   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          GLFW_PLATFORM_WIN32,
   607          _glfwInitWin32,
   608          _glfwTerminateWin32,
   609          _glfwGetCursorPosWin32,
   610          _glfwSetCursorPosWin32,
   611          _glfwSetCursorModeWin32,
   612          _glfwSetRawMouseMotionWin32,
   613          _glfwRawMouseMotionSupportedWin32,
   614          _glfwCreateCursorWin32,
   615          _glfwCreateStandardCursorWin32,
   616          _glfwDestroyCursorWin32,
   617          _glfwSetCursorWin32,
   618          _glfwGetScancodeNameWin32,
   619          _glfwGetKeyScancodeWin32,
   620          _glfwSetClipboardStringWin32,
   621          _glfwGetClipboardStringWin32,
   622          _glfwInitJoysticksWin32,
   623          _glfwTerminateJoysticksWin32,
   624          _glfwPollJoystickWin32,
   625          _glfwGetMappingNameWin32,
   626          _glfwUpdateGamepadGUIDWin32,
   627          _glfwFreeMonitorWin32,
   628          _glfwGetMonitorPosWin32,
   629          _glfwGetMonitorContentScaleWin32,
   630          _glfwGetMonitorWorkareaWin32,
   631          _glfwGetVideoModesWin32,
   632          _glfwGetVideoModeWin32,
   633          _glfwGetGammaRampWin32,
   634          _glfwSetGammaRampWin32,
   635          _glfwCreateWindowWin32,
   636          _glfwDestroyWindowWin32,
   637          _glfwSetWindowTitleWin32,
   638          _glfwSetWindowIconWin32,
   639          _glfwGetWindowPosWin32,
   640          _glfwSetWindowPosWin32,
   641          _glfwGetWindowSizeWin32,
   642          _glfwSetWindowSizeWin32,
   643          _glfwSetWindowSizeLimitsWin32,
   644          _glfwSetWindowAspectRatioWin32,
   645          _glfwGetFramebufferSizeWin32,
   646          _glfwGetWindowFrameSizeWin32,
   647          _glfwGetWindowContentScaleWin32,
   648          _glfwIconifyWindowWin32,
   649          _glfwRestoreWindowWin32,
   650          _glfwMaximizeWindowWin32,
   651          _glfwShowWindowWin32,
   652          _glfwHideWindowWin32,
   653          _glfwRequestWindowAttentionWin32,
   654          _glfwFocusWindowWin32,
   655          _glfwSetWindowMonitorWin32,
   656          _glfwWindowFocusedWin32,
   657          _glfwWindowIconifiedWin32,
   658          _glfwWindowVisibleWin32,
   659          _glfwWindowMaximizedWin32,
   660          _glfwWindowHoveredWin32,
   661          _glfwFramebufferTransparentWin32,
   662          _glfwGetWindowOpacityWin32,
   663          _glfwSetWindowResizableWin32,
   664          _glfwSetWindowDecoratedWin32,
   665          _glfwSetWindowFloatingWin32,
   666          _glfwSetWindowOpacityWin32,
   667          _glfwSetWindowMousePassthroughWin32,
   668          _glfwPollEventsWin32,
   669          _glfwWaitEventsWin32,
   670          _glfwWaitEventsTimeoutWin32,
   671          _glfwPostEmptyEventWin32,
   672          _glfwGetEGLPlatformWin32,
   673          _glfwGetEGLNativeDisplayWin32,
   674          _glfwGetEGLNativeWindowWin32,
   675          _glfwGetRequiredInstanceExtensionsWin32,
   676          _glfwGetPhysicalDevicePresentationSupportWin32,
   677          _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      createKeyTables();
   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.deviceNotificationHandle)
   709          UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
   710  
   711      if (_glfw.win32.helperWindowHandle)
   712          DestroyWindow(_glfw.win32.helperWindowHandle);
   713      if (_glfw.win32.helperWindowClass)
   714          UnregisterClassW(MAKEINTATOM(_glfw.win32.helperWindowClass), _glfw.win32.instance);
   715      if (_glfw.win32.mainWindowClass)
   716          UnregisterClassW(MAKEINTATOM(_glfw.win32.mainWindowClass), _glfw.win32.instance);
   717  
   718      _glfw_free(_glfw.win32.clipboardString);
   719      _glfw_free(_glfw.win32.rawInput);
   720  
   721      _glfwTerminateWGL();
   722      _glfwTerminateEGL();
   723      _glfwTerminateOSMesa();
   724  
   725      freeLibraries();
   726  }
   727