SDL 2.0
SDL_events.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
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.h"
26#include "SDL_events.h"
27#include "SDL_thread.h"
28#include "SDL_events_c.h"
29#include "../timer/SDL_timer_c.h"
30#if !SDL_JOYSTICK_DISABLED
31#include "../joystick/SDL_joystick_c.h"
32#endif
33#include "../video/SDL_sysvideo.h"
34#include "SDL_syswm.h"
35
36/* An arbitrary limit so we don't have unbounded growth */
37#define SDL_MAX_QUEUED_EVENTS 65535
38
39typedef struct SDL_EventWatcher {
41 void *userdata;
44
51
52typedef struct {
55
58
59/* Private data -- event queue */
60typedef struct _SDL_EventEntry
61{
64 struct _SDL_EventEntry *prev;
65 struct _SDL_EventEntry *next;
67
68typedef struct _SDL_SysWMEntry
69{
71 struct _SDL_SysWMEntry *next;
73
74static struct
75{
85} SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
86
87
88/* 0 (default) means no logging, 1 means logging, 2 means logging with mouse and finger motion */
89static int SDL_DoEventLogging = 0;
90
91static void SDLCALL
92SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
93{
94 SDL_DoEventLogging = (hint && *hint) ? SDL_max(SDL_min(SDL_atoi(hint), 2), 0) : 0;
95}
96
97static void
99{
100 char name[32];
101 char details[128];
102
103 /* mouse/finger motion are spammy, ignore these if they aren't demanded. */
104 if ( (SDL_DoEventLogging < 2) &&
105 ( (event->type == SDL_MOUSEMOTION) ||
106 (event->type == SDL_FINGERMOTION) ) ) {
107 return;
108 }
109
110 /* this is to make SDL_snprintf() calls cleaner. */
111 #define uint unsigned int
112
113 name[0] = '\0';
114 details[0] = '\0';
115
116 /* !!! FIXME: This code is kinda ugly, sorry. */
117
118 if ((event->type >= SDL_USEREVENT) && (event->type <= SDL_LASTEVENT)) {
119 char plusstr[16];
120 SDL_strlcpy(name, "SDL_USEREVENT", sizeof (name));
121 if (event->type > SDL_USEREVENT) {
122 SDL_snprintf(plusstr, sizeof (plusstr), "+%u", ((uint) event->type) - SDL_USEREVENT);
123 } else {
124 plusstr[0] = '\0';
125 }
126 SDL_snprintf(details, sizeof (details), "%s (timestamp=%u windowid=%u code=%d data1=%p data2=%p)",
127 plusstr, (uint) event->user.timestamp, (uint) event->user.windowID,
128 (int) event->user.code, event->user.data1, event->user.data2);
129 }
130
131 switch (event->type) {
132 #define SDL_EVENT_CASE(x) case x: SDL_strlcpy(name, #x, sizeof (name));
133 SDL_EVENT_CASE(SDL_FIRSTEVENT) SDL_strlcpy(details, " (THIS IS PROBABLY A BUG!)", sizeof (details)); break;
134 SDL_EVENT_CASE(SDL_QUIT) SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->quit.timestamp); break;
145
147 char name2[64];
148 switch(event->window.event) {
149 case SDL_WINDOWEVENT_NONE: SDL_strlcpy(name2, "SDL_WINDOWEVENT_NONE (THIS IS PROBABLY A BUG!)", sizeof (name2)); break;
150 #define SDL_WINDOWEVENT_CASE(x) case x: SDL_strlcpy(name2, #x, sizeof (name2)); break
167 #undef SDL_WINDOWEVENT_CASE
168 default: SDL_strlcpy(name2, "UNKNOWN (bug? fixme?)", sizeof (name2)); break;
169 }
170 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u event=%s data1=%d data2=%d)",
171 (uint) event->window.timestamp, (uint) event->window.windowID, name2, (int) event->window.data1, (int) event->window.data2);
172 break;
173 }
174
176 /* !!! FIXME: we don't delve further at the moment. */
177 SDL_snprintf(details, sizeof (details), " (timestamp=%u)", (uint) event->syswm.timestamp);
178 break;
179
180 #define PRINT_KEY_EVENT(event) \
181 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \
182 (uint) event->key.timestamp, (uint) event->key.windowID, \
183 event->key.state == SDL_PRESSED ? "pressed" : "released", \
184 event->key.repeat ? "true" : "false", \
185 (uint) event->key.keysym.scancode, \
186 (uint) event->key.keysym.sym, \
187 (uint) event->key.keysym.mod)
190 #undef PRINT_KEY_EVENT
191
193 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s' start=%d length=%d)",
194 (uint) event->edit.timestamp, (uint) event->edit.windowID,
195 event->edit.text, (int) event->edit.start, (int) event->edit.length);
196 break;
197
199 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u text='%s')", (uint) event->text.timestamp, (uint) event->text.windowID, event->text.text);
200 break;
201
202
204 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u state=%u x=%d y=%d xrel=%d yrel=%d)",
205 (uint) event->motion.timestamp, (uint) event->motion.windowID,
206 (uint) event->motion.which, (uint) event->motion.state,
207 (int) event->motion.x, (int) event->motion.y,
208 (int) event->motion.xrel, (int) event->motion.yrel);
209 break;
210
211 #define PRINT_MBUTTON_EVENT(event) \
212 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%d y=%d)", \
213 (uint) event->button.timestamp, (uint) event->button.windowID, \
214 (uint) event->button.which, (uint) event->button.button, \
215 event->button.state == SDL_PRESSED ? "pressed" : "released", \
216 (uint) event->button.clicks, (int) event->button.x, (int) event->button.y)
219 #undef PRINT_MBUTTON_EVENT
220
221
223 SDL_snprintf(details, sizeof (details), " (timestamp=%u windowid=%u which=%u x=%d y=%d direction=%s)",
224 (uint) event->wheel.timestamp, (uint) event->wheel.windowID,
225 (uint) event->wheel.which, (int) event->wheel.x, (int) event->wheel.y,
226 event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
227 break;
228
230 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)",
231 (uint) event->jaxis.timestamp, (int) event->jaxis.which,
232 (uint) event->jaxis.axis, (int) event->jaxis.value);
233 break;
234
236 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d ball=%u xrel=%d yrel=%d)",
237 (uint) event->jball.timestamp, (int) event->jball.which,
238 (uint) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel);
239 break;
240
242 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d hat=%u value=%u)",
243 (uint) event->jhat.timestamp, (int) event->jhat.which,
244 (uint) event->jhat.hat, (uint) event->jhat.value);
245 break;
246
247 #define PRINT_JBUTTON_EVENT(event) \
248 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \
249 (uint) event->jbutton.timestamp, (int) event->jbutton.which, \
250 (uint) event->jbutton.button, event->jbutton.state == SDL_PRESSED ? "pressed" : "released")
253 #undef PRINT_JBUTTON_EVENT
254
255 #define PRINT_JOYDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->jdevice.timestamp, (int) event->jdevice.which)
258 #undef PRINT_JOYDEV_EVENT
259
261 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d axis=%u value=%d)",
262 (uint) event->caxis.timestamp, (int) event->caxis.which,
263 (uint) event->caxis.axis, (int) event->caxis.value);
264 break;
265
266 #define PRINT_CBUTTON_EVENT(event) \
267 SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d button=%u state=%s)", \
268 (uint) event->cbutton.timestamp, (int) event->cbutton.which, \
269 (uint) event->cbutton.button, event->cbutton.state == SDL_PRESSED ? "pressed" : "released")
272 #undef PRINT_CBUTTON_EVENT
273
274 #define PRINT_CONTROLLERDEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%d)", (uint) event->cdevice.timestamp, (int) event->cdevice.which)
278 #undef PRINT_CONTROLLERDEV_EVENT
279
280 #define PRINT_FINGER_EVENT(event) \
281 SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" fingerid=%"SDL_PRIs64" x=%f y=%f dx=%f dy=%f pressure=%f)", \
282 (uint) event->tfinger.timestamp, event->tfinger.touchId, \
283 event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \
284 event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
288 #undef PRINT_FINGER_EVENT
289
290 #define PRINT_DOLLAR_EVENT(event) \
291 SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" gestureid=%"SDL_PRIs64" numfingers=%u error=%f x=%f y=%f)", \
292 (uint) event->dgesture.timestamp, event->dgesture.touchId, \
293 event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
294 event->dgesture.error, event->dgesture.x, event->dgesture.y);
297 #undef PRINT_DOLLAR_EVENT
298
300 SDL_snprintf(details, sizeof (details), " (timestamp=%u touchid=%"SDL_PRIs64" dtheta=%f ddist=%f x=%f y=%f numfingers=%u)",
301 (uint) event->mgesture.timestamp, event->mgesture.touchId,
302 event->mgesture.dTheta, event->mgesture.dDist,
303 event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers);
304 break;
305
306 #define PRINT_DROP_EVENT(event) SDL_snprintf(details, sizeof (details), " (file='%s' timestamp=%u windowid=%u)", event->drop.file, (uint) event->drop.timestamp, (uint) event->drop.windowID)
311 #undef PRINT_DROP_EVENT
312
313 #define PRINT_AUDIODEV_EVENT(event) SDL_snprintf(details, sizeof (details), " (timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false");
316 #undef PRINT_AUDIODEV_EVENT
317
318 #undef SDL_EVENT_CASE
319
320 default:
321 if (!name[0]) {
322 SDL_strlcpy(name, "UNKNOWN", sizeof (name));
323 SDL_snprintf(details, sizeof (details), " #%u! (Bug? FIXME?)", (uint) event->type);
324 }
325 break;
326 }
327
328 if (name[0]) {
329 SDL_Log("SDL EVENT: %s%s", name, details);
330 }
331
332 #undef uint
333}
334
335
336
337/* Public functions */
338
339void
341{
342 const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
343 int i;
344 SDL_EventEntry *entry;
345 SDL_SysWMEntry *wmmsg;
346
347 if (SDL_EventQ.lock) {
349 }
350
351 SDL_AtomicSet(&SDL_EventQ.active, 0);
352
353 if (report && SDL_atoi(report)) {
354 SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
355 SDL_EventQ.max_events_seen);
356 }
357
358 /* Clean out EventQ */
359 for (entry = SDL_EventQ.head; entry; ) {
360 SDL_EventEntry *next = entry->next;
361 SDL_free(entry);
362 entry = next;
363 }
364 for (entry = SDL_EventQ.free; entry; ) {
365 SDL_EventEntry *next = entry->next;
366 SDL_free(entry);
367 entry = next;
368 }
369 for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; ) {
370 SDL_SysWMEntry *next = wmmsg->next;
371 SDL_free(wmmsg);
372 wmmsg = next;
373 }
374 for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg; ) {
375 SDL_SysWMEntry *next = wmmsg->next;
376 SDL_free(wmmsg);
377 wmmsg = next;
378 }
379
380 SDL_AtomicSet(&SDL_EventQ.count, 0);
381 SDL_EventQ.max_events_seen = 0;
382 SDL_EventQ.head = NULL;
383 SDL_EventQ.tail = NULL;
384 SDL_EventQ.free = NULL;
385 SDL_EventQ.wmmsg_used = NULL;
386 SDL_EventQ.wmmsg_free = NULL;
387
388 /* Clear disabled event state */
389 for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
392 }
393
397 }
398 if (SDL_event_watchers) {
402 }
404
405 if (SDL_EventQ.lock) {
408 SDL_EventQ.lock = NULL;
409 }
410}
411
412/* This function (and associated calls) may be called more than once */
413int
415{
416 /* We'll leave the event queue alone, since we might have gotten
417 some important events at launch (like SDL_DROPFILE)
418
419 FIXME: Does this introduce any other bugs with events at startup?
420 */
421
422 /* Create the lock and set ourselves active */
423#if !SDL_THREADS_DISABLED
424 if (!SDL_EventQ.lock) {
426 if (SDL_EventQ.lock == NULL) {
427 return -1;
428 }
429 }
430
434 return -1;
435 }
436 }
437#endif /* !SDL_THREADS_DISABLED */
438
439 /* Process most event types */
443#if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */
446#endif
447
448 SDL_AtomicSet(&SDL_EventQ.active, 1);
449
450 return 0;
451}
452
453
454/* Add an event to the event queue -- called with the queue locked */
455static int
457{
458 SDL_EventEntry *entry;
459 const int initial_count = SDL_AtomicGet(&SDL_EventQ.count);
460 int final_count;
461
462 if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
463 SDL_SetError("Event queue is full (%d events)", initial_count);
464 return 0;
465 }
466
467 if (SDL_EventQ.free == NULL) {
468 entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
469 if (!entry) {
470 return 0;
471 }
472 } else {
473 entry = SDL_EventQ.free;
474 SDL_EventQ.free = entry->next;
475 }
476
477 if (SDL_DoEventLogging) {
479 }
480
481 entry->event = *event;
482 if (event->type == SDL_SYSWMEVENT) {
483 entry->msg = *event->syswm.msg;
484 entry->event.syswm.msg = &entry->msg;
485 }
486
487 if (SDL_EventQ.tail) {
488 SDL_EventQ.tail->next = entry;
489 entry->prev = SDL_EventQ.tail;
490 SDL_EventQ.tail = entry;
491 entry->next = NULL;
492 } else {
493 SDL_assert(!SDL_EventQ.head);
494 SDL_EventQ.head = entry;
495 SDL_EventQ.tail = entry;
496 entry->prev = NULL;
497 entry->next = NULL;
498 }
499
500 final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1;
501 if (final_count > SDL_EventQ.max_events_seen) {
502 SDL_EventQ.max_events_seen = final_count;
503 }
504
505 return 1;
506}
507
508/* Remove an event from the queue -- called with the queue locked */
509static void
511{
512 if (entry->prev) {
513 entry->prev->next = entry->next;
514 }
515 if (entry->next) {
516 entry->next->prev = entry->prev;
517 }
518
519 if (entry == SDL_EventQ.head) {
520 SDL_assert(entry->prev == NULL);
521 SDL_EventQ.head = entry->next;
522 }
523 if (entry == SDL_EventQ.tail) {
524 SDL_assert(entry->next == NULL);
525 SDL_EventQ.tail = entry->prev;
526 }
527
528 entry->next = SDL_EventQ.free;
529 SDL_EventQ.free = entry;
531 SDL_AtomicAdd(&SDL_EventQ.count, -1);
532}
533
534/* Lock the event queue, take a peep at it, and unlock it */
535int
537 Uint32 minType, Uint32 maxType)
538{
539 int i, used;
540
541 /* Don't look after we've quit */
542 if (!SDL_AtomicGet(&SDL_EventQ.active)) {
543 /* We get a few spurious events at shutdown, so don't warn then */
544 if (action != SDL_ADDEVENT) {
545 SDL_SetError("The event system has been shut down");
546 }
547 return (-1);
548 }
549 /* Lock the event queue */
550 used = 0;
551 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
552 if (action == SDL_ADDEVENT) {
553 for (i = 0; i < numevents; ++i) {
554 used += SDL_AddEvent(&events[i]);
555 }
556 } else {
557 SDL_EventEntry *entry, *next;
558 SDL_SysWMEntry *wmmsg, *wmmsg_next;
559 Uint32 type;
560
561 if (action == SDL_GETEVENT) {
562 /* Clean out any used wmmsg data
563 FIXME: Do we want to retain the data for some period of time?
564 */
565 for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
566 wmmsg_next = wmmsg->next;
567 wmmsg->next = SDL_EventQ.wmmsg_free;
568 SDL_EventQ.wmmsg_free = wmmsg;
569 }
570 SDL_EventQ.wmmsg_used = NULL;
571 }
572
573 for (entry = SDL_EventQ.head; entry && (!events || used < numevents); entry = next) {
574 next = entry->next;
575 type = entry->event.type;
576 if (minType <= type && type <= maxType) {
577 if (events) {
578 events[used] = entry->event;
579 if (entry->event.type == SDL_SYSWMEVENT) {
580 /* We need to copy the wmmsg somewhere safe.
581 For now we'll guarantee it's valid at least until
582 the next call to SDL_PeepEvents()
583 */
584 if (SDL_EventQ.wmmsg_free) {
585 wmmsg = SDL_EventQ.wmmsg_free;
586 SDL_EventQ.wmmsg_free = wmmsg->next;
587 } else {
588 wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
589 }
590 wmmsg->msg = *entry->event.syswm.msg;
591 wmmsg->next = SDL_EventQ.wmmsg_used;
592 SDL_EventQ.wmmsg_used = wmmsg;
593 events[used].syswm.msg = &wmmsg->msg;
594 }
595
596 if (action == SDL_GETEVENT) {
597 SDL_CutEvent(entry);
598 }
599 }
600 ++used;
601 }
602 }
603 }
604 if (SDL_EventQ.lock) {
606 }
607 } else {
608 return SDL_SetError("Couldn't lock event queue");
609 }
610 return (used);
611}
612
615{
616 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
617}
618
620SDL_HasEvents(Uint32 minType, Uint32 maxType)
621{
622 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
623}
624
625void
627{
629}
630
631void
633{
634 /* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and
635 drag'n'drop events if we're flushing them without passing them to the
636 app, but I don't know if this is the right place to do that. */
637
638 /* Don't look after we've quit */
639 if (!SDL_AtomicGet(&SDL_EventQ.active)) {
640 return;
641 }
642
643 /* Make sure the events are current */
644#if 0
645 /* Actually, we can't do this since we might be flushing while processing
646 a resize event, and calling this might trigger further resize events.
647 */
649#endif
650
651 /* Lock the event queue */
652 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
653 SDL_EventEntry *entry, *next;
654 Uint32 type;
655 for (entry = SDL_EventQ.head; entry; entry = next) {
656 next = entry->next;
657 type = entry->event.type;
658 if (minType <= type && type <= maxType) {
659 SDL_CutEvent(entry);
660 }
661 }
662 if (SDL_EventQ.lock) {
664 }
665 }
666}
667
668/* Run the system dependent event loops */
669void
671{
673
674 /* Get events from the video subsystem */
675 if (_this) {
677 }
678#if !SDL_JOYSTICK_DISABLED
679 /* Check for joystick state change */
682 }
683#endif
684
685#if !SDL_SENSOR_DISABLED
686 /* Check for sensor state change */
689 }
690#endif
691
692 SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */
693}
694
695/* Public functions */
696
697int
699{
700 return SDL_WaitEventTimeout(event, 0);
701}
702
703int
705{
706 return SDL_WaitEventTimeout(event, -1);
707}
708
709int
711{
712 Uint32 expiration = 0;
713
714 if (timeout > 0)
715 expiration = SDL_GetTicks() + timeout;
716
717 for (;;) {
720 case -1:
721 return 0;
722 case 0:
723 if (timeout == 0) {
724 /* Polling and no events, just return */
725 return 0;
726 }
727 if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
728 /* Timeout expired and no events */
729 return 0;
730 }
731 SDL_Delay(10);
732 break;
733 default:
734 /* Has events */
735 return 1;
736 }
737 }
738}
739
740int
742{
743 event->common.timestamp = SDL_GetTicks();
744
750 }
751 return 0;
752 }
753
754 if (SDL_event_watchers_count > 0) {
755 /* Make sure we only dispatch the current watcher list */
756 int i, event_watchers_count = SDL_event_watchers_count;
757
759 for (i = 0; i < event_watchers_count; ++i) {
760 if (!SDL_event_watchers[i].removed) {
762 }
763 }
765
767 for (i = SDL_event_watchers_count; i--; ) {
768 if (SDL_event_watchers[i].removed) {
772 }
773 }
774 }
776 }
777 }
778
781 }
782 }
783 }
784
785 if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
786 return -1;
787 }
788
790
791 return 1;
792}
793
794void
796{
798 /* Set filter and discard pending events */
800 SDL_EventOK.userdata = userdata;
802
805 }
806 }
807}
808
811{
812 SDL_EventWatcher event_ok;
813
815 event_ok = SDL_EventOK;
816
819 }
820 } else {
821 SDL_zero(event_ok);
822 }
823
824 if (filter) {
825 *filter = event_ok.callback;
826 }
827 if (userdata) {
828 *userdata = event_ok.userdata;
829 }
830 return event_ok.callback ? SDL_TRUE : SDL_FALSE;
831}
832
833void
835{
837 SDL_EventWatcher *event_watchers;
838
839 event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers));
840 if (event_watchers) {
841 SDL_EventWatcher *watcher;
842
843 SDL_event_watchers = event_watchers;
845 watcher->callback = filter;
846 watcher->userdata = userdata;
847 watcher->removed = SDL_FALSE;
849 }
850
853 }
854 }
855}
856
857void
859{
861 int i;
862
863 for (i = 0; i < SDL_event_watchers_count; ++i) {
864 if (SDL_event_watchers[i].callback == filter && SDL_event_watchers[i].userdata == userdata) {
868 } else {
872 }
873 }
874 break;
875 }
876 }
877
880 }
881 }
882}
883
884void
886{
887 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
888 SDL_EventEntry *entry, *next;
889 for (entry = SDL_EventQ.head; entry; entry = next) {
890 next = entry->next;
891 if (!filter(userdata, &entry->event)) {
892 SDL_CutEvent(entry);
893 }
894 }
895 if (SDL_EventQ.lock) {
897 }
898 }
899}
900
901Uint8
903{
904 const SDL_bool isdnd = ((state == SDL_DISABLE) || (state == SDL_ENABLE)) &&
905 ((type == SDL_DROPFILE) || (type == SDL_DROPTEXT));
906 Uint8 current_state;
907 Uint8 hi = ((type >> 8) & 0xff);
908 Uint8 lo = (type & 0xff);
909
910 if (SDL_disabled_events[hi] &&
911 (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
912 current_state = SDL_DISABLE;
913 } else {
914 current_state = SDL_ENABLE;
915 }
916
917 if (state != current_state)
918 {
919 switch (state) {
920 case SDL_DISABLE:
921 /* Disable this event type and discard pending events */
922 if (!SDL_disabled_events[hi]) {
924 if (!SDL_disabled_events[hi]) {
925 /* Out of memory, nothing we can do... */
926 break;
927 }
928 }
929 SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
931 break;
932 case SDL_ENABLE:
933 SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
934 break;
935 default:
936 /* Querying state... */
937 break;
938 }
939 }
940
941 /* turn off drag'n'drop support if we've disabled the events.
942 This might change some UI details at the OS level. */
943 if (isdnd) {
945 }
946
947 return current_state;
948}
949
950Uint32
951SDL_RegisterEvents(int numevents)
952{
953 Uint32 event_base;
954
955 if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) {
956 event_base = SDL_userevents;
957 SDL_userevents += numevents;
958 } else {
959 event_base = (Uint32)-1;
960 }
961 return event_base;
962}
963
964int
966{
967 int posted;
968
969 posted = 0;
970 if (SDL_GetEventState(eventType) == SDL_ENABLE) {
972 event.type = eventType;
973 posted = (SDL_PushEvent(&event) > 0);
974 }
975 return (posted);
976}
977
978int
980{
981 int posted;
982
983 posted = 0;
986 SDL_memset(&event, 0, sizeof(event));
987 event.type = SDL_SYSWMEVENT;
988 event.syswm.msg = message;
989 posted = (SDL_PushEvent(&event) > 0);
990 }
991 /* Update internal event state */
992 return (posted);
993}
994
995int
997{
999}
1000
1001int
1003{
1005 if (SDL_StartEventLoop() < 0) {
1007 return -1;
1008 }
1009
1010 SDL_QuitInit();
1011
1012 return 0;
1013}
1014
1015void
1017{
1018 SDL_QuitQuit();
1021}
1022
1023/* vi: set ts=4 sw=4 expandtab: */
#define SDL_assert(condition)
Definition: SDL_assert.h:169
#define SDL_AtomicSet
#define SDL_SetError
#define SDL_memset
#define SDL_JoystickUpdate
#define SDL_DelHintCallback
#define SDL_LockMutex
#define SDL_malloc
#define SDL_realloc
#define SDL_CreateMutex
#define SDL_strlcpy
#define SDL_free
#define SDL_Delay
#define SDL_SensorUpdate
#define SDL_JoystickEventState
#define SDL_AtomicGet
#define SDL_DestroyMutex
#define SDL_atoi
#define SDL_AddHintCallback
#define SDL_Log
#define SDL_snprintf
#define SDL_AtomicAdd
#define SDL_memmove
#define SDL_calloc
#define SDL_GetHint
#define SDL_UnlockMutex
#define PRINT_CONTROLLERDEV_EVENT(event)
SDL_SysWMEntry * wmmsg_used
Definition: SDL_events.c:83
static SDL_mutex * SDL_event_watchers_lock
Definition: SDL_events.c:45
static struct @23 SDL_EventQ
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:536
void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:858
SDL_EventEntry * head
Definition: SDL_events.c:80
#define SDL_EVENT_CASE(x)
SDL_atomic_t active
Definition: SDL_events.c:77
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:885
SDL_bool SDL_HasEvent(Uint32 type)
Definition: SDL_events.c:614
SDL_atomic_t count
Definition: SDL_events.c:78
SDL_EventEntry * free
Definition: SDL_events.c:82
int SDL_PollEvent(SDL_Event *event)
Polls for currently pending events.
Definition: SDL_events.c:698
SDL_SysWMEntry * wmmsg_free
Definition: SDL_events.c:84
Uint32 SDL_RegisterEvents(int numevents)
Definition: SDL_events.c:951
#define PRINT_DOLLAR_EVENT(event)
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:996
#define PRINT_KEY_EVENT(event)
static int SDL_AddEvent(SDL_Event *event)
Definition: SDL_events.c:456
#define SDL_MAX_QUEUED_EVENTS
Definition: SDL_events.c:37
#define PRINT_DROP_EVENT(event)
static int SDL_event_watchers_count
Definition: SDL_events.c:48
static void SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_events.c:92
#define PRINT_JOYDEV_EVENT(event)
#define PRINT_AUDIODEV_EVENT(event)
#define PRINT_FINGER_EVENT(event)
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:979
int max_events_seen
Definition: SDL_events.c:79
SDL_EventEntry * tail
Definition: SDL_events.c:81
static Uint32 SDL_userevents
Definition: SDL_events.c:57
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:795
SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
Definition: SDL_events.c:810
int SDL_SendAppEvent(SDL_EventType eventType)
Definition: SDL_events.c:965
static SDL_EventWatcher * SDL_event_watchers
Definition: SDL_events.c:47
#define SDL_WINDOWEVENT_CASE(x)
int SDL_EventsInit(void)
Definition: SDL_events.c:1002
void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:834
int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
Waits until the specified timeout (in milliseconds) for the next available event.
Definition: SDL_events.c:710
#define PRINT_JBUTTON_EVENT(event)
void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:632
void SDL_StopEventLoop(void)
Definition: SDL_events.c:340
void SDL_FlushEvent(Uint32 type)
Definition: SDL_events.c:626
int SDL_WaitEvent(SDL_Event *event)
Waits indefinitely for the next available event.
Definition: SDL_events.c:704
static void SDL_LogEvent(const SDL_Event *event)
Definition: SDL_events.c:98
Uint8 SDL_EventState(Uint32 type, int state)
Definition: SDL_events.c:902
int SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:741
static SDL_bool SDL_event_watchers_dispatching
Definition: SDL_events.c:49
void SDL_EventsQuit(void)
Definition: SDL_events.c:1016
SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:620
#define PRINT_CBUTTON_EVENT(event)
#define uint
#define PRINT_MBUTTON_EVENT(event)
SDL_mutex * lock
Definition: SDL_events.c:76
static int SDL_DoEventLogging
Definition: SDL_events.c:89
int SDL_StartEventLoop(void)
Definition: SDL_events.c:414
static void SDL_CutEvent(SDL_EventEntry *entry)
Definition: SDL_events.c:510
static SDL_DisabledEventBlock * SDL_disabled_events[256]
Definition: SDL_events.c:56
static SDL_bool SDL_event_watchers_removed
Definition: SDL_events.c:50
static SDL_EventWatcher SDL_EventOK
Definition: SDL_events.c:46
void SDL_PumpEvents(void)
Definition: SDL_events.c:670
SDL_EventType
The types of events that can be delivered.
Definition: SDL_events.h:56
@ SDL_MOUSEMOTION
Definition: SDL_events.h:105
@ SDL_JOYDEVICEADDED
Definition: SDL_events.h:116
@ SDL_DROPBEGIN
Definition: SDL_events.h:143
@ SDL_SENSORUPDATE
Definition: SDL_events.h:151
@ SDL_FINGERMOTION
Definition: SDL_events.h:130
@ SDL_TEXTEDITING
Definition: SDL_events.h:98
@ SDL_DROPTEXT
Definition: SDL_events.h:142
@ SDL_QUIT
Definition: SDL_events.h:60
@ SDL_APP_LOWMEMORY
Definition: SDL_events.h:67
@ SDL_JOYBUTTONDOWN
Definition: SDL_events.h:114
@ SDL_APP_WILLENTERFOREGROUND
Definition: SDL_events.h:79
@ SDL_USEREVENT
Definition: SDL_events.h:160
@ SDL_MOUSEBUTTONUP
Definition: SDL_events.h:107
@ SDL_JOYDEVICEREMOVED
Definition: SDL_events.h:117
@ SDL_TEXTINPUT
Definition: SDL_events.h:99
@ SDL_WINDOWEVENT
Definition: SDL_events.h:92
@ SDL_MOUSEWHEEL
Definition: SDL_events.h:108
@ SDL_CLIPBOARDUPDATE
Definition: SDL_events.h:138
@ SDL_SYSWMEVENT
Definition: SDL_events.h:93
@ SDL_JOYBUTTONUP
Definition: SDL_events.h:115
@ SDL_JOYBALLMOTION
Definition: SDL_events.h:112
@ SDL_FINGERUP
Definition: SDL_events.h:129
@ SDL_RENDER_DEVICE_RESET
Definition: SDL_events.h:155
@ SDL_CONTROLLERBUTTONUP
Definition: SDL_events.h:122
@ SDL_MOUSEBUTTONDOWN
Definition: SDL_events.h:106
@ SDL_CONTROLLERDEVICEADDED
Definition: SDL_events.h:123
@ SDL_APP_DIDENTERFOREGROUND
Definition: SDL_events.h:83
@ SDL_DOLLARRECORD
Definition: SDL_events.h:134
@ SDL_APP_WILLENTERBACKGROUND
Definition: SDL_events.h:71
@ SDL_MULTIGESTURE
Definition: SDL_events.h:135
@ SDL_FINGERDOWN
Definition: SDL_events.h:128
@ SDL_DROPCOMPLETE
Definition: SDL_events.h:144
@ SDL_DOLLARGESTURE
Definition: SDL_events.h:133
@ SDL_CONTROLLERBUTTONDOWN
Definition: SDL_events.h:121
@ SDL_APP_DIDENTERBACKGROUND
Definition: SDL_events.h:75
@ SDL_APP_TERMINATING
Definition: SDL_events.h:63
@ SDL_CONTROLLERAXISMOTION
Definition: SDL_events.h:120
@ SDL_KEYDOWN
Definition: SDL_events.h:96
@ SDL_KEYMAPCHANGED
Definition: SDL_events.h:100
@ SDL_AUDIODEVICEREMOVED
Definition: SDL_events.h:148
@ SDL_DROPFILE
Definition: SDL_events.h:141
@ SDL_AUDIODEVICEADDED
Definition: SDL_events.h:147
@ SDL_KEYUP
Definition: SDL_events.h:97
@ SDL_CONTROLLERDEVICEREMOVED
Definition: SDL_events.h:124
@ SDL_RENDER_TARGETS_RESET
Definition: SDL_events.h:154
@ SDL_CONTROLLERDEVICEREMAPPED
Definition: SDL_events.h:125
@ SDL_JOYAXISMOTION
Definition: SDL_events.h:111
@ SDL_JOYHATMOTION
Definition: SDL_events.h:113
@ SDL_FIRSTEVENT
Definition: SDL_events.h:57
@ SDL_LASTEVENT
Definition: SDL_events.h:165
#define SDL_QUERY
Definition: SDL_events.h:756
int(* SDL_EventFilter)(void *userdata, SDL_Event *event)
Definition: SDL_events.h:699
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
#define SDL_DISABLE
Definition: SDL_events.h:758
SDL_eventaction
Definition: SDL_events.h:614
@ SDL_ADDEVENT
Definition: SDL_events.h:615
@ SDL_PEEKEVENT
Definition: SDL_events.h:616
@ SDL_GETEVENT
Definition: SDL_events.h:617
#define SDL_ENABLE
Definition: SDL_events.h:759
void SDL_SendPendingSignalEvents(void)
Definition: SDL_quit.c:175
int SDL_QuitInit(void)
Definition: SDL_quit.c:154
void SDL_QuitQuit(void)
Definition: SDL_quit.c:165
void SDL_GestureProcessEvent(SDL_Event *event)
Definition: SDL_gesture.c:542
#define SDL_HINT_EVENT_LOGGING
A variable controlling whether SDL logs all events pushed onto its internal queue.
Definition: SDL_hints.h:1109
#define SDLCALL
Definition: SDL_internal.h:49
@ SDL_MOUSEWHEEL_NORMAL
Definition: SDL_mouse.h:68
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
struct _cl_event * event
GLbitfield GLuint64 timeout
GLuint GLsizei const GLchar * message
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLuint const GLchar * name
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_bool
Definition: SDL_stdinc.h:162
@ SDL_TRUE
Definition: SDL_stdinc.h:164
@ SDL_FALSE
Definition: SDL_stdinc.h:163
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_PRIs64
Definition: SDL_stdinc.h:227
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
uint8_t Uint8
Definition: SDL_stdinc.h:179
void SDL_ToggleDragAndDropSupport(void)
Definition: SDL_video.c:1371
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
@ SDL_WINDOWEVENT_HIDDEN
Definition: SDL_video.h:150
@ SDL_WINDOWEVENT_FOCUS_LOST
Definition: SDL_video.h:166
@ SDL_WINDOWEVENT_CLOSE
Definition: SDL_video.h:167
@ SDL_WINDOWEVENT_RESIZED
Definition: SDL_video.h:155
@ SDL_WINDOWEVENT_HIT_TEST
Definition: SDL_video.h:169
@ SDL_WINDOWEVENT_FOCUS_GAINED
Definition: SDL_video.h:165
@ SDL_WINDOWEVENT_SHOWN
Definition: SDL_video.h:149
@ SDL_WINDOWEVENT_MOVED
Definition: SDL_video.h:153
@ SDL_WINDOWEVENT_TAKE_FOCUS
Definition: SDL_video.h:168
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
@ SDL_WINDOWEVENT_LEAVE
Definition: SDL_video.h:164
@ SDL_WINDOWEVENT_MAXIMIZED
Definition: SDL_video.h:160
@ SDL_WINDOWEVENT_SIZE_CHANGED
Definition: SDL_video.h:156
@ SDL_WINDOWEVENT_RESTORED
Definition: SDL_video.h:161
@ SDL_WINDOWEVENT_EXPOSED
Definition: SDL_video.h:151
@ SDL_WINDOWEVENT_ENTER
Definition: SDL_video.h:163
@ SDL_WINDOWEVENT_NONE
Definition: SDL_video.h:148
struct xkb_state * state
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:167
Definition: SDL_events.c:61
SDL_Event event
Definition: SDL_events.c:62
struct _SDL_EventEntry * next
Definition: SDL_events.c:65
struct _SDL_EventEntry * prev
Definition: SDL_events.c:64
SDL_SysWMmsg msg
Definition: SDL_events.c:63
SDL_EventFilter callback
Definition: SDL_events.c:40
SDL_bool removed
Definition: SDL_events.c:42
Definition: SDL_events.c:69
SDL_SysWMmsg msg
Definition: SDL_events.c:70
struct _SDL_SysWMEntry * next
Definition: SDL_events.c:71
SDL_SysWMmsg * msg
Definition: SDL_events.h:551
union SDL_SysWMmsg::@15 msg
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:281
A type representing an atomic integer value. It is a struct so people don't accidentally use numeric ...
Definition: SDL_atomic.h:216
static SDL_Event events[EVENT_BUF_SIZE]
Definition: testgesture.c:39
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
General event structure.
Definition: SDL_events.h:558
Uint32 type
Definition: SDL_events.h:559
SDL_SysWMEvent syswm
Definition: SDL_events.h:581