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 
39 typedef struct SDL_EventWatcher {
41  void *userdata;
44 
48 static int SDL_event_watchers_count = 0;
51 
52 typedef struct {
55 
58 
59 /* Private data -- event queue */
60 typedef struct _SDL_EventEntry
61 {
64  struct _SDL_EventEntry *prev;
65  struct _SDL_EventEntry *next;
67 
68 typedef struct _SDL_SysWMEntry
69 {
71  struct _SDL_SysWMEntry *next;
73 
74 static 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 */
89 static int SDL_DoEventLogging = 0;
90 
91 static void SDLCALL
92 SDL_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 
97 static 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 
339 void
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) {
390  SDL_free(SDL_disabled_events[i]);
391  SDL_disabled_events[i] = NULL;
392  }
393 
394  if (SDL_event_watchers_lock) {
395  SDL_DestroyMutex(SDL_event_watchers_lock);
396  SDL_event_watchers_lock = NULL;
397  }
398  if (SDL_event_watchers) {
399  SDL_free(SDL_event_watchers);
400  SDL_event_watchers = NULL;
402  }
403  SDL_zero(SDL_EventOK);
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 */
413 int
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) {
425  SDL_EventQ.lock = SDL_CreateMutex();
426  if (SDL_EventQ.lock == NULL) {
427  return -1;
428  }
429  }
430 
431  if (!SDL_event_watchers_lock) {
432  SDL_event_watchers_lock = SDL_CreateMutex();
433  if (SDL_event_watchers_lock == NULL) {
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 */
455 static 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) {
478  SDL_LogEvent(event);
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 */
509 static 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;
530  SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0);
531  SDL_AtomicAdd(&SDL_EventQ.count, -1);
532 }
533 
534 /* Lock the event queue, take a peep at it, and unlock it */
535 int
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 
613 SDL_bool
615 {
616  return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
617 }
618 
619 SDL_bool
620 SDL_HasEvents(Uint32 minType, Uint32 maxType)
621 {
622  return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
623 }
624 
625 void
627 {
628  SDL_FlushEvents(type, type);
629 }
630 
631 void
632 SDL_FlushEvents(Uint32 minType, Uint32 maxType)
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  */
648  SDL_PumpEvents();
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 */
669 void
671 {
673 
674  /* Get events from the video subsystem */
675  if (_this) {
676  _this->PumpEvents(_this);
677  }
678 #if !SDL_JOYSTICK_DISABLED
679  /* Check for joystick state change */
680  if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
682  }
683 #endif
684 
685 #if !SDL_SENSOR_DISABLED
686  /* Check for sensor state change */
687  if (!SDL_disabled_events[SDL_SENSORUPDATE >> 8]) {
689  }
690 #endif
691 
692  SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */
693 }
694 
695 /* Public functions */
696 
697 int
699 {
700  return SDL_WaitEventTimeout(event, 0);
701 }
702 
703 int
705 {
706  return SDL_WaitEventTimeout(event, -1);
707 }
708 
709 int
711 {
712  Uint32 expiration = 0;
713 
714  if (timeout > 0)
715  expiration = SDL_GetTicks() + timeout;
716 
717  for (;;) {
718  SDL_PumpEvents();
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 
740 int
742 {
743  event->common.timestamp = SDL_GetTicks();
744 
745  if (SDL_EventOK.callback || SDL_event_watchers_count > 0) {
746  if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
747  if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) {
748  if (SDL_event_watchers_lock) {
749  SDL_UnlockMutex(SDL_event_watchers_lock);
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) {
761  SDL_event_watchers[i].callback(SDL_event_watchers[i].userdata, event);
762  }
763  }
765 
767  for (i = SDL_event_watchers_count; i--; ) {
768  if (SDL_event_watchers[i].removed) {
770  if (i < SDL_event_watchers_count) {
771  SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
772  }
773  }
774  }
776  }
777  }
778 
779  if (SDL_event_watchers_lock) {
780  SDL_UnlockMutex(SDL_event_watchers_lock);
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 
794 void
796 {
797  if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
798  /* Set filter and discard pending events */
799  SDL_EventOK.callback = filter;
800  SDL_EventOK.userdata = userdata;
802 
803  if (SDL_event_watchers_lock) {
804  SDL_UnlockMutex(SDL_event_watchers_lock);
805  }
806  }
807 }
808 
809 SDL_bool
811 {
812  SDL_EventWatcher event_ok;
813 
814  if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
815  event_ok = SDL_EventOK;
816 
817  if (SDL_event_watchers_lock) {
818  SDL_UnlockMutex(SDL_event_watchers_lock);
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 
833 void
835 {
836  if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
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;
844  watcher = &SDL_event_watchers[SDL_event_watchers_count];
845  watcher->callback = filter;
846  watcher->userdata = userdata;
847  watcher->removed = SDL_FALSE;
849  }
850 
851  if (SDL_event_watchers_lock) {
852  SDL_UnlockMutex(SDL_event_watchers_lock);
853  }
854  }
855 }
856 
857 void
859 {
860  if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) {
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) {
866  SDL_event_watchers[i].removed = SDL_TRUE;
868  } else {
870  if (i < SDL_event_watchers_count) {
871  SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i]));
872  }
873  }
874  break;
875  }
876  }
877 
878  if (SDL_event_watchers_lock) {
879  SDL_UnlockMutex(SDL_event_watchers_lock);
880  }
881  }
882 }
883 
884 void
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 
901 Uint8
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]) {
923  SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
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));
930  SDL_FlushEvent(type);
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 
950 Uint32
951 SDL_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 
964 int
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 
978 int
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 
995 int
997 {
999 }
1000 
1001 int
1003 {
1005  if (SDL_StartEventLoop() < 0) {
1007  return -1;
1008  }
1009 
1010  SDL_QuitInit();
1011 
1012  return 0;
1013 }
1014 
1015 void
1017 {
1018  SDL_QuitQuit();
1021 }
1022 
1023 /* vi: set ts=4 sw=4 expandtab: */
SDL_SysWMEntry * wmmsg_used
Definition: SDL_events.c:83
void * data1
Definition: SDL_events.h:533
SDL_JoystickID which
Definition: SDL_events.h:381
#define SDL_strlcpy
SDL_eventaction
Definition: SDL_events.h:613
SDL_MouseMotionEvent motion
Definition: SDL_events.h:566
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:536
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 SDL_LockMutex
SDL_ControllerAxisEvent caxis
Definition: SDL_events.h:574
SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
Definition: SDL_events.c:810
struct _SDL_EventEntry * next
Definition: SDL_events.c:65
static SDL_EventWatcher * SDL_event_watchers
Definition: SDL_events.c:47
#define SDL_WINDOWEVENT_CASE(x)
#define PRINT_JBUTTON_EVENT(event)
void SDL_PumpEvents(void)
Definition: SDL_events.c:670
#define SDL_min(x, y)
Definition: SDL_stdinc.h:406
static void SDL_LogEvent(const SDL_Event *event)
Definition: SDL_events.c:98
SDL_SysWMmsg msg
Definition: SDL_events.c:70
#define PRINT_AUDIODEV_EVENT(event)
SDL_bool removed
Definition: SDL_events.c:42
void * data2
Definition: SDL_events.h:534
GLuint GLsizei const GLchar * message
SDL_atomic_t active
Definition: SDL_events.c:77
SDL_EventFilter callback
Definition: SDL_events.c:40
SDL_bool SDL_HasEvent(Uint32 type)
Definition: SDL_events.c:614
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:216
static int SDL_AddEvent(SDL_Event *event)
Definition: SDL_events.c:456
#define PRINT_KEY_EVENT(event)
SDL_SysWMmsg * msg
Definition: SDL_events.h:551
#define PRINT_CONTROLLERDEV_EVENT(event)
#define SDL_CreateMutex
static int SDL_DoEventLogging
Definition: SDL_events.c:89
struct xkb_state * state
static SDL_Event events[EVENT_BUF_SIZE]
Definition: testgesture.c:39
SDL_EventEntry * free
Definition: SDL_events.c:82
int SDL_StartEventLoop(void)
Definition: SDL_events.c:414
SDL_JoyBallEvent jball
Definition: SDL_events.h:570
#define SDL_MAX_QUEUED_EVENTS
Definition: SDL_events.c:37
SDL_JoystickID which
Definition: SDL_events.h:304
static int SDL_event_watchers_count
Definition: SDL_events.c:48
Uint32 timestamp
Definition: SDL_events.h:512
int(* SDL_EventFilter)(void *userdata, SDL_Event *event)
Definition: SDL_events.h:699
#define SDL_GetHint
#define SDL_SensorUpdate
SDL_Event event
Definition: SDL_events.c:62
#define SDL_ENABLE
Definition: SDL_events.h:759
int max_events_seen
Definition: SDL_events.c:79
Definition: SDL_events.c:68
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
SDL_QuitEvent quit
Definition: SDL_events.h:579
#define SDL_realloc
Uint32 timestamp
Definition: SDL_events.h:530
static SDL_bool SDL_event_watchers_dispatching
Definition: SDL_events.c:49
void SDL_SendPendingSignalEvents(void)
Definition: SDL_quit.c:175
union SDL_SysWMmsg::@15 msg
SDL_MouseWheelEvent wheel
Definition: SDL_events.h:568
#define SDL_max(x, y)
Definition: SDL_stdinc.h:407
SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:620
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:979
GLuint const GLchar * name
int SDL_QuitInit(void)
Definition: SDL_quit.c:154
static SDL_VideoDevice * _this
Definition: SDL_video.c:118
struct _SDL_SysWMEntry * next
Definition: SDL_events.c:71
SDL_WindowEvent window
Definition: SDL_events.h:562
Uint32 timestamp
Definition: SDL_events.h:550
void SDL_GestureProcessEvent(SDL_Event *event)
Definition: SDL_gesture.c:542
static struct @23 SDL_EventQ
SDL_JoystickID which
Definition: SDL_events.h:320
#define SDL_Log
void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:632
SDL_TextInputEvent text
Definition: SDL_events.h:565
#define SDL_PRIs64
Definition: SDL_stdinc.h:227
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]
Definition: SDL_events.h:247
#define PRINT_FINGER_EVENT(event)
#define SDL_GetEventState(type)
Definition: SDL_events.h:772
static SDL_bool SDL_event_watchers_removed
Definition: SDL_events.c:50
#define SDL_EVENT_CASE(x)
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_JoyAxisEvent jaxis
Definition: SDL_events.h:569
uint8_t Uint8
Definition: SDL_stdinc.h:179
#define SDL_free
SDL_MultiGestureEvent mgesture
Definition: SDL_events.h:583
struct _cl_event * event
#define uint
SDL_EventType
The types of events that can be delivered.
Definition: SDL_events.h:55
void SDL_FlushEvent(Uint32 type)
Definition: SDL_events.c:626
char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
Definition: SDL_events.h:232
int SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:741
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
Uint32 windowID
Definition: SDL_events.h:531
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:885
Definition: SDL_events.c:60
#define SDL_memmove
Uint32 timestamp
Definition: SDL_events.h:335
#define PRINT_MBUTTON_EVENT(event)
static void SDL_CutEvent(SDL_EventEntry *entry)
Definition: SDL_events.c:510
#define SDL_atoi
Uint8 SDL_EventState(Uint32 type, int state)
Definition: SDL_events.c:902
#define SDL_Delay
#define PRINT_JOYDEV_EVENT(event)
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 PRINT_DROP_EVENT(event)
#define SDL_assert(condition)
Definition: SDL_assert.h:169
Uint32 timestamp
Definition: SDL_events.h:198
#define SDL_DISABLE
Definition: SDL_events.h:758
#define NULL
Definition: begin_code.h:167
#define SDL_AtomicAdd
SDL_bool
Definition: SDL_stdinc.h:161
SDL_EventEntry * tail
Definition: SDL_events.c:81
void SDL_ToggleDragAndDropSupport(void)
Definition: SDL_video.c:1371
SDL_TextEditingEvent edit
Definition: SDL_events.h:564
#define SDL_HINT_EVENT_LOGGING
A variable controlling whether SDL logs all events pushed onto its internal queue.
Definition: SDL_hints.h:1109
#define SDL_JoystickUpdate
#define SDL_SetError
SDL_SysWMEvent syswm
Definition: SDL_events.h:581
#define SDL_DestroyMutex
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:996
#define SDL_calloc
void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:858
struct _SDL_EventEntry * prev
Definition: SDL_events.c:64
void SDL_EventsQuit(void)
Definition: SDL_events.c:1016
SDL_mutex * lock
Definition: SDL_events.c:76
static void SDL_EventLoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
Definition: SDL_events.c:92
SDL_atomic_t count
Definition: SDL_events.c:78
GLbitfield GLuint64 timeout
static Uint32 SDL_userevents
Definition: SDL_events.c:57
uint32_t Uint32
Definition: SDL_stdinc.h:203
#define SDL_AddHintCallback
static SDL_DisabledEventBlock * SDL_disabled_events[256]
Definition: SDL_events.c:56
static SDL_mutex * SDL_event_watchers_lock
Definition: SDL_events.c:45
SDL_SysWMEntry * wmmsg_free
Definition: SDL_events.c:84
#define SDL_DelHintCallback
#define SDL_AtomicSet
#define SDL_AtomicGet
#define SDL_JoystickEventState
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
SDL_VideoDevice * SDL_GetVideoDevice(void)
Definition: SDL_video.c:583
#define SDL_snprintf
static SDL_EventWatcher SDL_EventOK
Definition: SDL_events.c:46
#define SDL_UnlockMutex
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
General event structure.
Definition: SDL_events.h:557
#define SDL_malloc
SDL_UserEvent user
Definition: SDL_events.h:580
int SDL_PollEvent(SDL_Event *event)
Polls for currently pending events.
Definition: SDL_events.c:698
int SDL_SendAppEvent(SDL_EventType eventType)
Definition: SDL_events.c:965
void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:834
#define SDL_QUERY
Definition: SDL_events.h:756
SDL_JoyHatEvent jhat
Definition: SDL_events.h:571
int SDL_WaitEvent(SDL_Event *event)
Waits indefinitely for the next available event.
Definition: SDL_events.c:704
SDL_EventEntry * head
Definition: SDL_events.c:80
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
#define SDLCALL
Definition: SDL_internal.h:49
SDL_JoystickID which
Definition: SDL_events.h:336
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:795
#define SDL_memset
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
int SDL_EventsInit(void)
Definition: SDL_events.c:1002
void SDL_QuitQuit(void)
Definition: SDL_quit.c:165
SDL_TouchID touchId
Definition: SDL_events.h:455
Uint32 type
Definition: SDL_events.h:559
void SDL_StopEventLoop(void)
Definition: SDL_events.c:340
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:281
Uint32 SDL_RegisterEvents(int numevents)
Definition: SDL_events.c:951
SDL_SysWMmsg msg
Definition: SDL_events.c:63
#define PRINT_DOLLAR_EVENT(event)
#define PRINT_CBUTTON_EVENT(event)