glfw3.c 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/GLFW/CMakeLists.txt +368 -0
  2. package/GLFW/cocoa_init.m +694 -0
  3. package/GLFW/cocoa_joystick.h +49 -0
  4. package/GLFW/cocoa_joystick.m +485 -0
  5. package/GLFW/cocoa_monitor.m +643 -0
  6. package/GLFW/cocoa_platform.h +302 -0
  7. package/GLFW/cocoa_time.c +57 -0
  8. package/GLFW/cocoa_time.h +35 -0
  9. package/GLFW/cocoa_window.m +2072 -0
  10. package/GLFW/context.c +765 -0
  11. package/GLFW/egl_context.c +911 -0
  12. package/GLFW/glfw.rc.in +30 -0
  13. package/GLFW/glfw3.c +109 -0
  14. package/GLFW/glfw3.h +6564 -0
  15. package/GLFW/glfw3native.h +663 -0
  16. package/GLFW/glx_context.c +719 -0
  17. package/GLFW/init.c +528 -0
  18. package/GLFW/input.c +1505 -0
  19. package/GLFW/internal.h +1022 -0
  20. package/GLFW/linux_joystick.c +436 -0
  21. package/GLFW/linux_joystick.h +64 -0
  22. package/GLFW/mappings.h +1001 -0
  23. package/GLFW/mappings.h.in +82 -0
  24. package/GLFW/monitor.c +548 -0
  25. package/GLFW/nsgl_context.m +384 -0
  26. package/GLFW/null_init.c +264 -0
  27. package/GLFW/null_joystick.c +56 -0
  28. package/GLFW/null_joystick.h +32 -0
  29. package/GLFW/null_monitor.c +160 -0
  30. package/GLFW/null_platform.h +271 -0
  31. package/GLFW/null_window.c +719 -0
  32. package/GLFW/osmesa_context.c +383 -0
  33. package/GLFW/platform.c +214 -0
  34. package/GLFW/platform.h +212 -0
  35. package/GLFW/posix_module.c +53 -0
  36. package/GLFW/posix_poll.c +83 -0
  37. package/GLFW/posix_poll.h +30 -0
  38. package/GLFW/posix_thread.c +107 -0
  39. package/GLFW/posix_thread.h +49 -0
  40. package/GLFW/posix_time.c +65 -0
  41. package/GLFW/posix_time.h +41 -0
  42. package/GLFW/vulkan.c +328 -0
  43. package/GLFW/wgl_context.c +798 -0
  44. package/GLFW/win32_init.c +731 -0
  45. package/GLFW/win32_joystick.c +767 -0
  46. package/GLFW/win32_joystick.h +51 -0
  47. package/GLFW/win32_module.c +51 -0
  48. package/GLFW/win32_monitor.c +569 -0
  49. package/GLFW/win32_platform.h +631 -0
  50. package/GLFW/win32_thread.c +100 -0
  51. package/GLFW/win32_thread.h +53 -0
  52. package/GLFW/win32_time.c +54 -0
  53. package/GLFW/win32_time.h +43 -0
  54. package/GLFW/win32_window.c +2592 -0
  55. package/GLFW/window.c +1172 -0
  56. package/GLFW/wl_init.c +1003 -0
  57. package/GLFW/wl_monitor.c +274 -0
  58. package/GLFW/wl_platform.h +691 -0
  59. package/GLFW/wl_window.c +3308 -0
  60. package/GLFW/x11_init.c +1656 -0
  61. package/GLFW/x11_monitor.c +641 -0
  62. package/GLFW/x11_platform.h +1004 -0
  63. package/GLFW/x11_window.c +3357 -0
  64. package/GLFW/xkb_unicode.c +943 -0
  65. package/GLFW/xkb_unicode.h +30 -0
  66. package/LICENSE +22 -0
  67. package/README.md +236 -0
  68. package/package.json +32 -0
