1 //========================================================================
2 // GLFW 3.3 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 
28 // We don't need all the fancy stuff
29 #ifndef NOMINMAX
30  #define NOMINMAX
31 #endif
32 
33 #ifndef VC_EXTRALEAN
34  #define VC_EXTRALEAN
35 #endif
36 
37 #ifndef WIN32_LEAN_AND_MEAN
38  #define WIN32_LEAN_AND_MEAN
39 #endif
40 
41 // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for
42 // example to allow applications to correctly declare a GL_ARB_debug_output
43 // callback) but windows.h assumes no one will define APIENTRY before it does
44 #undef APIENTRY
45 
46 // GLFW on Windows is Unicode only and does not work in MBCS mode
47 #ifndef UNICODE
48  #define UNICODE
49 #endif
50 
51 // GLFW requires Windows XP or later
52 #if WINVER < 0x0501
53  #undef WINVER
54  #define WINVER 0x0501
55 #endif
56 #if _WIN32_WINNT < 0x0501
57  #undef _WIN32_WINNT
58  #define _WIN32_WINNT 0x0501
59 #endif
60 
61 // GLFW uses DirectInput8 interfaces
62 #define DIRECTINPUT_VERSION 0x0800
63 
64 // GLFW uses OEM cursor resources
65 #define OEMRESOURCE
66 
67 #include <wctype.h>
68 #include <windows.h>
69 #include <dinput.h>
70 #include <xinput.h>
71 #include <dbt.h>
72 
73 // HACK: Define macros that some windows.h variants don't
74 #ifndef WM_MOUSEHWHEEL
75  #define WM_MOUSEHWHEEL 0x020E
76 #endif
77 #ifndef WM_DWMCOMPOSITIONCHANGED
78  #define WM_DWMCOMPOSITIONCHANGED 0x031E
79 #endif
80 #ifndef WM_DWMCOLORIZATIONCOLORCHANGED
81  #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
82 #endif
83 #ifndef WM_COPYGLOBALDATA
84  #define WM_COPYGLOBALDATA 0x0049
85 #endif
86 #ifndef WM_UNICHAR
87  #define WM_UNICHAR 0x0109
88 #endif
89 #ifndef UNICODE_NOCHAR
90  #define UNICODE_NOCHAR 0xFFFF
91 #endif
92 #ifndef WM_DPICHANGED
93  #define WM_DPICHANGED 0x02E0
94 #endif
95 #ifndef GET_XBUTTON_WPARAM
96  #define GET_XBUTTON_WPARAM(w) (HIWORD(w))
97 #endif
98 #ifndef EDS_ROTATEDMODE
99  #define EDS_ROTATEDMODE 0x00000004
100 #endif
101 #ifndef DISPLAY_DEVICE_ACTIVE
102  #define DISPLAY_DEVICE_ACTIVE 0x00000001
103 #endif
104 #ifndef _WIN32_WINNT_WINBLUE
105  #define _WIN32_WINNT_WINBLUE 0x0603
106 #endif
107 #ifndef _WIN32_WINNT_WIN8
108  #define _WIN32_WINNT_WIN8 0x0602
109 #endif
110 #ifndef WM_GETDPISCALEDSIZE
111  #define WM_GETDPISCALEDSIZE 0x02e4
112 #endif
113 #ifndef USER_DEFAULT_SCREEN_DPI
114  #define USER_DEFAULT_SCREEN_DPI 96
115 #endif
116 #ifndef OCR_HAND
117  #define OCR_HAND 32649
118 #endif
119 
120 #if WINVER < 0x0601
121 typedef struct
122 {
123     DWORD cbSize;
124     DWORD ExtStatus;
125 } CHANGEFILTERSTRUCT;
126 #ifndef MSGFLT_ALLOW
127  #define MSGFLT_ALLOW 1
128 #endif
129 #endif /*Windows 7*/
130 
131 #if WINVER < 0x0600
132 #define DWM_BB_ENABLE 0x00000001
133 #define DWM_BB_BLURREGION 0x00000002
134 typedef struct
135 {
136     DWORD dwFlags;
137     BOOL fEnable;
138     HRGN hRgnBlur;
139     BOOL fTransitionOnMaximized;
140 } DWM_BLURBEHIND;
141 #else
142  #include <dwmapi.h>
143 #endif /*Windows Vista*/
144 
145 #ifndef DPI_ENUMS_DECLARED
146 typedef enum
147 {
148     PROCESS_DPI_UNAWARE = 0,
149     PROCESS_SYSTEM_DPI_AWARE = 1,
150     PROCESS_PER_MONITOR_DPI_AWARE = 2
151 } PROCESS_DPI_AWARENESS;
152 typedef enum
153 {
154     MDT_EFFECTIVE_DPI = 0,
155     MDT_ANGULAR_DPI = 1,
156     MDT_RAW_DPI = 2,
157     MDT_DEFAULT = MDT_EFFECTIVE_DPI
158 } MONITOR_DPI_TYPE;
159 #endif /*DPI_ENUMS_DECLARED*/
160 
161 #ifndef DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
162 #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE) -4)
163 #endif /*DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2*/
164 
165 // HACK: Define versionhelpers.h functions manually as MinGW lacks the header
166 #define IsWindowsXPOrGreater()                                 \
167     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINXP),   \
168                                         LOBYTE(_WIN32_WINNT_WINXP), 0)
169 #define IsWindowsVistaOrGreater()                                     \
170     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_VISTA),   \
171                                         LOBYTE(_WIN32_WINNT_VISTA), 0)
172 #define IsWindows7OrGreater()                                         \
173     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN7),    \
174                                         LOBYTE(_WIN32_WINNT_WIN7), 0)
175 #define IsWindows8OrGreater()                                         \
176     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WIN8),    \
177                                         LOBYTE(_WIN32_WINNT_WIN8), 0)
178 #define IsWindows8Point1OrGreater()                                   \
179     _glfwIsWindowsVersionOrGreaterWin32(HIBYTE(_WIN32_WINNT_WINBLUE), \
180                                         LOBYTE(_WIN32_WINNT_WINBLUE), 0)
181 
182 #define _glfwIsWindows10AnniversaryUpdateOrGreaterWin32() \
183     _glfwIsWindows10BuildOrGreaterWin32(14393)
184 #define _glfwIsWindows10CreatorsUpdateOrGreaterWin32() \
185     _glfwIsWindows10BuildOrGreaterWin32(15063)
186 
187 // HACK: Define macros that some xinput.h variants don't
188 #ifndef XINPUT_CAPS_WIRELESS
189  #define XINPUT_CAPS_WIRELESS 0x0002
190 #endif
191 #ifndef XINPUT_DEVSUBTYPE_WHEEL
192  #define XINPUT_DEVSUBTYPE_WHEEL 0x02
193 #endif
194 #ifndef XINPUT_DEVSUBTYPE_ARCADE_STICK
195  #define XINPUT_DEVSUBTYPE_ARCADE_STICK 0x03
196 #endif
197 #ifndef XINPUT_DEVSUBTYPE_FLIGHT_STICK
198  #define XINPUT_DEVSUBTYPE_FLIGHT_STICK 0x04
199 #endif
200 #ifndef XINPUT_DEVSUBTYPE_DANCE_PAD
201  #define XINPUT_DEVSUBTYPE_DANCE_PAD 0x05
202 #endif
203 #ifndef XINPUT_DEVSUBTYPE_GUITAR
204  #define XINPUT_DEVSUBTYPE_GUITAR 0x06
205 #endif
206 #ifndef XINPUT_DEVSUBTYPE_DRUM_KIT
207  #define XINPUT_DEVSUBTYPE_DRUM_KIT 0x08
208 #endif
209 #ifndef XINPUT_DEVSUBTYPE_ARCADE_PAD
210  #define XINPUT_DEVSUBTYPE_ARCADE_PAD 0x13
211 #endif
212 #ifndef XUSER_MAX_COUNT
213  #define XUSER_MAX_COUNT 4
214 #endif
215 
216 // HACK: Define macros that some dinput.h variants don't
217 #ifndef DIDFT_OPTIONAL
218  #define DIDFT_OPTIONAL 0x80000000
219 #endif
220 
221 // winmm.dll function pointer typedefs
222 typedef DWORD (WINAPI * PFN_timeGetTime)(void);
223 #define timeGetTime _glfw.win32.winmm.GetTime
224 
225 // xinput.dll function pointer typedefs
226 typedef DWORD (WINAPI * PFN_XInputGetCapabilities)(DWORD,DWORD,XINPUT_CAPABILITIES*);
227 typedef DWORD (WINAPI * PFN_XInputGetState)(DWORD,XINPUT_STATE*);
228 #define XInputGetCapabilities _glfw.win32.xinput.GetCapabilities
229 #define XInputGetState _glfw.win32.xinput.GetState
230 
231 // dinput8.dll function pointer typedefs
232 typedef HRESULT (WINAPI * PFN_DirectInput8Create)(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
233 #define DirectInput8Create _glfw.win32.dinput8.Create
234 
235 // user32.dll function pointer typedefs
236 typedef BOOL (WINAPI * PFN_SetProcessDPIAware)(void);
237 typedef BOOL (WINAPI * PFN_ChangeWindowMessageFilterEx)(HWND,UINT,DWORD,CHANGEFILTERSTRUCT*);
238 typedef BOOL (WINAPI * PFN_EnableNonClientDpiScaling)(HWND);
239 typedef BOOL (WINAPI * PFN_SetProcessDpiAwarenessContext)(HANDLE);
240 typedef UINT (WINAPI * PFN_GetDpiForWindow)(HWND);
241 typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
242 #define SetProcessDPIAware _glfw.win32.user32.SetProcessDPIAware_
243 #define ChangeWindowMessageFilterEx _glfw.win32.user32.ChangeWindowMessageFilterEx_
244 #define EnableNonClientDpiScaling _glfw.win32.user32.EnableNonClientDpiScaling_
245 #define SetProcessDpiAwarenessContext _glfw.win32.user32.SetProcessDpiAwarenessContext_
246 #define GetDpiForWindow _glfw.win32.user32.GetDpiForWindow_
247 #define AdjustWindowRectExForDpi _glfw.win32.user32.AdjustWindowRectExForDpi_
248 
249 // dwmapi.dll function pointer typedefs
250 typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
251 typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
252 typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
253 typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
254 #define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
255 #define DwmFlush _glfw.win32.dwmapi.Flush
256 #define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
257 #define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
258 
259 // shcore.dll function pointer typedefs
260 typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
261 typedef HRESULT (WINAPI * PFN_GetDpiForMonitor)(HMONITOR,MONITOR_DPI_TYPE,UINT*,UINT*);
262 #define SetProcessDpiAwareness _glfw.win32.shcore.SetProcessDpiAwareness_
263 #define GetDpiForMonitor _glfw.win32.shcore.GetDpiForMonitor_
264 
265 // ntdll.dll function pointer typedefs
266 typedef LONG (WINAPI * PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*,ULONG,ULONGLONG);
267 #define RtlVerifyVersionInfo _glfw.win32.ntdll.RtlVerifyVersionInfo_
268 
269 typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
270 
271 typedef struct VkWin32SurfaceCreateInfoKHR
272 {
273     VkStructureType                 sType;
274     const void*                     pNext;
275     VkWin32SurfaceCreateFlagsKHR    flags;
276     HINSTANCE                       hinstance;
277     HWND                            hwnd;
278 } VkWin32SurfaceCreateInfoKHR;
279 
280 typedef VkResult (APIENTRY *PFN_vkCreateWin32SurfaceKHR)(VkInstance,const VkWin32SurfaceCreateInfoKHR*,const VkAllocationCallbacks*,VkSurfaceKHR*);
281 typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice,uint32_t);
282 
283 #include "win32_joystick.h"
284 #include "wgl_context.h"
285 #include "egl_context.h"
286 #include "osmesa_context.h"
287 
288 #if !defined(_GLFW_WNDCLASSNAME)
289  #define _GLFW_WNDCLASSNAME L"GLFW30"
290 #endif
291 
292 #define _glfw_dlopen(name) LoadLibraryA(name)
293 #define _glfw_dlclose(handle) FreeLibrary((HMODULE) handle)
294 #define _glfw_dlsym(handle, name) GetProcAddress((HMODULE) handle, name)
295 
296 #define _GLFW_EGL_NATIVE_WINDOW  ((EGLNativeWindowType) window->win32.handle)
297 #define _GLFW_EGL_NATIVE_DISPLAY EGL_DEFAULT_DISPLAY
298 
299 #define _GLFW_PLATFORM_WINDOW_STATE         _GLFWwindowWin32  win32
300 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32
301 #define _GLFW_PLATFORM_LIBRARY_TIMER_STATE  _GLFWtimerWin32   win32
302 #define _GLFW_PLATFORM_MONITOR_STATE        _GLFWmonitorWin32 win32
303 #define _GLFW_PLATFORM_CURSOR_STATE         _GLFWcursorWin32  win32
304 #define _GLFW_PLATFORM_TLS_STATE            _GLFWtlsWin32     win32
305 #define _GLFW_PLATFORM_MUTEX_STATE          _GLFWmutexWin32   win32
306 
307 
308 // Win32-specific per-window data
309 //
310 typedef struct _GLFWwindowWin32
311 {
312     HWND                handle;
313     HICON               bigIcon;
314     HICON               smallIcon;
315 
316     GLFWbool            cursorTracked;
317     GLFWbool            frameAction;
318     GLFWbool            iconified;
319     GLFWbool            maximized;
320     // Whether to enable framebuffer transparency on DWM
321     GLFWbool            transparent;
322     GLFWbool            scaleToMonitor;
323 
324     // Cached size used to filter out duplicate events
325     int                 width, height;
326 
327     // The last received cursor position, regardless of source
328     int                 lastCursorPosX, lastCursorPosY;
329     // The last recevied high surrogate when decoding pairs of UTF-16 messages
330     WCHAR               highSurrogate;
331 
332 } _GLFWwindowWin32;
333 
334 // Win32-specific global data
335 //
336 typedef struct _GLFWlibraryWin32
337 {
338     HWND                helperWindowHandle;
339     HDEVNOTIFY          deviceNotificationHandle;
340     DWORD               foregroundLockTimeout;
341     int                 acquiredMonitorCount;
342     char*               clipboardString;
343     short int           keycodes[512];
344     short int           scancodes[GLFW_KEY_LAST + 1];
345     char                keynames[GLFW_KEY_LAST + 1][5];
346     // Where to place the cursor when re-enabled
347     double              restoreCursorPosX, restoreCursorPosY;
348     // The window whose disabled cursor mode is active
349     _GLFWwindow*        disabledCursorWindow;
350     RAWINPUT*           rawInput;
351     int                 rawInputSize;
352     UINT                mouseTrailSize;
353 
354     struct {
355         HINSTANCE                       instance;
356         PFN_timeGetTime                 GetTime;
357     } winmm;
358 
359     struct {
360         HINSTANCE                       instance;
361         PFN_DirectInput8Create          Create;
362         IDirectInput8W*                 api;
363     } dinput8;
364 
365     struct {
366         HINSTANCE                       instance;
367         PFN_XInputGetCapabilities       GetCapabilities;
368         PFN_XInputGetState              GetState;
369     } xinput;
370 
371     struct {
372         HINSTANCE                       instance;
373         PFN_SetProcessDPIAware          SetProcessDPIAware_;
374         PFN_ChangeWindowMessageFilterEx ChangeWindowMessageFilterEx_;
375         PFN_EnableNonClientDpiScaling   EnableNonClientDpiScaling_;
376         PFN_SetProcessDpiAwarenessContext SetProcessDpiAwarenessContext_;
377         PFN_GetDpiForWindow             GetDpiForWindow_;
378         PFN_AdjustWindowRectExForDpi    AdjustWindowRectExForDpi_;
379     } user32;
380 
381     struct {
382         HINSTANCE                       instance;
383         PFN_DwmIsCompositionEnabled     IsCompositionEnabled;
384         PFN_DwmFlush                    Flush;
385         PFN_DwmEnableBlurBehindWindow   EnableBlurBehindWindow;
386         PFN_DwmGetColorizationColor     GetColorizationColor;
387     } dwmapi;
388 
389     struct {
390         HINSTANCE                       instance;
391         PFN_SetProcessDpiAwareness      SetProcessDpiAwareness_;
392         PFN_GetDpiForMonitor            GetDpiForMonitor_;
393     } shcore;
394 
395     struct {
396         HINSTANCE                       instance;
397         PFN_RtlVerifyVersionInfo        RtlVerifyVersionInfo_;
398     } ntdll;
399 
400 } _GLFWlibraryWin32;
401 
402 // Win32-specific per-monitor data
403 //
404 typedef struct _GLFWmonitorWin32
405 {
406     HMONITOR            handle;
407     // This size matches the static size of DISPLAY_DEVICE.DeviceName
408     WCHAR               adapterName[32];
409     WCHAR               displayName[32];
410     char                publicAdapterName[32];
411     char                publicDisplayName[32];
412     GLFWbool            modesPruned;
413     GLFWbool            modeChanged;
414 
415 } _GLFWmonitorWin32;
416 
417 // Win32-specific per-cursor data
418 //
419 typedef struct _GLFWcursorWin32
420 {
421     HCURSOR             handle;
422 
423 } _GLFWcursorWin32;
424 
425 // Win32-specific global timer data
426 //
427 typedef struct _GLFWtimerWin32
428 {
429     GLFWbool            hasPC;
430     uint64_t            frequency;
431 
432 } _GLFWtimerWin32;
433 
434 // Win32-specific thread local storage data
435 //
436 typedef struct _GLFWtlsWin32
437 {
438     GLFWbool            allocated;
439     DWORD               index;
440 
441 } _GLFWtlsWin32;
442 
443 // Win32-specific mutex data
444 //
445 typedef struct _GLFWmutexWin32
446 {
447     GLFWbool            allocated;
448     CRITICAL_SECTION    section;
449 
450 } _GLFWmutexWin32;
451 
452 
453 GLFWbool _glfwRegisterWindowClassWin32(void);
454 void _glfwUnregisterWindowClassWin32(void);
455 
456 WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source);
457 char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source);
458 BOOL _glfwIsWindowsVersionOrGreaterWin32(WORD major, WORD minor, WORD sp);
459 BOOL _glfwIsWindows10BuildOrGreaterWin32(WORD build);
460 void _glfwInputErrorWin32(int error, const char* description);
461 void _glfwUpdateKeyNamesWin32(void);
462 
463 void _glfwInitTimerWin32(void);
464 
465 void _glfwPollMonitorsWin32(void);
466 void _glfwSetVideoModeWin32(_GLFWmonitor* monitor, const GLFWvidmode* desired);
467 void _glfwRestoreVideoModeWin32(_GLFWmonitor* monitor);
468 void _glfwGetMonitorContentScaleWin32(HMONITOR handle, float* xscale, float* yscale);
469 
470