Mercurial > sdl-ios-xcode
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); |