Atlas - SDL_events.c
Home / ext / SDL2 / src / events Lines: 3 | Size: 33407 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../SDL_internal.h" 22 23/* General event handling code for SDL */ 24 25#include "SDL.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 41typedef struct SDL_EventWatcher { 42 SDL_EventFilter callback; 43 void *userdata; 44 SDL_bool removed; 45} SDL_EventWatcher; 46 47static SDL_mutex *SDL_event_watchers_lock; 48static SDL_EventWatcher SDL_EventOK; 49static SDL_EventWatcher *SDL_event_watchers = NULL; 50static int SDL_event_watchers_count = 0; 51static SDL_bool SDL_event_watchers_dispatching = SDL_FALSE; 52static SDL_bool SDL_event_watchers_removed = SDL_FALSE; 53 54typedef struct { 55 Uint32 bits[8]; 56} SDL_DisabledEventBlock; 57 58static SDL_DisabledEventBlock *SDL_disabled_events[256]; 59static Uint32 SDL_userevents = SDL_USEREVENT; 60 61/* Private data -- event queue */ 62typedef struct _SDL_EventEntry 63{ 64 SDL_Event event; 65 SDL_SysWMmsg msg; 66 struct _SDL_EventEntry *prev; 67 struct _SDL_EventEntry *next; 68} SDL_EventEntry; 69 70typedef struct _SDL_SysWMEntry 71{ 72 SDL_SysWMmsg msg; 73 struct _SDL_SysWMEntry *next; 74} SDL_SysWMEntry; 75 76static struct 77{ 78 SDL_mutex *lock; 79 SDL_atomic_t active; 80 SDL_atomic_t count; 81 int max_events_seen; 82 SDL_EventEntry *head; 83 SDL_EventEntry *tail; 84 SDL_EventEntry *free; 85 SDL_SysWMEntry *wmmsg_used; 86 SDL_SysWMEntry *wmmsg_free; 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 95static void 96SDL_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 316void 317SDL_StopEventLoop(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) { 325 SDL_LockMutex(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_DestroyMutex(SDL_event_watchers_lock); 373 SDL_event_watchers_lock = NULL; 374 } 375 if (SDL_event_watchers) { 376 SDL_free(SDL_event_watchers); 377 SDL_event_watchers = NULL; 378 SDL_event_watchers_count = 0; 379 } 380 SDL_zero(SDL_EventOK); 381 382 if (SDL_EventQ.lock) { 383 SDL_UnlockMutex(SDL_EventQ.lock); 384 SDL_DestroyMutex(SDL_EventQ.lock); 385 SDL_EventQ.lock = NULL; 386 } 387} 388 389/* This function (and associated calls) may be called more than once */ 390int 391SDL_StartEventLoop(void) 392{ 393 /* We'll leave the event queue alone, since we might have gotten 394 some important events at launch (like SDL_DROPFILE) 395 396 FIXME: Does this introduce any other bugs with events at startup? 397 */ 398 399 /* Create the lock and set ourselves active */ 400#if !SDL_THREADS_DISABLED 401 if (!SDL_EventQ.lock) { 402 SDL_EventQ.lock = SDL_CreateMutex(); 403 if (SDL_EventQ.lock == NULL) { 404 return -1; 405 } 406 } 407 408 if (!SDL_event_watchers_lock) { 409 SDL_event_watchers_lock = SDL_CreateMutex(); 410 if (SDL_event_watchers_lock == NULL) { 411 return -1; 412 } 413 } 414#endif /* !SDL_THREADS_DISABLED */ 415 416 /* Process most event types */ 417 SDL_EventState(SDL_TEXTINPUT, SDL_DISABLE); 418 SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE); 419 SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE); 420 SDL_EventState(SDL_DROPFILE, SDL_DISABLE); 421 SDL_EventState(SDL_DROPTEXT, SDL_DISABLE); 422 423 SDL_AtomicSet(&SDL_EventQ.active, 1); 424 425 return 0; 426} 427 428 429/* Add an event to the event queue -- called with the queue locked */ 430static int 431SDL_AddEvent(SDL_Event * event) 432{ 433 SDL_EventEntry *entry; 434 const int initial_count = SDL_AtomicGet(&SDL_EventQ.count); 435 int final_count; 436 437 if (initial_count >= SDL_MAX_QUEUED_EVENTS) { 438 SDL_SetError("Event queue is full (%d events)", initial_count); 439 return 0; 440 } 441 442 if (SDL_EventQ.free == NULL) { 443 entry = (SDL_EventEntry *)SDL_malloc(sizeof(*entry)); 444 if (!entry) { 445 return 0; 446 } 447 } else { 448 entry = SDL_EventQ.free; 449 SDL_EventQ.free = entry->next; 450 } 451 452 #ifdef SDL_DEBUG_EVENTS 453 SDL_DebugPrintEvent(event); 454 #endif 455 456 entry->event = *event; 457 if (event->type == SDL_SYSWMEVENT) { 458 entry->msg = *event->syswm.msg; 459 entry->event.syswm.msg = &entry->msg; 460 } 461 462 if (SDL_EventQ.tail) { 463 SDL_EventQ.tail->next = entry; 464 entry->prev = SDL_EventQ.tail; 465 SDL_EventQ.tail = entry; 466 entry->next = NULL; 467 } else { 468 SDL_assert(!SDL_EventQ.head); 469 SDL_EventQ.head = entry; 470 SDL_EventQ.tail = entry; 471 entry->prev = NULL; 472 entry->next = NULL; 473 } 474 475 final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1; 476 if (final_count > SDL_EventQ.max_events_seen) { 477 SDL_EventQ.max_events_seen = final_count; 478 } 479 480 return 1; 481} 482 483/* Remove an event from the queue -- called with the queue locked */ 484static void 485SDL_CutEvent(SDL_EventEntry *entry) 486{ 487 if (entry->prev) { 488 entry->prev->next = entry->next; 489 } 490 if (entry->next) { 491 entry->next->prev = entry->prev; 492 } 493 494 if (entry == SDL_EventQ.head) { 495 SDL_assert(entry->prev == NULL); 496 SDL_EventQ.head = entry->next; 497 } 498 if (entry == SDL_EventQ.tail) { 499 SDL_assert(entry->next == NULL); 500 SDL_EventQ.tail = entry->prev; 501 } 502 503 entry->next = SDL_EventQ.free; 504 SDL_EventQ.free = entry; 505 SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0); 506 SDL_AtomicAdd(&SDL_EventQ.count, -1); 507} 508 509/* Lock the event queue, take a peep at it, and unlock it */ 510int 511SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, 512 Uint32 minType, Uint32 maxType) 513{ 514 int i, used; 515 516 /* Don't look after we've quit */ 517 if (!SDL_AtomicGet(&SDL_EventQ.active)) { 518 /* We get a few spurious events at shutdown, so don't warn then */ 519 if (action != SDL_ADDEVENT) { 520 SDL_SetError("The event system has been shut down"); 521 } 522 return (-1); 523 } 524 /* Lock the event queue */ 525 used = 0; 526 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { 527 if (action == SDL_ADDEVENT) { 528 for (i = 0; i < numevents; ++i) { 529 used += SDL_AddEvent(&events[i]); 530 } 531 } else { 532 SDL_EventEntry *entry, *next; 533 SDL_SysWMEntry *wmmsg, *wmmsg_next; 534 Uint32 type; 535 536 if (action == SDL_GETEVENT) { 537 /* Clean out any used wmmsg data 538 FIXME: Do we want to retain the data for some period of time? 539 */ 540 for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) { 541 wmmsg_next = wmmsg->next; 542 wmmsg->next = SDL_EventQ.wmmsg_free; 543 SDL_EventQ.wmmsg_free = wmmsg; 544 } 545 SDL_EventQ.wmmsg_used = NULL; 546 } 547 548 for (entry = SDL_EventQ.head; entry && (!events || used < numevents); entry = next) { 549 next = entry->next; 550 type = entry->event.type; 551 if (minType <= type && type <= maxType) { 552 if (events) { 553 events[used] = entry->event; 554 if (entry->event.type == SDL_SYSWMEVENT) { 555 /* We need to copy the wmmsg somewhere safe. 556 For now we'll guarantee it's valid at least until 557 the next call to SDL_PeepEvents() 558 */ 559 if (SDL_EventQ.wmmsg_free) { 560 wmmsg = SDL_EventQ.wmmsg_free; 561 SDL_EventQ.wmmsg_free = wmmsg->next; 562 } else { 563 wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg)); 564 } 565 wmmsg->msg = *entry->event.syswm.msg; 566 wmmsg->next = SDL_EventQ.wmmsg_used; 567 SDL_EventQ.wmmsg_used = wmmsg; 568 events[used].syswm.msg = &wmmsg->msg; 569 } 570 571 if (action == SDL_GETEVENT) { 572 SDL_CutEvent(entry); 573 } 574 } 575 ++used; 576 } 577 } 578 } 579 if (SDL_EventQ.lock) { 580 SDL_UnlockMutex(SDL_EventQ.lock); 581 } 582 } else { 583 return SDL_SetError("Couldn't lock event queue"); 584 } 585 return (used); 586} 587 588SDL_bool 589SDL_HasEvent(Uint32 type) 590{ 591 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0); 592} 593 594SDL_bool 595SDL_HasEvents(Uint32 minType, Uint32 maxType) 596{ 597 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0); 598} 599 600void 601SDL_FlushEvent(Uint32 type) 602{ 603 SDL_FlushEvents(type, type); 604} 605 606void 607SDL_FlushEvents(Uint32 minType, Uint32 maxType) 608{ 609 /* !!! FIXME: we need to manually SDL_free() the strings in TEXTINPUT and 610 drag'n'drop events if we're flushing them without passing them to the 611 app, but I don't know if this is the right place to do that. */ 612 613 /* Don't look after we've quit */ 614 if (!SDL_AtomicGet(&SDL_EventQ.active)) { 615 return; 616 } 617 618 /* Make sure the events are current */ 619#if 0 620 /* Actually, we can't do this since we might be flushing while processing 621 a resize event, and calling this might trigger further resize events. 622 */ 623 SDL_PumpEvents(); 624#endif 625 626 /* Lock the event queue */ 627 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { 628 SDL_EventEntry *entry, *next; 629 Uint32 type; 630 for (entry = SDL_EventQ.head; entry; entry = next) { 631 next = entry->next; 632 type = entry->event.type; 633 if (minType <= type && type <= maxType) { 634 SDL_CutEvent(entry); 635 } 636 } 637 if (SDL_EventQ.lock) { 638 SDL_UnlockMutex(SDL_EventQ.lock); 639 } 640 } 641} 642 643/* Run the system dependent event loops */ 644void 645SDL_PumpEvents(void) 646{ 647 SDL_VideoDevice *_this = SDL_GetVideoDevice(); 648 649 /* Get events from the video subsystem */ 650 if (_this) { 651 _this->PumpEvents(_this); 652 } 653#if !SDL_JOYSTICK_DISABLED 654 /* Check for joystick state change */ 655 if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) { 656 SDL_JoystickUpdate(); 657 } 658#endif 659 660#if !SDL_SENSOR_DISABLED 661 /* Check for sensor state change */ 662 if (!SDL_disabled_events[SDL_SENSORUPDATE >> 8]) { 663 SDL_SensorUpdate(); 664 } 665#endif 666 667 SDL_SendPendingQuit(); /* in case we had a signal handler fire, etc. */ 668} 669 670/* Public functions */ 671 672int 673SDL_PollEvent(SDL_Event * event) 674{ 675 return SDL_WaitEventTimeout(event, 0); 676} 677 678int 679SDL_WaitEvent(SDL_Event * event) 680{ 681 return SDL_WaitEventTimeout(event, -1); 682} 683 684int 685SDL_WaitEventTimeout(SDL_Event * event, int timeout) 686{ 687 Uint32 expiration = 0; 688 689 if (timeout > 0) 690 expiration = SDL_GetTicks() + timeout; 691 692 for (;;) { 693 SDL_PumpEvents(); 694 switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { 695 case -1: 696 return 0; 697 case 0: 698 if (timeout == 0) { 699 /* Polling and no events, just return */ 700 return 0; 701 } 702 if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) { 703 /* Timeout expired and no events */ 704 return 0; 705 } 706 SDL_Delay(10); 707 break; 708 default: 709 /* Has events */ 710 return 1; 711 } 712 } 713} 714 715int 716SDL_PushEvent(SDL_Event * event) 717{ 718 event->common.timestamp = SDL_GetTicks(); 719 720 if (SDL_EventOK.callback || SDL_event_watchers_count > 0) { 721 if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) { 722 if (SDL_EventOK.callback && !SDL_EventOK.callback(SDL_EventOK.userdata, event)) { 723 if (SDL_event_watchers_lock) { 724 SDL_UnlockMutex(SDL_event_watchers_lock); 725 } 726 return 0; 727 } 728 729 if (SDL_event_watchers_count > 0) { 730 /* Make sure we only dispatch the current watcher list */ 731 int i, event_watchers_count = SDL_event_watchers_count; 732 733 SDL_event_watchers_dispatching = SDL_TRUE; 734 for (i = 0; i < event_watchers_count; ++i) { 735 if (!SDL_event_watchers[i].removed) { 736 SDL_event_watchers[i].callback(SDL_event_watchers[i].userdata, event); 737 } 738 } 739 SDL_event_watchers_dispatching = SDL_FALSE; 740 741 if (SDL_event_watchers_removed) { 742 for (i = SDL_event_watchers_count; i--; ) { 743 if (SDL_event_watchers[i].removed) { 744 --SDL_event_watchers_count; 745 if (i < SDL_event_watchers_count) { 746 SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i])); 747 } 748 } 749 } 750 SDL_event_watchers_removed = SDL_FALSE; 751 } 752 } 753 754 if (SDL_event_watchers_lock) { 755 SDL_UnlockMutex(SDL_event_watchers_lock); 756 } 757 } 758 } 759 760 if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) { 761 return -1; 762 } 763 764 SDL_GestureProcessEvent(event); 765 766 return 1; 767} 768 769void 770SDL_SetEventFilter(SDL_EventFilter filter, void *userdata) 771{ 772 if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) { 773 /* Set filter and discard pending events */ 774 SDL_EventOK.callback = filter; 775 SDL_EventOK.userdata = userdata; 776 SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT); 777 778 if (SDL_event_watchers_lock) { 779 SDL_UnlockMutex(SDL_event_watchers_lock); 780 } 781 } 782} 783 784SDL_bool 785SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata) 786{ 787 SDL_EventWatcher event_ok; 788 789 if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) { 790 event_ok = SDL_EventOK; 791 792 if (SDL_event_watchers_lock) { 793 SDL_UnlockMutex(SDL_event_watchers_lock); 794 } 795 } else { 796 SDL_zero(event_ok); 797 } 798 799 if (filter) { 800 *filter = event_ok.callback; 801 } 802 if (userdata) { 803 *userdata = event_ok.userdata; 804 } 805 return event_ok.callback ? SDL_TRUE : SDL_FALSE; 806} 807 808void 809SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) 810{ 811 if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) { 812 SDL_EventWatcher *event_watchers; 813 814 event_watchers = SDL_realloc(SDL_event_watchers, (SDL_event_watchers_count + 1) * sizeof(*event_watchers)); 815 if (event_watchers) { 816 SDL_EventWatcher *watcher; 817 818 SDL_event_watchers = event_watchers; 819 watcher = &SDL_event_watchers[SDL_event_watchers_count]; 820 watcher->callback = filter; 821 watcher->userdata = userdata; 822 watcher->removed = SDL_FALSE; 823 ++SDL_event_watchers_count; 824 } 825 826 if (SDL_event_watchers_lock) { 827 SDL_UnlockMutex(SDL_event_watchers_lock); 828 } 829 } 830} 831 832void 833SDL_DelEventWatch(SDL_EventFilter filter, void *userdata) 834{ 835 if (!SDL_event_watchers_lock || SDL_LockMutex(SDL_event_watchers_lock) == 0) { 836 int i; 837 838 for (i = 0; i < SDL_event_watchers_count; ++i) { 839 if (SDL_event_watchers[i].callback == filter && SDL_event_watchers[i].userdata == userdata) { 840 if (SDL_event_watchers_dispatching) { 841 SDL_event_watchers[i].removed = SDL_TRUE; 842 SDL_event_watchers_removed = SDL_TRUE; 843 } else { 844 --SDL_event_watchers_count; 845 if (i < SDL_event_watchers_count) { 846 SDL_memmove(&SDL_event_watchers[i], &SDL_event_watchers[i+1], (SDL_event_watchers_count - i) * sizeof(SDL_event_watchers[i])); 847 } 848 } 849 break; 850 } 851 } 852 853 if (SDL_event_watchers_lock) { 854 SDL_UnlockMutex(SDL_event_watchers_lock); 855 } 856 } 857} 858 859void 860SDL_FilterEvents(SDL_EventFilter filter, void *userdata) 861{ 862 if (!SDL_EventQ.lock || SDL_LockMutex(SDL_EventQ.lock) == 0) { 863 SDL_EventEntry *entry, *next; 864 for (entry = SDL_EventQ.head; entry; entry = next) { 865 next = entry->next; 866 if (!filter(userdata, &entry->event)) { 867 SDL_CutEvent(entry); 868 } 869 } 870 if (SDL_EventQ.lock) { 871 SDL_UnlockMutex(SDL_EventQ.lock); 872 } 873 } 874} 875 876Uint8 877SDL_EventState(Uint32 type, int state) 878{ 879 const SDL_bool isdnd = ((state == SDL_DISABLE) || (state == SDL_ENABLE)) && 880 ((type == SDL_DROPFILE) || (type == SDL_DROPTEXT)); 881 Uint8 current_state; 882 Uint8 hi = ((type >> 8) & 0xff); 883 Uint8 lo = (type & 0xff); 884 885 if (SDL_disabled_events[hi] && 886 (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) { 887 current_state = SDL_DISABLE; 888 } else { 889 current_state = SDL_ENABLE; 890 } 891 892 if (state != current_state) 893 { 894 switch (state) { 895 case SDL_DISABLE: 896 /* Disable this event type and discard pending events */ 897 if (!SDL_disabled_events[hi]) { 898 SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock)); 899 if (!SDL_disabled_events[hi]) { 900 /* Out of memory, nothing we can do... */ 901 break; 902 } 903 } 904 SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31)); 905 SDL_FlushEvent(type); 906 break; 907 case SDL_ENABLE: 908 SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31)); 909 break; 910 default: 911 /* Querying state... */ 912 break; 913 } 914 } 915 916 /* turn off drag'n'drop support if we've disabled the events. 917 This might change some UI details at the OS level. */ 918 if (isdnd) { 919 SDL_ToggleDragAndDropSupport(); 920 } 921 922 return current_state; 923} 924 925Uint32 926SDL_RegisterEvents(int numevents) 927{ 928 Uint32 event_base; 929 930 if ((numevents > 0) && (SDL_userevents+numevents <= SDL_LASTEVENT)) { 931 event_base = SDL_userevents; 932 SDL_userevents += numevents; 933 } else { 934 event_base = (Uint32)-1; 935 } 936 return event_base; 937} 938 939int 940SDL_SendAppEvent(SDL_EventType eventType) 941{ 942 int posted; 943 944 posted = 0; 945 if (SDL_GetEventState(eventType) == SDL_ENABLE) { 946 SDL_Event event; 947 event.type = eventType; 948 posted = (SDL_PushEvent(&event) > 0); 949 } 950 return (posted); 951} 952 953int 954SDL_SendSysWMEvent(SDL_SysWMmsg * message) 955{ 956 int posted; 957 958 posted = 0; 959 if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { 960 SDL_Event event; 961 SDL_memset(&event, 0, sizeof(event)); 962 event.type = SDL_SYSWMEVENT; 963 event.syswm.msg = message; 964 posted = (SDL_PushEvent(&event) > 0); 965 } 966 /* Update internal event state */ 967 return (posted); 968} 969 970int 971SDL_SendKeymapChangedEvent(void) 972{ 973 return SDL_SendAppEvent(SDL_KEYMAPCHANGED); 974} 975 976/* vi: set ts=4 sw=4 expandtab: */ 977[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.