Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/events/SDL_events.c
22240 views
1
/*
2
Simple DirectMedia Layer
3
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
4
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
8
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
12
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
20
*/
21
#include "SDL_internal.h"
22
23
// General event handling code for SDL
24
25
#include "SDL_events_c.h"
26
#include "SDL_eventwatch_c.h"
27
#include "../SDL_hints_c.h"
28
#include "../timer/SDL_timer_c.h"
29
#ifndef SDL_JOYSTICK_DISABLED
30
#include "../joystick/SDL_joystick_c.h"
31
#endif
32
#ifndef SDL_SENSOR_DISABLED
33
#include "../sensor/SDL_sensor_c.h"
34
#endif
35
//#include "../video/SDL_sysvideo.h"
36
37
#ifdef SDL_PLATFORM_ANDROID
38
#include "../core/android/SDL_android.h"
39
#include "../video/android/SDL_androidevents.h"
40
#endif
41
42
// An arbitrary limit so we don't have unbounded growth
43
#define SDL_MAX_QUEUED_EVENTS 65535
44
45
// Determines how often we pump events if joystick or sensor subsystems are active
46
#define ENUMERATION_POLL_INTERVAL_NS (3 * SDL_NS_PER_SECOND)
47
48
// Determines how often to pump events if joysticks or sensors are actively being read
49
#define EVENT_POLL_INTERVAL_NS SDL_MS_TO_NS(1)
50
51
// Make sure the type in the SDL_Event aligns properly across the union
52
SDL_COMPILE_TIME_ASSERT(SDL_Event_type, sizeof(Uint32) == sizeof(SDL_EventType));
53
54
#define SDL2_SYSWMEVENT 0x201
55
56
#ifdef SDL_VIDEO_DRIVER_WINDOWS
57
#include "../core/windows/SDL_windows.h"
58
#endif
59
60
#ifdef SDL_VIDEO_DRIVER_X11
61
#include <X11/Xlib.h>
62
#endif
63
64
typedef struct SDL2_version
65
{
66
Uint8 major;
67
Uint8 minor;
68
Uint8 patch;
69
} SDL2_version;
70
71
typedef enum
72
{
73
SDL2_SYSWM_UNKNOWN
74
} SDL2_SYSWM_TYPE;
75
76
typedef struct SDL2_SysWMmsg
77
{
78
SDL2_version version;
79
SDL2_SYSWM_TYPE subsystem;
80
union
81
{
82
#ifdef SDL_VIDEO_DRIVER_WINDOWS
83
struct {
84
HWND hwnd; /**< The window for the message */
85
UINT msg; /**< The type of message */
86
WPARAM wParam; /**< WORD message parameter */
87
LPARAM lParam; /**< LONG message parameter */
88
} win;
89
#endif
90
#ifdef SDL_VIDEO_DRIVER_X11
91
struct {
92
XEvent event;
93
} x11;
94
#endif
95
/* Can't have an empty union */
96
int dummy;
97
} msg;
98
} SDL2_SysWMmsg;
99
100
static SDL_EventWatchList SDL_event_watchers;
101
static SDL_AtomicInt SDL_sentinel_pending;
102
static Uint32 SDL_last_event_id = 0;
103
104
typedef struct
105
{
106
Uint32 bits[8];
107
} SDL_DisabledEventBlock;
108
109
static SDL_DisabledEventBlock *SDL_disabled_events[256];
110
static SDL_AtomicInt SDL_userevents;
111
112
typedef struct SDL_TemporaryMemory
113
{
114
void *memory;
115
struct SDL_TemporaryMemory *prev;
116
struct SDL_TemporaryMemory *next;
117
} SDL_TemporaryMemory;
118
119
typedef struct SDL_TemporaryMemoryState
120
{
121
SDL_TemporaryMemory *head;
122
SDL_TemporaryMemory *tail;
123
} SDL_TemporaryMemoryState;
124
125
static SDL_TLSID SDL_temporary_memory;
126
127
typedef struct SDL_EventEntry
128
{
129
SDL_Event event;
130
SDL_TemporaryMemory *memory;
131
struct SDL_EventEntry *prev;
132
struct SDL_EventEntry *next;
133
} SDL_EventEntry;
134
135
static struct
136
{
137
SDL_Mutex *lock;
138
bool active;
139
SDL_AtomicInt count;
140
int max_events_seen;
141
SDL_EventEntry *head;
142
SDL_EventEntry *tail;
143
SDL_EventEntry *free;
144
} SDL_EventQ = { NULL, false, { 0 }, 0, NULL, NULL, NULL };
145
146
147
static void SDL_CleanupTemporaryMemory(void *data)
148
{
149
SDL_TemporaryMemoryState *state = (SDL_TemporaryMemoryState *)data;
150
151
SDL_FreeTemporaryMemory();
152
SDL_free(state);
153
}
154
155
static SDL_TemporaryMemoryState *SDL_GetTemporaryMemoryState(bool create)
156
{
157
SDL_TemporaryMemoryState *state;
158
159
state = (SDL_TemporaryMemoryState *)SDL_GetTLS(&SDL_temporary_memory);
160
if (!state) {
161
if (!create) {
162
return NULL;
163
}
164
165
state = (SDL_TemporaryMemoryState *)SDL_calloc(1, sizeof(*state));
166
if (!state) {
167
return NULL;
168
}
169
170
if (!SDL_SetTLS(&SDL_temporary_memory, state, SDL_CleanupTemporaryMemory)) {
171
SDL_free(state);
172
return NULL;
173
}
174
}
175
return state;
176
}
177
178
static SDL_TemporaryMemory *SDL_GetTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, const void *mem)
179
{
180
SDL_TemporaryMemory *entry;
181
182
// Start from the end, it's likely to have been recently allocated
183
for (entry = state->tail; entry; entry = entry->prev) {
184
if (mem == entry->memory) {
185
return entry;
186
}
187
}
188
return NULL;
189
}
190
191
static void SDL_LinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry)
192
{
193
entry->prev = state->tail;
194
entry->next = NULL;
195
196
if (state->tail) {
197
state->tail->next = entry;
198
} else {
199
state->head = entry;
200
}
201
state->tail = entry;
202
}
203
204
static void SDL_UnlinkTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry)
205
{
206
if (state->head == entry) {
207
state->head = entry->next;
208
}
209
if (state->tail == entry) {
210
state->tail = entry->prev;
211
}
212
213
if (entry->prev) {
214
entry->prev->next = entry->next;
215
}
216
if (entry->next) {
217
entry->next->prev = entry->prev;
218
}
219
220
entry->prev = NULL;
221
entry->next = NULL;
222
}
223
224
static void SDL_FreeTemporaryMemoryEntry(SDL_TemporaryMemoryState *state, SDL_TemporaryMemory *entry, bool free_data)
225
{
226
if (free_data) {
227
SDL_free(entry->memory);
228
}
229
SDL_free(entry);
230
}
231
232
static void SDL_LinkTemporaryMemoryToEvent(SDL_EventEntry *event, const void *mem)
233
{
234
SDL_TemporaryMemoryState *state;
235
SDL_TemporaryMemory *entry;
236
237
state = SDL_GetTemporaryMemoryState(false);
238
if (!state) {
239
return;
240
}
241
242
entry = SDL_GetTemporaryMemoryEntry(state, mem);
243
if (entry) {
244
SDL_UnlinkTemporaryMemoryEntry(state, entry);
245
entry->next = event->memory;
246
event->memory = entry;
247
}
248
}
249
250
static void SDL_TransferSysWMMemoryToEvent(SDL_EventEntry *event)
251
{
252
SDL2_SysWMmsg **wmmsg = (SDL2_SysWMmsg **)((&event->event.common)+1);
253
SDL2_SysWMmsg *mem = SDL_AllocateTemporaryMemory(sizeof(*mem));
254
if (mem) {
255
SDL_copyp(mem, *wmmsg);
256
*wmmsg = mem;
257
SDL_LinkTemporaryMemoryToEvent(event, mem);
258
}
259
}
260
261
// Transfer the event memory from the thread-local event memory list to the event
262
static void SDL_TransferTemporaryMemoryToEvent(SDL_EventEntry *event)
263
{
264
switch (event->event.type) {
265
case SDL_EVENT_TEXT_EDITING:
266
SDL_LinkTemporaryMemoryToEvent(event, event->event.edit.text);
267
break;
268
case SDL_EVENT_TEXT_EDITING_CANDIDATES:
269
SDL_LinkTemporaryMemoryToEvent(event, event->event.edit_candidates.candidates);
270
break;
271
case SDL_EVENT_TEXT_INPUT:
272
SDL_LinkTemporaryMemoryToEvent(event, event->event.text.text);
273
break;
274
case SDL_EVENT_DROP_BEGIN:
275
case SDL_EVENT_DROP_FILE:
276
case SDL_EVENT_DROP_TEXT:
277
case SDL_EVENT_DROP_COMPLETE:
278
case SDL_EVENT_DROP_POSITION:
279
SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.source);
280
SDL_LinkTemporaryMemoryToEvent(event, event->event.drop.data);
281
break;
282
case SDL_EVENT_CLIPBOARD_UPDATE:
283
SDL_LinkTemporaryMemoryToEvent(event, event->event.clipboard.mime_types);
284
break;
285
case SDL2_SYSWMEVENT:
286
// We need to copy the stack pointer into temporary memory
287
SDL_TransferSysWMMemoryToEvent(event);
288
break;
289
default:
290
break;
291
}
292
}
293
294
// Transfer the event memory from the event to the thread-local event memory list
295
static void SDL_TransferTemporaryMemoryFromEvent(SDL_EventEntry *event)
296
{
297
SDL_TemporaryMemoryState *state;
298
SDL_TemporaryMemory *entry, *next;
299
300
if (!event->memory) {
301
return;
302
}
303
304
state = SDL_GetTemporaryMemoryState(true);
305
if (!state) {
306
return; // this is now a leak, but you probably have bigger problems if malloc failed.
307
}
308
309
for (entry = event->memory; entry; entry = next) {
310
next = entry->next;
311
SDL_LinkTemporaryMemoryEntry(state, entry);
312
}
313
event->memory = NULL;
314
}
315
316
static void *SDL_FreeLater(void *memory)
317
{
318
SDL_TemporaryMemoryState *state;
319
320
if (memory == NULL) {
321
return NULL;
322
}
323
324
// Make sure we're not adding this to the list twice
325
//SDL_assert(!SDL_ClaimTemporaryMemory(memory));
326
327
state = SDL_GetTemporaryMemoryState(true);
328
if (!state) {
329
return memory; // this is now a leak, but you probably have bigger problems if malloc failed.
330
}
331
332
SDL_TemporaryMemory *entry = (SDL_TemporaryMemory *)SDL_malloc(sizeof(*entry));
333
if (!entry) {
334
return memory; // this is now a leak, but you probably have bigger problems if malloc failed. We could probably pool up and reuse entries, though.
335
}
336
337
entry->memory = memory;
338
339
SDL_LinkTemporaryMemoryEntry(state, entry);
340
341
return memory;
342
}
343
344
void *SDL_AllocateTemporaryMemory(size_t size)
345
{
346
return SDL_FreeLater(SDL_malloc(size));
347
}
348
349
const char *SDL_CreateTemporaryString(const char *string)
350
{
351
if (string) {
352
return (const char *)SDL_FreeLater(SDL_strdup(string));
353
}
354
return NULL;
355
}
356
357
void *SDL_ClaimTemporaryMemory(const void *mem)
358
{
359
SDL_TemporaryMemoryState *state;
360
361
state = SDL_GetTemporaryMemoryState(false);
362
if (state && mem) {
363
SDL_TemporaryMemory *entry = SDL_GetTemporaryMemoryEntry(state, mem);
364
if (entry) {
365
SDL_UnlinkTemporaryMemoryEntry(state, entry);
366
SDL_FreeTemporaryMemoryEntry(state, entry, false);
367
return (void *)mem;
368
}
369
}
370
return NULL;
371
}
372
373
void SDL_FreeTemporaryMemory(void)
374
{
375
SDL_TemporaryMemoryState *state;
376
377
state = SDL_GetTemporaryMemoryState(false);
378
if (!state) {
379
return;
380
}
381
382
while (state->head) {
383
SDL_TemporaryMemory *entry = state->head;
384
385
SDL_UnlinkTemporaryMemoryEntry(state, entry);
386
SDL_FreeTemporaryMemoryEntry(state, entry, true);
387
}
388
}
389
390
#ifndef SDL_JOYSTICK_DISABLED
391
392
static bool SDL_update_joysticks = true;
393
394
static void SDLCALL SDL_AutoUpdateJoysticksChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
395
{
396
SDL_update_joysticks = SDL_GetStringBoolean(hint, true);
397
}
398
399
#endif // !SDL_JOYSTICK_DISABLED
400
401
#ifndef SDL_SENSOR_DISABLED
402
403
static bool SDL_update_sensors = true;
404
405
static void SDLCALL SDL_AutoUpdateSensorsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
406
{
407
SDL_update_sensors = SDL_GetStringBoolean(hint, true);
408
}
409
410
#endif // !SDL_SENSOR_DISABLED
411
412
static void SDLCALL SDL_PollSentinelChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
413
{
414
SDL_SetEventEnabled(SDL_EVENT_POLL_SENTINEL, SDL_GetStringBoolean(hint, true));
415
}
416
417
/**
418
* Verbosity of logged events as defined in SDL_HINT_EVENT_LOGGING:
419
* - 0: (default) no logging
420
* - 1: logging of most events
421
* - 2: as above, plus mouse, pen, and finger motion
422
*/
423
static int SDL_EventLoggingVerbosity = 0;
424
425
static void SDLCALL SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
426
{
427
SDL_EventLoggingVerbosity = (hint && *hint) ? SDL_clamp(SDL_atoi(hint), 0, 3) : 0;
428
}
429
430
static void SDL_LogEvent(const SDL_Event *event)
431
{
432
static const char *pen_axisnames[] = { "PRESSURE", "XTILT", "YTILT", "DISTANCE", "ROTATION", "SLIDER", "TANGENTIAL_PRESSURE" };
433
SDL_COMPILE_TIME_ASSERT(pen_axisnames_array_matches, SDL_arraysize(pen_axisnames) == SDL_PEN_AXIS_COUNT);
434
435
char name[64];
436
char details[128];
437
438
// sensor/mouse/pen/finger motion are spammy, ignore these if they aren't demanded.
439
if ((SDL_EventLoggingVerbosity < 2) &&
440
((event->type == SDL_EVENT_MOUSE_MOTION) ||
441
(event->type == SDL_EVENT_FINGER_MOTION) ||
442
(event->type == SDL_EVENT_PEN_AXIS) ||
443
(event->type == SDL_EVENT_PEN_MOTION) ||
444
(event->type == SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION) ||
445
(event->type == SDL_EVENT_GAMEPAD_SENSOR_UPDATE) ||
446
(event->type == SDL_EVENT_SENSOR_UPDATE))) {
447
return;
448
}
449
450
// this is to make (void)SDL_snprintf() calls cleaner.
451
#define uint unsigned int
452
453
name[0] = '\0';
454
details[0] = '\0';
455
456
// !!! FIXME: This code is kinda ugly, sorry.
457
458
if ((event->type >= SDL_EVENT_USER) && (event->type <= SDL_EVENT_LAST)) {
459
char plusstr[16];
460
SDL_strlcpy(name, "SDL_EVENT_USER", sizeof(name));
461
if (event->type > SDL_EVENT_USER) {
462
(void)SDL_snprintf(plusstr, sizeof(plusstr), "+%u", ((uint)event->type) - SDL_EVENT_USER);
463
} else {
464
plusstr[0] = '\0';
465
}
466
(void)SDL_snprintf(details, sizeof(details), "%s (timestamp=%u windowid=%u code=%d data1=%p data2=%p)",
467
plusstr, (uint)event->user.timestamp, (uint)event->user.windowID,
468
(int)event->user.code, event->user.data1, event->user.data2);
469
}
470
471
switch (event->type) {
472
#define SDL_EVENT_CASE(x) \
473
case x: \
474
SDL_strlcpy(name, #x, sizeof(name));
475
SDL_EVENT_CASE(SDL_EVENT_FIRST)
476
SDL_strlcpy(details, " (THIS IS PROBABLY A BUG!)", sizeof(details));
477
break;
478
SDL_EVENT_CASE(SDL_EVENT_QUIT)
479
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u)", (uint)event->quit.timestamp);
480
break;
481
SDL_EVENT_CASE(SDL_EVENT_TERMINATING)
482
break;
483
SDL_EVENT_CASE(SDL_EVENT_LOW_MEMORY)
484
break;
485
SDL_EVENT_CASE(SDL_EVENT_WILL_ENTER_BACKGROUND)
486
break;
487
SDL_EVENT_CASE(SDL_EVENT_DID_ENTER_BACKGROUND)
488
break;
489
SDL_EVENT_CASE(SDL_EVENT_WILL_ENTER_FOREGROUND)
490
break;
491
SDL_EVENT_CASE(SDL_EVENT_DID_ENTER_FOREGROUND)
492
break;
493
SDL_EVENT_CASE(SDL_EVENT_LOCALE_CHANGED)
494
break;
495
SDL_EVENT_CASE(SDL_EVENT_SYSTEM_THEME_CHANGED)
496
break;
497
SDL_EVENT_CASE(SDL_EVENT_KEYMAP_CHANGED)
498
break;
499
SDL_EVENT_CASE(SDL_EVENT_CLIPBOARD_UPDATE)
500
break;
501
502
#define SDL_RENDEREVENT_CASE(x) \
503
case x: \
504
SDL_strlcpy(name, #x, sizeof(name)); \
505
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u event=%s windowid=%u)", \
506
(uint)event->display.timestamp, name, (uint)event->render.windowID); \
507
break
508
SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_TARGETS_RESET);
509
SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_DEVICE_RESET);
510
SDL_RENDEREVENT_CASE(SDL_EVENT_RENDER_DEVICE_LOST);
511
512
#define SDL_DISPLAYEVENT_CASE(x) \
513
case x: \
514
SDL_strlcpy(name, #x, sizeof(name)); \
515
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u display=%u event=%s data1=%d, data2=%d)", \
516
(uint)event->display.timestamp, (uint)event->display.displayID, name, (int)event->display.data1, (int)event->display.data2); \
517
break
518
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ORIENTATION);
519
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_ADDED);
520
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_REMOVED);
521
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_MOVED);
522
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED);
523
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED);
524
SDL_DISPLAYEVENT_CASE(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED);
525
#undef SDL_DISPLAYEVENT_CASE
526
527
#define SDL_WINDOWEVENT_CASE(x) \
528
case x: \
529
SDL_strlcpy(name, #x, sizeof(name)); \
530
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u event=%s data1=%d data2=%d)", \
531
(uint)event->window.timestamp, (uint)event->window.windowID, name, (int)event->window.data1, (int)event->window.data2); \
532
break
533
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SHOWN);
534
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HIDDEN);
535
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_EXPOSED);
536
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOVED);
537
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESIZED);
538
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED);
539
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_METAL_VIEW_RESIZED);
540
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED);
541
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MINIMIZED);
542
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MAXIMIZED);
543
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_RESTORED);
544
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_ENTER);
545
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_MOUSE_LEAVE);
546
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_GAINED);
547
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_FOCUS_LOST);
548
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_CLOSE_REQUESTED);
549
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HIT_TEST);
550
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ICCPROF_CHANGED);
551
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_CHANGED);
552
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED);
553
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_OCCLUDED);
554
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_ENTER_FULLSCREEN);
555
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN);
556
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_DESTROYED);
557
SDL_WINDOWEVENT_CASE(SDL_EVENT_WINDOW_HDR_STATE_CHANGED);
558
#undef SDL_WINDOWEVENT_CASE
559
560
#define PRINT_KEYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->kdevice.timestamp, (uint)event->kdevice.which)
561
SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_ADDED)
562
PRINT_KEYDEV_EVENT(event);
563
break;
564
SDL_EVENT_CASE(SDL_EVENT_KEYBOARD_REMOVED)
565
PRINT_KEYDEV_EVENT(event);
566
break;
567
#undef PRINT_KEYDEV_EVENT
568
569
#define PRINT_KEY_EVENT(event) \
570
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%s repeat=%s scancode=%u keycode=%u mod=0x%x)", \
571
(uint)event->key.timestamp, (uint)event->key.windowID, (uint)event->key.which, \
572
event->key.down ? "pressed" : "released", \
573
event->key.repeat ? "true" : "false", \
574
(uint)event->key.scancode, \
575
(uint)event->key.key, \
576
(uint)event->key.mod)
577
SDL_EVENT_CASE(SDL_EVENT_KEY_DOWN)
578
PRINT_KEY_EVENT(event);
579
break;
580
SDL_EVENT_CASE(SDL_EVENT_KEY_UP)
581
PRINT_KEY_EVENT(event);
582
break;
583
#undef PRINT_KEY_EVENT
584
585
SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING)
586
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)",
587
(uint)event->edit.timestamp, (uint)event->edit.windowID,
588
event->edit.text, (int)event->edit.start, (int)event->edit.length);
589
break;
590
591
SDL_EVENT_CASE(SDL_EVENT_TEXT_EDITING_CANDIDATES)
592
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u num_candidates=%d selected_candidate=%d)",
593
(uint)event->edit_candidates.timestamp, (uint)event->edit_candidates.windowID,
594
(int)event->edit_candidates.num_candidates, (int)event->edit_candidates.selected_candidate);
595
break;
596
597
SDL_EVENT_CASE(SDL_EVENT_TEXT_INPUT)
598
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u text='%s')", (uint)event->text.timestamp, (uint)event->text.windowID, event->text.text);
599
break;
600
601
#define PRINT_MOUSEDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->mdevice.timestamp, (uint)event->mdevice.which)
602
SDL_EVENT_CASE(SDL_EVENT_MOUSE_ADDED)
603
PRINT_MOUSEDEV_EVENT(event);
604
break;
605
SDL_EVENT_CASE(SDL_EVENT_MOUSE_REMOVED)
606
PRINT_MOUSEDEV_EVENT(event);
607
break;
608
#undef PRINT_MOUSEDEV_EVENT
609
610
SDL_EVENT_CASE(SDL_EVENT_MOUSE_MOTION)
611
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u state=%u x=%g y=%g xrel=%g yrel=%g)",
612
(uint)event->motion.timestamp, (uint)event->motion.windowID,
613
(uint)event->motion.which, (uint)event->motion.state,
614
event->motion.x, event->motion.y,
615
event->motion.xrel, event->motion.yrel);
616
break;
617
618
#define PRINT_MBUTTON_EVENT(event) \
619
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%g y=%g)", \
620
(uint)event->button.timestamp, (uint)event->button.windowID, \
621
(uint)event->button.which, (uint)event->button.button, \
622
event->button.down ? "pressed" : "released", \
623
(uint)event->button.clicks, event->button.x, event->button.y)
624
SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_DOWN)
625
PRINT_MBUTTON_EVENT(event);
626
break;
627
SDL_EVENT_CASE(SDL_EVENT_MOUSE_BUTTON_UP)
628
PRINT_MBUTTON_EVENT(event);
629
break;
630
#undef PRINT_MBUTTON_EVENT
631
632
SDL_EVENT_CASE(SDL_EVENT_MOUSE_WHEEL)
633
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u x=%g y=%g integer_x=%d integer_y=%d direction=%s)",
634
(uint)event->wheel.timestamp, (uint)event->wheel.windowID,
635
(uint)event->wheel.which, event->wheel.x, event->wheel.y,
636
(int)event->wheel.integer_x, (int)event->wheel.integer_y,
637
event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
638
break;
639
640
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_AXIS_MOTION)
641
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d axis=%u value=%d)",
642
(uint)event->jaxis.timestamp, (int)event->jaxis.which,
643
(uint)event->jaxis.axis, (int)event->jaxis.value);
644
break;
645
646
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BALL_MOTION)
647
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)",
648
(uint)event->jball.timestamp, (int)event->jball.which,
649
(uint)event->jball.ball, (int)event->jball.xrel, (int)event->jball.yrel);
650
break;
651
652
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_HAT_MOTION)
653
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d hat=%u value=%u)",
654
(uint)event->jhat.timestamp, (int)event->jhat.which,
655
(uint)event->jhat.hat, (uint)event->jhat.value);
656
break;
657
658
#define PRINT_JBUTTON_EVENT(event) \
659
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \
660
(uint)event->jbutton.timestamp, (int)event->jbutton.which, \
661
(uint)event->jbutton.button, event->jbutton.down ? "pressed" : "released")
662
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BUTTON_DOWN)
663
PRINT_JBUTTON_EVENT(event);
664
break;
665
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BUTTON_UP)
666
PRINT_JBUTTON_EVENT(event);
667
break;
668
#undef PRINT_JBUTTON_EVENT
669
670
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_BATTERY_UPDATED)
671
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d state=%u percent=%d)",
672
(uint)event->jbattery.timestamp, (int)event->jbattery.which,
673
event->jbattery.state, event->jbattery.percent);
674
break;
675
676
#define PRINT_JOYDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->jdevice.timestamp, (int)event->jdevice.which)
677
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_ADDED)
678
PRINT_JOYDEV_EVENT(event);
679
break;
680
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_REMOVED)
681
PRINT_JOYDEV_EVENT(event);
682
break;
683
SDL_EVENT_CASE(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE)
684
PRINT_JOYDEV_EVENT(event);
685
break;
686
#undef PRINT_JOYDEV_EVENT
687
688
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_AXIS_MOTION)
689
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d axis=%u value=%d)",
690
(uint)event->gaxis.timestamp, (int)event->gaxis.which,
691
(uint)event->gaxis.axis, (int)event->gaxis.value);
692
break;
693
694
#define PRINT_CBUTTON_EVENT(event) \
695
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d button=%u state=%s)", \
696
(uint)event->gbutton.timestamp, (int)event->gbutton.which, \
697
(uint)event->gbutton.button, event->gbutton.down ? "pressed" : "released")
698
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_BUTTON_DOWN)
699
PRINT_CBUTTON_EVENT(event);
700
break;
701
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_BUTTON_UP)
702
PRINT_CBUTTON_EVENT(event);
703
break;
704
#undef PRINT_CBUTTON_EVENT
705
706
#define PRINT_GAMEPADDEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d)", (uint)event->gdevice.timestamp, (int)event->gdevice.which)
707
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_ADDED)
708
PRINT_GAMEPADDEV_EVENT(event);
709
break;
710
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMOVED)
711
PRINT_GAMEPADDEV_EVENT(event);
712
break;
713
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_REMAPPED)
714
PRINT_GAMEPADDEV_EVENT(event);
715
break;
716
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE)
717
PRINT_GAMEPADDEV_EVENT(event);
718
break;
719
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED)
720
PRINT_GAMEPADDEV_EVENT(event);
721
break;
722
#undef PRINT_GAMEPADDEV_EVENT
723
724
#define PRINT_CTOUCHPAD_EVENT(event) \
725
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d touchpad=%d finger=%d x=%f y=%f pressure=%f)", \
726
(uint)event->gtouchpad.timestamp, (int)event->gtouchpad.which, \
727
(int)event->gtouchpad.touchpad, (int)event->gtouchpad.finger, \
728
event->gtouchpad.x, event->gtouchpad.y, event->gtouchpad.pressure)
729
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN)
730
PRINT_CTOUCHPAD_EVENT(event);
731
break;
732
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_UP)
733
PRINT_CTOUCHPAD_EVENT(event);
734
break;
735
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION)
736
PRINT_CTOUCHPAD_EVENT(event);
737
break;
738
#undef PRINT_CTOUCHPAD_EVENT
739
740
SDL_EVENT_CASE(SDL_EVENT_GAMEPAD_SENSOR_UPDATE)
741
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d sensor=%d data[0]=%f data[1]=%f data[2]=%f)",
742
(uint)event->gsensor.timestamp, (int)event->gsensor.which, (int)event->gsensor.sensor,
743
event->gsensor.data[0], event->gsensor.data[1], event->gsensor.data[2]);
744
break;
745
746
#define PRINT_FINGER_EVENT(event) \
747
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u touchid=%" SDL_PRIu64 " fingerid=%" SDL_PRIu64 " x=%f y=%f dx=%f dy=%f pressure=%f)", \
748
(uint)event->tfinger.timestamp, event->tfinger.touchID, \
749
event->tfinger.fingerID, event->tfinger.x, event->tfinger.y, \
750
event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
751
SDL_EVENT_CASE(SDL_EVENT_FINGER_DOWN)
752
PRINT_FINGER_EVENT(event);
753
break;
754
SDL_EVENT_CASE(SDL_EVENT_FINGER_UP)
755
PRINT_FINGER_EVENT(event);
756
break;
757
SDL_EVENT_CASE(SDL_EVENT_FINGER_CANCELED)
758
PRINT_FINGER_EVENT(event);
759
break;
760
SDL_EVENT_CASE(SDL_EVENT_FINGER_MOTION)
761
PRINT_FINGER_EVENT(event);
762
break;
763
#undef PRINT_FINGER_EVENT
764
765
#define PRINT_PTOUCH_EVENT(event) \
766
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g eraser=%s state=%s)", \
767
(uint)event->ptouch.timestamp, (uint)event->ptouch.windowID, (uint)event->ptouch.which, (uint)event->ptouch.pen_state, event->ptouch.x, event->ptouch.y, \
768
event->ptouch.eraser ? "yes" : "no", event->ptouch.down ? "down" : "up");
769
SDL_EVENT_CASE(SDL_EVENT_PEN_DOWN)
770
PRINT_PTOUCH_EVENT(event);
771
break;
772
SDL_EVENT_CASE(SDL_EVENT_PEN_UP)
773
PRINT_PTOUCH_EVENT(event);
774
break;
775
#undef PRINT_PTOUCH_EVENT
776
777
#define PRINT_PPROXIMITY_EVENT(event) \
778
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u)", \
779
(uint)event->pproximity.timestamp, (uint)event->pproximity.windowID, (uint)event->pproximity.which);
780
SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_IN)
781
PRINT_PPROXIMITY_EVENT(event);
782
break;
783
SDL_EVENT_CASE(SDL_EVENT_PEN_PROXIMITY_OUT)
784
PRINT_PPROXIMITY_EVENT(event);
785
break;
786
#undef PRINT_PPROXIMITY_EVENT
787
788
SDL_EVENT_CASE(SDL_EVENT_PEN_AXIS)
789
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g axis=%s value=%g)",
790
(uint)event->paxis.timestamp, (uint)event->paxis.windowID, (uint)event->paxis.which, (uint)event->paxis.pen_state, event->paxis.x, event->paxis.y,
791
((((int) event->paxis.axis) >= 0) && (event->paxis.axis < SDL_arraysize(pen_axisnames))) ? pen_axisnames[event->paxis.axis] : "[UNKNOWN]", event->paxis.value);
792
break;
793
794
SDL_EVENT_CASE(SDL_EVENT_PEN_MOTION)
795
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g)",
796
(uint)event->pmotion.timestamp, (uint)event->pmotion.windowID, (uint)event->pmotion.which, (uint)event->pmotion.pen_state, event->pmotion.x, event->pmotion.y);
797
break;
798
799
#define PRINT_PBUTTON_EVENT(event) \
800
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u windowid=%u which=%u pen_state=%u x=%g y=%g button=%u state=%s)", \
801
(uint)event->pbutton.timestamp, (uint)event->pbutton.windowID, (uint)event->pbutton.which, (uint)event->pbutton.pen_state, event->pbutton.x, event->pbutton.y, \
802
(uint)event->pbutton.button, event->pbutton.down ? "down" : "up");
803
SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_DOWN)
804
PRINT_PBUTTON_EVENT(event);
805
break;
806
SDL_EVENT_CASE(SDL_EVENT_PEN_BUTTON_UP)
807
PRINT_PBUTTON_EVENT(event);
808
break;
809
#undef PRINT_PBUTTON_EVENT
810
811
#define PRINT_DROP_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (data='%s' timestamp=%u windowid=%u x=%f y=%f)", event->drop.data, (uint)event->drop.timestamp, (uint)event->drop.windowID, event->drop.x, event->drop.y)
812
SDL_EVENT_CASE(SDL_EVENT_DROP_FILE)
813
PRINT_DROP_EVENT(event);
814
break;
815
SDL_EVENT_CASE(SDL_EVENT_DROP_TEXT)
816
PRINT_DROP_EVENT(event);
817
break;
818
SDL_EVENT_CASE(SDL_EVENT_DROP_BEGIN)
819
PRINT_DROP_EVENT(event);
820
break;
821
SDL_EVENT_CASE(SDL_EVENT_DROP_COMPLETE)
822
PRINT_DROP_EVENT(event);
823
break;
824
SDL_EVENT_CASE(SDL_EVENT_DROP_POSITION)
825
PRINT_DROP_EVENT(event);
826
break;
827
#undef PRINT_DROP_EVENT
828
829
#define PRINT_AUDIODEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u recording=%s)", (uint)event->adevice.timestamp, (uint)event->adevice.which, event->adevice.recording ? "true" : "false")
830
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_ADDED)
831
PRINT_AUDIODEV_EVENT(event);
832
break;
833
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_REMOVED)
834
PRINT_AUDIODEV_EVENT(event);
835
break;
836
SDL_EVENT_CASE(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED)
837
PRINT_AUDIODEV_EVENT(event);
838
break;
839
#undef PRINT_AUDIODEV_EVENT
840
841
#define PRINT_CAMERADEV_EVENT(event) (void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%u)", (uint)event->cdevice.timestamp, (uint)event->cdevice.which)
842
SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_ADDED)
843
PRINT_CAMERADEV_EVENT(event);
844
break;
845
SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_REMOVED)
846
PRINT_CAMERADEV_EVENT(event);
847
break;
848
SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_APPROVED)
849
PRINT_CAMERADEV_EVENT(event);
850
break;
851
SDL_EVENT_CASE(SDL_EVENT_CAMERA_DEVICE_DENIED)
852
PRINT_CAMERADEV_EVENT(event);
853
break;
854
#undef PRINT_CAMERADEV_EVENT
855
856
SDL_EVENT_CASE(SDL_EVENT_SENSOR_UPDATE)
857
(void)SDL_snprintf(details, sizeof(details), " (timestamp=%u which=%d data[0]=%f data[1]=%f data[2]=%f data[3]=%f data[4]=%f data[5]=%f)",
858
(uint)event->sensor.timestamp, (int)event->sensor.which,
859
event->sensor.data[0], event->sensor.data[1], event->sensor.data[2],
860
event->sensor.data[3], event->sensor.data[4], event->sensor.data[5]);
861
break;
862
863
#undef SDL_EVENT_CASE
864
865
case SDL_EVENT_POLL_SENTINEL:
866
// No logging necessary for this one
867
break;
868
869
default:
870
if (!name[0]) {
871
if (event->type >= SDL_EVENT_USER) {
872
SDL_strlcpy(name, "USER", sizeof(name));
873
} else {
874
SDL_strlcpy(name, "UNKNOWN", sizeof(name));
875
}
876
(void)SDL_snprintf(details, sizeof(details), " 0x%x", (uint)event->type);
877
}
878
break;
879
}
880
881
if (name[0]) {
882
SDL_Log("SDL EVENT: %s%s", name, details);
883
}
884
885
#undef uint
886
}
887
888
void SDL_StopEventLoop(void)
889
{
890
const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
891
int i;
892
SDL_EventEntry *entry;
893
894
SDL_LockMutex(SDL_EventQ.lock);
895
896
SDL_EventQ.active = false;
897
898
if (report && SDL_atoi(report)) {
899
SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d",
900
SDL_EventQ.max_events_seen);
901
}
902
903
// Clean out EventQ
904
for (entry = SDL_EventQ.head; entry;) {
905
SDL_EventEntry *next = entry->next;
906
SDL_TransferTemporaryMemoryFromEvent(entry);
907
SDL_free(entry);
908
entry = next;
909
}
910
for (entry = SDL_EventQ.free; entry;) {
911
SDL_EventEntry *next = entry->next;
912
SDL_free(entry);
913
entry = next;
914
}
915
916
SDL_SetAtomicInt(&SDL_EventQ.count, 0);
917
SDL_EventQ.max_events_seen = 0;
918
SDL_EventQ.head = NULL;
919
SDL_EventQ.tail = NULL;
920
SDL_EventQ.free = NULL;
921
SDL_SetAtomicInt(&SDL_sentinel_pending, 0);
922
923
// Clear disabled event state
924
for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
925
SDL_free(SDL_disabled_events[i]);
926
SDL_disabled_events[i] = NULL;
927
}
928
929
SDL_QuitEventWatchList(&SDL_event_watchers);
930
//SDL_QuitWindowEventWatch();
931
932
SDL_Mutex *lock = NULL;
933
if (SDL_EventQ.lock) {
934
lock = SDL_EventQ.lock;
935
SDL_EventQ.lock = NULL;
936
}
937
938
SDL_UnlockMutex(lock);
939
940
if (lock) {
941
SDL_DestroyMutex(lock);
942
}
943
}
944
945
// This function (and associated calls) may be called more than once
946
bool SDL_StartEventLoop(void)
947
{
948
/* We'll leave the event queue alone, since we might have gotten
949
some important events at launch (like SDL_EVENT_DROP_FILE)
950
951
FIXME: Does this introduce any other bugs with events at startup?
952
*/
953
954
// Create the lock and set ourselves active
955
#ifndef SDL_THREADS_DISABLED
956
if (!SDL_EventQ.lock) {
957
SDL_EventQ.lock = SDL_CreateMutex();
958
if (SDL_EventQ.lock == NULL) {
959
return false;
960
}
961
}
962
SDL_LockMutex(SDL_EventQ.lock);
963
964
if (!SDL_InitEventWatchList(&SDL_event_watchers)) {
965
SDL_UnlockMutex(SDL_EventQ.lock);
966
return false;
967
}
968
#endif // !SDL_THREADS_DISABLED
969
970
//SDL_InitWindowEventWatch();
971
972
SDL_EventQ.active = true;
973
974
#ifndef SDL_THREADS_DISABLED
975
SDL_UnlockMutex(SDL_EventQ.lock);
976
#endif
977
return true;
978
}
979
980
// Add an event to the event queue -- called with the queue locked
981
static int SDL_AddEvent(SDL_Event *event)
982
{
983
SDL_EventEntry *entry;
984
const int initial_count = SDL_GetAtomicInt(&SDL_EventQ.count);
985
int final_count;
986
987
if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
988
SDL_SetError("Event queue is full (%d events)", initial_count);
989
return 0;
990
}
991
992
if (SDL_EventQ.free == NULL) {
993
entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
994
if (entry == NULL) {
995
return 0;
996
}
997
} else {
998
entry = SDL_EventQ.free;
999
SDL_EventQ.free = entry->next;
1000
}
1001
1002
if (SDL_EventLoggingVerbosity > 0) {
1003
SDL_LogEvent(event);
1004
}
1005
1006
SDL_copyp(&entry->event, event);
1007
if (event->type == SDL_EVENT_POLL_SENTINEL) {
1008
SDL_AddAtomicInt(&SDL_sentinel_pending, 1);
1009
}
1010
entry->memory = NULL;
1011
SDL_TransferTemporaryMemoryToEvent(entry);
1012
1013
if (SDL_EventQ.tail) {
1014
SDL_EventQ.tail->next = entry;
1015
entry->prev = SDL_EventQ.tail;
1016
SDL_EventQ.tail = entry;
1017
entry->next = NULL;
1018
} else {
1019
SDL_assert(!SDL_EventQ.head);
1020
SDL_EventQ.head = entry;
1021
SDL_EventQ.tail = entry;
1022
entry->prev = NULL;
1023
entry->next = NULL;
1024
}
1025
1026
final_count = SDL_AddAtomicInt(&SDL_EventQ.count, 1) + 1;
1027
if (final_count > SDL_EventQ.max_events_seen) {
1028
SDL_EventQ.max_events_seen = final_count;
1029
}
1030
1031
++SDL_last_event_id;
1032
1033
return 1;
1034
}
1035
1036
// Remove an event from the queue -- called with the queue locked
1037
static void SDL_CutEvent(SDL_EventEntry *entry)
1038
{
1039
SDL_TransferTemporaryMemoryFromEvent(entry);
1040
1041
if (entry->prev) {
1042
entry->prev->next = entry->next;
1043
}
1044
if (entry->next) {
1045
entry->next->prev = entry->prev;
1046
}
1047
1048
if (entry == SDL_EventQ.head) {
1049
SDL_assert(entry->prev == NULL);
1050
SDL_EventQ.head = entry->next;
1051
}
1052
if (entry == SDL_EventQ.tail) {
1053
SDL_assert(entry->next == NULL);
1054
SDL_EventQ.tail = entry->prev;
1055
}
1056
1057
if (entry->event.type == SDL_EVENT_POLL_SENTINEL) {
1058
SDL_AddAtomicInt(&SDL_sentinel_pending, -1);
1059
}
1060
1061
entry->next = SDL_EventQ.free;
1062
SDL_EventQ.free = entry;
1063
SDL_assert(SDL_GetAtomicInt(&SDL_EventQ.count) > 0);
1064
SDL_AddAtomicInt(&SDL_EventQ.count, -1);
1065
}
1066
1067
static void SDL_SendWakeupEvent(void)
1068
{
1069
#ifdef SDL_PLATFORM_ANDROID
1070
Android_SendLifecycleEvent(SDL_ANDROID_LIFECYCLE_WAKE);
1071
#endif
1072
}
1073
1074
// Lock the event queue, take a peep at it, and unlock it
1075
static int SDL_PeepEventsInternal(SDL_Event *events, int numevents, SDL_EventAction action,
1076
Uint32 minType, Uint32 maxType, bool include_sentinel)
1077
{
1078
int i, used, sentinels_expected = 0;
1079
1080
// Lock the event queue
1081
used = 0;
1082
1083
SDL_LockMutex(SDL_EventQ.lock);
1084
{
1085
// Don't look after we've quit
1086
if (!SDL_EventQ.active) {
1087
// We get a few spurious events at shutdown, so don't warn then
1088
if (action == SDL_GETEVENT) {
1089
SDL_SetError("The event system has been shut down");
1090
}
1091
SDL_UnlockMutex(SDL_EventQ.lock);
1092
return -1;
1093
}
1094
if (action == SDL_ADDEVENT) {
1095
if (!events) {
1096
SDL_UnlockMutex(SDL_EventQ.lock);
1097
SDL_InvalidParamError("events");
1098
return -1;
1099
}
1100
for (i = 0; i < numevents; ++i) {
1101
used += SDL_AddEvent(&events[i]);
1102
}
1103
} else {
1104
SDL_EventEntry *entry, *next;
1105
Uint32 type;
1106
1107
for (entry = SDL_EventQ.head; entry && (events == NULL || used < numevents); entry = next) {
1108
next = entry->next;
1109
type = entry->event.type;
1110
if (minType <= type && type <= maxType) {
1111
if (events) {
1112
SDL_copyp(&events[used], &entry->event);
1113
1114
if (action == SDL_GETEVENT) {
1115
SDL_CutEvent(entry);
1116
}
1117
}
1118
if (type == SDL_EVENT_POLL_SENTINEL) {
1119
// Special handling for the sentinel event
1120
if (!include_sentinel) {
1121
// Skip it, we don't want to include it
1122
continue;
1123
}
1124
if (events == NULL || action != SDL_GETEVENT) {
1125
++sentinels_expected;
1126
}
1127
if (SDL_GetAtomicInt(&SDL_sentinel_pending) > sentinels_expected) {
1128
// Skip it, there's another one pending
1129
continue;
1130
}
1131
}
1132
++used;
1133
}
1134
}
1135
}
1136
}
1137
SDL_UnlockMutex(SDL_EventQ.lock);
1138
1139
if (used > 0 && action == SDL_ADDEVENT) {
1140
SDL_SendWakeupEvent();
1141
}
1142
1143
return used;
1144
}
1145
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_EventAction action,
1146
Uint32 minType, Uint32 maxType)
1147
{
1148
return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, false);
1149
}
1150
1151
bool SDL_HasEvent(Uint32 type)
1152
{
1153
return SDL_HasEvents(type, type);
1154
}
1155
1156
bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
1157
{
1158
bool found = false;
1159
1160
SDL_LockMutex(SDL_EventQ.lock);
1161
{
1162
if (SDL_EventQ.active) {
1163
for (SDL_EventEntry *entry = SDL_EventQ.head; entry; entry = entry->next) {
1164
const Uint32 type = entry->event.type;
1165
if (minType <= type && type <= maxType) {
1166
found = true;
1167
break;
1168
}
1169
}
1170
}
1171
}
1172
SDL_UnlockMutex(SDL_EventQ.lock);
1173
1174
return found;
1175
}
1176
1177
void SDL_FlushEvent(Uint32 type)
1178
{
1179
SDL_FlushEvents(type, type);
1180
}
1181
1182
void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
1183
{
1184
SDL_EventEntry *entry, *next;
1185
Uint32 type;
1186
1187
// Make sure the events are current
1188
#if 0
1189
/* Actually, we can't do this since we might be flushing while processing
1190
a resize event, and calling this might trigger further resize events.
1191
*/
1192
SDL_PumpEvents();
1193
#endif
1194
1195
// Lock the event queue
1196
SDL_LockMutex(SDL_EventQ.lock);
1197
{
1198
// Don't look after we've quit
1199
if (!SDL_EventQ.active) {
1200
SDL_UnlockMutex(SDL_EventQ.lock);
1201
return;
1202
}
1203
for (entry = SDL_EventQ.head; entry; entry = next) {
1204
next = entry->next;
1205
type = entry->event.type;
1206
if (minType <= type && type <= maxType) {
1207
SDL_CutEvent(entry);
1208
}
1209
}
1210
}
1211
SDL_UnlockMutex(SDL_EventQ.lock);
1212
}
1213
1214
typedef enum
1215
{
1216
SDL_MAIN_CALLBACK_WAITING,
1217
SDL_MAIN_CALLBACK_COMPLETE,
1218
SDL_MAIN_CALLBACK_CANCELED,
1219
} SDL_MainThreadCallbackState;
1220
1221
typedef struct SDL_MainThreadCallbackEntry
1222
{
1223
SDL_MainThreadCallback callback;
1224
void *userdata;
1225
SDL_AtomicInt state;
1226
SDL_Semaphore *semaphore;
1227
struct SDL_MainThreadCallbackEntry *next;
1228
} SDL_MainThreadCallbackEntry;
1229
1230
static SDL_Mutex *SDL_main_callbacks_lock;
1231
static SDL_MainThreadCallbackEntry *SDL_main_callbacks_head;
1232
static SDL_MainThreadCallbackEntry *SDL_main_callbacks_tail;
1233
1234
static SDL_MainThreadCallbackEntry *SDL_CreateMainThreadCallback(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1235
{
1236
SDL_MainThreadCallbackEntry *entry = (SDL_MainThreadCallbackEntry *)SDL_malloc(sizeof(*entry));
1237
if (!entry) {
1238
return NULL;
1239
}
1240
1241
entry->callback = callback;
1242
entry->userdata = userdata;
1243
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_WAITING);
1244
if (wait_complete) {
1245
entry->semaphore = SDL_CreateSemaphore(0);
1246
if (!entry->semaphore) {
1247
SDL_free(entry);
1248
return NULL;
1249
}
1250
} else {
1251
entry->semaphore = NULL;
1252
}
1253
entry->next = NULL;
1254
1255
return entry;
1256
}
1257
1258
static void SDL_DestroyMainThreadCallback(SDL_MainThreadCallbackEntry *entry)
1259
{
1260
if (entry->semaphore) {
1261
SDL_DestroySemaphore(entry->semaphore);
1262
}
1263
SDL_free(entry);
1264
}
1265
1266
static void SDL_InitMainThreadCallbacks(void)
1267
{
1268
SDL_main_callbacks_lock = SDL_CreateMutex();
1269
SDL_assert(SDL_main_callbacks_head == NULL &&
1270
SDL_main_callbacks_tail == NULL);
1271
}
1272
1273
static void SDL_QuitMainThreadCallbacks(void)
1274
{
1275
SDL_MainThreadCallbackEntry *entry;
1276
1277
SDL_LockMutex(SDL_main_callbacks_lock);
1278
{
1279
entry = SDL_main_callbacks_head;
1280
SDL_main_callbacks_head = NULL;
1281
SDL_main_callbacks_tail = NULL;
1282
}
1283
SDL_UnlockMutex(SDL_main_callbacks_lock);
1284
1285
while (entry) {
1286
SDL_MainThreadCallbackEntry *next = entry->next;
1287
1288
if (entry->semaphore) {
1289
// Let the waiting thread know this is canceled
1290
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_CANCELED);
1291
SDL_SignalSemaphore(entry->semaphore);
1292
} else {
1293
// Nobody's waiting for this, clean it up
1294
SDL_DestroyMainThreadCallback(entry);
1295
}
1296
entry = next;
1297
}
1298
1299
SDL_DestroyMutex(SDL_main_callbacks_lock);
1300
SDL_main_callbacks_lock = NULL;
1301
}
1302
1303
static void SDL_RunMainThreadCallbacks(void)
1304
{
1305
SDL_MainThreadCallbackEntry *entry;
1306
1307
SDL_LockMutex(SDL_main_callbacks_lock);
1308
{
1309
entry = SDL_main_callbacks_head;
1310
SDL_main_callbacks_head = NULL;
1311
SDL_main_callbacks_tail = NULL;
1312
}
1313
SDL_UnlockMutex(SDL_main_callbacks_lock);
1314
1315
while (entry) {
1316
SDL_MainThreadCallbackEntry *next = entry->next;
1317
1318
entry->callback(entry->userdata);
1319
1320
if (entry->semaphore) {
1321
// Let the waiting thread know this is done
1322
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_COMPLETE);
1323
SDL_SignalSemaphore(entry->semaphore);
1324
} else {
1325
// Nobody's waiting for this, clean it up
1326
SDL_DestroyMainThreadCallback(entry);
1327
}
1328
entry = next;
1329
}
1330
}
1331
1332
bool SDL_RunOnMainThread(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1333
{
1334
if (SDL_IsMainThread() || !SDL_WasInit(SDL_INIT_EVENTS)) {
1335
// No need to queue the callback
1336
callback(userdata);
1337
return true;
1338
}
1339
1340
SDL_MainThreadCallbackEntry *entry = SDL_CreateMainThreadCallback(callback, userdata, wait_complete);
1341
if (!entry) {
1342
return false;
1343
}
1344
1345
SDL_LockMutex(SDL_main_callbacks_lock);
1346
{
1347
if (SDL_main_callbacks_tail) {
1348
SDL_main_callbacks_tail->next = entry;
1349
SDL_main_callbacks_tail = entry;
1350
} else {
1351
SDL_main_callbacks_head = entry;
1352
SDL_main_callbacks_tail = entry;
1353
}
1354
}
1355
SDL_UnlockMutex(SDL_main_callbacks_lock);
1356
1357
// If the main thread is waiting for events, wake it up
1358
SDL_SendWakeupEvent();
1359
1360
if (!wait_complete) {
1361
// Queued for execution, wait not requested
1362
return true;
1363
}
1364
1365
SDL_WaitSemaphore(entry->semaphore);
1366
1367
switch (SDL_GetAtomicInt(&entry->state)) {
1368
case SDL_MAIN_CALLBACK_COMPLETE:
1369
// Execution complete!
1370
SDL_DestroyMainThreadCallback(entry);
1371
return true;
1372
1373
case SDL_MAIN_CALLBACK_CANCELED:
1374
// The callback was canceled on the main thread
1375
SDL_DestroyMainThreadCallback(entry);
1376
return SDL_SetError("Callback canceled");
1377
1378
default:
1379
// Probably hit a deadlock in the callback
1380
// We can't destroy the entry as the semaphore will be signaled
1381
// if it ever comes back, just leak it here.
1382
return SDL_SetError("Callback timed out");
1383
}
1384
}
1385
1386
void SDL_PumpEventMaintenance(void)
1387
{
1388
#ifndef SDL_AUDIO_DISABLED
1389
SDL_UpdateAudio();
1390
#endif
1391
1392
#ifndef SDL_CAMERA_DISABLED
1393
SDL_UpdateCamera();
1394
#endif
1395
1396
#ifndef SDL_SENSOR_DISABLED
1397
// Check for sensor state change
1398
if (SDL_update_sensors) {
1399
SDL_UpdateSensors();
1400
}
1401
#endif
1402
1403
#ifndef SDL_JOYSTICK_DISABLED
1404
// Check for joystick state change
1405
if (SDL_update_joysticks) {
1406
SDL_UpdateJoysticks();
1407
}
1408
#endif
1409
1410
//SDL_UpdateTrays();
1411
1412
//SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.
1413
}
1414
1415
// Run the system dependent event loops
1416
static void SDL_PumpEventsInternal(bool push_sentinel)
1417
{
1418
// Free any temporary memory from old events
1419
SDL_FreeTemporaryMemory();
1420
1421
// Release any keys held down from last frame
1422
//SDL_ReleaseAutoReleaseKeys();
1423
1424
// Run any pending main thread callbacks
1425
SDL_RunMainThreadCallbacks();
1426
1427
#ifdef SDL_PLATFORM_ANDROID
1428
// Android event processing is independent of the video subsystem
1429
Android_PumpEvents(0);
1430
#endif
1431
1432
SDL_PumpEventMaintenance();
1433
1434
if (push_sentinel && SDL_EventEnabled(SDL_EVENT_POLL_SENTINEL)) {
1435
SDL_Event sentinel;
1436
1437
// Make sure we don't already have a sentinel in the queue, and add one to the end
1438
if (SDL_GetAtomicInt(&SDL_sentinel_pending) > 0) {
1439
SDL_PeepEventsInternal(&sentinel, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1440
}
1441
1442
sentinel.type = SDL_EVENT_POLL_SENTINEL;
1443
sentinel.common.timestamp = 0;
1444
SDL_PushEvent(&sentinel);
1445
}
1446
}
1447
1448
void SDL_PumpEvents(void)
1449
{
1450
SDL_PumpEventsInternal(false);
1451
}
1452
1453
// Public functions
1454
1455
bool SDL_PollEvent(SDL_Event *event)
1456
{
1457
return SDL_WaitEventTimeoutNS(event, 0);
1458
}
1459
1460
bool SDL_WaitEvent(SDL_Event *event)
1461
{
1462
return SDL_WaitEventTimeoutNS(event, -1);
1463
}
1464
1465
bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS)
1466
{
1467
Sint64 timeoutNS;
1468
1469
if (timeoutMS > 0) {
1470
timeoutNS = SDL_MS_TO_NS(timeoutMS);
1471
} else {
1472
timeoutNS = timeoutMS;
1473
}
1474
return SDL_WaitEventTimeoutNS(event, timeoutNS);
1475
}
1476
1477
bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
1478
{
1479
Uint64 start, expiration;
1480
bool include_sentinel = (timeoutNS == 0);
1481
int result;
1482
1483
if (timeoutNS > 0) {
1484
start = SDL_GetTicksNS();
1485
expiration = start + timeoutNS;
1486
} else {
1487
start = 0;
1488
expiration = 0;
1489
}
1490
1491
// If there isn't a poll sentinel event pending, pump events and add one
1492
if (SDL_GetAtomicInt(&SDL_sentinel_pending) == 0) {
1493
SDL_PumpEventsInternal(true);
1494
}
1495
1496
// First check for existing events
1497
result = SDL_PeepEventsInternal(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, include_sentinel);
1498
if (result < 0) {
1499
return false;
1500
}
1501
if (include_sentinel) {
1502
if (event) {
1503
if (event->type == SDL_EVENT_POLL_SENTINEL) {
1504
// Reached the end of a poll cycle, and not willing to wait
1505
return false;
1506
}
1507
} else {
1508
// Need to peek the next event to check for sentinel
1509
SDL_Event dummy;
1510
1511
if (SDL_PeepEventsInternal(&dummy, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, true) &&
1512
dummy.type == SDL_EVENT_POLL_SENTINEL) {
1513
SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1514
// Reached the end of a poll cycle, and not willing to wait
1515
return false;
1516
}
1517
}
1518
}
1519
if (result == 0) {
1520
if (timeoutNS == 0) {
1521
// No events available, and not willing to wait
1522
return false;
1523
}
1524
} else {
1525
// Has existing events
1526
return true;
1527
}
1528
// We should have completely handled timeoutNS == 0 above
1529
SDL_assert(timeoutNS != 0);
1530
1531
#ifdef SDL_PLATFORM_ANDROID
1532
for (;;) {
1533
SDL_PumpEventsInternal(true);
1534
1535
if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1536
return true;
1537
}
1538
1539
Uint64 delay = -1;
1540
if (timeoutNS > 0) {
1541
Uint64 now = SDL_GetTicksNS();
1542
if (now >= expiration) {
1543
// Timeout expired and no events
1544
return false;
1545
}
1546
delay = (expiration - now);
1547
}
1548
Android_PumpEvents(delay);
1549
}
1550
#else
1551
for (;;) {
1552
SDL_PumpEventsInternal(true);
1553
1554
if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1555
return true;
1556
}
1557
1558
Uint64 delay = EVENT_POLL_INTERVAL_NS;
1559
if (timeoutNS > 0) {
1560
Uint64 now = SDL_GetTicksNS();
1561
if (now >= expiration) {
1562
// Timeout expired and no events
1563
return false;
1564
}
1565
delay = SDL_min((expiration - now), delay);
1566
}
1567
SDL_DelayNS(delay);
1568
}
1569
#endif // SDL_PLATFORM_ANDROID
1570
}
1571
1572
static bool SDL_CallEventWatchers(SDL_Event *event)
1573
{
1574
if (event->common.type == SDL_EVENT_POLL_SENTINEL) {
1575
return true;
1576
}
1577
1578
return SDL_DispatchEventWatchList(&SDL_event_watchers, event);
1579
}
1580
1581
bool SDL_PushEvent(SDL_Event *event)
1582
{
1583
if (!event->common.timestamp) {
1584
event->common.timestamp = SDL_GetTicksNS();
1585
}
1586
1587
if (!SDL_CallEventWatchers(event)) {
1588
SDL_ClearError();
1589
return false;
1590
}
1591
1592
if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
1593
return false;
1594
}
1595
1596
return true;
1597
}
1598
1599
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
1600
{
1601
SDL_EventEntry *event, *next;
1602
SDL_LockMutex(SDL_event_watchers.lock);
1603
{
1604
// Set filter and discard pending events
1605
SDL_event_watchers.filter.callback = filter;
1606
SDL_event_watchers.filter.userdata = userdata;
1607
if (filter) {
1608
// Cut all events not accepted by the filter
1609
SDL_LockMutex(SDL_EventQ.lock);
1610
{
1611
for (event = SDL_EventQ.head; event; event = next) {
1612
next = event->next;
1613
if (!filter(userdata, &event->event)) {
1614
SDL_CutEvent(event);
1615
}
1616
}
1617
}
1618
SDL_UnlockMutex(SDL_EventQ.lock);
1619
}
1620
}
1621
SDL_UnlockMutex(SDL_event_watchers.lock);
1622
}
1623
1624
bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
1625
{
1626
SDL_EventWatcher event_ok;
1627
1628
SDL_LockMutex(SDL_event_watchers.lock);
1629
{
1630
event_ok = SDL_event_watchers.filter;
1631
}
1632
SDL_UnlockMutex(SDL_event_watchers.lock);
1633
1634
if (filter) {
1635
*filter = event_ok.callback;
1636
}
1637
if (userdata) {
1638
*userdata = event_ok.userdata;
1639
}
1640
return event_ok.callback ? true : false;
1641
}
1642
1643
bool SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
1644
{
1645
return SDL_AddEventWatchList(&SDL_event_watchers, filter, userdata);
1646
}
1647
1648
void SDL_RemoveEventWatch(SDL_EventFilter filter, void *userdata)
1649
{
1650
SDL_RemoveEventWatchList(&SDL_event_watchers, filter, userdata);
1651
}
1652
1653
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
1654
{
1655
SDL_LockMutex(SDL_EventQ.lock);
1656
{
1657
SDL_EventEntry *entry, *next;
1658
for (entry = SDL_EventQ.head; entry; entry = next) {
1659
next = entry->next;
1660
if (!filter(userdata, &entry->event)) {
1661
SDL_CutEvent(entry);
1662
}
1663
}
1664
}
1665
SDL_UnlockMutex(SDL_EventQ.lock);
1666
}
1667
1668
void SDL_SetEventEnabled(Uint32 type, bool enabled)
1669
{
1670
bool current_state;
1671
Uint8 hi = ((type >> 8) & 0xff);
1672
Uint8 lo = (type & 0xff);
1673
1674
if (SDL_disabled_events[hi] &&
1675
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
1676
current_state = false;
1677
} else {
1678
current_state = true;
1679
}
1680
1681
if ((enabled != false) != current_state) {
1682
if (enabled) {
1683
SDL_assert(SDL_disabled_events[hi] != NULL);
1684
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1U << (lo & 31));
1685
1686
// Gamepad events depend on joystick events
1687
switch (type) {
1688
case SDL_EVENT_GAMEPAD_ADDED:
1689
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_ADDED, true);
1690
break;
1691
case SDL_EVENT_GAMEPAD_REMOVED:
1692
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_REMOVED, true);
1693
break;
1694
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
1695
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
1696
case SDL_EVENT_GAMEPAD_BUTTON_UP:
1697
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION, true);
1698
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION, true);
1699
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_DOWN, true);
1700
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_UP, true);
1701
break;
1702
case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
1703
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, true);
1704
break;
1705
default:
1706
break;
1707
}
1708
} else {
1709
// Disable this event type and discard pending events
1710
if (!SDL_disabled_events[hi]) {
1711
SDL_disabled_events[hi] = (SDL_DisabledEventBlock *)SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
1712
}
1713
// Out of memory, nothing we can do...
1714
if (SDL_disabled_events[hi]) {
1715
SDL_disabled_events[hi]->bits[lo / 32] |= (1U << (lo & 31));
1716
SDL_FlushEvent(type);
1717
}
1718
}
1719
1720
/* turn off drag'n'drop support if we've disabled the events.
1721
This might change some UI details at the OS level. */
1722
if (type == SDL_EVENT_DROP_FILE || type == SDL_EVENT_DROP_TEXT) {
1723
//SDL_ToggleDragAndDropSupport();
1724
}
1725
}
1726
}
1727
1728
bool SDL_EventEnabled(Uint32 type)
1729
{
1730
Uint8 hi = ((type >> 8) & 0xff);
1731
Uint8 lo = (type & 0xff);
1732
1733
if (SDL_disabled_events[hi] &&
1734
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
1735
return false;
1736
} else {
1737
return true;
1738
}
1739
}
1740
1741
Uint32 SDL_RegisterEvents(int numevents)
1742
{
1743
Uint32 event_base = 0;
1744
1745
if (numevents > 0) {
1746
int value = SDL_AddAtomicInt(&SDL_userevents, numevents);
1747
if (value >= 0 && value <= (SDL_EVENT_LAST - SDL_EVENT_USER)) {
1748
event_base = (Uint32)(SDL_EVENT_USER + value);
1749
}
1750
}
1751
return event_base;
1752
}
1753
1754
void SDL_SendAppEvent(SDL_EventType eventType)
1755
{
1756
if (SDL_EventEnabled(eventType)) {
1757
SDL_Event event;
1758
event.type = eventType;
1759
event.common.timestamp = 0;
1760
1761
switch (eventType) {
1762
case SDL_EVENT_TERMINATING:
1763
case SDL_EVENT_LOW_MEMORY:
1764
case SDL_EVENT_WILL_ENTER_BACKGROUND:
1765
case SDL_EVENT_DID_ENTER_BACKGROUND:
1766
case SDL_EVENT_WILL_ENTER_FOREGROUND:
1767
case SDL_EVENT_DID_ENTER_FOREGROUND:
1768
// We won't actually queue this event, it needs to be handled in this call stack by an event watcher
1769
if (SDL_EventLoggingVerbosity > 0) {
1770
SDL_LogEvent(&event);
1771
}
1772
SDL_CallEventWatchers(&event);
1773
break;
1774
default:
1775
SDL_PushEvent(&event);
1776
break;
1777
}
1778
}
1779
}
1780
1781
void SDL_SendKeymapChangedEvent(void)
1782
{
1783
SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED);
1784
}
1785
1786
void SDL_SendLocaleChangedEvent(void)
1787
{
1788
SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED);
1789
}
1790
1791
void SDL_SendSystemThemeChangedEvent(void)
1792
{
1793
SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED);
1794
}
1795
1796
bool SDL_InitEvents(void)
1797
{
1798
#ifdef SDL_PLATFORM_ANDROID
1799
Android_InitEvents();
1800
#endif
1801
#ifndef SDL_JOYSTICK_DISABLED
1802
SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1803
#endif
1804
#ifndef SDL_SENSOR_DISABLED
1805
SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1806
#endif
1807
SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1808
SDL_AddHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1809
SDL_InitMainThreadCallbacks();
1810
if (!SDL_StartEventLoop()) {
1811
SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1812
return false;
1813
}
1814
1815
//SDL_InitQuit();
1816
1817
return true;
1818
}
1819
1820
void SDL_QuitEvents(void)
1821
{
1822
//SDL_QuitQuit();
1823
SDL_StopEventLoop();
1824
SDL_QuitMainThreadCallbacks();
1825
SDL_RemoveHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1826
SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1827
#ifndef SDL_JOYSTICK_DISABLED
1828
SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1829
#endif
1830
#ifndef SDL_SENSOR_DISABLED
1831
SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1832
#endif
1833
#ifdef SDL_PLATFORM_ANDROID
1834
Android_QuitEvents();
1835
#endif
1836
}
1837
1838