Mercurial > sdl-ios-xcode
annotate src/events/SDL_events.c @ 1118:65f4b2dd46b7
Date: Wed, 17 Aug 2005 11:23:40 -0400
From: Matt L <prometheus.uw@gmail.com>
To: "Ryan C. Gordon" <icculus@clutteredmind.org>
Subject: SDL Patch
Hio,
I saw your last call on the mailing list. Here's a patch which I
submitted about two weeks ago which hasn't made it in.
In the current sdl.m4, there's a bug where if your configure.ac, you
have AC_LANG(C++) specified, it won't properly compile and link the SDL
test program when you run the configure script. This is because only the
default CFLAGS is overriden in sdl.m4, and in the patch below, I've
fixed it so it overrides CXXFLAGS as well, allowing it to work with g++.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Thu, 18 Aug 2005 06:06:02 +0000 |
parents | 5ba65305c954 |
children | 28ac87a38c17 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
384
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* General event handling code for SDL */ | |
29 | |
30 #include <stdio.h> | |
31 #include <string.h> | |
32 | |
33 #include "SDL.h" | |
34 #include "SDL_thread.h" | |
35 #include "SDL_mutex.h" | |
36 #include "SDL_events.h" | |
37 #include "SDL_events_c.h" | |
38 #include "SDL_timer_c.h" | |
39 #ifndef DISABLE_JOYSTICK | |
40 #include "SDL_joystick_c.h" | |
41 #endif | |
42 #ifndef ENABLE_X11 | |
43 #define DISABLE_X11 | |
44 #endif | |
45 #include "SDL_syswm.h" | |
46 #include "SDL_sysevents.h" | |
47 | |
48 /* Public data -- the event filter */ | |
49 SDL_EventFilter SDL_EventOK = NULL; | |
50 Uint8 SDL_ProcessEvents[SDL_NUMEVENTS]; | |
51 static Uint32 SDL_eventstate = 0; | |
52 | |
53 /* Private data -- event queue */ | |
54 #define MAXEVENTS 128 | |
55 static struct { | |
56 SDL_mutex *lock; | |
57 int active; | |
58 int head; | |
59 int tail; | |
60 SDL_Event event[MAXEVENTS]; | |
61 int wmmsg_next; | |
62 struct SDL_SysWMmsg wmmsg[MAXEVENTS]; | |
63 } SDL_EventQ; | |
64 | |
65 /* Private data -- event locking structure */ | |
66 static struct { | |
67 SDL_mutex *lock; | |
68 int safe; | |
69 } SDL_EventLock; | |
70 | |
71 /* Thread functions */ | |
72 static SDL_Thread *SDL_EventThread = NULL; /* Thread handle */ | |
73 static Uint32 event_thread; /* The event thread id */ | |
74 | |
75 void SDL_Lock_EventThread(void) | |
76 { | |
77 if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) { | |
78 /* Grab lock and spin until we're sure event thread stopped */ | |
79 SDL_mutexP(SDL_EventLock.lock); | |
80 while ( ! SDL_EventLock.safe ) { | |
81 SDL_Delay(1); | |
82 } | |
83 } | |
84 } | |
85 void SDL_Unlock_EventThread(void) | |
86 { | |
87 if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) { | |
88 SDL_mutexV(SDL_EventLock.lock); | |
89 } | |
90 } | |
91 | |
92 static int SDL_GobbleEvents(void *unused) | |
93 { | |
94 event_thread = SDL_ThreadID(); | |
95 while ( SDL_EventQ.active ) { | |
96 SDL_VideoDevice *video = current_video; | |
97 SDL_VideoDevice *this = current_video; | |
98 | |
99 /* Get events from the video subsystem */ | |
100 if ( video ) { | |
101 video->PumpEvents(this); | |
102 } | |
103 | |
104 /* Queue pending key-repeat events */ | |
105 SDL_CheckKeyRepeat(); | |
106 | |
107 #ifndef DISABLE_JOYSTICK | |
108 /* Check for joystick state change */ | |
109 if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) { | |
110 SDL_JoystickUpdate(); | |
111 } | |
112 #endif | |
113 | |
114 /* Give up the CPU for the rest of our timeslice */ | |
115 SDL_EventLock.safe = 1; | |
1028
5ba65305c954
Fix various problems with the timer code.
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
116 if ( SDL_timer_running ) { |
0 | 117 SDL_ThreadedTimerCheck(); |
118 } | |
119 SDL_Delay(1); | |
120 | |
121 /* Check for event locking. | |
122 On the P of the lock mutex, if the lock is held, this thread | |
123 will wait until the lock is released before continuing. The | |
124 safe flag will be set, meaning that the other thread can go | |
125 about it's business. The safe flag is reset before the V, | |
126 so as soon as the mutex is free, other threads can see that | |
127 it's not safe to interfere with the event thread. | |
128 */ | |
129 SDL_mutexP(SDL_EventLock.lock); | |
130 SDL_EventLock.safe = 0; | |
131 SDL_mutexV(SDL_EventLock.lock); | |
132 } | |
133 SDL_SetTimerThreaded(0); | |
134 event_thread = 0; | |
135 return(0); | |
136 } | |
137 | |
138 static int SDL_StartEventThread(Uint32 flags) | |
139 { | |
140 /* Reset everything to zero */ | |
141 SDL_EventThread = NULL; | |
142 memset(&SDL_EventLock, 0, sizeof(SDL_EventLock)); | |
143 | |
144 /* Create the lock and set ourselves active */ | |
145 #ifndef DISABLE_THREADS | |
146 SDL_EventQ.lock = SDL_CreateMutex(); | |
147 if ( SDL_EventQ.lock == NULL ) { | |
148 #ifdef macintosh /* On MacOS 7/8, you can't multithread, so no lock needed */ | |
149 ; | |
150 #else | |
151 return(-1); | |
152 #endif | |
153 } | |
154 #endif /* !DISABLE_THREADS */ | |
155 SDL_EventQ.active = 1; | |
156 | |
157 if ( (flags&SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) { | |
158 SDL_EventLock.lock = SDL_CreateMutex(); | |
159 if ( SDL_EventLock.lock == NULL ) { | |
160 return(-1); | |
161 } | |
162 SDL_EventLock.safe = 0; | |
163 | |
1028
5ba65305c954
Fix various problems with the timer code.
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
164 /* The event thread will handle timers too */ |
5ba65305c954
Fix various problems with the timer code.
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
165 SDL_SetTimerThreaded(2); |
0 | 166 SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL); |
167 if ( SDL_EventThread == NULL ) { | |
168 return(-1); | |
169 } | |
170 } else { | |
171 event_thread = 0; | |
172 } | |
173 return(0); | |
174 } | |
175 | |
176 static void SDL_StopEventThread(void) | |
177 { | |
178 SDL_EventQ.active = 0; | |
179 if ( SDL_EventThread ) { | |
180 SDL_WaitThread(SDL_EventThread, NULL); | |
181 SDL_EventThread = NULL; | |
182 SDL_DestroyMutex(SDL_EventLock.lock); | |
183 } | |
184 SDL_DestroyMutex(SDL_EventQ.lock); | |
185 } | |
186 | |
187 Uint32 SDL_EventThreadID(void) | |
188 { | |
189 return(event_thread); | |
190 } | |
191 | |
192 /* Public functions */ | |
193 | |
194 void SDL_StopEventLoop(void) | |
195 { | |
196 /* Halt the event thread, if running */ | |
197 SDL_StopEventThread(); | |
198 | |
199 /* Clean out EventQ */ | |
200 SDL_EventQ.head = 0; | |
201 SDL_EventQ.tail = 0; | |
202 SDL_EventQ.wmmsg_next = 0; | |
203 } | |
204 | |
205 /* This function (and associated calls) may be called more than once */ | |
206 int SDL_StartEventLoop(Uint32 flags) | |
207 { | |
208 int retcode; | |
209 | |
210 /* Clean out the event queue */ | |
211 SDL_EventThread = NULL; | |
212 SDL_EventQ.lock = NULL; | |
213 SDL_StopEventLoop(); | |
214 | |
215 /* No filter to start with, process most event types */ | |
216 SDL_EventOK = NULL; | |
217 memset(SDL_ProcessEvents,SDL_ENABLE,sizeof(SDL_ProcessEvents)); | |
218 SDL_eventstate = ~0; | |
219 /* It's not save to call SDL_EventState() yet */ | |
220 SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT); | |
221 SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE; | |
222 | |
223 /* Initialize event handlers */ | |
224 retcode = 0; | |
225 retcode += SDL_AppActiveInit(); | |
226 retcode += SDL_KeyboardInit(); | |
227 retcode += SDL_MouseInit(); | |
228 retcode += SDL_QuitInit(); | |
229 if ( retcode < 0 ) { | |
230 /* We don't expect them to fail, but... */ | |
231 return(-1); | |
232 } | |
233 | |
234 /* Create the lock and event thread */ | |
235 if ( SDL_StartEventThread(flags) < 0 ) { | |
236 SDL_StopEventLoop(); | |
237 return(-1); | |
238 } | |
239 return(0); | |
240 } | |
241 | |
242 | |
243 /* Add an event to the event queue -- called with the queue locked */ | |
244 static int SDL_AddEvent(SDL_Event *event) | |
245 { | |
246 int tail, added; | |
247 | |
248 tail = (SDL_EventQ.tail+1)%MAXEVENTS; | |
249 if ( tail == SDL_EventQ.head ) { | |
250 /* Overflow, drop event */ | |
251 added = 0; | |
252 } else { | |
253 SDL_EventQ.event[SDL_EventQ.tail] = *event; | |
254 if (event->type == SDL_SYSWMEVENT) { | |
255 /* Note that it's possible to lose an event */ | |
256 int next = SDL_EventQ.wmmsg_next; | |
257 SDL_EventQ.wmmsg[next] = *event->syswm.msg; | |
258 SDL_EventQ.event[SDL_EventQ.tail].syswm.msg = | |
259 &SDL_EventQ.wmmsg[next]; | |
260 SDL_EventQ.wmmsg_next = (next+1)%MAXEVENTS; | |
261 } | |
262 SDL_EventQ.tail = tail; | |
263 added = 1; | |
264 } | |
265 return(added); | |
266 } | |
267 | |
268 /* Cut an event, and return the next valid spot, or the tail */ | |
269 /* -- called with the queue locked */ | |
270 static int SDL_CutEvent(int spot) | |
271 { | |
272 if ( spot == SDL_EventQ.head ) { | |
273 SDL_EventQ.head = (SDL_EventQ.head+1)%MAXEVENTS; | |
274 return(SDL_EventQ.head); | |
275 } else | |
276 if ( (spot+1)%MAXEVENTS == SDL_EventQ.tail ) { | |
277 SDL_EventQ.tail = spot; | |
278 return(SDL_EventQ.tail); | |
279 } else | |
280 /* We cut the middle -- shift everything over */ | |
281 { | |
282 int here, next; | |
283 | |
284 /* This can probably be optimized with memcpy() -- careful! */ | |
285 if ( --SDL_EventQ.tail < 0 ) { | |
286 SDL_EventQ.tail = MAXEVENTS-1; | |
287 } | |
288 for ( here=spot; here != SDL_EventQ.tail; here = next ) { | |
289 next = (here+1)%MAXEVENTS; | |
290 SDL_EventQ.event[here] = SDL_EventQ.event[next]; | |
291 } | |
292 return(spot); | |
293 } | |
294 /* NOTREACHED */ | |
295 } | |
296 | |
297 /* Lock the event queue, take a peep at it, and unlock it */ | |
298 int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action, | |
299 Uint32 mask) | |
300 { | |
301 int i, used; | |
302 | |
303 /* Don't look after we've quit */ | |
304 if ( ! SDL_EventQ.active ) { | |
276
8af85680ca0a
Updated the documentation for the SDL_PushEvent() call.
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
305 return(-1); |
0 | 306 } |
307 /* Lock the event queue */ | |
308 used = 0; | |
309 if ( SDL_mutexP(SDL_EventQ.lock) == 0 ) { | |
310 if ( action == SDL_ADDEVENT ) { | |
311 for ( i=0; i<numevents; ++i ) { | |
312 used += SDL_AddEvent(&events[i]); | |
313 } | |
314 } else { | |
315 SDL_Event tmpevent; | |
316 int spot; | |
317 | |
318 /* If 'events' is NULL, just see if they exist */ | |
319 if ( events == NULL ) { | |
320 action = SDL_PEEKEVENT; | |
321 numevents = 1; | |
322 events = &tmpevent; | |
323 } | |
324 spot = SDL_EventQ.head; | |
325 while ((used < numevents)&&(spot != SDL_EventQ.tail)) { | |
326 if ( mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type) ) { | |
327 events[used++] = SDL_EventQ.event[spot]; | |
328 if ( action == SDL_GETEVENT ) { | |
329 spot = SDL_CutEvent(spot); | |
330 } else { | |
331 spot = (spot+1)%MAXEVENTS; | |
332 } | |
333 } else { | |
334 spot = (spot+1)%MAXEVENTS; | |
335 } | |
336 } | |
337 } | |
338 SDL_mutexV(SDL_EventQ.lock); | |
339 } else { | |
340 SDL_SetError("Couldn't lock event queue"); | |
341 used = -1; | |
342 } | |
343 return(used); | |
344 } | |
345 | |
346 /* Run the system dependent event loops */ | |
347 void SDL_PumpEvents(void) | |
348 { | |
349 if ( !SDL_EventThread ) { | |
350 SDL_VideoDevice *video = current_video; | |
351 SDL_VideoDevice *this = current_video; | |
352 | |
353 /* Get events from the video subsystem */ | |
354 if ( video ) { | |
355 video->PumpEvents(this); | |
356 } | |
357 | |
358 /* Queue pending key-repeat events */ | |
359 SDL_CheckKeyRepeat(); | |
360 | |
361 #ifndef DISABLE_JOYSTICK | |
362 /* Check for joystick state change */ | |
363 if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) { | |
364 SDL_JoystickUpdate(); | |
365 } | |
366 #endif | |
367 } | |
368 } | |
369 | |
370 /* Public functions */ | |
371 | |
372 int SDL_PollEvent (SDL_Event *event) | |
373 { | |
374 SDL_PumpEvents(); | |
375 | |
352
b49fc922e7f6
Fixed SDL_PollEvent() so it only returns a boolean value (not -1)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
376 /* We can't return -1, just return 0 (no event) on error */ |
b49fc922e7f6
Fixed SDL_PollEvent() so it only returns a boolean value (not -1)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
377 if ( SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS) <= 0 ) |
b49fc922e7f6
Fixed SDL_PollEvent() so it only returns a boolean value (not -1)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
378 return 0; |
b49fc922e7f6
Fixed SDL_PollEvent() so it only returns a boolean value (not -1)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
379 return 1; |
0 | 380 } |
381 | |
382 int SDL_WaitEvent (SDL_Event *event) | |
383 { | |
384 while ( 1 ) { | |
385 SDL_PumpEvents(); | |
386 switch(SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) { | |
353
d47637068e52
The documented error return value for SDL_WaitEvent() is 0.
Sam Lantinga <slouken@libsdl.org>
parents:
352
diff
changeset
|
387 case -1: return 0; |
0 | 388 case 1: return 1; |
389 case 0: SDL_Delay(10); | |
390 } | |
391 } | |
392 } | |
393 | |
394 int SDL_PushEvent(SDL_Event *event) | |
395 { | |
384 | 396 if ( SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0) <= 0 ) |
397 return -1; | |
398 return 0; | |
0 | 399 } |
400 | |
401 void SDL_SetEventFilter (SDL_EventFilter filter) | |
402 { | |
403 SDL_Event bitbucket; | |
404 | |
405 /* Set filter and discard pending events */ | |
406 SDL_EventOK = filter; | |
407 while ( SDL_PollEvent(&bitbucket) > 0 ) | |
408 ; | |
409 } | |
410 | |
411 SDL_EventFilter SDL_GetEventFilter(void) | |
412 { | |
413 return(SDL_EventOK); | |
414 } | |
415 | |
416 Uint8 SDL_EventState (Uint8 type, int state) | |
417 { | |
418 SDL_Event bitbucket; | |
419 Uint8 current_state; | |
420 | |
421 /* If SDL_ALLEVENTS was specified... */ | |
422 if ( type == 0xFF ) { | |
423 current_state = SDL_IGNORE; | |
424 for ( type=0; type<SDL_NUMEVENTS; ++type ) { | |
425 if ( SDL_ProcessEvents[type] != SDL_IGNORE ) { | |
426 current_state = SDL_ENABLE; | |
427 } | |
428 SDL_ProcessEvents[type] = state; | |
429 if ( state == SDL_ENABLE ) { | |
430 SDL_eventstate |= (0x00000001 << (type)); | |
431 } else { | |
432 SDL_eventstate &= ~(0x00000001 << (type)); | |
433 } | |
434 } | |
435 while ( SDL_PollEvent(&bitbucket) > 0 ) | |
436 ; | |
437 return(current_state); | |
438 } | |
439 | |
440 /* Just set the state for one event type */ | |
441 current_state = SDL_ProcessEvents[type]; | |
442 switch (state) { | |
443 case SDL_IGNORE: | |
444 case SDL_ENABLE: | |
445 /* Set state and discard pending events */ | |
446 SDL_ProcessEvents[type] = state; | |
447 if ( state == SDL_ENABLE ) { | |
448 SDL_eventstate |= (0x00000001 << (type)); | |
449 } else { | |
450 SDL_eventstate &= ~(0x00000001 << (type)); | |
451 } | |
452 while ( SDL_PollEvent(&bitbucket) > 0 ) | |
453 ; | |
454 break; | |
455 default: | |
456 /* Querying state? */ | |
457 break; | |
458 } | |
459 return(current_state); | |
460 } | |
461 | |
462 /* This is a generic event handler. | |
463 */ | |
464 int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message) | |
465 { | |
466 int posted; | |
467 | |
468 posted = 0; | |
469 if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) { | |
470 SDL_Event event; | |
471 memset(&event, 0, sizeof(event)); | |
472 event.type = SDL_SYSWMEVENT; | |
473 event.syswm.msg = message; | |
474 if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) { | |
475 posted = 1; | |
476 SDL_PushEvent(&event); | |
477 } | |
478 } | |
479 /* Update internal event state */ | |
480 return(posted); | |
481 } |