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