Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/sdl/events/SDL_events.c
9903 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
return SDL_InvalidParamError("events");
1098
}
1099
for (i = 0; i < numevents; ++i) {
1100
used += SDL_AddEvent(&events[i]);
1101
}
1102
} else {
1103
SDL_EventEntry *entry, *next;
1104
Uint32 type;
1105
1106
for (entry = SDL_EventQ.head; entry && (events == NULL || used < numevents); entry = next) {
1107
next = entry->next;
1108
type = entry->event.type;
1109
if (minType <= type && type <= maxType) {
1110
if (events) {
1111
SDL_copyp(&events[used], &entry->event);
1112
1113
if (action == SDL_GETEVENT) {
1114
SDL_CutEvent(entry);
1115
}
1116
}
1117
if (type == SDL_EVENT_POLL_SENTINEL) {
1118
// Special handling for the sentinel event
1119
if (!include_sentinel) {
1120
// Skip it, we don't want to include it
1121
continue;
1122
}
1123
if (events == NULL || action != SDL_GETEVENT) {
1124
++sentinels_expected;
1125
}
1126
if (SDL_GetAtomicInt(&SDL_sentinel_pending) > sentinels_expected) {
1127
// Skip it, there's another one pending
1128
continue;
1129
}
1130
}
1131
++used;
1132
}
1133
}
1134
}
1135
}
1136
SDL_UnlockMutex(SDL_EventQ.lock);
1137
1138
if (used > 0 && action == SDL_ADDEVENT) {
1139
SDL_SendWakeupEvent();
1140
}
1141
1142
return used;
1143
}
1144
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_EventAction action,
1145
Uint32 minType, Uint32 maxType)
1146
{
1147
return SDL_PeepEventsInternal(events, numevents, action, minType, maxType, false);
1148
}
1149
1150
bool SDL_HasEvent(Uint32 type)
1151
{
1152
return SDL_HasEvents(type, type);
1153
}
1154
1155
bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
1156
{
1157
bool found = false;
1158
1159
SDL_LockMutex(SDL_EventQ.lock);
1160
{
1161
if (SDL_EventQ.active) {
1162
for (SDL_EventEntry *entry = SDL_EventQ.head; entry; entry = entry->next) {
1163
const Uint32 type = entry->event.type;
1164
if (minType <= type && type <= maxType) {
1165
found = true;
1166
break;
1167
}
1168
}
1169
}
1170
}
1171
SDL_UnlockMutex(SDL_EventQ.lock);
1172
1173
return found;
1174
}
1175
1176
void SDL_FlushEvent(Uint32 type)
1177
{
1178
SDL_FlushEvents(type, type);
1179
}
1180
1181
void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
1182
{
1183
SDL_EventEntry *entry, *next;
1184
Uint32 type;
1185
1186
// Make sure the events are current
1187
#if 0
1188
/* Actually, we can't do this since we might be flushing while processing
1189
a resize event, and calling this might trigger further resize events.
1190
*/
1191
SDL_PumpEvents();
1192
#endif
1193
1194
// Lock the event queue
1195
SDL_LockMutex(SDL_EventQ.lock);
1196
{
1197
// Don't look after we've quit
1198
if (!SDL_EventQ.active) {
1199
SDL_UnlockMutex(SDL_EventQ.lock);
1200
return;
1201
}
1202
for (entry = SDL_EventQ.head; entry; entry = next) {
1203
next = entry->next;
1204
type = entry->event.type;
1205
if (minType <= type && type <= maxType) {
1206
SDL_CutEvent(entry);
1207
}
1208
}
1209
}
1210
SDL_UnlockMutex(SDL_EventQ.lock);
1211
}
1212
1213
typedef enum
1214
{
1215
SDL_MAIN_CALLBACK_WAITING,
1216
SDL_MAIN_CALLBACK_COMPLETE,
1217
SDL_MAIN_CALLBACK_CANCELED,
1218
} SDL_MainThreadCallbackState;
1219
1220
typedef struct SDL_MainThreadCallbackEntry
1221
{
1222
SDL_MainThreadCallback callback;
1223
void *userdata;
1224
SDL_AtomicInt state;
1225
SDL_Semaphore *semaphore;
1226
struct SDL_MainThreadCallbackEntry *next;
1227
} SDL_MainThreadCallbackEntry;
1228
1229
static SDL_Mutex *SDL_main_callbacks_lock;
1230
static SDL_MainThreadCallbackEntry *SDL_main_callbacks_head;
1231
static SDL_MainThreadCallbackEntry *SDL_main_callbacks_tail;
1232
1233
static SDL_MainThreadCallbackEntry *SDL_CreateMainThreadCallback(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1234
{
1235
SDL_MainThreadCallbackEntry *entry = (SDL_MainThreadCallbackEntry *)SDL_malloc(sizeof(*entry));
1236
if (!entry) {
1237
return NULL;
1238
}
1239
1240
entry->callback = callback;
1241
entry->userdata = userdata;
1242
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_WAITING);
1243
if (wait_complete) {
1244
entry->semaphore = SDL_CreateSemaphore(0);
1245
if (!entry->semaphore) {
1246
SDL_free(entry);
1247
return NULL;
1248
}
1249
} else {
1250
entry->semaphore = NULL;
1251
}
1252
entry->next = NULL;
1253
1254
return entry;
1255
}
1256
1257
static void SDL_DestroyMainThreadCallback(SDL_MainThreadCallbackEntry *entry)
1258
{
1259
if (entry->semaphore) {
1260
SDL_DestroySemaphore(entry->semaphore);
1261
}
1262
SDL_free(entry);
1263
}
1264
1265
static void SDL_InitMainThreadCallbacks(void)
1266
{
1267
SDL_main_callbacks_lock = SDL_CreateMutex();
1268
SDL_assert(SDL_main_callbacks_head == NULL &&
1269
SDL_main_callbacks_tail == NULL);
1270
}
1271
1272
static void SDL_QuitMainThreadCallbacks(void)
1273
{
1274
SDL_MainThreadCallbackEntry *entry;
1275
1276
SDL_LockMutex(SDL_main_callbacks_lock);
1277
{
1278
entry = SDL_main_callbacks_head;
1279
SDL_main_callbacks_head = NULL;
1280
SDL_main_callbacks_tail = NULL;
1281
}
1282
SDL_UnlockMutex(SDL_main_callbacks_lock);
1283
1284
while (entry) {
1285
SDL_MainThreadCallbackEntry *next = entry->next;
1286
1287
if (entry->semaphore) {
1288
// Let the waiting thread know this is canceled
1289
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_CANCELED);
1290
SDL_SignalSemaphore(entry->semaphore);
1291
} else {
1292
// Nobody's waiting for this, clean it up
1293
SDL_DestroyMainThreadCallback(entry);
1294
}
1295
entry = next;
1296
}
1297
1298
SDL_DestroyMutex(SDL_main_callbacks_lock);
1299
SDL_main_callbacks_lock = NULL;
1300
}
1301
1302
static void SDL_RunMainThreadCallbacks(void)
1303
{
1304
SDL_MainThreadCallbackEntry *entry;
1305
1306
SDL_LockMutex(SDL_main_callbacks_lock);
1307
{
1308
entry = SDL_main_callbacks_head;
1309
SDL_main_callbacks_head = NULL;
1310
SDL_main_callbacks_tail = NULL;
1311
}
1312
SDL_UnlockMutex(SDL_main_callbacks_lock);
1313
1314
while (entry) {
1315
SDL_MainThreadCallbackEntry *next = entry->next;
1316
1317
entry->callback(entry->userdata);
1318
1319
if (entry->semaphore) {
1320
// Let the waiting thread know this is done
1321
SDL_SetAtomicInt(&entry->state, SDL_MAIN_CALLBACK_COMPLETE);
1322
SDL_SignalSemaphore(entry->semaphore);
1323
} else {
1324
// Nobody's waiting for this, clean it up
1325
SDL_DestroyMainThreadCallback(entry);
1326
}
1327
entry = next;
1328
}
1329
}
1330
1331
bool SDL_RunOnMainThread(SDL_MainThreadCallback callback, void *userdata, bool wait_complete)
1332
{
1333
if (SDL_IsMainThread() || !SDL_WasInit(SDL_INIT_EVENTS)) {
1334
// No need to queue the callback
1335
callback(userdata);
1336
return true;
1337
}
1338
1339
SDL_MainThreadCallbackEntry *entry = SDL_CreateMainThreadCallback(callback, userdata, wait_complete);
1340
if (!entry) {
1341
return false;
1342
}
1343
1344
SDL_LockMutex(SDL_main_callbacks_lock);
1345
{
1346
if (SDL_main_callbacks_tail) {
1347
SDL_main_callbacks_tail->next = entry;
1348
SDL_main_callbacks_tail = entry;
1349
} else {
1350
SDL_main_callbacks_head = entry;
1351
SDL_main_callbacks_tail = entry;
1352
}
1353
}
1354
SDL_UnlockMutex(SDL_main_callbacks_lock);
1355
1356
// If the main thread is waiting for events, wake it up
1357
SDL_SendWakeupEvent();
1358
1359
if (!wait_complete) {
1360
// Queued for execution, wait not requested
1361
return true;
1362
}
1363
1364
SDL_WaitSemaphore(entry->semaphore);
1365
1366
switch (SDL_GetAtomicInt(&entry->state)) {
1367
case SDL_MAIN_CALLBACK_COMPLETE:
1368
// Execution complete!
1369
SDL_DestroyMainThreadCallback(entry);
1370
return true;
1371
1372
case SDL_MAIN_CALLBACK_CANCELED:
1373
// The callback was canceled on the main thread
1374
SDL_DestroyMainThreadCallback(entry);
1375
return SDL_SetError("Callback canceled");
1376
1377
default:
1378
// Probably hit a deadlock in the callback
1379
// We can't destroy the entry as the semaphore will be signaled
1380
// if it ever comes back, just leak it here.
1381
return SDL_SetError("Callback timed out");
1382
}
1383
}
1384
1385
void SDL_PumpEventMaintenance(void)
1386
{
1387
#ifndef SDL_AUDIO_DISABLED
1388
SDL_UpdateAudio();
1389
#endif
1390
1391
#ifndef SDL_CAMERA_DISABLED
1392
SDL_UpdateCamera();
1393
#endif
1394
1395
#ifndef SDL_SENSOR_DISABLED
1396
// Check for sensor state change
1397
if (SDL_update_sensors) {
1398
SDL_UpdateSensors();
1399
}
1400
#endif
1401
1402
#ifndef SDL_JOYSTICK_DISABLED
1403
// Check for joystick state change
1404
if (SDL_update_joysticks) {
1405
SDL_UpdateJoysticks();
1406
}
1407
#endif
1408
1409
//SDL_UpdateTrays();
1410
1411
//SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.
1412
}
1413
1414
// Run the system dependent event loops
1415
static void SDL_PumpEventsInternal(bool push_sentinel)
1416
{
1417
// Free any temporary memory from old events
1418
SDL_FreeTemporaryMemory();
1419
1420
// Release any keys held down from last frame
1421
//SDL_ReleaseAutoReleaseKeys();
1422
1423
// Run any pending main thread callbacks
1424
SDL_RunMainThreadCallbacks();
1425
1426
#ifdef SDL_PLATFORM_ANDROID
1427
// Android event processing is independent of the video subsystem
1428
Android_PumpEvents(0);
1429
#endif
1430
1431
SDL_PumpEventMaintenance();
1432
1433
if (push_sentinel && SDL_EventEnabled(SDL_EVENT_POLL_SENTINEL)) {
1434
SDL_Event sentinel;
1435
1436
// Make sure we don't already have a sentinel in the queue, and add one to the end
1437
if (SDL_GetAtomicInt(&SDL_sentinel_pending) > 0) {
1438
SDL_PeepEventsInternal(&sentinel, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1439
}
1440
1441
sentinel.type = SDL_EVENT_POLL_SENTINEL;
1442
sentinel.common.timestamp = 0;
1443
SDL_PushEvent(&sentinel);
1444
}
1445
}
1446
1447
void SDL_PumpEvents(void)
1448
{
1449
SDL_PumpEventsInternal(false);
1450
}
1451
1452
// Public functions
1453
1454
bool SDL_PollEvent(SDL_Event *event)
1455
{
1456
return SDL_WaitEventTimeoutNS(event, 0);
1457
}
1458
1459
bool SDL_WaitEvent(SDL_Event *event)
1460
{
1461
return SDL_WaitEventTimeoutNS(event, -1);
1462
}
1463
1464
bool SDL_WaitEventTimeout(SDL_Event *event, Sint32 timeoutMS)
1465
{
1466
Sint64 timeoutNS;
1467
1468
if (timeoutMS > 0) {
1469
timeoutNS = SDL_MS_TO_NS(timeoutMS);
1470
} else {
1471
timeoutNS = timeoutMS;
1472
}
1473
return SDL_WaitEventTimeoutNS(event, timeoutNS);
1474
}
1475
1476
bool SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS)
1477
{
1478
Uint64 start, expiration;
1479
bool include_sentinel = (timeoutNS == 0);
1480
int result;
1481
1482
if (timeoutNS > 0) {
1483
start = SDL_GetTicksNS();
1484
expiration = start + timeoutNS;
1485
} else {
1486
start = 0;
1487
expiration = 0;
1488
}
1489
1490
// If there isn't a poll sentinel event pending, pump events and add one
1491
if (SDL_GetAtomicInt(&SDL_sentinel_pending) == 0) {
1492
SDL_PumpEventsInternal(true);
1493
}
1494
1495
// First check for existing events
1496
result = SDL_PeepEventsInternal(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, include_sentinel);
1497
if (result < 0) {
1498
return false;
1499
}
1500
if (include_sentinel) {
1501
if (event) {
1502
if (event->type == SDL_EVENT_POLL_SENTINEL) {
1503
// Reached the end of a poll cycle, and not willing to wait
1504
return false;
1505
}
1506
} else {
1507
// Need to peek the next event to check for sentinel
1508
SDL_Event dummy;
1509
1510
if (SDL_PeepEventsInternal(&dummy, 1, SDL_PEEKEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST, true) &&
1511
dummy.type == SDL_EVENT_POLL_SENTINEL) {
1512
SDL_PeepEventsInternal(&dummy, 1, SDL_GETEVENT, SDL_EVENT_POLL_SENTINEL, SDL_EVENT_POLL_SENTINEL, true);
1513
// Reached the end of a poll cycle, and not willing to wait
1514
return false;
1515
}
1516
}
1517
}
1518
if (result == 0) {
1519
if (timeoutNS == 0) {
1520
// No events available, and not willing to wait
1521
return false;
1522
}
1523
} else {
1524
// Has existing events
1525
return true;
1526
}
1527
// We should have completely handled timeoutNS == 0 above
1528
SDL_assert(timeoutNS != 0);
1529
1530
#ifdef SDL_PLATFORM_ANDROID
1531
for (;;) {
1532
if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1533
return true;
1534
}
1535
1536
Uint64 delay = -1;
1537
if (timeoutNS > 0) {
1538
Uint64 now = SDL_GetTicksNS();
1539
if (now >= expiration) {
1540
// Timeout expired and no events
1541
return false;
1542
}
1543
delay = (expiration - now);
1544
}
1545
Android_PumpEvents(delay);
1546
}
1547
#else
1548
for (;;) {
1549
SDL_PumpEventsInternal(true);
1550
1551
if (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST) > 0) {
1552
return true;
1553
}
1554
1555
Uint64 delay = EVENT_POLL_INTERVAL_NS;
1556
if (timeoutNS > 0) {
1557
Uint64 now = SDL_GetTicksNS();
1558
if (now >= expiration) {
1559
// Timeout expired and no events
1560
return false;
1561
}
1562
delay = SDL_min((expiration - now), delay);
1563
}
1564
SDL_DelayNS(delay);
1565
}
1566
#endif // SDL_PLATFORM_ANDROID
1567
}
1568
1569
static bool SDL_CallEventWatchers(SDL_Event *event)
1570
{
1571
if (event->common.type == SDL_EVENT_POLL_SENTINEL) {
1572
return true;
1573
}
1574
1575
return SDL_DispatchEventWatchList(&SDL_event_watchers, event);
1576
}
1577
1578
bool SDL_PushEvent(SDL_Event *event)
1579
{
1580
if (!event->common.timestamp) {
1581
event->common.timestamp = SDL_GetTicksNS();
1582
}
1583
1584
if (!SDL_CallEventWatchers(event)) {
1585
SDL_ClearError();
1586
return false;
1587
}
1588
1589
if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
1590
return false;
1591
}
1592
1593
return true;
1594
}
1595
1596
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
1597
{
1598
SDL_EventEntry *event, *next;
1599
SDL_LockMutex(SDL_event_watchers.lock);
1600
{
1601
// Set filter and discard pending events
1602
SDL_event_watchers.filter.callback = filter;
1603
SDL_event_watchers.filter.userdata = userdata;
1604
if (filter) {
1605
// Cut all events not accepted by the filter
1606
SDL_LockMutex(SDL_EventQ.lock);
1607
{
1608
for (event = SDL_EventQ.head; event; event = next) {
1609
next = event->next;
1610
if (!filter(userdata, &event->event)) {
1611
SDL_CutEvent(event);
1612
}
1613
}
1614
}
1615
SDL_UnlockMutex(SDL_EventQ.lock);
1616
}
1617
}
1618
SDL_UnlockMutex(SDL_event_watchers.lock);
1619
}
1620
1621
bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
1622
{
1623
SDL_EventWatcher event_ok;
1624
1625
SDL_LockMutex(SDL_event_watchers.lock);
1626
{
1627
event_ok = SDL_event_watchers.filter;
1628
}
1629
SDL_UnlockMutex(SDL_event_watchers.lock);
1630
1631
if (filter) {
1632
*filter = event_ok.callback;
1633
}
1634
if (userdata) {
1635
*userdata = event_ok.userdata;
1636
}
1637
return event_ok.callback ? true : false;
1638
}
1639
1640
bool SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
1641
{
1642
return SDL_AddEventWatchList(&SDL_event_watchers, filter, userdata);
1643
}
1644
1645
void SDL_RemoveEventWatch(SDL_EventFilter filter, void *userdata)
1646
{
1647
SDL_RemoveEventWatchList(&SDL_event_watchers, filter, userdata);
1648
}
1649
1650
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
1651
{
1652
SDL_LockMutex(SDL_EventQ.lock);
1653
{
1654
SDL_EventEntry *entry, *next;
1655
for (entry = SDL_EventQ.head; entry; entry = next) {
1656
next = entry->next;
1657
if (!filter(userdata, &entry->event)) {
1658
SDL_CutEvent(entry);
1659
}
1660
}
1661
}
1662
SDL_UnlockMutex(SDL_EventQ.lock);
1663
}
1664
1665
void SDL_SetEventEnabled(Uint32 type, bool enabled)
1666
{
1667
bool current_state;
1668
Uint8 hi = ((type >> 8) & 0xff);
1669
Uint8 lo = (type & 0xff);
1670
1671
if (SDL_disabled_events[hi] &&
1672
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
1673
current_state = false;
1674
} else {
1675
current_state = true;
1676
}
1677
1678
if ((enabled != false) != current_state) {
1679
if (enabled) {
1680
SDL_assert(SDL_disabled_events[hi] != NULL);
1681
SDL_disabled_events[hi]->bits[lo / 32] &= ~(1U << (lo & 31));
1682
1683
// Gamepad events depend on joystick events
1684
switch (type) {
1685
case SDL_EVENT_GAMEPAD_ADDED:
1686
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_ADDED, true);
1687
break;
1688
case SDL_EVENT_GAMEPAD_REMOVED:
1689
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_REMOVED, true);
1690
break;
1691
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
1692
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
1693
case SDL_EVENT_GAMEPAD_BUTTON_UP:
1694
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_AXIS_MOTION, true);
1695
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_HAT_MOTION, true);
1696
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_DOWN, true);
1697
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_BUTTON_UP, true);
1698
break;
1699
case SDL_EVENT_GAMEPAD_UPDATE_COMPLETE:
1700
SDL_SetEventEnabled(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, true);
1701
break;
1702
default:
1703
break;
1704
}
1705
} else {
1706
// Disable this event type and discard pending events
1707
if (!SDL_disabled_events[hi]) {
1708
SDL_disabled_events[hi] = (SDL_DisabledEventBlock *)SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
1709
}
1710
// Out of memory, nothing we can do...
1711
if (SDL_disabled_events[hi]) {
1712
SDL_disabled_events[hi]->bits[lo / 32] |= (1U << (lo & 31));
1713
SDL_FlushEvent(type);
1714
}
1715
}
1716
1717
/* turn off drag'n'drop support if we've disabled the events.
1718
This might change some UI details at the OS level. */
1719
if (type == SDL_EVENT_DROP_FILE || type == SDL_EVENT_DROP_TEXT) {
1720
//SDL_ToggleDragAndDropSupport();
1721
}
1722
}
1723
}
1724
1725
bool SDL_EventEnabled(Uint32 type)
1726
{
1727
Uint8 hi = ((type >> 8) & 0xff);
1728
Uint8 lo = (type & 0xff);
1729
1730
if (SDL_disabled_events[hi] &&
1731
(SDL_disabled_events[hi]->bits[lo / 32] & (1U << (lo & 31)))) {
1732
return false;
1733
} else {
1734
return true;
1735
}
1736
}
1737
1738
Uint32 SDL_RegisterEvents(int numevents)
1739
{
1740
Uint32 event_base = 0;
1741
1742
if (numevents > 0) {
1743
int value = SDL_AddAtomicInt(&SDL_userevents, numevents);
1744
if (value >= 0 && value <= (SDL_EVENT_LAST - SDL_EVENT_USER)) {
1745
event_base = (Uint32)(SDL_EVENT_USER + value);
1746
}
1747
}
1748
return event_base;
1749
}
1750
1751
void SDL_SendAppEvent(SDL_EventType eventType)
1752
{
1753
if (SDL_EventEnabled(eventType)) {
1754
SDL_Event event;
1755
event.type = eventType;
1756
event.common.timestamp = 0;
1757
1758
switch (eventType) {
1759
case SDL_EVENT_TERMINATING:
1760
case SDL_EVENT_LOW_MEMORY:
1761
case SDL_EVENT_WILL_ENTER_BACKGROUND:
1762
case SDL_EVENT_DID_ENTER_BACKGROUND:
1763
case SDL_EVENT_WILL_ENTER_FOREGROUND:
1764
case SDL_EVENT_DID_ENTER_FOREGROUND:
1765
// We won't actually queue this event, it needs to be handled in this call stack by an event watcher
1766
if (SDL_EventLoggingVerbosity > 0) {
1767
SDL_LogEvent(&event);
1768
}
1769
SDL_CallEventWatchers(&event);
1770
break;
1771
default:
1772
SDL_PushEvent(&event);
1773
break;
1774
}
1775
}
1776
}
1777
1778
void SDL_SendKeymapChangedEvent(void)
1779
{
1780
SDL_SendAppEvent(SDL_EVENT_KEYMAP_CHANGED);
1781
}
1782
1783
void SDL_SendLocaleChangedEvent(void)
1784
{
1785
SDL_SendAppEvent(SDL_EVENT_LOCALE_CHANGED);
1786
}
1787
1788
void SDL_SendSystemThemeChangedEvent(void)
1789
{
1790
SDL_SendAppEvent(SDL_EVENT_SYSTEM_THEME_CHANGED);
1791
}
1792
1793
bool SDL_InitEvents(void)
1794
{
1795
#ifdef SDL_PLATFORM_ANDROID
1796
Android_InitEvents();
1797
#endif
1798
#ifndef SDL_JOYSTICK_DISABLED
1799
SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1800
#endif
1801
#ifndef SDL_SENSOR_DISABLED
1802
SDL_AddHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1803
#endif
1804
SDL_AddHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1805
SDL_AddHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1806
SDL_InitMainThreadCallbacks();
1807
if (!SDL_StartEventLoop()) {
1808
SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1809
return false;
1810
}
1811
1812
//SDL_InitQuit();
1813
1814
return true;
1815
}
1816
1817
void SDL_QuitEvents(void)
1818
{
1819
//SDL_QuitQuit();
1820
SDL_StopEventLoop();
1821
SDL_QuitMainThreadCallbacks();
1822
SDL_RemoveHintCallback(SDL_HINT_POLL_SENTINEL, SDL_PollSentinelChanged, NULL);
1823
SDL_RemoveHintCallback(SDL_HINT_EVENT_LOGGING, SDL_EventLoggingChanged, NULL);
1824
#ifndef SDL_JOYSTICK_DISABLED
1825
SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_JOYSTICKS, SDL_AutoUpdateJoysticksChanged, NULL);
1826
#endif
1827
#ifndef SDL_SENSOR_DISABLED
1828
SDL_RemoveHintCallback(SDL_HINT_AUTO_UPDATE_SENSORS, SDL_AutoUpdateSensorsChanged, NULL);
1829
#endif
1830
#ifdef SDL_PLATFORM_ANDROID
1831
Android_QuitEvents();
1832
#endif
1833
}
1834
1835