SDL  2.0
SDL_events.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2017 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 /*#define SDL_DEBUG_EVENTS 1*/
37 
38 /* An arbitrary limit so we don't have unbounded growth */
39 #define SDL_MAX_QUEUED_EVENTS 65535
40 
41 /* Public data -- the event filter */
44 
45 typedef struct SDL_EventWatcher {
47  void *userdata;
50 
52 
53 typedef struct {
56 
59 
60 /* Private data -- event queue */
61 typedef struct _SDL_EventEntry
62 {
65  struct _SDL_EventEntry *prev;
66  struct _SDL_EventEntry *next;
68 
69 typedef struct _SDL_SysWMEntry
70 {
72  struct _SDL_SysWMEntry *next;
74 
75 static struct
76 {
86 } SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
87 
88 
89 #ifdef SDL_DEBUG_EVENTS
90 
91 /* this is to make printf() calls cleaner. */
92 #define uint unsigned int
93 
94 static void
95 SDL_DebugPrintEvent(const SDL_Event *event)
96 {
97  /* !!! FIXME: This code is kinda ugly, sorry. */
98  printf("SDL EVENT: ");
99 
100  if ((event->type >= SDL_USEREVENT) && (event->type <= SDL_LASTEVENT)) {
101  printf("SDL_USEREVENT");
102  if (event->type > SDL_USEREVENT) {
103  printf("+%u", ((uint) event->type) - SDL_USEREVENT);
104  }
105  printf(" (timestamp=%u windowid=%u code=%d data1=%p data2=%p)",
106  (uint) event->user.timestamp, (uint) event->user.windowID,
107  (int) event->user.code, event->user.data1, event->user.data2);
108  return;
109  }
110 
111  switch (event->type) {
112  #define SDL_EVENT_CASE(x) case x: printf("%s", #x);
113  SDL_EVENT_CASE(SDL_FIRSTEVENT) printf("(THIS IS PROBABLY A BUG!)"); break;
114  SDL_EVENT_CASE(SDL_QUIT) printf("(timestamp=%u)", (uint) event->quit.timestamp); break;
115  SDL_EVENT_CASE(SDL_APP_TERMINATING) break;
116  SDL_EVENT_CASE(SDL_APP_LOWMEMORY) break;
117  SDL_EVENT_CASE(SDL_APP_WILLENTERBACKGROUND) break;
118  SDL_EVENT_CASE(SDL_APP_DIDENTERBACKGROUND) break;
119  SDL_EVENT_CASE(SDL_APP_WILLENTERFOREGROUND) break;
120  SDL_EVENT_CASE(SDL_APP_DIDENTERFOREGROUND) break;
121  SDL_EVENT_CASE(SDL_KEYMAPCHANGED) break;
122  SDL_EVENT_CASE(SDL_CLIPBOARDUPDATE) break;
123  SDL_EVENT_CASE(SDL_RENDER_TARGETS_RESET) break;
124  SDL_EVENT_CASE(SDL_RENDER_DEVICE_RESET) break;
125  #undef SDL_EVENT_CASE
126 
127  #define SDL_EVENT_CASE(x) case x: printf("%s ", #x);
128 
129  SDL_EVENT_CASE(SDL_WINDOWEVENT)
130  printf("(timestamp=%u windowid=%u event=", (uint) event->window.timestamp, (uint) event->window.windowID);
131  switch(event->window.event) {
132  case SDL_WINDOWEVENT_NONE: printf("none(THIS IS PROBABLY A BUG!)"); break;
133  #define SDL_WINDOWEVENT_CASE(x) case x: printf("%s", #x); break
134  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_SHOWN);
135  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIDDEN);
136  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_EXPOSED);
137  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MOVED);
138  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_RESIZED);
139  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_SIZE_CHANGED);
140  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MINIMIZED);
141  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_MAXIMIZED);
142  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_RESTORED);
143  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_ENTER);
144  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_LEAVE);
145  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_FOCUS_GAINED);
146  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_FOCUS_LOST);
147  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_CLOSE);
148  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_TAKE_FOCUS);
149  SDL_WINDOWEVENT_CASE(SDL_WINDOWEVENT_HIT_TEST);
150  #undef SDL_WINDOWEVENT_CASE
151  default: printf("UNKNOWN(bug? fixme?)"); break;
152  }
153  printf(" data1=%d data2=%d)", (int) event->window.data1, (int) event->window.data2);
154  break;
155 
156  SDL_EVENT_CASE(SDL_SYSWMEVENT)
157  printf("(timestamp=%u)", (uint) event->syswm.timestamp);
158  /* !!! FIXME: we don't delve further at the moment. */
159  break;
160 
161  #define PRINT_KEY_EVENT(event) \
162  printf("(timestamp=%u windowid=%u state=%s repeat=%s scancode=%u keycode=%u mod=%u)", \
163  (uint) event->key.timestamp, (uint) event->key.windowID, \
164  event->key.state == SDL_PRESSED ? "pressed" : "released", \
165  event->key.repeat ? "true" : "false", \
166  (uint) event->key.keysym.scancode, \
167  (uint) event->key.keysym.sym, \
168  (uint) event->key.keysym.mod)
169  SDL_EVENT_CASE(SDL_KEYDOWN) PRINT_KEY_EVENT(event); break;
170  SDL_EVENT_CASE(SDL_KEYUP) PRINT_KEY_EVENT(event); break;
171  #undef PRINT_KEY_EVENT
172 
173  SDL_EVENT_CASE(SDL_TEXTEDITING)
174  printf("(timestamp=%u windowid=%u text='%s' start=%d length=%d)",
175  (uint) event->edit.timestamp, (uint) event->edit.windowID,
176  event->edit.text, (int) event->edit.start, (int) event->edit.length);
177  break;
178 
179  SDL_EVENT_CASE(SDL_TEXTINPUT)
180  printf("(timestamp=%u windowid=%u text='%s')", (uint) event->text.timestamp, (uint) event->text.windowID, event->text.text);
181  break;
182 
183 
184  SDL_EVENT_CASE(SDL_MOUSEMOTION)
185  printf("(timestamp=%u windowid=%u which=%u state=%u x=%d y=%d xrel=%d yrel=%d)",
186  (uint) event->motion.timestamp, (uint) event->motion.windowID,
187  (uint) event->motion.which, (uint) event->motion.state,
188  (int) event->motion.x, (int) event->motion.y,
189  (int) event->motion.xrel, (int) event->motion.yrel);
190  break;
191 
192  #define PRINT_MBUTTON_EVENT(event) \
193  printf("(timestamp=%u windowid=%u which=%u button=%u state=%s clicks=%u x=%d y=%d)", \
194  (uint) event->button.timestamp, (uint) event->button.windowID, \
195  (uint) event->button.which, (uint) event->button.button, \
196  event->button.state == SDL_PRESSED ? "pressed" : "released", \
197  (uint) event->button.clicks, (int) event->button.x, (int) event->button.y)
198  SDL_EVENT_CASE(SDL_MOUSEBUTTONDOWN) PRINT_MBUTTON_EVENT(event); break;
199  SDL_EVENT_CASE(SDL_MOUSEBUTTONUP) PRINT_MBUTTON_EVENT(event); break;
200  #undef PRINT_MBUTTON_EVENT
201 
202 
203  SDL_EVENT_CASE(SDL_MOUSEWHEEL)
204  printf("(timestamp=%u windowid=%u which=%u x=%d y=%d direction=%s)",
205  (uint) event->wheel.timestamp, (uint) event->wheel.windowID,
206  (uint) event->wheel.which, (int) event->wheel.x, (int) event->wheel.y,
207  event->wheel.direction == SDL_MOUSEWHEEL_NORMAL ? "normal" : "flipped");
208  break;
209 
210  SDL_EVENT_CASE(SDL_JOYAXISMOTION)
211  printf("(timestamp=%u which=%d axis=%u value=%d)",
212  (uint) event->jaxis.timestamp, (int) event->jaxis.which,
213  (uint) event->jaxis.axis, (int) event->jaxis.value);
214  break;
215 
216  SDL_EVENT_CASE(SDL_JOYBALLMOTION)
217  printf("(timestamp=%u which=%d ball=%u xrel=%d yrel=%d)",
218  (uint) event->jball.timestamp, (int) event->jball.which,
219  (uint) event->jball.ball, (int) event->jball.xrel, (int) event->jball.yrel);
220  break;
221 
222  SDL_EVENT_CASE(SDL_JOYHATMOTION)
223  printf("(timestamp=%u which=%d hat=%u value=%u)",
224  (uint) event->jhat.timestamp, (int) event->jhat.which,
225  (uint) event->jhat.hat, (uint) event->jhat.value);
226  break;
227 
228  #define PRINT_JBUTTON_EVENT(event) \
229  printf("(timestamp=%u which=%d button=%u state=%s)", \
230  (uint) event->jbutton.timestamp, (int) event->jbutton.which, \
231  (uint) event->jbutton.button, event->jbutton.state == SDL_PRESSED ? "pressed" : "released")
232  SDL_EVENT_CASE(SDL_JOYBUTTONDOWN) PRINT_JBUTTON_EVENT(event); break;
233  SDL_EVENT_CASE(SDL_JOYBUTTONUP) PRINT_JBUTTON_EVENT(event); break;
234  #undef PRINT_JBUTTON_EVENT
235 
236  #define PRINT_JOYDEV_EVENT(event) printf("(timestamp=%u which=%d)", (uint) event->jdevice.timestamp, (int) event->jdevice.which)
237  SDL_EVENT_CASE(SDL_JOYDEVICEADDED) PRINT_JOYDEV_EVENT(event); break;
238  SDL_EVENT_CASE(SDL_JOYDEVICEREMOVED) PRINT_JOYDEV_EVENT(event); break;
239  #undef PRINT_JOYDEV_EVENT
240 
241  SDL_EVENT_CASE(SDL_CONTROLLERAXISMOTION)
242  printf("(timestamp=%u which=%d axis=%u value=%d)",
243  (uint) event->caxis.timestamp, (int) event->caxis.which,
244  (uint) event->caxis.axis, (int) event->caxis.value);
245  break;
246 
247  #define PRINT_CBUTTON_EVENT(event) \
248  printf("(timestamp=%u which=%d button=%u state=%s)", \
249  (uint) event->cbutton.timestamp, (int) event->cbutton.which, \
250  (uint) event->cbutton.button, event->cbutton.state == SDL_PRESSED ? "pressed" : "released")
251  SDL_EVENT_CASE(SDL_CONTROLLERBUTTONDOWN) PRINT_CBUTTON_EVENT(event); break;
252  SDL_EVENT_CASE(SDL_CONTROLLERBUTTONUP) PRINT_CBUTTON_EVENT(event); break;
253  #undef PRINT_CBUTTON_EVENT
254 
255  #define PRINT_CONTROLLERDEV_EVENT(event) printf("(timestamp=%u which=%d)", (uint) event->cdevice.timestamp, (int) event->cdevice.which)
256  SDL_EVENT_CASE(SDL_CONTROLLERDEVICEADDED) PRINT_CONTROLLERDEV_EVENT(event); break;
257  SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMOVED) PRINT_CONTROLLERDEV_EVENT(event); break;
258  SDL_EVENT_CASE(SDL_CONTROLLERDEVICEREMAPPED) PRINT_CONTROLLERDEV_EVENT(event); break;
259  #undef PRINT_CONTROLLERDEV_EVENT
260 
261  #define PRINT_FINGER_EVENT(event) \
262  printf("(timestamp=%u touchid=%lld fingerid=%lld x=%f y=%f dx=%f dy=%f pressure=%f)", \
263  (uint) event->tfinger.timestamp, (long long) event->tfinger.touchId, \
264  (long long) event->tfinger.fingerId, event->tfinger.x, event->tfinger.y, \
265  event->tfinger.dx, event->tfinger.dy, event->tfinger.pressure)
266  SDL_EVENT_CASE(SDL_FINGERDOWN) PRINT_FINGER_EVENT(event); break;
267  SDL_EVENT_CASE(SDL_FINGERUP) PRINT_FINGER_EVENT(event); break;
268  SDL_EVENT_CASE(SDL_FINGERMOTION) PRINT_FINGER_EVENT(event); break;
269  #undef PRINT_FINGER_EVENT
270 
271  #define PRINT_DOLLAR_EVENT(event) \
272  printf("(timestamp=%u touchid=%lld gestureid=%lld numfingers=%u error=%f x=%f y=%f)", \
273  (uint) event->dgesture.timestamp, (long long) event->dgesture.touchId, \
274  (long long) event->dgesture.gestureId, (uint) event->dgesture.numFingers, \
275  event->dgesture.error, event->dgesture.x, event->dgesture.y);
276  SDL_EVENT_CASE(SDL_DOLLARGESTURE) PRINT_DOLLAR_EVENT(event); break;
277  SDL_EVENT_CASE(SDL_DOLLARRECORD) PRINT_DOLLAR_EVENT(event); break;
278  #undef PRINT_DOLLAR_EVENT
279 
280  SDL_EVENT_CASE(SDL_MULTIGESTURE)
281  printf("(timestamp=%u touchid=%lld dtheta=%f ddist=%f x=%f y=%f numfingers=%u)",
282  (uint) event->mgesture.timestamp, (long long) event->mgesture.touchId,
283  event->mgesture.dTheta, event->mgesture.dDist,
284  event->mgesture.x, event->mgesture.y, (uint) event->mgesture.numFingers);
285  break;
286 
287  #define PRINT_DROP_EVENT(event) printf("(file='%s' timestamp=%u windowid=%u)", event->drop.file, (uint) event->drop.timestamp, (uint) event->drop.windowID)
288  SDL_EVENT_CASE(SDL_DROPFILE) PRINT_DROP_EVENT(event); break;
289  SDL_EVENT_CASE(SDL_DROPTEXT) PRINT_DROP_EVENT(event); break;
290  SDL_EVENT_CASE(SDL_DROPBEGIN) PRINT_DROP_EVENT(event); break;
291  SDL_EVENT_CASE(SDL_DROPCOMPLETE) PRINT_DROP_EVENT(event); break;
292  #undef PRINT_DROP_EVENT
293 
294  #define PRINT_AUDIODEV_EVENT(event) printf("(timestamp=%u which=%u iscapture=%s)", (uint) event->adevice.timestamp, (uint) event->adevice.which, event->adevice.iscapture ? "true" : "false");
295  SDL_EVENT_CASE(SDL_AUDIODEVICEADDED) PRINT_AUDIODEV_EVENT(event); break;
296  SDL_EVENT_CASE(SDL_AUDIODEVICEREMOVED) PRINT_AUDIODEV_EVENT(event); break;
297  #undef PRINT_AUDIODEV_EVENT
298 
299  #undef SDL_EVENT_CASE
300 
301  default:
302  printf("UNKNOWN SDL EVENT #%u! (Bug? FIXME?)", (uint) event->type);
303  break;
304  }
305 
306  printf("\n");
307 }
308 #undef uint
309 #endif
310 
311 
312 
313 /* Public functions */
314 
315 void
317 {
318  const char *report = SDL_GetHint("SDL_EVENT_QUEUE_STATISTICS");
319  int i;
320  SDL_EventEntry *entry;
321  SDL_SysWMEntry *wmmsg;
322 
323  if (SDL_EventQ.lock) {
325  }
326 
327  SDL_AtomicSet(&SDL_EventQ.active, 0);
328 
329  if (report && SDL_atoi(report)) {
330  SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
331  SDL_EventQ.max_events_seen);
332  }
333 
334  /* Clean out EventQ */
335  for (entry = SDL_EventQ.head; entry; ) {
336  SDL_EventEntry *next = entry->next;
337  SDL_free(entry);
338  entry = next;
339  }
340  for (entry = SDL_EventQ.free; entry; ) {
341  SDL_EventEntry *next = entry->next;
342  SDL_free(entry);
343  entry = next;
344  }
345  for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; ) {
346  SDL_SysWMEntry *next = wmmsg->next;
347  SDL_free(wmmsg);
348  wmmsg = next;
349  }
350  for (wmmsg = SDL_EventQ.wmmsg_free; wmmsg; ) {
351  SDL_SysWMEntry *next = wmmsg->next;
352  SDL_free(wmmsg);
353  wmmsg = next;
354  }
355 
356  SDL_AtomicSet(&SDL_EventQ.count, 0);
357  SDL_EventQ.max_events_seen = 0;
358  SDL_EventQ.head = NULL;
359  SDL_EventQ.tail = NULL;
360  SDL_EventQ.free = NULL;
361  SDL_EventQ.wmmsg_used = NULL;
362  SDL_EventQ.wmmsg_free = NULL;
363 
364  /* Clear disabled event state */
365  for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
366  SDL_free(SDL_disabled_events[i]);
367  SDL_disabled_events[i] = NULL;
368  }
369 
370  while (SDL_event_watchers) {
372  SDL_event_watchers = tmp->next;
373  SDL_free(tmp);
374  }
375  SDL_EventOK = NULL;
376 
377  if (SDL_EventQ.lock) {
380  SDL_EventQ.lock = NULL;
381  }
382 }
383 
384 /* This function (and associated calls) may be called more than once */
385 int
387 {
388  /* We'll leave the event queue alone, since we might have gotten
389  some important events at launch (like SDL_DROPFILE)
390 
391  FIXME: Does this introduce any other bugs with events at startup?
392  */
393 
394  /* Create the lock and set ourselves active */
395 #if !SDL_THREADS_DISABLED
396  if (!SDL_EventQ.lock) {
397  SDL_EventQ.lock = SDL_CreateMutex();
398  }
399  if (SDL_EventQ.lock == NULL) {
400  return -1;
401  }
402 #endif /* !SDL_THREADS_DISABLED */
403 
404  /* Process most event types */
408 
409  SDL_AtomicSet(&SDL_EventQ.active, 1);
410 
411  return 0;
412 }
413 
414 
415 /* Add an event to the event queue -- called with the queue locked */
416 static int
418 {
419  SDL_EventEntry *entry;
420  const int initial_count = SDL_AtomicGet(&SDL_EventQ.count);
421  int final_count;
422 
423  if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
424  SDL_SetError("Event queue is full (%d events)", initial_count);
425  return 0;
426  }
427 
428  if (SDL_EventQ.free == NULL) {
429  entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry));
430  if (!entry) {
431  return 0;
432  }
433  } else {
434  entry = SDL_EventQ.free;
435  SDL_EventQ.free = entry->next;
436  }
437 
438  #ifdef SDL_DEBUG_EVENTS
439  SDL_DebugPrintEvent(event);
440  #endif
441 
442  entry->event = *event;
443  if (event->type == SDL_SYSWMEVENT) {
444  entry->msg = *event->syswm.msg;
445  entry->event.syswm.msg = &entry->msg;
446  }
447 
448  if (SDL_EventQ.tail) {
449  SDL_EventQ.tail->next = entry;
450  entry->prev = SDL_EventQ.tail;
451  SDL_EventQ.tail = entry;
452  entry->next = NULL;
453  } else {
454  SDL_assert(!SDL_EventQ.head);
455  SDL_EventQ.head = entry;
456  SDL_EventQ.tail = entry;
457  entry->prev = NULL;
458  entry->next = NULL;
459  }
460 
461  final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1;
462  if (final_count > SDL_EventQ.max_events_seen) {
463  SDL_EventQ.max_events_seen = final_count;
464  }
465 
466  return 1;
467 }
468 
469 /* Remove an event from the queue -- called with the queue locked */
470 static void
472 {
473  if (entry->prev) {
474  entry->prev->next = entry->next;
475  }
476  if (entry->next) {
477  entry->next->prev = entry->prev;
478  }
479 
480  if (entry == SDL_EventQ.head) {
481  SDL_assert(entry->prev == NULL);
482  SDL_EventQ.head = entry->next;
483  }
484  if (entry == SDL_EventQ.tail) {
485  SDL_assert(entry->next == NULL);
486  SDL_EventQ.tail = entry->prev;
487  }
488 
489  entry->next = SDL_EventQ.free;
490  SDL_EventQ.free = entry;
491  SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0);
492  SDL_AtomicAdd(&SDL_EventQ.count, -1);
493 }
494 
495 /* Lock the event queue, take a peep at it, and unlock it */
496 int
498  Uint32 minType, Uint32 maxType)
499 {
500  int i, used;
501 
502  /* Don't look after we've quit */
503  if (!SDL_AtomicGet(&SDL_EventQ.active)) {
504  /* We get a few spurious events at shutdown, so don't warn then */
505  if (action != SDL_ADDEVENT) {
506  SDL_SetError("The event system has been shut down");
507  }
508  return (-1);
509  }
510  /* Lock the event queue */
511  used = 0;
512  if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) {
513  if (action == SDL_ADDEVENT) {
514  for (i = 0; i < numevents; ++i) {
515  used += SDL_AddEvent(&events[i]);
516  }
517  } else {
518  SDL_EventEntry *entry, *next;
519  SDL_SysWMEntry *wmmsg, *wmmsg_next;
520  Uint32 type;
521 
522  if (action == SDL_GETEVENT) {
523  /* Clean out any used wmmsg data
524  FIXME: Do we want to retain the data for some period of time?
525  */
526  for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
527  wmmsg_next = wmmsg->next;
528  wmmsg->next = SDL_EventQ.wmmsg_free;
529  SDL_EventQ.wmmsg_free = wmmsg;
530  }
531  SDL_EventQ.wmmsg_used = NULL;
532  }
533 
534  for (entry = SDL_EventQ.head; entry && (!events || used < numevents); entry = next) {
535  next = entry->next;
536  type = entry->event.type;
537  if (minType <= type && type <= maxType) {
538  if (events) {
539  events[used] = entry->event;
540  if (entry->event.type == SDL_SYSWMEVENT) {
541  /* We need to copy the wmmsg somewhere safe.
542  For now we'll guarantee it's valid at least until
543  the next call to SDL_PeepEvents()
544  */
545  if (SDL_EventQ.wmmsg_free) {
546  wmmsg = SDL_EventQ.wmmsg_free;
547  SDL_EventQ.wmmsg_free = wmmsg->next;
548  } else {
549  wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
550  }
551  wmmsg->msg = *entry->event.syswm.msg;
552  wmmsg->next = SDL_EventQ.wmmsg_used;
553  SDL_EventQ.wmmsg_used = wmmsg;
554  events[used].syswm.msg = &wmmsg->msg;
555  }
556 
557  if (action == SDL_GETEVENT) {
558  SDL_CutEvent(entry);
559  }
560  }
561  ++used;
562  }
563  }
564  }
565  if (SDL_EventQ.lock) {
567  }
568  } else {
569  return SDL_SetError("Couldn't lock event queue");
570  }
571  return (used);
572 }
573 
574 SDL_bool
576 {
577  return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
578 }
579 
580 SDL_bool
581 SDL_HasEvents(Uint32 minType, Uint32 maxType)
582 {
583  return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
584 }
585 
586 void
588 {
589  SDL_FlushEvents(type, type);
590 }
591 
592 void
593 SDL_FlushEvents(Uint32 minType, Uint32 maxType)
594 {
595  /* Don't look after we've quit */
596  if (!SDL_AtomicGet(&SDL_EventQ.active)) {
597  return;
598  }
599 
600  /* Make sure the events are current */
601 #if 0
602  /* Actually, we can't do this since we might be flushing while processing
603  a resize event, and calling this might trigger further resize events.
604  */
605  SDL_PumpEvents();
606 #endif
607 
608  /* Lock the event queue */
609  if (SDL_EventQ.lock && SDL_LockMutex(SDL_EventQ.lock) == 0) {
610  SDL_EventEntry *entry, *next;
611  Uint32 type;
612  for (entry = SDL_EventQ.head; entry; entry = next) {
613  next = entry->next;
614  type = entry->event.type;
615  if (minType <= type && type <= maxType) {
616  SDL_CutEvent(entry);
617  }
618  }
620  }
621 }
622 
623 /* Run the system dependent event loops */
624 void
626 {
628 
629  /* Get events from the video subsystem */
630  if (_this) {
631  _this->PumpEvents(_this);
632  }
633 #if !SDL_JOYSTICK_DISABLED
634  /* Check for joystick state change */
635  if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
637  }
638 #endif
639 
640  SDL_SendPendingQuit(); /* in case we had a signal handler fire, etc. */
641 }
642 
643 /* Public functions */
644 
645 int
647 {
648  return SDL_WaitEventTimeout(event, 0);
649 }
650 
651 int
653 {
654  return SDL_WaitEventTimeout(event, -1);
655 }
656 
657 int
659 {
660  Uint32 expiration = 0;
661 
662  if (timeout > 0)
663  expiration = SDL_GetTicks() + timeout;
664 
665  for (;;) {
666  SDL_PumpEvents();
668  case -1:
669  return 0;
670  case 0:
671  if (timeout == 0) {
672  /* Polling and no events, just return */
673  return 0;
674  }
675  if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
676  /* Timeout expired and no events */
677  return 0;
678  }
679  SDL_Delay(10);
680  break;
681  default:
682  /* Has events */
683  return 1;
684  }
685  }
686 }
687 
688 int
690 {
691  SDL_EventWatcher *curr;
692 
693  event->common.timestamp = SDL_GetTicks();
694 
695  if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
696  return 0;
697  }
698 
699  for (curr = SDL_event_watchers; curr; curr = curr->next) {
700  curr->callback(curr->userdata, event);
701  }
702 
703  if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
704  return -1;
705  }
706 
708 
709  return 1;
710 }
711 
712 void
714 {
715  /* Set filter and discard pending events */
716  SDL_EventOK = NULL;
720 }
721 
722 SDL_bool
724 {
725  if (filter) {
726  *filter = SDL_EventOK;
727  }
728  if (userdata) {
729  *userdata = SDL_EventOKParam;
730  }
731  return SDL_EventOK ? SDL_TRUE : SDL_FALSE;
732 }
733 
734 /* FIXME: This is not thread-safe yet */
735 void
737 {
738  SDL_EventWatcher *watcher, *tail;
739 
740  watcher = (SDL_EventWatcher *)SDL_malloc(sizeof(*watcher));
741  if (!watcher) {
742  /* Uh oh... */
743  return;
744  }
745 
746  /* create the watcher */
747  watcher->callback = filter;
748  watcher->userdata = userdata;
749  watcher->next = NULL;
750 
751  /* add the watcher to the end of the list */
752  if (SDL_event_watchers) {
753  for (tail = SDL_event_watchers; tail->next; tail = tail->next) {
754  continue;
755  }
756  tail->next = watcher;
757  } else {
758  SDL_event_watchers = watcher;
759  }
760 }
761 
762 /* FIXME: This is not thread-safe yet */
763 void
765 {
766  SDL_EventWatcher *prev = NULL;
767  SDL_EventWatcher *curr;
768 
769  for (curr = SDL_event_watchers; curr; prev = curr, curr = curr->next) {
770  if (curr->callback == filter && curr->userdata == userdata) {
771  if (prev) {
772  prev->next = curr->next;
773  } else {
774  SDL_event_watchers = curr->next;
775  }
776  SDL_free(curr);
777  break;
778  }
779  }
780 }
781 
782 void
784 {
785  if (SDL_EventQ.lock && SDL_LockMutex(SDL_EventQ.lock) == 0) {
786  SDL_EventEntry *entry, *next;
787  for (entry = SDL_EventQ.head; entry; entry = next) {
788  next = entry->next;
789  if (!filter(userdata, &entry->event)) {
790  SDL_CutEvent(entry);
791  }
792  }
794  }
795 }
796 
797 Uint8
799 {
800  Uint8 current_state;
801  Uint8 hi = ((type >> 8) & 0xff);
802  Uint8 lo = (type & 0xff);
803 
804  if (SDL_disabled_events[hi] &&
805  (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
806  current_state = SDL_DISABLE;
807  } else {
808  current_state = SDL_ENABLE;
809  }
810 
811  if (state != current_state)
812  {
813  switch (state) {
814  case SDL_DISABLE:
815  /* Disable this event type and discard pending events */
816  if (!SDL_disabled_events[hi]) {
817  SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
818  if (!SDL_disabled_events[hi]) {
819  /* Out of memory, nothing we can do... */
820  break;
821  }
822  }
823  SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
824  SDL_FlushEvent(type);
825  break;
826  case SDL_ENABLE:
827  SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
828  break;
829  default:
830  /* Querying state... */
831  break;
832  }
833  }
834 
835  return current_state;
836 }
837 
838 Uint32
839 SDL_RegisterEvents(int numevents)
840 {
841  Uint32 event_base;
842 
843  if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) {
844  event_base = SDL_userevents;
845  SDL_userevents += numevents;
846  } else {
847  event_base = (Uint32)-1;
848  }
849  return event_base;
850 }
851 
852 int
854 {
855  int posted;
856 
857  posted = 0;
858  if (SDL_GetEventState(eventType) == SDL_ENABLE) {
860  event.type = eventType;
861  posted = (SDL_PushEvent(&event) > 0);
862  }
863  return (posted);
864 }
865 
866 int
868 {
869  int posted;
870 
871  posted = 0;
874  SDL_memset(&event, 0, sizeof(event));
875  event.type = SDL_SYSWMEVENT;
876  event.syswm.msg = message;
877  posted = (SDL_PushEvent(&event) > 0);
878  }
879  /* Update internal event state */
880  return (posted);
881 }
882 
883 int
885 {
887 }
888 
889 /* vi: set ts=4 sw=4 expandtab: */
SDL_SysWMEntry * wmmsg_used
Definition: SDL_events.c:84
void * data1
Definition: SDL_events.h:501
SDL_JoystickID which
Definition: SDL_events.h:360
SDL_eventaction
Definition: SDL_events.h:576
SDL_MouseMotionEvent motion
Definition: SDL_events.h:533
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:497
int SDL_WaitEventTimeout(SDL_Event *event, int timeout)
Waits until the specified timeout (in milliseconds) for the next available event. ...
Definition: SDL_events.c:658
#define SDL_LockMutex
SDL_ControllerAxisEvent caxis
Definition: SDL_events.h:541
SDL_bool SDL_GetEventFilter(SDL_EventFilter *filter, void **userdata)
Definition: SDL_events.c:723
struct _SDL_EventEntry * next
Definition: SDL_events.c:66
static SDL_EventWatcher * SDL_event_watchers
Definition: SDL_events.c:51
void SDL_PumpEvents(void)
Definition: SDL_events.c:625
SDL_SysWMmsg msg
Definition: SDL_events.c:71
void * data2
Definition: SDL_events.h:502
GLuint GLsizei const GLchar * message
SDL_atomic_t active
Definition: SDL_events.c:78
SDL_EventFilter callback
Definition: SDL_events.c:46
SDL_bool SDL_HasEvent(Uint32 type)
Definition: SDL_events.c:575
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:195
static int SDL_AddEvent(SDL_Event *event)
Definition: SDL_events.c:417
SDL_SysWMmsg * msg
Definition: SDL_events.h:519
#define SDL_CreateMutex
struct xkb_state * state
static SDL_Event events[EVENT_BUF_SIZE]
Definition: testgesture.c:35
SDL_EventEntry * free
Definition: SDL_events.c:83
int SDL_StartEventLoop(void)
Definition: SDL_events.c:386
SDL_JoyBallEvent jball
Definition: SDL_events.h:537
#define SDL_MAX_QUEUED_EVENTS
Definition: SDL_events.c:39
SDL_JoystickID which
Definition: SDL_events.h:283
Uint32 timestamp
Definition: SDL_events.h:480
int(* SDL_EventFilter)(void *userdata, SDL_Event *event)
Definition: SDL_events.h:662
#define SDL_GetHint
SDL_Event event
Definition: SDL_events.c:63
#define SDL_ENABLE
Definition: SDL_events.h:722
int max_events_seen
Definition: SDL_events.c:80
Definition: SDL_events.c:69
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
SDL_QuitEvent quit
Definition: SDL_events.h:545
uint32_t Uint32
Definition: SDL_stdinc.h:181
Uint32 timestamp
Definition: SDL_events.h:498
union SDL_SysWMmsg::@16 msg
SDL_MouseWheelEvent wheel
Definition: SDL_events.h:535
SDL_bool SDL_HasEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:581
int SDL_SendSysWMEvent(SDL_SysWMmsg *message)
Definition: SDL_events.c:867
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
struct _SDL_SysWMEntry * next
Definition: SDL_events.c:72
SDL_WindowEvent window
Definition: SDL_events.h:529
Uint32 timestamp
Definition: SDL_events.h:518
void SDL_GestureProcessEvent(SDL_Event *event)
Definition: SDL_gesture.c:538
SDL_JoystickID which
Definition: SDL_events.h:299
#define SDL_Log
void SDL_FlushEvents(Uint32 minType, Uint32 maxType)
Definition: SDL_events.c:593
SDL_TextInputEvent text
Definition: SDL_events.h:532
void * SDL_calloc(size_t nmemb, size_t size)
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]
Definition: SDL_events.h:226
#define SDL_GetEventState(type)
Definition: SDL_events.h:735
Uint32 SDL_GetTicks(void)
Get the number of milliseconds since the SDL library initialization.
SDL_JoyAxisEvent jaxis
Definition: SDL_events.h:536
uint8_t Uint8
Definition: SDL_stdinc.h:157
SDL_MultiGestureEvent mgesture
Definition: SDL_events.h:549
struct _cl_event * event
struct SDL_EventWatcher * next
Definition: SDL_events.c:48
void SDL_free(void *mem)
SDL_EventFilter SDL_EventOK
Definition: SDL_events.c:42
SDL_EventType
The types of events that can be delivered.
Definition: SDL_events.h:55
void SDL_FlushEvent(Uint32 type)
Definition: SDL_events.c:587
char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
Definition: SDL_events.h:211
int SDL_PushEvent(SDL_Event *event)
Add an event to the event queue.
Definition: SDL_events.c:689
Uint32 windowID
Definition: SDL_events.h:499
void SDL_FilterEvents(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:783
Definition: SDL_events.c:61
Uint32 timestamp
Definition: SDL_events.h:314
static void SDL_CutEvent(SDL_EventEntry *entry)
Definition: SDL_events.c:471
#define SDL_atoi
Uint8 SDL_EventState(Uint32 type, int state)
Definition: SDL_events.c:798
#define SDL_Delay
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 SDL_assert(condition)
Definition: SDL_assert.h:169
void * SDL_EventOKParam
Definition: SDL_events.c:43
Uint32 timestamp
Definition: SDL_events.h:177
#define SDL_DISABLE
Definition: SDL_events.h:721
#define NULL
Definition: begin_code.h:164
#define SDL_AtomicAdd
SDL_bool
Definition: SDL_stdinc.h:139
SDL_EventEntry * tail
Definition: SDL_events.c:82
SDL_TextEditingEvent edit
Definition: SDL_events.h:531
#define SDL_JoystickUpdate
#define SDL_SetError
SDL_SysWMEvent syswm
Definition: SDL_events.h:547
#define SDL_DestroyMutex
int SDL_SendKeymapChangedEvent(void)
Definition: SDL_events.c:884
void SDL_DelEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:764
struct _SDL_EventEntry * prev
Definition: SDL_events.c:65
SDL_mutex * lock
Definition: SDL_events.c:77
SDL_atomic_t count
Definition: SDL_events.c:79
GLbitfield GLuint64 timeout
static Uint32 SDL_userevents
Definition: SDL_events.c:58
static SDL_DisabledEventBlock * SDL_disabled_events[256]
Definition: SDL_events.c:57
SDL_SysWMEntry * wmmsg_free
Definition: SDL_events.c:85
#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:586
#define SDL_UnlockMutex
void SDL_SendPendingQuit(void)
Definition: SDL_quit.c:144
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:93
General event structure.
Definition: SDL_events.h:525
#define SDL_malloc
SDL_UserEvent user
Definition: SDL_events.h:546
int SDL_PollEvent(SDL_Event *event)
Polls for currently pending events.
Definition: SDL_events.c:646
int SDL_SendAppEvent(SDL_EventType eventType)
Definition: SDL_events.c:853
void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:736
#define SDL_QUERY
Definition: SDL_events.h:719
SDL_JoyHatEvent jhat
Definition: SDL_events.h:538
int SDL_WaitEvent(SDL_Event *event)
Waits indefinitely for the next available event.
Definition: SDL_events.c:652
SDL_EventEntry * head
Definition: SDL_events.c:81
static struct @21 SDL_EventQ
#define SDL_TICKS_PASSED(A, B)
Compare SDL ticks values, and return true if A has passed B.
Definition: SDL_timer.h:56
SDL_JoystickID which
Definition: SDL_events.h:315
void SDL_SetEventFilter(SDL_EventFilter filter, void *userdata)
Definition: SDL_events.c:713
#define SDL_memset
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
SDL_TouchID touchId
Definition: SDL_events.h:434
Uint32 type
Definition: SDL_events.h:527
void SDL_StopEventLoop(void)
Definition: SDL_events.c:316
void(* PumpEvents)(_THIS)
Definition: SDL_sysvideo.h:280
Uint32 SDL_RegisterEvents(int numevents)
Definition: SDL_events.c:839
SDL_SysWMmsg msg
Definition: SDL_events.c:64