comparison src/events/SDL_events.c @ 4429:faa9fc8e7f67

General improvements for user custom event registration * Switched event type to enum (int32) * Switched polling by mask to polling by type range * Added SDL_RegisterEvents() to allow dynamic user event registration * Spread events out to allow inserting new related events without breaking binary compatibility * Added padding to event structures so they're the same size regardless of 32-bit compiler structure packing settings * Split SDL_HasEvent() to SDL_HasEvent() for a single event and SDL_HasEvents() for a range of events * Added SDL_GetEventState() as a shortcut for SDL_EventState(X, SDL_QUERY) * Added SDL_FlushEvent() and SDL_FlushEvents() to clear events from the event queue
author Sam Lantinga <slouken@libsdl.org>
date Thu, 25 Mar 2010 01:08:26 -0700
parents f7b03b6838cb
children 363604b42e84
comparison
equal deleted inserted replaced
4428:68dfd6df47da 4429:faa9fc8e7f67
35 #endif 35 #endif
36 36
37 /* Public data -- the event filter */ 37 /* Public data -- the event filter */
38 SDL_EventFilter SDL_EventOK = NULL; 38 SDL_EventFilter SDL_EventOK = NULL;
39 void *SDL_EventOKParam; 39 void *SDL_EventOKParam;
40 Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; 40
41 static Uint32 SDL_eventstate = 0; 41 typedef struct {
42 Uint32 bits[8];
43 } SDL_DisabledEventBlock;
44
45 static SDL_DisabledEventBlock *SDL_disabled_events[256];
46 static Uint32 SDL_userevents = SDL_USEREVENT;
42 47
43 /* Private data -- event queue */ 48 /* Private data -- event queue */
44 #define MAXEVENTS 128 49 #define MAXEVENTS 128
45 static struct 50 static struct
46 { 51 {
82 if (SDL_EventThread && (SDL_ThreadID() != event_thread)) { 87 if (SDL_EventThread && (SDL_ThreadID() != event_thread)) {
83 SDL_mutexV(SDL_EventLock.lock); 88 SDL_mutexV(SDL_EventLock.lock);
84 } 89 }
85 } 90 }
86 91
92 static __inline__ SDL_bool
93 SDL_ShouldPollJoystick()
94 {
95 if (SDL_numjoysticks &&
96 (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] ||
97 SDL_JoystickEventState(SDL_QUERY))) {
98 return SDL_TRUE;
99 }
100 return SDL_FALSE;
101 }
102
87 static int SDLCALL 103 static int SDLCALL
88 SDL_GobbleEvents(void *unused) 104 SDL_GobbleEvents(void *unused)
89 { 105 {
90 event_thread = SDL_ThreadID(); 106 event_thread = SDL_ThreadID();
91 107
96 if (_this) { 112 if (_this) {
97 _this->PumpEvents(_this); 113 _this->PumpEvents(_this);
98 } 114 }
99 #if !SDL_JOYSTICK_DISABLED 115 #if !SDL_JOYSTICK_DISABLED
100 /* Check for joystick state change */ 116 /* Check for joystick state change */
101 if (SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK)) { 117 if (SDL_ShouldPollJoystick()) {
102 SDL_JoystickUpdate(); 118 SDL_JoystickUpdate();
103 } 119 }
104 #endif 120 #endif
105 121
106 /* Give up the CPU for the rest of our timeslice */ 122 /* Give up the CPU for the rest of our timeslice */
193 /* Public functions */ 209 /* Public functions */
194 210
195 void 211 void
196 SDL_StopEventLoop(void) 212 SDL_StopEventLoop(void)
197 { 213 {
214 int i;
215
198 /* Halt the event thread, if running */ 216 /* Halt the event thread, if running */
199 SDL_StopEventThread(); 217 SDL_StopEventThread();
200 218
201 /* Shutdown event handlers */ 219 /* Shutdown event handlers */
202 SDL_KeyboardQuit(); 220 SDL_KeyboardQuit();
205 223
206 /* Clean out EventQ */ 224 /* Clean out EventQ */
207 SDL_EventQ.head = 0; 225 SDL_EventQ.head = 0;
208 SDL_EventQ.tail = 0; 226 SDL_EventQ.tail = 0;
209 SDL_EventQ.wmmsg_next = 0; 227 SDL_EventQ.wmmsg_next = 0;
228
229 /* Clear disabled event state */
230 for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
231 if (SDL_disabled_events[i]) {
232 SDL_free(SDL_disabled_events[i]);
233 SDL_disabled_events[i] = NULL;
234 }
235 }
210 } 236 }
211 237
212 /* This function (and associated calls) may be called more than once */ 238 /* This function (and associated calls) may be called more than once */
213 int 239 int
214 SDL_StartEventLoop(Uint32 flags) 240 SDL_StartEventLoop(Uint32 flags)
220 SDL_EventQ.lock = NULL; 246 SDL_EventQ.lock = NULL;
221 SDL_StopEventLoop(); 247 SDL_StopEventLoop();
222 248
223 /* No filter to start with, process most event types */ 249 /* No filter to start with, process most event types */
224 SDL_EventOK = NULL; 250 SDL_EventOK = NULL;
225 SDL_memset(SDL_ProcessEvents, SDL_ENABLE, sizeof(SDL_ProcessEvents)); 251 SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
226 SDL_eventstate = ~0;
227 /* It's not save to call SDL_EventState() yet */
228 SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT);
229 SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE;
230 252
231 /* Initialize event handlers */ 253 /* Initialize event handlers */
232 retcode = 0; 254 retcode = 0;
233 retcode += SDL_KeyboardInit(); 255 retcode += SDL_KeyboardInit();
234 retcode += SDL_MouseInit(); 256 retcode += SDL_MouseInit();
303 } 325 }
304 326
305 /* Lock the event queue, take a peep at it, and unlock it */ 327 /* Lock the event queue, take a peep at it, and unlock it */
306 int 328 int
307 SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, 329 SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
308 Uint32 mask) 330 Uint32 minType, Uint32 maxType)
309 { 331 {
310 int i, used; 332 int i, used;
311 333
312 /* Don't look after we've quit */ 334 /* Don't look after we've quit */
313 if (!SDL_EventQ.active) { 335 if (!SDL_EventQ.active) {
330 numevents = 1; 352 numevents = 1;
331 events = &tmpevent; 353 events = &tmpevent;
332 } 354 }
333 spot = SDL_EventQ.head; 355 spot = SDL_EventQ.head;
334 while ((used < numevents) && (spot != SDL_EventQ.tail)) { 356 while ((used < numevents) && (spot != SDL_EventQ.tail)) {
335 if (mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type)) { 357 Uint32 type = SDL_EventQ.event[spot].type;
358 if (minType <= type && type <= maxType) {
336 events[used++] = SDL_EventQ.event[spot]; 359 events[used++] = SDL_EventQ.event[spot];
337 if (action == SDL_GETEVENT) { 360 if (action == SDL_GETEVENT) {
338 spot = SDL_CutEvent(spot); 361 spot = SDL_CutEvent(spot);
339 } else { 362 } else {
340 spot = (spot + 1) % MAXEVENTS; 363 spot = (spot + 1) % MAXEVENTS;
351 } 374 }
352 return (used); 375 return (used);
353 } 376 }
354 377
355 SDL_bool 378 SDL_bool
356 SDL_HasEvent(Uint32 mask) 379 SDL_HasEvent(Uint32 type)
357 { 380 {
358 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask) > 0); 381 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0);
382 }
383
384 SDL_bool
385 SDL_HasEvents(Uint32 minType, Uint32 maxType)
386 {
387 return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0);
388 }
389
390 void
391 SDL_FlushEvent(Uint32 type)
392 {
393 SDL_FlushEvents(type, type);
394 }
395
396 void
397 SDL_FlushEvents(Uint32 minType, Uint32 maxType)
398 {
399 /* Don't look after we've quit */
400 if (!SDL_EventQ.active) {
401 return;
402 }
403
404 /* Lock the event queue */
405 if (SDL_mutexP(SDL_EventQ.lock) == 0) {
406 int spot = SDL_EventQ.head;
407 while (spot != SDL_EventQ.tail) {
408 Uint32 type = SDL_EventQ.event[spot].type;
409 if (minType <= type && type <= maxType) {
410 spot = SDL_CutEvent(spot);
411 } else {
412 spot = (spot + 1) % MAXEVENTS;
413 }
414 }
415 SDL_mutexV(SDL_EventQ.lock);
416 }
359 } 417 }
360 418
361 /* Run the system dependent event loops */ 419 /* Run the system dependent event loops */
362 void 420 void
363 SDL_PumpEvents(void) 421 SDL_PumpEvents(void)
369 if (_this) { 427 if (_this) {
370 _this->PumpEvents(_this); 428 _this->PumpEvents(_this);
371 } 429 }
372 #if !SDL_JOYSTICK_DISABLED 430 #if !SDL_JOYSTICK_DISABLED
373 /* Check for joystick state change */ 431 /* Check for joystick state change */
374 if (SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK)) { 432 if (SDL_ShouldPollJoystick()) {
375 SDL_JoystickUpdate(); 433 SDL_JoystickUpdate();
376 } 434 }
377 #endif 435 #endif
378 } 436 }
379 } 437 }
400 if (timeout > 0) 458 if (timeout > 0)
401 expiration = SDL_GetTicks() + timeout; 459 expiration = SDL_GetTicks() + timeout;
402 460
403 for (;;) { 461 for (;;) {
404 SDL_PumpEvents(); 462 SDL_PumpEvents();
405 switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) { 463 switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
406 case -1: 464 case -1:
407 return 0; 465 return 0;
408 case 1: 466 case 1:
409 return 1; 467 return 1;
410 case 0: 468 case 0:
426 SDL_PushEvent(SDL_Event * event) 484 SDL_PushEvent(SDL_Event * event)
427 { 485 {
428 if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) { 486 if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) {
429 return 0; 487 return 0;
430 } 488 }
431 if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0) <= 0) { 489 if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) {
432 return -1; 490 return -1;
433 } 491 }
434 return 1; 492 return 1;
435 } 493 }
436 494
474 } 532 }
475 SDL_mutexV(SDL_EventQ.lock); 533 SDL_mutexV(SDL_EventQ.lock);
476 } 534 }
477 535
478 Uint8 536 Uint8
479 SDL_EventState(Uint8 type, int state) 537 SDL_EventState(Uint32 type, int state)
480 { 538 {
481 SDL_Event bitbucket;
482 Uint8 current_state; 539 Uint8 current_state;
483 540 Uint8 hi = ((type >> 8) & 0xff);
484 /* If SDL_ALLEVENTS was specified... */ 541 Uint8 lo = (type & 0xff);
485 if (type == 0xFF) { 542
486 current_state = SDL_IGNORE; 543 if (SDL_disabled_events[hi] &&
487 for (type = 0; type < SDL_NUMEVENTS; ++type) { 544 (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) {
488 if (SDL_ProcessEvents[type] != SDL_IGNORE) { 545 current_state = SDL_DISABLE;
489 current_state = SDL_ENABLE; 546 } else {
490 } 547 current_state = SDL_ENABLE;
491 SDL_ProcessEvents[type] = state; 548 }
492 if (state == SDL_ENABLE) { 549
493 SDL_eventstate |= (0x00000001 << (type)); 550 if (state != current_state)
494 } else { 551 {
495 SDL_eventstate &= ~(0x00000001 << (type)); 552 switch (state) {
496 } 553 case SDL_DISABLE:
497 } 554 /* Disable this event type and discard pending events */
498 while (SDL_PollEvent(&bitbucket) > 0); 555 if (!SDL_disabled_events[hi]) {
499 return (current_state); 556 SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock));
500 } 557 if (!SDL_disabled_events[hi]) {
501 558 /* Out of memory, nothing we can do... */
502 /* Just set the state for one event type */ 559 break;
503 current_state = SDL_ProcessEvents[type]; 560 }
504 switch (state) { 561 }
505 case SDL_IGNORE: 562 SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31));
506 case SDL_ENABLE: 563 SDL_FlushEvent(type);
507 /* Set state and discard pending events */ 564 break;
508 SDL_ProcessEvents[type] = state; 565 case SDL_ENABLE:
509 if (state == SDL_ENABLE) { 566 SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31));
510 SDL_eventstate |= (0x00000001 << (type)); 567 break;
511 } else { 568 default:
512 SDL_eventstate &= ~(0x00000001 << (type)); 569 /* Querying state... */
513 } 570 break;
514 while (SDL_PollEvent(&bitbucket) > 0); 571 }
515 break; 572 }
516 default: 573
517 /* Querying state? */ 574 return current_state;
518 break; 575 }
519 } 576
520 return (current_state); 577 Uint32
578 SDL_RegisterEvents(int numevents)
579 {
580 Uint32 event_base;
581
582 if (SDL_userevents+numevents <= SDL_LASTEVENT) {
583 event_base = SDL_userevents;
584 SDL_userevents += numevents;
585 } else {
586 event_base = (Uint32)-1;
587 }
588 return event_base;
521 } 589 }
522 590
523 /* This is a generic event handler. 591 /* This is a generic event handler.
524 */ 592 */
525 int 593 int
526 SDL_SendSysWMEvent(SDL_SysWMmsg * message) 594 SDL_SendSysWMEvent(SDL_SysWMmsg * message)
527 { 595 {
528 int posted; 596 int posted;
529 597
530 posted = 0; 598 posted = 0;
531 if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { 599 if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
532 SDL_Event event; 600 SDL_Event event;
533 SDL_memset(&event, 0, sizeof(event)); 601 SDL_memset(&event, 0, sizeof(event));
534 event.type = SDL_SYSWMEVENT; 602 event.type = SDL_SYSWMEVENT;
535 event.syswm.msg = message; 603 event.syswm.msg = message;
536 posted = (SDL_PushEvent(&event) > 0); 604 posted = (SDL_PushEvent(&event) > 0);