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
package/GLFW/input.c ADDED
@@ -0,0 +1,1505 @@
1
+ //========================================================================
2
+ // GLFW 3.4 - 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
+ #include "mappings.h"
30
+
31
+ #include <assert.h>
32
+ #include <float.h>
33
+ #include <math.h>
34
+ #include <stdlib.h>
35
+ #include <string.h>
36
+
37
+ // Internal key state used for sticky keys
38
+ #define _GLFW_STICK 3
39
+
40
+ // Internal constants for gamepad mapping source types
41
+ #define _GLFW_JOYSTICK_AXIS 1
42
+ #define _GLFW_JOYSTICK_BUTTON 2
43
+ #define _GLFW_JOYSTICK_HATBIT 3
44
+
45
+ #define GLFW_MOD_MASK (GLFW_MOD_SHIFT | \
46
+ GLFW_MOD_CONTROL | \
47
+ GLFW_MOD_ALT | \
48
+ GLFW_MOD_SUPER | \
49
+ GLFW_MOD_CAPS_LOCK | \
50
+ GLFW_MOD_NUM_LOCK)
51
+
52
+ // Initializes the platform joystick API if it has not been already
53
+ //
54
+ static GLFWbool initJoysticks(void)
55
+ {
56
+ if (!_glfw.joysticksInitialized)
57
+ {
58
+ if (!_glfw.platform.initJoysticks())
59
+ {
60
+ _glfw.platform.terminateJoysticks();
61
+ return GLFW_FALSE;
62
+ }
63
+ }
64
+
65
+ return _glfw.joysticksInitialized = GLFW_TRUE;
66
+ }
67
+
68
+ // Finds a mapping based on joystick GUID
69
+ //
70
+ static _GLFWmapping* findMapping(const char* guid)
71
+ {
72
+ int i;
73
+
74
+ for (i = 0; i < _glfw.mappingCount; i++)
75
+ {
76
+ if (strcmp(_glfw.mappings[i].guid, guid) == 0)
77
+ return _glfw.mappings + i;
78
+ }
79
+
80
+ return NULL;
81
+ }
82
+
83
+ // Checks whether a gamepad mapping element is present in the hardware
84
+ //
85
+ static GLFWbool isValidElementForJoystick(const _GLFWmapelement* e,
86
+ const _GLFWjoystick* js)
87
+ {
88
+ if (e->type == _GLFW_JOYSTICK_HATBIT && (e->index >> 4) >= js->hatCount)
89
+ return GLFW_FALSE;
90
+ else if (e->type == _GLFW_JOYSTICK_BUTTON && e->index >= js->buttonCount)
91
+ return GLFW_FALSE;
92
+ else if (e->type == _GLFW_JOYSTICK_AXIS && e->index >= js->axisCount)
93
+ return GLFW_FALSE;
94
+
95
+ return GLFW_TRUE;
96
+ }
97
+
98
+ // Finds a mapping based on joystick GUID and verifies element indices
99
+ //
100
+ static _GLFWmapping* findValidMapping(const _GLFWjoystick* js)
101
+ {
102
+ _GLFWmapping* mapping = findMapping(js->guid);
103
+ if (mapping)
104
+ {
105
+ int i;
106
+
107
+ for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
108
+ {
109
+ if (!isValidElementForJoystick(mapping->buttons + i, js))
110
+ return NULL;
111
+ }
112
+
113
+ for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
114
+ {
115
+ if (!isValidElementForJoystick(mapping->axes + i, js))
116
+ return NULL;
117
+ }
118
+ }
119
+
120
+ return mapping;
121
+ }
122
+
123
+ // Parses an SDL_GameControllerDB line and adds it to the mapping list
124
+ //
125
+ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string)
126
+ {
127
+ const char* c = string;
128
+ size_t i, length;
129
+ struct
130
+ {
131
+ const char* name;
132
+ _GLFWmapelement* element;
133
+ } fields[] =
134
+ {
135
+ { "platform", NULL },
136
+ { "a", mapping->buttons + GLFW_GAMEPAD_BUTTON_A },
137
+ { "b", mapping->buttons + GLFW_GAMEPAD_BUTTON_B },
138
+ { "x", mapping->buttons + GLFW_GAMEPAD_BUTTON_X },
139
+ { "y", mapping->buttons + GLFW_GAMEPAD_BUTTON_Y },
140
+ { "back", mapping->buttons + GLFW_GAMEPAD_BUTTON_BACK },
141
+ { "start", mapping->buttons + GLFW_GAMEPAD_BUTTON_START },
142
+ { "guide", mapping->buttons + GLFW_GAMEPAD_BUTTON_GUIDE },
143
+ { "leftshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_BUMPER },
144
+ { "rightshoulder", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER },
145
+ { "leftstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_LEFT_THUMB },
146
+ { "rightstick", mapping->buttons + GLFW_GAMEPAD_BUTTON_RIGHT_THUMB },
147
+ { "dpup", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_UP },
148
+ { "dpright", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_RIGHT },
149
+ { "dpdown", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_DOWN },
150
+ { "dpleft", mapping->buttons + GLFW_GAMEPAD_BUTTON_DPAD_LEFT },
151
+ { "lefttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_TRIGGER },
152
+ { "righttrigger", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER },
153
+ { "leftx", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_X },
154
+ { "lefty", mapping->axes + GLFW_GAMEPAD_AXIS_LEFT_Y },
155
+ { "rightx", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_X },
156
+ { "righty", mapping->axes + GLFW_GAMEPAD_AXIS_RIGHT_Y }
157
+ };
158
+
159
+ length = strcspn(c, ",");
160
+ if (length != 32 || c[length] != ',')
161
+ {
162
+ _glfwInputError(GLFW_INVALID_VALUE, NULL);
163
+ return GLFW_FALSE;
164
+ }
165
+
166
+ memcpy(mapping->guid, c, length);
167
+ c += length + 1;
168
+
169
+ length = strcspn(c, ",");
170
+ if (length >= sizeof(mapping->name) || c[length] != ',')
171
+ {
172
+ _glfwInputError(GLFW_INVALID_VALUE, NULL);
173
+ return GLFW_FALSE;
174
+ }
175
+
176
+ memcpy(mapping->name, c, length);
177
+ c += length + 1;
178
+
179
+ while (*c)
180
+ {
181
+ // TODO: Implement output modifiers
182
+ if (*c == '+' || *c == '-')
183
+ return GLFW_FALSE;
184
+
185
+ for (i = 0; i < sizeof(fields) / sizeof(fields[0]); i++)
186
+ {
187
+ length = strlen(fields[i].name);
188
+ if (strncmp(c, fields[i].name, length) != 0 || c[length] != ':')
189
+ continue;
190
+
191
+ c += length + 1;
192
+
193
+ if (fields[i].element)
194
+ {
195
+ _GLFWmapelement* e = fields[i].element;
196
+ int8_t minimum = -1;
197
+ int8_t maximum = 1;
198
+
199
+ if (*c == '+')
200
+ {
201
+ minimum = 0;
202
+ c += 1;
203
+ }
204
+ else if (*c == '-')
205
+ {
206
+ maximum = 0;
207
+ c += 1;
208
+ }
209
+
210
+ if (*c == 'a')
211
+ e->type = _GLFW_JOYSTICK_AXIS;
212
+ else if (*c == 'b')
213
+ e->type = _GLFW_JOYSTICK_BUTTON;
214
+ else if (*c == 'h')
215
+ e->type = _GLFW_JOYSTICK_HATBIT;
216
+ else
217
+ break;
218
+
219
+ if (e->type == _GLFW_JOYSTICK_HATBIT)
220
+ {
221
+ const unsigned long hat = strtoul(c + 1, (char**) &c, 10);
222
+ const unsigned long bit = strtoul(c + 1, (char**) &c, 10);
223
+ e->index = (uint8_t) ((hat << 4) | bit);
224
+ }
225
+ else
226
+ e->index = (uint8_t) strtoul(c + 1, (char**) &c, 10);
227
+
228
+ if (e->type == _GLFW_JOYSTICK_AXIS)
229
+ {
230
+ e->axisScale = 2 / (maximum - minimum);
231
+ e->axisOffset = -(maximum + minimum);
232
+
233
+ if (*c == '~')
234
+ {
235
+ e->axisScale = -e->axisScale;
236
+ e->axisOffset = -e->axisOffset;
237
+ }
238
+ }
239
+ }
240
+ else
241
+ {
242
+ const char* name = _glfw.platform.getMappingName();
243
+ length = strlen(name);
244
+ if (strncmp(c, name, length) != 0)
245
+ return GLFW_FALSE;
246
+ }
247
+
248
+ break;
249
+ }
250
+
251
+ c += strcspn(c, ",");
252
+ c += strspn(c, ",");
253
+ }
254
+
255
+ for (i = 0; i < 32; i++)
256
+ {
257
+ if (mapping->guid[i] >= 'A' && mapping->guid[i] <= 'F')
258
+ mapping->guid[i] += 'a' - 'A';
259
+ }
260
+
261
+ _glfw.platform.updateGamepadGUID(mapping->guid);
262
+ return GLFW_TRUE;
263
+ }
264
+
265
+
266
+ //////////////////////////////////////////////////////////////////////////
267
+ ////// GLFW event API //////
268
+ //////////////////////////////////////////////////////////////////////////
269
+
270
+ // Notifies shared code of a physical key event
271
+ //
272
+ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods)
273
+ {
274
+ assert(window != NULL);
275
+ assert(key >= 0 || key == GLFW_KEY_UNKNOWN);
276
+ assert(key <= GLFW_KEY_LAST);
277
+ assert(action == GLFW_PRESS || action == GLFW_RELEASE);
278
+ assert(mods == (mods & GLFW_MOD_MASK));
279
+
280
+ if (key >= 0 && key <= GLFW_KEY_LAST)
281
+ {
282
+ GLFWbool repeated = GLFW_FALSE;
283
+
284
+ if (action == GLFW_RELEASE && window->keys[key] == GLFW_RELEASE)
285
+ return;
286
+
287
+ if (action == GLFW_PRESS && window->keys[key] == GLFW_PRESS)
288
+ repeated = GLFW_TRUE;
289
+
290
+ if (action == GLFW_RELEASE && window->stickyKeys)
291
+ window->keys[key] = _GLFW_STICK;
292
+ else
293
+ window->keys[key] = (char) action;
294
+
295
+ if (repeated)
296
+ action = GLFW_REPEAT;
297
+ }
298
+
299
+ if (!window->lockKeyMods)
300
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
301
+
302
+ if (window->callbacks.key)
303
+ window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods);
304
+ }
305
+
306
+ // Notifies shared code of a Unicode codepoint input event
307
+ // The 'plain' parameter determines whether to emit a regular character event
308
+ //
309
+ void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain)
310
+ {
311
+ assert(window != NULL);
312
+ assert(mods == (mods & GLFW_MOD_MASK));
313
+ assert(plain == GLFW_TRUE || plain == GLFW_FALSE);
314
+
315
+ if (codepoint < 32 || (codepoint > 126 && codepoint < 160))
316
+ return;
317
+
318
+ if (!window->lockKeyMods)
319
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
320
+
321
+ if (window->callbacks.charmods)
322
+ window->callbacks.charmods((GLFWwindow*) window, codepoint, mods);
323
+
324
+ if (plain)
325
+ {
326
+ if (window->callbacks.character)
327
+ window->callbacks.character((GLFWwindow*) window, codepoint);
328
+ }
329
+ }
330
+
331
+ // Notifies shared code of a scroll event
332
+ //
333
+ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset)
334
+ {
335
+ assert(window != NULL);
336
+ assert(xoffset > -FLT_MAX);
337
+ assert(xoffset < FLT_MAX);
338
+ assert(yoffset > -FLT_MAX);
339
+ assert(yoffset < FLT_MAX);
340
+
341
+ if (window->callbacks.scroll)
342
+ window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset);
343
+ }
344
+
345
+ // Notifies shared code of a mouse button click event
346
+ //
347
+ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods)
348
+ {
349
+ assert(window != NULL);
350
+ assert(button >= 0);
351
+ assert(button <= GLFW_MOUSE_BUTTON_LAST);
352
+ assert(action == GLFW_PRESS || action == GLFW_RELEASE);
353
+ assert(mods == (mods & GLFW_MOD_MASK));
354
+
355
+ if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST)
356
+ return;
357
+
358
+ if (!window->lockKeyMods)
359
+ mods &= ~(GLFW_MOD_CAPS_LOCK | GLFW_MOD_NUM_LOCK);
360
+
361
+ if (action == GLFW_RELEASE && window->stickyMouseButtons)
362
+ window->mouseButtons[button] = _GLFW_STICK;
363
+ else
364
+ window->mouseButtons[button] = (char) action;
365
+
366
+ if (window->callbacks.mouseButton)
367
+ window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods);
368
+ }
369
+
370
+ // Notifies shared code of a cursor motion event
371
+ // The position is specified in content area relative screen coordinates
372
+ //
373
+ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos)
374
+ {
375
+ assert(window != NULL);
376
+ assert(xpos > -FLT_MAX);
377
+ assert(xpos < FLT_MAX);
378
+ assert(ypos > -FLT_MAX);
379
+ assert(ypos < FLT_MAX);
380
+
381
+ if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos)
382
+ return;
383
+
384
+ window->virtualCursorPosX = xpos;
385
+ window->virtualCursorPosY = ypos;
386
+
387
+ if (window->callbacks.cursorPos)
388
+ window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos);
389
+ }
390
+
391
+ // Notifies shared code of a cursor enter/leave event
392
+ //
393
+ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered)
394
+ {
395
+ assert(window != NULL);
396
+ assert(entered == GLFW_TRUE || entered == GLFW_FALSE);
397
+
398
+ if (window->callbacks.cursorEnter)
399
+ window->callbacks.cursorEnter((GLFWwindow*) window, entered);
400
+ }
401
+
402
+ // Notifies shared code of files or directories dropped on a window
403
+ //
404
+ void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths)
405
+ {
406
+ assert(window != NULL);
407
+ assert(count > 0);
408
+ assert(paths != NULL);
409
+
410
+ if (window->callbacks.drop)
411
+ window->callbacks.drop((GLFWwindow*) window, count, paths);
412
+ }
413
+
414
+ // Notifies shared code of a joystick connection or disconnection
415
+ //
416
+ void _glfwInputJoystick(_GLFWjoystick* js, int event)
417
+ {
418
+ assert(js != NULL);
419
+ assert(event == GLFW_CONNECTED || event == GLFW_DISCONNECTED);
420
+
421
+ if (event == GLFW_CONNECTED)
422
+ js->connected = GLFW_TRUE;
423
+ else if (event == GLFW_DISCONNECTED)
424
+ js->connected = GLFW_FALSE;
425
+
426
+ if (_glfw.callbacks.joystick)
427
+ _glfw.callbacks.joystick((int) (js - _glfw.joysticks), event);
428
+ }
429
+
430
+ // Notifies shared code of the new value of a joystick axis
431
+ //
432
+ void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value)
433
+ {
434
+ assert(js != NULL);
435
+ assert(axis >= 0);
436
+ assert(axis < js->axisCount);
437
+
438
+ js->axes[axis] = value;
439
+ }
440
+
441
+ // Notifies shared code of the new value of a joystick button
442
+ //
443
+ void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value)
444
+ {
445
+ assert(js != NULL);
446
+ assert(button >= 0);
447
+ assert(button < js->buttonCount);
448
+ assert(value == GLFW_PRESS || value == GLFW_RELEASE);
449
+
450
+ js->buttons[button] = value;
451
+ }
452
+
453
+ // Notifies shared code of the new value of a joystick hat
454
+ //
455
+ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value)
456
+ {
457
+ int base;
458
+
459
+ assert(js != NULL);
460
+ assert(hat >= 0);
461
+ assert(hat < js->hatCount);
462
+
463
+ // Valid hat values only use the least significant nibble
464
+ assert((value & 0xf0) == 0);
465
+ // Valid hat values do not have both bits of an axis set
466
+ assert((value & GLFW_HAT_LEFT) == 0 || (value & GLFW_HAT_RIGHT) == 0);
467
+ assert((value & GLFW_HAT_UP) == 0 || (value & GLFW_HAT_DOWN) == 0);
468
+
469
+ base = js->buttonCount + hat * 4;
470
+
471
+ js->buttons[base + 0] = (value & 0x01) ? GLFW_PRESS : GLFW_RELEASE;
472
+ js->buttons[base + 1] = (value & 0x02) ? GLFW_PRESS : GLFW_RELEASE;
473
+ js->buttons[base + 2] = (value & 0x04) ? GLFW_PRESS : GLFW_RELEASE;
474
+ js->buttons[base + 3] = (value & 0x08) ? GLFW_PRESS : GLFW_RELEASE;
475
+
476
+ js->hats[hat] = value;
477
+ }
478
+
479
+
480
+ //////////////////////////////////////////////////////////////////////////
481
+ ////// GLFW internal API //////
482
+ //////////////////////////////////////////////////////////////////////////
483
+
484
+ // Adds the built-in set of gamepad mappings
485
+ //
486
+ void _glfwInitGamepadMappings(void)
487
+ {
488
+ size_t i;
489
+ const size_t count = sizeof(_glfwDefaultMappings) / sizeof(char*);
490
+ _glfw.mappings = _glfw_calloc(count, sizeof(_GLFWmapping));
491
+
492
+ for (i = 0; i < count; i++)
493
+ {
494
+ if (parseMapping(&_glfw.mappings[_glfw.mappingCount], _glfwDefaultMappings[i]))
495
+ _glfw.mappingCount++;
496
+ }
497
+ }
498
+
499
+ // Returns an available joystick object with arrays and name allocated
500
+ //
501
+ _GLFWjoystick* _glfwAllocJoystick(const char* name,
502
+ const char* guid,
503
+ int axisCount,
504
+ int buttonCount,
505
+ int hatCount)
506
+ {
507
+ int jid;
508
+ _GLFWjoystick* js;
509
+
510
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
511
+ {
512
+ if (!_glfw.joysticks[jid].allocated)
513
+ break;
514
+ }
515
+
516
+ if (jid > GLFW_JOYSTICK_LAST)
517
+ return NULL;
518
+
519
+ js = _glfw.joysticks + jid;
520
+ js->allocated = GLFW_TRUE;
521
+ js->axes = _glfw_calloc(axisCount, sizeof(float));
522
+ js->buttons = _glfw_calloc(buttonCount + (size_t) hatCount * 4, 1);
523
+ js->hats = _glfw_calloc(hatCount, 1);
524
+ js->axisCount = axisCount;
525
+ js->buttonCount = buttonCount;
526
+ js->hatCount = hatCount;
527
+
528
+ strncpy(js->name, name, sizeof(js->name) - 1);
529
+ strncpy(js->guid, guid, sizeof(js->guid) - 1);
530
+ js->mapping = findValidMapping(js);
531
+
532
+ return js;
533
+ }
534
+
535
+ // Frees arrays and name and flags the joystick object as unused
536
+ //
537
+ void _glfwFreeJoystick(_GLFWjoystick* js)
538
+ {
539
+ _glfw_free(js->axes);
540
+ _glfw_free(js->buttons);
541
+ _glfw_free(js->hats);
542
+ memset(js, 0, sizeof(_GLFWjoystick));
543
+ }
544
+
545
+ // Center the cursor in the content area of the specified window
546
+ //
547
+ void _glfwCenterCursorInContentArea(_GLFWwindow* window)
548
+ {
549
+ int width, height;
550
+
551
+ _glfw.platform.getWindowSize(window, &width, &height);
552
+ _glfw.platform.setCursorPos(window, width / 2.0, height / 2.0);
553
+ }
554
+
555
+
556
+ //////////////////////////////////////////////////////////////////////////
557
+ ////// GLFW public API //////
558
+ //////////////////////////////////////////////////////////////////////////
559
+
560
+ GLFWAPI int glfwGetInputMode(GLFWwindow* handle, int mode)
561
+ {
562
+ _GLFWwindow* window = (_GLFWwindow*) handle;
563
+ assert(window != NULL);
564
+
565
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
566
+
567
+ switch (mode)
568
+ {
569
+ case GLFW_CURSOR:
570
+ return window->cursorMode;
571
+ case GLFW_STICKY_KEYS:
572
+ return window->stickyKeys;
573
+ case GLFW_STICKY_MOUSE_BUTTONS:
574
+ return window->stickyMouseButtons;
575
+ case GLFW_LOCK_KEY_MODS:
576
+ return window->lockKeyMods;
577
+ case GLFW_RAW_MOUSE_MOTION:
578
+ return window->rawMouseMotion;
579
+ }
580
+
581
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
582
+ return 0;
583
+ }
584
+
585
+ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
586
+ {
587
+ _GLFWwindow* window = (_GLFWwindow*) handle;
588
+ assert(window != NULL);
589
+
590
+ _GLFW_REQUIRE_INIT();
591
+
592
+ switch (mode)
593
+ {
594
+ case GLFW_CURSOR:
595
+ {
596
+ if (value != GLFW_CURSOR_NORMAL &&
597
+ value != GLFW_CURSOR_HIDDEN &&
598
+ value != GLFW_CURSOR_DISABLED &&
599
+ value != GLFW_CURSOR_CAPTURED)
600
+ {
601
+ _glfwInputError(GLFW_INVALID_ENUM,
602
+ "Invalid cursor mode 0x%08X",
603
+ value);
604
+ return;
605
+ }
606
+
607
+ if (window->cursorMode == value)
608
+ return;
609
+
610
+ window->cursorMode = value;
611
+
612
+ _glfw.platform.getCursorPos(window,
613
+ &window->virtualCursorPosX,
614
+ &window->virtualCursorPosY);
615
+ _glfw.platform.setCursorMode(window, value);
616
+ return;
617
+ }
618
+
619
+ case GLFW_STICKY_KEYS:
620
+ {
621
+ value = value ? GLFW_TRUE : GLFW_FALSE;
622
+ if (window->stickyKeys == value)
623
+ return;
624
+
625
+ if (!value)
626
+ {
627
+ int i;
628
+
629
+ // Release all sticky keys
630
+ for (i = 0; i <= GLFW_KEY_LAST; i++)
631
+ {
632
+ if (window->keys[i] == _GLFW_STICK)
633
+ window->keys[i] = GLFW_RELEASE;
634
+ }
635
+ }
636
+
637
+ window->stickyKeys = value;
638
+ return;
639
+ }
640
+
641
+ case GLFW_STICKY_MOUSE_BUTTONS:
642
+ {
643
+ value = value ? GLFW_TRUE : GLFW_FALSE;
644
+ if (window->stickyMouseButtons == value)
645
+ return;
646
+
647
+ if (!value)
648
+ {
649
+ int i;
650
+
651
+ // Release all sticky mouse buttons
652
+ for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
653
+ {
654
+ if (window->mouseButtons[i] == _GLFW_STICK)
655
+ window->mouseButtons[i] = GLFW_RELEASE;
656
+ }
657
+ }
658
+
659
+ window->stickyMouseButtons = value;
660
+ return;
661
+ }
662
+
663
+ case GLFW_LOCK_KEY_MODS:
664
+ {
665
+ window->lockKeyMods = value ? GLFW_TRUE : GLFW_FALSE;
666
+ return;
667
+ }
668
+
669
+ case GLFW_RAW_MOUSE_MOTION:
670
+ {
671
+ if (!_glfw.platform.rawMouseMotionSupported())
672
+ {
673
+ _glfwInputError(GLFW_PLATFORM_ERROR,
674
+ "Raw mouse motion is not supported on this system");
675
+ return;
676
+ }
677
+
678
+ value = value ? GLFW_TRUE : GLFW_FALSE;
679
+ if (window->rawMouseMotion == value)
680
+ return;
681
+
682
+ window->rawMouseMotion = value;
683
+ _glfw.platform.setRawMouseMotion(window, value);
684
+ return;
685
+ }
686
+ }
687
+
688
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
689
+ }
690
+
691
+ GLFWAPI int glfwRawMouseMotionSupported(void)
692
+ {
693
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
694
+ return _glfw.platform.rawMouseMotionSupported();
695
+ }
696
+
697
+ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
698
+ {
699
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
700
+
701
+ if (key != GLFW_KEY_UNKNOWN)
702
+ {
703
+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
704
+ {
705
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
706
+ return NULL;
707
+ }
708
+
709
+ if (key != GLFW_KEY_KP_EQUAL &&
710
+ (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) &&
711
+ (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2))
712
+ {
713
+ return NULL;
714
+ }
715
+
716
+ scancode = _glfw.platform.getKeyScancode(key);
717
+ }
718
+
719
+ return _glfw.platform.getScancodeName(scancode);
720
+ }
721
+
722
+ GLFWAPI int glfwGetKeyScancode(int key)
723
+ {
724
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
725
+
726
+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
727
+ {
728
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
729
+ return -1;
730
+ }
731
+
732
+ return _glfw.platform.getKeyScancode(key);
733
+ }
734
+
735
+ GLFWAPI int glfwGetKey(GLFWwindow* handle, int key)
736
+ {
737
+ _GLFWwindow* window = (_GLFWwindow*) handle;
738
+ assert(window != NULL);
739
+
740
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
741
+
742
+ if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST)
743
+ {
744
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key);
745
+ return GLFW_RELEASE;
746
+ }
747
+
748
+ if (window->keys[key] == _GLFW_STICK)
749
+ {
750
+ // Sticky mode: release key now
751
+ window->keys[key] = GLFW_RELEASE;
752
+ return GLFW_PRESS;
753
+ }
754
+
755
+ return (int) window->keys[key];
756
+ }
757
+
758
+ GLFWAPI int glfwGetMouseButton(GLFWwindow* handle, int button)
759
+ {
760
+ _GLFWwindow* window = (_GLFWwindow*) handle;
761
+ assert(window != NULL);
762
+
763
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_RELEASE);
764
+
765
+ if (button < GLFW_MOUSE_BUTTON_1 || button > GLFW_MOUSE_BUTTON_LAST)
766
+ {
767
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid mouse button %i", button);
768
+ return GLFW_RELEASE;
769
+ }
770
+
771
+ if (window->mouseButtons[button] == _GLFW_STICK)
772
+ {
773
+ // Sticky mode: release mouse button now
774
+ window->mouseButtons[button] = GLFW_RELEASE;
775
+ return GLFW_PRESS;
776
+ }
777
+
778
+ return (int) window->mouseButtons[button];
779
+ }
780
+
781
+ GLFWAPI void glfwGetCursorPos(GLFWwindow* handle, double* xpos, double* ypos)
782
+ {
783
+ _GLFWwindow* window = (_GLFWwindow*) handle;
784
+ assert(window != NULL);
785
+
786
+ if (xpos)
787
+ *xpos = 0;
788
+ if (ypos)
789
+ *ypos = 0;
790
+
791
+ _GLFW_REQUIRE_INIT();
792
+
793
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
794
+ {
795
+ if (xpos)
796
+ *xpos = window->virtualCursorPosX;
797
+ if (ypos)
798
+ *ypos = window->virtualCursorPosY;
799
+ }
800
+ else
801
+ _glfw.platform.getCursorPos(window, xpos, ypos);
802
+ }
803
+
804
+ GLFWAPI void glfwSetCursorPos(GLFWwindow* handle, double xpos, double ypos)
805
+ {
806
+ _GLFWwindow* window = (_GLFWwindow*) handle;
807
+ assert(window != NULL);
808
+
809
+ _GLFW_REQUIRE_INIT();
810
+
811
+ if (xpos != xpos || xpos < -DBL_MAX || xpos > DBL_MAX ||
812
+ ypos != ypos || ypos < -DBL_MAX || ypos > DBL_MAX)
813
+ {
814
+ _glfwInputError(GLFW_INVALID_VALUE,
815
+ "Invalid cursor position %f %f",
816
+ xpos, ypos);
817
+ return;
818
+ }
819
+
820
+ if (!_glfw.platform.windowFocused(window))
821
+ return;
822
+
823
+ if (window->cursorMode == GLFW_CURSOR_DISABLED)
824
+ {
825
+ // Only update the accumulated position if the cursor is disabled
826
+ window->virtualCursorPosX = xpos;
827
+ window->virtualCursorPosY = ypos;
828
+ }
829
+ else
830
+ {
831
+ // Update system cursor position
832
+ _glfw.platform.setCursorPos(window, xpos, ypos);
833
+ }
834
+ }
835
+
836
+ GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot)
837
+ {
838
+ _GLFWcursor* cursor;
839
+
840
+ assert(image != NULL);
841
+ assert(image->pixels != NULL);
842
+
843
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
844
+
845
+ if (image->width <= 0 || image->height <= 0)
846
+ {
847
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid image dimensions for cursor");
848
+ return NULL;
849
+ }
850
+
851
+ cursor = _glfw_calloc(1, sizeof(_GLFWcursor));
852
+ cursor->next = _glfw.cursorListHead;
853
+ _glfw.cursorListHead = cursor;
854
+
855
+ if (!_glfw.platform.createCursor(cursor, image, xhot, yhot))
856
+ {
857
+ glfwDestroyCursor((GLFWcursor*) cursor);
858
+ return NULL;
859
+ }
860
+
861
+ return (GLFWcursor*) cursor;
862
+ }
863
+
864
+ GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape)
865
+ {
866
+ _GLFWcursor* cursor;
867
+
868
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
869
+
870
+ if (shape != GLFW_ARROW_CURSOR &&
871
+ shape != GLFW_IBEAM_CURSOR &&
872
+ shape != GLFW_CROSSHAIR_CURSOR &&
873
+ shape != GLFW_POINTING_HAND_CURSOR &&
874
+ shape != GLFW_RESIZE_EW_CURSOR &&
875
+ shape != GLFW_RESIZE_NS_CURSOR &&
876
+ shape != GLFW_RESIZE_NWSE_CURSOR &&
877
+ shape != GLFW_RESIZE_NESW_CURSOR &&
878
+ shape != GLFW_RESIZE_ALL_CURSOR &&
879
+ shape != GLFW_NOT_ALLOWED_CURSOR)
880
+ {
881
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid standard cursor 0x%08X", shape);
882
+ return NULL;
883
+ }
884
+
885
+ cursor = _glfw_calloc(1, sizeof(_GLFWcursor));
886
+ cursor->next = _glfw.cursorListHead;
887
+ _glfw.cursorListHead = cursor;
888
+
889
+ if (!_glfw.platform.createStandardCursor(cursor, shape))
890
+ {
891
+ glfwDestroyCursor((GLFWcursor*) cursor);
892
+ return NULL;
893
+ }
894
+
895
+ return (GLFWcursor*) cursor;
896
+ }
897
+
898
+ GLFWAPI void glfwDestroyCursor(GLFWcursor* handle)
899
+ {
900
+ _GLFWcursor* cursor = (_GLFWcursor*) handle;
901
+
902
+ _GLFW_REQUIRE_INIT();
903
+
904
+ if (cursor == NULL)
905
+ return;
906
+
907
+ // Make sure the cursor is not being used by any window
908
+ {
909
+ _GLFWwindow* window;
910
+
911
+ for (window = _glfw.windowListHead; window; window = window->next)
912
+ {
913
+ if (window->cursor == cursor)
914
+ glfwSetCursor((GLFWwindow*) window, NULL);
915
+ }
916
+ }
917
+
918
+ _glfw.platform.destroyCursor(cursor);
919
+
920
+ // Unlink cursor from global linked list
921
+ {
922
+ _GLFWcursor** prev = &_glfw.cursorListHead;
923
+
924
+ while (*prev != cursor)
925
+ prev = &((*prev)->next);
926
+
927
+ *prev = cursor->next;
928
+ }
929
+
930
+ _glfw_free(cursor);
931
+ }
932
+
933
+ GLFWAPI void glfwSetCursor(GLFWwindow* windowHandle, GLFWcursor* cursorHandle)
934
+ {
935
+ _GLFWwindow* window = (_GLFWwindow*) windowHandle;
936
+ _GLFWcursor* cursor = (_GLFWcursor*) cursorHandle;
937
+ assert(window != NULL);
938
+
939
+ _GLFW_REQUIRE_INIT();
940
+
941
+ window->cursor = cursor;
942
+
943
+ _glfw.platform.setCursor(window, cursor);
944
+ }
945
+
946
+ GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* handle, GLFWkeyfun cbfun)
947
+ {
948
+ _GLFWwindow* window = (_GLFWwindow*) handle;
949
+ assert(window != NULL);
950
+
951
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
952
+ _GLFW_SWAP(GLFWkeyfun, window->callbacks.key, cbfun);
953
+ return cbfun;
954
+ }
955
+
956
+ GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* handle, GLFWcharfun cbfun)
957
+ {
958
+ _GLFWwindow* window = (_GLFWwindow*) handle;
959
+ assert(window != NULL);
960
+
961
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
962
+ _GLFW_SWAP(GLFWcharfun, window->callbacks.character, cbfun);
963
+ return cbfun;
964
+ }
965
+
966
+ GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* handle, GLFWcharmodsfun cbfun)
967
+ {
968
+ _GLFWwindow* window = (_GLFWwindow*) handle;
969
+ assert(window != NULL);
970
+
971
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
972
+ _GLFW_SWAP(GLFWcharmodsfun, window->callbacks.charmods, cbfun);
973
+ return cbfun;
974
+ }
975
+
976
+ GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* handle,
977
+ GLFWmousebuttonfun cbfun)
978
+ {
979
+ _GLFWwindow* window = (_GLFWwindow*) handle;
980
+ assert(window != NULL);
981
+
982
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
983
+ _GLFW_SWAP(GLFWmousebuttonfun, window->callbacks.mouseButton, cbfun);
984
+ return cbfun;
985
+ }
986
+
987
+ GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* handle,
988
+ GLFWcursorposfun cbfun)
989
+ {
990
+ _GLFWwindow* window = (_GLFWwindow*) handle;
991
+ assert(window != NULL);
992
+
993
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
994
+ _GLFW_SWAP(GLFWcursorposfun, window->callbacks.cursorPos, cbfun);
995
+ return cbfun;
996
+ }
997
+
998
+ GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* handle,
999
+ GLFWcursorenterfun cbfun)
1000
+ {
1001
+ _GLFWwindow* window = (_GLFWwindow*) handle;
1002
+ assert(window != NULL);
1003
+
1004
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1005
+ _GLFW_SWAP(GLFWcursorenterfun, window->callbacks.cursorEnter, cbfun);
1006
+ return cbfun;
1007
+ }
1008
+
1009
+ GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* handle,
1010
+ GLFWscrollfun cbfun)
1011
+ {
1012
+ _GLFWwindow* window = (_GLFWwindow*) handle;
1013
+ assert(window != NULL);
1014
+
1015
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1016
+ _GLFW_SWAP(GLFWscrollfun, window->callbacks.scroll, cbfun);
1017
+ return cbfun;
1018
+ }
1019
+
1020
+ GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* handle, GLFWdropfun cbfun)
1021
+ {
1022
+ _GLFWwindow* window = (_GLFWwindow*) handle;
1023
+ assert(window != NULL);
1024
+
1025
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1026
+ _GLFW_SWAP(GLFWdropfun, window->callbacks.drop, cbfun);
1027
+ return cbfun;
1028
+ }
1029
+
1030
+ GLFWAPI int glfwJoystickPresent(int jid)
1031
+ {
1032
+ _GLFWjoystick* js;
1033
+
1034
+ assert(jid >= GLFW_JOYSTICK_1);
1035
+ assert(jid <= GLFW_JOYSTICK_LAST);
1036
+
1037
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
1038
+
1039
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1040
+ {
1041
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1042
+ return GLFW_FALSE;
1043
+ }
1044
+
1045
+ if (!initJoysticks())
1046
+ return GLFW_FALSE;
1047
+
1048
+ js = _glfw.joysticks + jid;
1049
+ if (!js->connected)
1050
+ return GLFW_FALSE;
1051
+
1052
+ return _glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE);
1053
+ }
1054
+
1055
+ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count)
1056
+ {
1057
+ _GLFWjoystick* js;
1058
+
1059
+ assert(jid >= GLFW_JOYSTICK_1);
1060
+ assert(jid <= GLFW_JOYSTICK_LAST);
1061
+ assert(count != NULL);
1062
+
1063
+ *count = 0;
1064
+
1065
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1066
+
1067
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1068
+ {
1069
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1070
+ return NULL;
1071
+ }
1072
+
1073
+ if (!initJoysticks())
1074
+ return NULL;
1075
+
1076
+ js = _glfw.joysticks + jid;
1077
+ if (!js->connected)
1078
+ return NULL;
1079
+
1080
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_AXES))
1081
+ return NULL;
1082
+
1083
+ *count = js->axisCount;
1084
+ return js->axes;
1085
+ }
1086
+
1087
+ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count)
1088
+ {
1089
+ _GLFWjoystick* js;
1090
+
1091
+ assert(jid >= GLFW_JOYSTICK_1);
1092
+ assert(jid <= GLFW_JOYSTICK_LAST);
1093
+ assert(count != NULL);
1094
+
1095
+ *count = 0;
1096
+
1097
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1098
+
1099
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1100
+ {
1101
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1102
+ return NULL;
1103
+ }
1104
+
1105
+ if (!initJoysticks())
1106
+ return NULL;
1107
+
1108
+ js = _glfw.joysticks + jid;
1109
+ if (!js->connected)
1110
+ return NULL;
1111
+
1112
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
1113
+ return NULL;
1114
+
1115
+ if (_glfw.hints.init.hatButtons)
1116
+ *count = js->buttonCount + js->hatCount * 4;
1117
+ else
1118
+ *count = js->buttonCount;
1119
+
1120
+ return js->buttons;
1121
+ }
1122
+
1123
+ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count)
1124
+ {
1125
+ _GLFWjoystick* js;
1126
+
1127
+ assert(jid >= GLFW_JOYSTICK_1);
1128
+ assert(jid <= GLFW_JOYSTICK_LAST);
1129
+ assert(count != NULL);
1130
+
1131
+ *count = 0;
1132
+
1133
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1134
+
1135
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1136
+ {
1137
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1138
+ return NULL;
1139
+ }
1140
+
1141
+ if (!initJoysticks())
1142
+ return NULL;
1143
+
1144
+ js = _glfw.joysticks + jid;
1145
+ if (!js->connected)
1146
+ return NULL;
1147
+
1148
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_BUTTONS))
1149
+ return NULL;
1150
+
1151
+ *count = js->hatCount;
1152
+ return js->hats;
1153
+ }
1154
+
1155
+ GLFWAPI const char* glfwGetJoystickName(int jid)
1156
+ {
1157
+ _GLFWjoystick* js;
1158
+
1159
+ assert(jid >= GLFW_JOYSTICK_1);
1160
+ assert(jid <= GLFW_JOYSTICK_LAST);
1161
+
1162
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1163
+
1164
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1165
+ {
1166
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1167
+ return NULL;
1168
+ }
1169
+
1170
+ if (!initJoysticks())
1171
+ return NULL;
1172
+
1173
+ js = _glfw.joysticks + jid;
1174
+ if (!js->connected)
1175
+ return NULL;
1176
+
1177
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
1178
+ return NULL;
1179
+
1180
+ return js->name;
1181
+ }
1182
+
1183
+ GLFWAPI const char* glfwGetJoystickGUID(int jid)
1184
+ {
1185
+ _GLFWjoystick* js;
1186
+
1187
+ assert(jid >= GLFW_JOYSTICK_1);
1188
+ assert(jid <= GLFW_JOYSTICK_LAST);
1189
+
1190
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1191
+
1192
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1193
+ {
1194
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1195
+ return NULL;
1196
+ }
1197
+
1198
+ if (!initJoysticks())
1199
+ return NULL;
1200
+
1201
+ js = _glfw.joysticks + jid;
1202
+ if (!js->connected)
1203
+ return NULL;
1204
+
1205
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
1206
+ return NULL;
1207
+
1208
+ return js->guid;
1209
+ }
1210
+
1211
+ GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer)
1212
+ {
1213
+ _GLFWjoystick* js;
1214
+
1215
+ assert(jid >= GLFW_JOYSTICK_1);
1216
+ assert(jid <= GLFW_JOYSTICK_LAST);
1217
+
1218
+ _GLFW_REQUIRE_INIT();
1219
+
1220
+ js = _glfw.joysticks + jid;
1221
+ if (!js->allocated)
1222
+ return;
1223
+
1224
+ js->userPointer = pointer;
1225
+ }
1226
+
1227
+ GLFWAPI void* glfwGetJoystickUserPointer(int jid)
1228
+ {
1229
+ _GLFWjoystick* js;
1230
+
1231
+ assert(jid >= GLFW_JOYSTICK_1);
1232
+ assert(jid <= GLFW_JOYSTICK_LAST);
1233
+
1234
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1235
+
1236
+ js = _glfw.joysticks + jid;
1237
+ if (!js->allocated)
1238
+ return NULL;
1239
+
1240
+ return js->userPointer;
1241
+ }
1242
+
1243
+ GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun)
1244
+ {
1245
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1246
+
1247
+ if (!initJoysticks())
1248
+ return NULL;
1249
+
1250
+ _GLFW_SWAP(GLFWjoystickfun, _glfw.callbacks.joystick, cbfun);
1251
+ return cbfun;
1252
+ }
1253
+
1254
+ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
1255
+ {
1256
+ int jid;
1257
+ const char* c = string;
1258
+
1259
+ assert(string != NULL);
1260
+
1261
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
1262
+
1263
+ while (*c)
1264
+ {
1265
+ if ((*c >= '0' && *c <= '9') ||
1266
+ (*c >= 'a' && *c <= 'f') ||
1267
+ (*c >= 'A' && *c <= 'F'))
1268
+ {
1269
+ char line[1024];
1270
+
1271
+ const size_t length = strcspn(c, "\r\n");
1272
+ if (length < sizeof(line))
1273
+ {
1274
+ _GLFWmapping mapping = {{0}};
1275
+
1276
+ memcpy(line, c, length);
1277
+ line[length] = '\0';
1278
+
1279
+ if (parseMapping(&mapping, line))
1280
+ {
1281
+ _GLFWmapping* previous = findMapping(mapping.guid);
1282
+ if (previous)
1283
+ *previous = mapping;
1284
+ else
1285
+ {
1286
+ _glfw.mappingCount++;
1287
+ _glfw.mappings =
1288
+ _glfw_realloc(_glfw.mappings,
1289
+ sizeof(_GLFWmapping) * _glfw.mappingCount);
1290
+ _glfw.mappings[_glfw.mappingCount - 1] = mapping;
1291
+ }
1292
+ }
1293
+ }
1294
+
1295
+ c += length;
1296
+ }
1297
+ else
1298
+ {
1299
+ c += strcspn(c, "\r\n");
1300
+ c += strspn(c, "\r\n");
1301
+ }
1302
+ }
1303
+
1304
+ for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
1305
+ {
1306
+ _GLFWjoystick* js = _glfw.joysticks + jid;
1307
+ if (js->connected)
1308
+ js->mapping = findValidMapping(js);
1309
+ }
1310
+
1311
+ return GLFW_TRUE;
1312
+ }
1313
+
1314
+ GLFWAPI int glfwJoystickIsGamepad(int jid)
1315
+ {
1316
+ _GLFWjoystick* js;
1317
+
1318
+ assert(jid >= GLFW_JOYSTICK_1);
1319
+ assert(jid <= GLFW_JOYSTICK_LAST);
1320
+
1321
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
1322
+
1323
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1324
+ {
1325
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1326
+ return GLFW_FALSE;
1327
+ }
1328
+
1329
+ if (!initJoysticks())
1330
+ return GLFW_FALSE;
1331
+
1332
+ js = _glfw.joysticks + jid;
1333
+ if (!js->connected)
1334
+ return GLFW_FALSE;
1335
+
1336
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
1337
+ return GLFW_FALSE;
1338
+
1339
+ return js->mapping != NULL;
1340
+ }
1341
+
1342
+ GLFWAPI const char* glfwGetGamepadName(int jid)
1343
+ {
1344
+ _GLFWjoystick* js;
1345
+
1346
+ assert(jid >= GLFW_JOYSTICK_1);
1347
+ assert(jid <= GLFW_JOYSTICK_LAST);
1348
+
1349
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1350
+
1351
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1352
+ {
1353
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1354
+ return NULL;
1355
+ }
1356
+
1357
+ if (!initJoysticks())
1358
+ return NULL;
1359
+
1360
+ js = _glfw.joysticks + jid;
1361
+ if (!js->connected)
1362
+ return NULL;
1363
+
1364
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_PRESENCE))
1365
+ return NULL;
1366
+
1367
+ if (!js->mapping)
1368
+ return NULL;
1369
+
1370
+ return js->mapping->name;
1371
+ }
1372
+
1373
+ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
1374
+ {
1375
+ int i;
1376
+ _GLFWjoystick* js;
1377
+
1378
+ assert(jid >= GLFW_JOYSTICK_1);
1379
+ assert(jid <= GLFW_JOYSTICK_LAST);
1380
+ assert(state != NULL);
1381
+
1382
+ memset(state, 0, sizeof(GLFWgamepadstate));
1383
+
1384
+ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
1385
+
1386
+ if (jid < 0 || jid > GLFW_JOYSTICK_LAST)
1387
+ {
1388
+ _glfwInputError(GLFW_INVALID_ENUM, "Invalid joystick ID %i", jid);
1389
+ return GLFW_FALSE;
1390
+ }
1391
+
1392
+ if (!initJoysticks())
1393
+ return GLFW_FALSE;
1394
+
1395
+ js = _glfw.joysticks + jid;
1396
+ if (!js->connected)
1397
+ return GLFW_FALSE;
1398
+
1399
+ if (!_glfw.platform.pollJoystick(js, _GLFW_POLL_ALL))
1400
+ return GLFW_FALSE;
1401
+
1402
+ if (!js->mapping)
1403
+ return GLFW_FALSE;
1404
+
1405
+ for (i = 0; i <= GLFW_GAMEPAD_BUTTON_LAST; i++)
1406
+ {
1407
+ const _GLFWmapelement* e = js->mapping->buttons + i;
1408
+ if (e->type == _GLFW_JOYSTICK_AXIS)
1409
+ {
1410
+ const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
1411
+ // HACK: This should be baked into the value transform
1412
+ // TODO: Bake into transform when implementing output modifiers
1413
+ if (e->axisOffset < 0 || (e->axisOffset == 0 && e->axisScale > 0))
1414
+ {
1415
+ if (value >= 0.f)
1416
+ state->buttons[i] = GLFW_PRESS;
1417
+ }
1418
+ else
1419
+ {
1420
+ if (value <= 0.f)
1421
+ state->buttons[i] = GLFW_PRESS;
1422
+ }
1423
+ }
1424
+ else if (e->type == _GLFW_JOYSTICK_HATBIT)
1425
+ {
1426
+ const unsigned int hat = e->index >> 4;
1427
+ const unsigned int bit = e->index & 0xf;
1428
+ if (js->hats[hat] & bit)
1429
+ state->buttons[i] = GLFW_PRESS;
1430
+ }
1431
+ else if (e->type == _GLFW_JOYSTICK_BUTTON)
1432
+ state->buttons[i] = js->buttons[e->index];
1433
+ }
1434
+
1435
+ for (i = 0; i <= GLFW_GAMEPAD_AXIS_LAST; i++)
1436
+ {
1437
+ const _GLFWmapelement* e = js->mapping->axes + i;
1438
+ if (e->type == _GLFW_JOYSTICK_AXIS)
1439
+ {
1440
+ const float value = js->axes[e->index] * e->axisScale + e->axisOffset;
1441
+ state->axes[i] = fminf(fmaxf(value, -1.f), 1.f);
1442
+ }
1443
+ else if (e->type == _GLFW_JOYSTICK_HATBIT)
1444
+ {
1445
+ const unsigned int hat = e->index >> 4;
1446
+ const unsigned int bit = e->index & 0xf;
1447
+ if (js->hats[hat] & bit)
1448
+ state->axes[i] = 1.f;
1449
+ else
1450
+ state->axes[i] = -1.f;
1451
+ }
1452
+ else if (e->type == _GLFW_JOYSTICK_BUTTON)
1453
+ state->axes[i] = js->buttons[e->index] * 2.f - 1.f;
1454
+ }
1455
+
1456
+ return GLFW_TRUE;
1457
+ }
1458
+
1459
+ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
1460
+ {
1461
+ assert(string != NULL);
1462
+
1463
+ _GLFW_REQUIRE_INIT();
1464
+ _glfw.platform.setClipboardString(string);
1465
+ }
1466
+
1467
+ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle)
1468
+ {
1469
+ _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
1470
+ return _glfw.platform.getClipboardString();
1471
+ }
1472
+
1473
+ GLFWAPI double glfwGetTime(void)
1474
+ {
1475
+ _GLFW_REQUIRE_INIT_OR_RETURN(0.0);
1476
+ return (double) (_glfwPlatformGetTimerValue() - _glfw.timer.offset) /
1477
+ _glfwPlatformGetTimerFrequency();
1478
+ }
1479
+
1480
+ GLFWAPI void glfwSetTime(double time)
1481
+ {
1482
+ _GLFW_REQUIRE_INIT();
1483
+
1484
+ if (time != time || time < 0.0 || time > 18446744073.0)
1485
+ {
1486
+ _glfwInputError(GLFW_INVALID_VALUE, "Invalid time %f", time);
1487
+ return;
1488
+ }
1489
+
1490
+ _glfw.timer.offset = _glfwPlatformGetTimerValue() -
1491
+ (uint64_t) (time * _glfwPlatformGetTimerFrequency());
1492
+ }
1493
+
1494
+ GLFWAPI uint64_t glfwGetTimerValue(void)
1495
+ {
1496
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
1497
+ return _glfwPlatformGetTimerValue();
1498
+ }
1499
+
1500
+ GLFWAPI uint64_t glfwGetTimerFrequency(void)
1501
+ {
1502
+ _GLFW_REQUIRE_INIT_OR_RETURN(0);
1503
+ return _glfwPlatformGetTimerFrequency();
1504
+ }
1505
+