Mercurial > sdl-ios-xcode
diff 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 |
line wrap: on
line diff
--- a/src/events/SDL_events.c Wed Mar 10 15:07:20 2010 +0000 +++ b/src/events/SDL_events.c Thu Mar 25 01:08:26 2010 -0700 @@ -37,8 +37,13 @@ /* Public data -- the event filter */ SDL_EventFilter SDL_EventOK = NULL; void *SDL_EventOKParam; -Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; -static Uint32 SDL_eventstate = 0; + +typedef struct { + Uint32 bits[8]; +} SDL_DisabledEventBlock; + +static SDL_DisabledEventBlock *SDL_disabled_events[256]; +static Uint32 SDL_userevents = SDL_USEREVENT; /* Private data -- event queue */ #define MAXEVENTS 128 @@ -84,6 +89,17 @@ } } +static __inline__ SDL_bool +SDL_ShouldPollJoystick() +{ + if (SDL_numjoysticks && + (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || + SDL_JoystickEventState(SDL_QUERY))) { + return SDL_TRUE; + } + return SDL_FALSE; +} + static int SDLCALL SDL_GobbleEvents(void *unused) { @@ -98,7 +114,7 @@ } #if !SDL_JOYSTICK_DISABLED /* Check for joystick state change */ - if (SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK)) { + if (SDL_ShouldPollJoystick()) { SDL_JoystickUpdate(); } #endif @@ -195,6 +211,8 @@ void SDL_StopEventLoop(void) { + int i; + /* Halt the event thread, if running */ SDL_StopEventThread(); @@ -207,6 +225,14 @@ SDL_EventQ.head = 0; SDL_EventQ.tail = 0; SDL_EventQ.wmmsg_next = 0; + + /* Clear disabled event state */ + for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) { + if (SDL_disabled_events[i]) { + SDL_free(SDL_disabled_events[i]); + SDL_disabled_events[i] = NULL; + } + } } /* This function (and associated calls) may be called more than once */ @@ -222,11 +248,7 @@ /* No filter to start with, process most event types */ SDL_EventOK = NULL; - SDL_memset(SDL_ProcessEvents, SDL_ENABLE, sizeof(SDL_ProcessEvents)); - SDL_eventstate = ~0; - /* It's not save to call SDL_EventState() yet */ - SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT); - SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE; + SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE); /* Initialize event handlers */ retcode = 0; @@ -305,7 +327,7 @@ /* Lock the event queue, take a peep at it, and unlock it */ int SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, - Uint32 mask) + Uint32 minType, Uint32 maxType) { int i, used; @@ -332,7 +354,8 @@ } spot = SDL_EventQ.head; while ((used < numevents) && (spot != SDL_EventQ.tail)) { - if (mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type)) { + Uint32 type = SDL_EventQ.event[spot].type; + if (minType <= type && type <= maxType) { events[used++] = SDL_EventQ.event[spot]; if (action == SDL_GETEVENT) { spot = SDL_CutEvent(spot); @@ -353,9 +376,44 @@ } SDL_bool -SDL_HasEvent(Uint32 mask) +SDL_HasEvent(Uint32 type) +{ + return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, type, type) > 0); +} + +SDL_bool +SDL_HasEvents(Uint32 minType, Uint32 maxType) +{ + return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, minType, maxType) > 0); +} + +void +SDL_FlushEvent(Uint32 type) { - return (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask) > 0); + SDL_FlushEvents(type, type); +} + +void +SDL_FlushEvents(Uint32 minType, Uint32 maxType) +{ + /* Don't look after we've quit */ + if (!SDL_EventQ.active) { + return; + } + + /* Lock the event queue */ + if (SDL_mutexP(SDL_EventQ.lock) == 0) { + int spot = SDL_EventQ.head; + while (spot != SDL_EventQ.tail) { + Uint32 type = SDL_EventQ.event[spot].type; + if (minType <= type && type <= maxType) { + spot = SDL_CutEvent(spot); + } else { + spot = (spot + 1) % MAXEVENTS; + } + } + SDL_mutexV(SDL_EventQ.lock); + } } /* Run the system dependent event loops */ @@ -371,7 +429,7 @@ } #if !SDL_JOYSTICK_DISABLED /* Check for joystick state change */ - if (SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK)) { + if (SDL_ShouldPollJoystick()) { SDL_JoystickUpdate(); } #endif @@ -402,7 +460,7 @@ for (;;) { SDL_PumpEvents(); - switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) { + switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { case -1: return 0; case 1: @@ -428,7 +486,7 @@ if (SDL_EventOK && !SDL_EventOK(SDL_EventOKParam, event)) { return 0; } - if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0) <= 0) { + if (SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0, 0) <= 0) { return -1; } return 1; @@ -476,48 +534,58 @@ } Uint8 -SDL_EventState(Uint8 type, int state) +SDL_EventState(Uint32 type, int state) { - SDL_Event bitbucket; Uint8 current_state; + Uint8 hi = ((type >> 8) & 0xff); + Uint8 lo = (type & 0xff); - /* If SDL_ALLEVENTS was specified... */ - if (type == 0xFF) { - current_state = SDL_IGNORE; - for (type = 0; type < SDL_NUMEVENTS; ++type) { - if (SDL_ProcessEvents[type] != SDL_IGNORE) { - current_state = SDL_ENABLE; - } - SDL_ProcessEvents[type] = state; - if (state == SDL_ENABLE) { - SDL_eventstate |= (0x00000001 << (type)); - } else { - SDL_eventstate &= ~(0x00000001 << (type)); - } - } - while (SDL_PollEvent(&bitbucket) > 0); - return (current_state); + if (SDL_disabled_events[hi] && + (SDL_disabled_events[hi]->bits[lo/32] & (1 << (lo&31)))) { + current_state = SDL_DISABLE; + } else { + current_state = SDL_ENABLE; } - /* Just set the state for one event type */ - current_state = SDL_ProcessEvents[type]; - switch (state) { - case SDL_IGNORE: - case SDL_ENABLE: - /* Set state and discard pending events */ - SDL_ProcessEvents[type] = state; - if (state == SDL_ENABLE) { - SDL_eventstate |= (0x00000001 << (type)); - } else { - SDL_eventstate &= ~(0x00000001 << (type)); + if (state != current_state) + { + switch (state) { + case SDL_DISABLE: + /* Disable this event type and discard pending events */ + if (!SDL_disabled_events[hi]) { + SDL_disabled_events[hi] = (SDL_DisabledEventBlock*) SDL_calloc(1, sizeof(SDL_DisabledEventBlock)); + if (!SDL_disabled_events[hi]) { + /* Out of memory, nothing we can do... */ + break; + } + } + SDL_disabled_events[hi]->bits[lo/32] |= (1 << (lo&31)); + SDL_FlushEvent(type); + break; + case SDL_ENABLE: + SDL_disabled_events[hi]->bits[lo/32] &= ~(1 << (lo&31)); + break; + default: + /* Querying state... */ + break; } - while (SDL_PollEvent(&bitbucket) > 0); - break; - default: - /* Querying state? */ - break; } - return (current_state); + + return current_state; +} + +Uint32 +SDL_RegisterEvents(int numevents) +{ + Uint32 event_base; + + if (SDL_userevents+numevents <= SDL_LASTEVENT) { + event_base = SDL_userevents; + SDL_userevents += numevents; + } else { + event_base = (Uint32)-1; + } + return event_base; } /* This is a generic event handler. @@ -528,7 +596,7 @@ int posted; posted = 0; - if (SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE) { + if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) { SDL_Event event; SDL_memset(&event, 0, sizeof(event)); event.type = SDL_SYSWMEVENT;