@@ -0,0 +1,767 @@
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
+
28
+ #include "internal.h"
29
+
30
+ #if defined(_GLFW_WIN32)
31
+
32
+ #include <stdio.h>
33
+ #include <math.h>
34
+
35
+ #define _GLFW_TYPE_AXIS 0
36
+ #define _GLFW_TYPE_SLIDER 1
37
+ #define _GLFW_TYPE_BUTTON 2
38
+ #define _GLFW_TYPE_POV 3
39
+
40
+ // Data produced with DirectInput device object enumeration
41
+ //
42
+ typedef struct _GLFWobjenumWin32
43
+ {
44
+ IDirectInputDevice8W* device;
45
+ _GLFWjoyobjectWin32* objects;
46
+ int objectCount;
47
+ int axisCount;
48
+ int sliderCount;
49
+ int buttonCount;
50
+ int povCount;
51
+ } _GLFWobjenumWin32;
52
+
53
+ // Define local copies of the necessary GUIDs
54
+ //
55
+ static const GUID _glfw_IID_IDirectInput8W =
56
+ {0xbf798031,0x483a,0x4da2,{0xaa,0x99,0x5d,0x64,0xed,0x36,0x97,0x00}};
57
+ static const GUID _glfw_GUID_XAxis =
58
+ {0xa36d02e0,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
59
+ static const GUID _glfw_GUID_YAxis =
60
+ {0xa36d02e1,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
61
+ static const GUID _glfw_GUID_ZAxis =
62
+ {0xa36d02e2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
63
+ static const GUID _glfw_GUID_RxAxis =
64
+ {0xa36d02f4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
65
+ static const GUID _glfw_GUID_RyAxis =
66
+ {0xa36d02f5,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
67
+ static const GUID _glfw_GUID_RzAxis =
68
+ {0xa36d02e3,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
69
+ static const GUID _glfw_GUID_Slider =
70
+ {0xa36d02e4,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
71
+ static const GUID _glfw_GUID_POV =
72
+ {0xa36d02f2,0xc9f3,0x11cf,{0xbf,0xc7,0x44,0x45,0x53,0x54,0x00,0x00}};
73
+
74
+ #define IID_IDirectInput8W _glfw_IID_IDirectInput8W
75
+ #define GUID_XAxis _glfw_GUID_XAxis
76
+ #define GUID_YAxis _glfw_GUID_YAxis
77
+ #define GUID_ZAxis _glfw_GUID_ZAxis
78
+ #define GUID_RxAxis _glfw_GUID_RxAxis
79
+ #define GUID_RyAxis _glfw_GUID_RyAxis
80
+ #define GUID_RzAxis _glfw_GUID_RzAxis
81
+ #define GUID_Slider _glfw_GUID_Slider
82
+ #define GUID_POV _glfw_GUID_POV
83
+
84
+ // Object data array for our clone of c_dfDIJoystick
85
+ // Generated with https://github.com/elmindreda/c_dfDIJoystick2
86
+ //
87
+ static DIOBJECTDATAFORMAT _glfwObjectDataFormats[] =
88
+ {
89
+ { &GUID_XAxis,DIJOFS_X,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
90
+ { &GUID_YAxis,DIJOFS_Y,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
91
+ { &GUID_ZAxis,DIJOFS_Z,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
92
+ { &GUID_RxAxis,DIJOFS_RX,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
93
+ { &GUID_RyAxis,DIJOFS_RY,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
94
+ { &GUID_RzAxis,DIJOFS_RZ,DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
95
+ { &GUID_Slider,DIJOFS_SLIDER(0),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
96
+ { &GUID_Slider,DIJOFS_SLIDER(1),DIDFT_AXIS|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,DIDOI_ASPECTPOSITION },
97
+ { &GUID_POV,DIJOFS_POV(0),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
98
+ { &GUID_POV,DIJOFS_POV(1),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
99
+ { &GUID_POV,DIJOFS_POV(2),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
100
+ { &GUID_POV,DIJOFS_POV(3),DIDFT_POV|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
101
+ { NULL,DIJOFS_BUTTON(0),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
102
+ { NULL,DIJOFS_BUTTON(1),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
103
+ { NULL,DIJOFS_BUTTON(2),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
104
+ { NULL,DIJOFS_BUTTON(3),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
105
+ { NULL,DIJOFS_BUTTON(4),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
106
+ { NULL,DIJOFS_BUTTON(5),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
107
+ { NULL,DIJOFS_BUTTON(6),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
108
+ { NULL,DIJOFS_BUTTON(7),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
109
+ { NULL,DIJOFS_BUTTON(8),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
110
+ { NULL,DIJOFS_BUTTON(9),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
111
+ { NULL,DIJOFS_BUTTON(10),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
112
+ { NULL,DIJOFS_BUTTON(11),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
113
+ { NULL,DIJOFS_BUTTON(12),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
114
+ { NULL,DIJOFS_BUTTON(13),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
115
+ { NULL,DIJOFS_BUTTON(14),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
116
+ { NULL,DIJOFS_BUTTON(15),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
117
+ { NULL,DIJOFS_BUTTON(16),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
118
+ { NULL,DIJOFS_BUTTON(17),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
119
+ { NULL,DIJOFS_BUTTON(18),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
120
+ { NULL,DIJOFS_BUTTON(19),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
121
+ { NULL,DIJOFS_BUTTON(20),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
122
+ { NULL,DIJOFS_BUTTON(21),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
123
+ { NULL,DIJOFS_BUTTON(22),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
124
+ { NULL,DIJOFS_BUTTON(23),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
125
+ { NULL,DIJOFS_BUTTON(24),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
126
+ { NULL,DIJOFS_BUTTON(25),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
127
+ { NULL,DIJOFS_BUTTON(26),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
128
+ { NULL,DIJOFS_BUTTON(27),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
129
+ { NULL,DIJOFS_BUTTON(28),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
130
+ { NULL,DIJOFS_BUTTON(29),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
131
+ { NULL,DIJOFS_BUTTON(30),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
132
+ { NULL,DIJOFS_BUTTON(31),DIDFT_BUTTON|DIDFT_OPTIONAL|DIDFT_ANYINSTANCE,0 },
133
+ };
134
+
135
+ // Our clone of c_dfDIJoystick
136
+ //
137
+ static const DIDATAFORMAT _glfwDataFormat =
138
+ {
139
+ sizeof(DIDATAFORMAT),
140
+ sizeof(DIOBJECTDATAFORMAT),
141
+ DIDFT_ABSAXIS,
142
+ sizeof(DIJOYSTATE),
143
+ sizeof(_glfwObjectDataFormats) / sizeof(DIOBJECTDATAFORMAT),
144
+ _glfwObjectDataFormats
145
+ };
146
+
147
+ // Returns a description fitting the specified XInput capabilities
148
+ //
149
+ static const char* getDeviceDescription(const XINPUT_CAPABILITIES* xic)
150
+ {
151
+ switch (xic->SubType)
152
+ {
153
+ case XINPUT_DEVSUBTYPE_WHEEL:
154
+ return "XInput Wheel";
155
+ case XINPUT_DEVSUBTYPE_ARCADE_STICK:
156
+ return "XInput Arcade Stick";
157
+ case XINPUT_DEVSUBTYPE_FLIGHT_STICK:
158
+ return "XInput Flight Stick";
159
+ case XINPUT_DEVSUBTYPE_DANCE_PAD:
160
+ return "XInput Dance Pad";
161
+ case XINPUT_DEVSUBTYPE_GUITAR:
162
+ return "XInput Guitar";
163
+ case XINPUT_DEVSUBTYPE_DRUM_KIT:
164
+ return "XInput Drum Kit";
165
+ case XINPUT_DEVSUBTYPE_GAMEPAD:
166
+ {
167
+ if (xic->Flags & XINPUT_CAPS_WIRELESS)
168
+ return "Wireless Xbox Controller";
169
+ else
170
+ return "Xbox Controller";
171
+ }
172
+ }
173
+
174
+ return "Unknown XInput Device";
175
+ }
176
+
177
+ // Lexically compare device objects
178
+ //
179
+ static int compareJoystickObjects(const void* first, const void* second)
180
+ {
181
+ const _GLFWjoyobjectWin32* fo = first;
182
+ const _GLFWjoyobjectWin32* so = second;
183
+
184
+ if (fo->type != so->type)
185
+ return fo->type - so->type;
186
+
187
+ return fo->offset - so->offset;
188
+ }
189
+
190
+ // Checks whether the specified device supports XInput
191
+ // Technique from FDInputJoystickManager::IsXInputDeviceFast in ZDoom
192
+ //
193
+ static GLFWbool supportsXInput(const GUID* guid)
194
+ {
195
+ UINT i, count = 0;
196
+ RAWINPUTDEVICELIST* ridl;
197
+ GLFWbool result = GLFW_FALSE;
198
+
199
+ if (GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST)) != 0)
200
+ return GLFW_FALSE;
201
+
202
+ ridl = _glfw_calloc(count, sizeof(RAWINPUTDEVICELIST));
203
+
204
+ if (GetRawInputDeviceList(ridl, &count, sizeof(RAWINPUTDEVICELIST)) == (UINT) -1)
205
+ {
206
+ _glfw_free(ridl);
207
+ return GLFW_FALSE;
208
+ }
209
+
210
+ for (i = 0; i < count; i++)
211
+ {
212
+ RID_DEVICE_INFO rdi;
213
+ char name[256];
214
+ UINT size;
215
+
216
+ if (ridl[i].dwType != RIM_TYPEHID)
217
+ continue;
218
+
219
+ ZeroMemory(&rdi, sizeof(rdi));
220
+ rdi.cbSize = sizeof(rdi);
221
+ size = sizeof(rdi);
222
+
223
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
224
+ RIDI_DEVICEINFO,
225
+ &rdi, &size) == -1)
226
+ {
227
+ continue;
228
+ }
229
+
230
+ if (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) != (LONG) guid->Data1)
231
+ continue;
232
+
233
+ memset(name, 0, sizeof(name));
234
+ size = sizeof(name);
235
+
236
+ if ((INT) GetRawInputDeviceInfoA(ridl[i].hDevice,
237
+ RIDI_DEVICENAME,
238
+ name, &size) == -1)
239
+ {
240
+ break;
241
+ }
242
+
243
+ name[sizeof(name) - 1] = '\0';
244
+ if (strstr(name, "IG_"))
245
+ {
246
+ result = GLFW_TRUE;
247
+ break;
248
+ }
249
+ }
250
+
251
+ _glfw_free(ridl);
252
+ return result;
253
+ }
254
+
255
+ // Frees all resources associated with the specified joystick
256
+ //
257
+ static void closeJoystick(_GLFWjoystick* js)
258
+ {
259
+ _glfwInputJoystick(js, GLFW_DISCONNECTED);
260
+
261
+ if (js->win32.device)
262
+ {
263
+ IDirectInputDevice8_Unacquire(js->win32.device);
264
+ IDirectInputDevice8_Release(js->win32.device);
265
+ }
266
+
267
+ _glfw_free(js->win32.objects);
268
+ _glfwFreeJoystick(js);
269
+ }
270
+
271
+ // DirectInput device object enumeration callback
272
+ // Insights gleaned from SDL
273
+ //
274
+ static BOOL CALLBACK deviceObjectCallback(const DIDEVICEOBJECTINSTANCEW* doi,
275
+ void* user)
276
+ {
277
+ _GLFWobjenumWin32* data = user;
278
+ _GLFWjoyobjectWin32* object = data->objects + data->objectCount;
279
+
280
+ if (DIDFT_GETTYPE(doi->dwType) & DIDFT_AXIS)
281
+ {
282
+ DIPROPRANGE dipr;
283
+
284
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
285
+ object->offset = DIJOFS_SLIDER(data->sliderCount);
286
+ else if (memcmp(&doi->guidType, &GUID_XAxis, sizeof(GUID)) == 0)
287
+ object->offset = DIJOFS_X;
288
+ else if (memcmp(&doi->guidType, &GUID_YAxis, sizeof(GUID)) == 0)
289
+ object->offset = DIJOFS_Y;
290
+ else if (memcmp(&doi->guidType, &GUID_ZAxis, sizeof(GUID)) == 0)
291
+ object->offset = DIJOFS_Z;
292
+ else if (memcmp(&doi->guidType, &GUID_RxAxis, sizeof(GUID)) == 0)
293
+ object->offset = DIJOFS_RX;
294
+ else if (memcmp(&doi->guidType, &GUID_RyAxis, sizeof(GUID)) == 0)
295
+ object->offset = DIJOFS_RY;
296
+ else if (memcmp(&doi->guidType, &GUID_RzAxis, sizeof(GUID)) == 0)
297
+ object->offset = DIJOFS_RZ;
298
+ else
299
+ return DIENUM_CONTINUE;
300
+
301
+ ZeroMemory(&dipr, sizeof(dipr));
302
+ dipr.diph.dwSize = sizeof(dipr);
303
+ dipr.diph.dwHeaderSize = sizeof(dipr.diph);
304
+ dipr.diph.dwObj = doi->dwType;
305
+ dipr.diph.dwHow = DIPH_BYID;
306
+ dipr.lMin = -32768;
307
+ dipr.lMax = 32767;
308
+
309
+ if (FAILED(IDirectInputDevice8_SetProperty(data->device,
310
+ DIPROP_RANGE,
311
+ &dipr.diph)))
312
+ {
313
+ return DIENUM_CONTINUE;
314
+ }
315
+
316
+ if (memcmp(&doi->guidType, &GUID_Slider, sizeof(GUID)) == 0)
317
+ {
318
+ object->type = _GLFW_TYPE_SLIDER;
319
+ data->sliderCount++;
320
+ }
321
+ else
322
+ {
323
+ object->type = _GLFW_TYPE_AXIS;
324
+ data->axisCount++;
325
+ }
326
+ }
327
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_BUTTON)
328
+ {
329
+ object->offset = DIJOFS_BUTTON(data->buttonCount);
330
+ object->type = _GLFW_TYPE_BUTTON;
331
+ data->buttonCount++;
332
+ }
333
+ else if (DIDFT_GETTYPE(doi->dwType) & DIDFT_POV)
334
+ {
335
+ object->offset = DIJOFS_POV(data->povCount);
336
+ object->type = _GLFW_TYPE_POV;
337
+ data->povCount++;
338
+ }
339
+
340
+ data->objectCount++;
341
+ return DIENUM_CONTINUE;
342
+ }
343
+
344
+ // DirectInput device enumeration callback
345
+ //
346
+ static BOOL CALLBACK deviceCallback(const DIDEVICEINSTANCE* di, void* user)
347
+ {
348
+ int jid = 0;
349
+ DIDEVCAPS dc;
350
+ DIPROPDWORD dipd;
351
+ IDirectInputDevice8* device;
352
+ _GLFWobjenumWin32 data;
353
+ _GLFWjoystick* js;
354
+ char guid[33];
355
+ char name[256];
356
+
357
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
358
+ {
359
+ js = _glfw.joysticks + jid;
360
+ if (js->connected)
361
+ {
362
+ if (memcmp(&js->win32.guid, &di->guidInstance, sizeof(GUID)) == 0)
363
+ return DIENUM_CONTINUE;
364
+ }
365
+ }
366
+
367
+ if (supportsXInput(&di->guidProduct))
368
+ return DIENUM_CONTINUE;
369
+
370
+ if (FAILED(IDirectInput8_CreateDevice(_glfw.win32.dinput8.api,
371
+ &di->guidInstance,
372
+ &device,
373
+ NULL)))
374
+ {
375
+ _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create device");
376
+ return DIENUM_CONTINUE;
377
+ }
378
+
379
+ if (FAILED(IDirectInputDevice8_SetDataFormat(device, &_glfwDataFormat)))
380
+ {
381
+ _glfwInputError(GLFW_PLATFORM_ERROR,
382
+ "Win32: Failed to set device data format");
383
+
384
+ IDirectInputDevice8_Release(device);
385
+ return DIENUM_CONTINUE;
386
+ }
387
+
388
+ ZeroMemory(&dc, sizeof(dc));
389
+ dc.dwSize = sizeof(dc);
390
+
391
+ if (FAILED(IDirectInputDevice8_GetCapabilities(device, &dc)))
392
+ {
393
+ _glfwInputError(GLFW_PLATFORM_ERROR,
394
+ "Win32: Failed to query device capabilities");
395
+
396
+ IDirectInputDevice8_Release(device);
397
+ return DIENUM_CONTINUE;
398
+ }
399
+
400
+ ZeroMemory(&dipd, sizeof(dipd));
401
+ dipd.diph.dwSize = sizeof(dipd);
402
+ dipd.diph.dwHeaderSize = sizeof(dipd.diph);
403
+ dipd.diph.dwHow = DIPH_DEVICE;
404
+ dipd.dwData = DIPROPAXISMODE_ABS;
405
+
406
+ if (FAILED(IDirectInputDevice8_SetProperty(device,
407
+ DIPROP_AXISMODE,
408
+ &dipd.diph)))
409
+ {
410
+ _glfwInputError(GLFW_PLATFORM_ERROR,
411
+ "Win32: Failed to set device axis mode");
412
+
413
+ IDirectInputDevice8_Release(device);
414
+ return DIENUM_CONTINUE;
415
+ }
416
+
417
+ memset(&data, 0, sizeof(data));
418
+ data.device = device;
419
+ data.objects = _glfw_calloc(dc.dwAxes + (size_t) dc.dwButtons + dc.dwPOVs,
420
+ sizeof(_GLFWjoyobjectWin32));
421
+
422
+ if (FAILED(IDirectInputDevice8_EnumObjects(device,
423
+ deviceObjectCallback,
424
+ &data,
425
+ DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV)))
426
+ {
427
+ _glfwInputError(GLFW_PLATFORM_ERROR,
428
+ "Win32: Failed to enumerate device objects");
429
+
430
+ IDirectInputDevice8_Release(device);
431
+ _glfw_free(data.objects);
432
+ return DIENUM_CONTINUE;
433
+ }
434
+
435
+ qsort(data.objects, data.objectCount,
436
+ sizeof(_GLFWjoyobjectWin32),
437
+ compareJoystickObjects);
438
+
439
+ if (!WideCharToMultiByte(CP_UTF8, 0,
440
+ di->tszInstanceName, -1,
441
+ name, sizeof(name),
442
+ NULL, NULL))
443
+ {
444
+ _glfwInputError(GLFW_PLATFORM_ERROR,
445
+ "Win32: Failed to convert joystick name to UTF-8");
446
+
447
+ IDirectInputDevice8_Release(device);
448
+ _glfw_free(data.objects);
449
+ return DIENUM_STOP;
450
+ }
451
+
452
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
453
+ if (memcmp(&di->guidProduct.Data4[2], "PIDVID", 6) == 0)
454
+ {
455
+ sprintf(guid, "03000000%02x%02x0000%02x%02x000000000000",
456
+ (uint8_t) di->guidProduct.Data1,
457
+ (uint8_t) (di->guidProduct.Data1 >> 8),
458
+ (uint8_t) (di->guidProduct.Data1 >> 16),
459
+ (uint8_t) (di->guidProduct.Data1 >> 24));
460
+ }
461
+ else
462
+ {
463
+ sprintf(guid, "05000000%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x00",
464
+ name[0], name[1], name[2], name[3],
465
+ name[4], name[5], name[6], name[7],
466
+ name[8], name[9], name[10]);
467
+ }
468
+
469
+ js = _glfwAllocJoystick(name, guid,
470
+ data.axisCount + data.sliderCount,
471
+ data.buttonCount,
472
+ data.povCount);
473
+ if (!js)
474
+ {
475
+ IDirectInputDevice8_Release(device);
476
+ _glfw_free(data.objects);
477
+ return DIENUM_STOP;
478
+ }
479
+
480
+ js->win32.device = device;
481
+ js->win32.guid = di->guidInstance;
482
+ js->win32.objects = data.objects;
483
+ js->win32.objectCount = data.objectCount;
484
+
485
+ _glfwInputJoystick(js, GLFW_CONNECTED);
486
+ return DIENUM_CONTINUE;
487
+ }
488
+
489
+
490
+ //////////////////////////////////////////////////////////////////////////
491
+ ////// GLFW internal API //////
492
+ //////////////////////////////////////////////////////////////////////////
493
+
494
+ // Checks for new joysticks after DBT_DEVICEARRIVAL
495
+ //
496
+ void _glfwDetectJoystickConnectionWin32(void)
497
+ {
498
+ if (_glfw.win32.xinput.instance)
499
+ {
500
+ DWORD index;
501
+
502
+ for (index = 0; index < XUSER_MAX_COUNT; index++)
503
+ {
504
+ int jid;
505
+ char guid[33];
506
+ XINPUT_CAPABILITIES xic;
507
+ _GLFWjoystick* js;
508
+
509
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
510
+ {
511
+ if (_glfw.joysticks[jid].connected &&
512
+ _glfw.joysticks[jid].win32.device == NULL &&
513
+ _glfw.joysticks[jid].win32.index == index)
514
+ {
515
+ break;
516
+ }
517
+ }
518
+
519
+ if (jid <= GLFW_JOYSTICK_LAST)
520
+ continue;
521
+
522
+ if (XInputGetCapabilities(index, 0, &xic) != ERROR_SUCCESS)
523
+ continue;
524
+
525
+ // Generate a joystick GUID that matches the SDL 2.0.5+ one
526
+ sprintf(guid, "78696e707574%02x000000000000000000",
527
+ xic.SubType & 0xff);
528
+
529
+ js = _glfwAllocJoystick(getDeviceDescription(&xic), guid, 6, 10, 1);
530
+ if (!js)
531
+ continue;
532
+
533
+ js->win32.index = index;
534
+
535
+ _glfwInputJoystick(js, GLFW_CONNECTED);
536
+ }
537
+ }
538
+
539
+ if (_glfw.win32.dinput8.api)
540
+ {
541
+ if (FAILED(IDirectInput8_EnumDevices(_glfw.win32.dinput8.api,
542
+ DI8DEVCLASS_GAMECTRL,
543
+ deviceCallback,
544
+ NULL,
545
+ DIEDFL_ALLDEVICES)))
546
+ {
547
+ _glfwInputError(GLFW_PLATFORM_ERROR,
548
+ "Failed to enumerate DirectInput8 devices");
549
+ return;
550
+ }
551
+ }
552
+ }
553
+
554
+ // Checks for joystick disconnection after DBT_DEVICEREMOVECOMPLETE
555
+ //
556
+ void _glfwDetectJoystickDisconnectionWin32(void)
557
+ {
558
+ int jid;
559
+
560
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
561
+ {
562
+ _GLFWjoystick* js = _glfw.joysticks + jid;
563
+ if (js->connected)
564
+ _glfwPollJoystickWin32(js, _GLFW_POLL_PRESENCE);
565
+ }
566
+ }
567
+
568
+
569
+ //////////////////////////////////////////////////////////////////////////
570
+ ////// GLFW platform API //////
571
+ //////////////////////////////////////////////////////////////////////////
572
+
573
+ GLFWbool _glfwInitJoysticksWin32(void)
574
+ {
575
+ if (_glfw.win32.dinput8.instance)
576
+ {
577
+ if (FAILED(DirectInput8Create(_glfw.win32.instance,
578
+ DIRECTINPUT_VERSION,
579
+ &IID_IDirectInput8W,
580
+ (void**) &_glfw.win32.dinput8.api,
581
+ NULL)))
582
+ {
583
+ _glfwInputError(GLFW_PLATFORM_ERROR,
584
+ "Win32: Failed to create interface");
585
+ return GLFW_FALSE;
586
+ }
587
+ }
588
+
589
+ _glfwDetectJoystickConnectionWin32();
590
+ return GLFW_TRUE;
591
+ }
592
+
593
+ void _glfwTerminateJoysticksWin32(void)
594
+ {
595
+ int jid;
596
+
597
+ for (jid = GLFW_JOYSTICK_1; jid <= GLFW_JOYSTICK_LAST; jid++)
598
+ closeJoystick(_glfw.joysticks + jid);
599
+
600
+ if (_glfw.win32.dinput8.api)
601
+ IDirectInput8_Release(_glfw.win32.dinput8.api);
602
+ }
603
+
604
+ GLFWbool _glfwPollJoystickWin32(_GLFWjoystick* js, int mode)
605
+ {
606
+ if (js->win32.device)
607
+ {
608
+ int i, ai = 0, bi = 0, pi = 0;
609
+ HRESULT result;
610
+ DIJOYSTATE state = {0};
611
+
612
+ IDirectInputDevice8_Poll(js->win32.device);
613
+ result = IDirectInputDevice8_GetDeviceState(js->win32.device,
614
+ sizeof(state),
615
+ &state);
616
+ if (result == DIERR_NOTACQUIRED || result == DIERR_INPUTLOST)
617
+ {
618
+ IDirectInputDevice8_Acquire(js->win32.device);
619
+ IDirectInputDevice8_Poll(js->win32.device);
620
+ result = IDirectInputDevice8_GetDeviceState(js->win32.device,
621
+ sizeof(state),
622
+ &state);
623
+ }
624
+
625
+ if (FAILED(result))
626
+ {
627
+ closeJoystick(js);
628
+ return GLFW_FALSE;
629
+ }
630
+
631
+ if (mode == _GLFW_POLL_PRESENCE)
632
+ return GLFW_TRUE;
633
+
634
+ for (i = 0; i < js->win32.objectCount; i++)
635
+ {
636
+ const void* data = (char*) &state + js->win32.objects[i].offset;
637
+
638
+ switch (js->win32.objects[i].type)
639
+ {
640
+ case _GLFW_TYPE_AXIS:
641
+ case _GLFW_TYPE_SLIDER:
642
+ {
643
+ const float value = (*((LONG*) data) + 0.5f) / 32767.5f;
644
+ _glfwInputJoystickAxis(js, ai, value);
645
+ ai++;
646
+ break;
647
+ }
648
+
649
+ case _GLFW_TYPE_BUTTON:
650
+ {
651
+ const char value = (*((BYTE*) data) & 0x80) != 0;
652
+ _glfwInputJoystickButton(js, bi, value);
653
+ bi++;
654
+ break;
655
+ }
656
+
657
+ case _GLFW_TYPE_POV:
658
+ {
659
+ const int states[9] =
660
+ {
661
+ GLFW_HAT_UP,
662
+ GLFW_HAT_RIGHT_UP,
663
+ GLFW_HAT_RIGHT,
664
+ GLFW_HAT_RIGHT_DOWN,
665
+ GLFW_HAT_DOWN,
666
+ GLFW_HAT_LEFT_DOWN,
667
+ GLFW_HAT_LEFT,
668
+ GLFW_HAT_LEFT_UP,
669
+ GLFW_HAT_CENTERED
670
+ };
671
+
672
+ // Screams of horror are appropriate at this point
673
+ int stateIndex = LOWORD(*(DWORD*) data) / (45 * DI_DEGREES);
674
+ if (stateIndex < 0 || stateIndex > 8)
675
+ stateIndex = 8;
676
+
677
+ _glfwInputJoystickHat(js, pi, states[stateIndex]);
678
+ pi++;
679
+ break;
680
+ }
681
+ }
682
+ }
683
+ }
684
+ else
685
+ {
686
+ int i, dpad = 0;
687
+ DWORD result;
688
+ XINPUT_STATE xis;
689
+ const WORD buttons[10] =
690
+ {
691
+ XINPUT_GAMEPAD_A,
692
+ XINPUT_GAMEPAD_B,
693
+ XINPUT_GAMEPAD_X,
694
+ XINPUT_GAMEPAD_Y,
695
+ XINPUT_GAMEPAD_LEFT_SHOULDER,
696
+ XINPUT_GAMEPAD_RIGHT_SHOULDER,
697
+ XINPUT_GAMEPAD_BACK,
698
+ XINPUT_GAMEPAD_START,
699
+ XINPUT_GAMEPAD_LEFT_THUMB,
700
+ XINPUT_GAMEPAD_RIGHT_THUMB
701
+ };
702
+
703
+ result = XInputGetState(js->win32.index, &xis);
704
+ if (result != ERROR_SUCCESS)
705
+ {
706
+ if (result == ERROR_DEVICE_NOT_CONNECTED)
707
+ closeJoystick(js);
708
+
709
+ return GLFW_FALSE;
710
+ }
711
+
712
+ if (mode == _GLFW_POLL_PRESENCE)
713
+ return GLFW_TRUE;
714
+
715
+ _glfwInputJoystickAxis(js, 0, (xis.Gamepad.sThumbLX + 0.5f) / 32767.5f);
716
+ _glfwInputJoystickAxis(js, 1, -(xis.Gamepad.sThumbLY + 0.5f) / 32767.5f);
717
+ _glfwInputJoystickAxis(js, 2, (xis.Gamepad.sThumbRX + 0.5f) / 32767.5f);
718
+ _glfwInputJoystickAxis(js, 3, -(xis.Gamepad.sThumbRY + 0.5f) / 32767.5f);
719
+ _glfwInputJoystickAxis(js, 4, xis.Gamepad.bLeftTrigger / 127.5f - 1.f);
720
+ _glfwInputJoystickAxis(js, 5, xis.Gamepad.bRightTrigger / 127.5f - 1.f);
721
+
722
+ for (i = 0; i < 10; i++)
723
+ {
724
+ const char value = (xis.Gamepad.wButtons & buttons[i]) ? 1 : 0;
725
+ _glfwInputJoystickButton(js, i, value);
726
+ }
727
+
728
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP)
729
+ dpad |= GLFW_HAT_UP;
730
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT)
731
+ dpad |= GLFW_HAT_RIGHT;
732
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN)
733
+ dpad |= GLFW_HAT_DOWN;
734
+ if (xis.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT)
735
+ dpad |= GLFW_HAT_LEFT;
736
+
737
+ // Treat invalid combinations as neither being pressed
738
+ // while preserving what data can be preserved
739
+ if ((dpad & GLFW_HAT_RIGHT) && (dpad & GLFW_HAT_LEFT))
740
+ dpad &= ~(GLFW_HAT_RIGHT | GLFW_HAT_LEFT);
741
+ if ((dpad & GLFW_HAT_UP) && (dpad & GLFW_HAT_DOWN))
742
+ dpad &= ~(GLFW_HAT_UP | GLFW_HAT_DOWN);
743
+
744
+ _glfwInputJoystickHat(js, 0, dpad);
745
+ }
746
+
747
+ return GLFW_TRUE;
748
+ }
749
+
750
+ const char* _glfwGetMappingNameWin32(void)
751
+ {
752
+ return "Windows";
753
+ }
754
+
755
+ void _glfwUpdateGamepadGUIDWin32(char* guid)
756
+ {
757
+ if (strcmp(guid + 20, "504944564944") == 0)
758
+ {
759
+ char original[33];
760
+ strncpy(original, guid, sizeof(original) - 1);
761
+ sprintf(guid, "03000000%.4s0000%.4s000000000000",
762
+ original, original + 4);
763
+ }
764
+ }
765
+
766
+ #endif // _GLFW_WIN32
767
+