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