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