Mercurial > sdl-ios-xcode
annotate test/threadwin.c @ 1348:40d0975c1769
Date: Mon, 6 Feb 2006 11:41:04 -0500
From: "mystml@adinet.com.uy"
Subject: [SDL] ALT-F4 using DirectX
My game isn't getting SDL_QUIT when I press ALT-F4 using the DirectX
driver; it does get SDL_QUIT when I press the red X in the window.
I tracked this down to DX5_HandleMessage() in SDL_dx5events.c;
WM_SYSKEYDOWN is being trapped and ignored which causes Windows not to post
a WM_CLOSE, hence no SDL_QUIT is being generated.
The relevant code is this :
/* The keyboard is handled via DirectInput */
case WM_SYSKEYUP:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_KEYDOWN: {
/* Ignore windows keyboard messages */;
}
return(0);
If I comment the WM_SYSKEYDOWN case, it falls through DefWindowProc() and
ALT-F4 starts working again.
I'm not sure about the best way to fix this. One option is handling ALT-F4
as a particular case somehow, but doesn't sound good. Another option would
be to handle WM_SYSKEYDOWN separately and breaking instead of returning 0,
so processing falls through and goes to DefWindowProc which does The Right
Thing (TM). This seems to be the minimal change that makes ALT-F4 work and
normal keyboard input continues to work.
Does this sound reasonable? Am I overlooking anything? Do I submit a patch?
--Gabriel
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Wed, 08 Feb 2006 17:19:43 +0000 |
parents | be9c9c8f6d53 |
children | 14717b52abc0 |
rev | line source |
---|---|
0 | 1 |
2 /* Test out the multi-threaded event handling functions */ | |
3 | |
4 #include <stdlib.h> | |
5 #include <stdio.h> | |
6 #include <string.h> | |
7 | |
8 #include "SDL.h" | |
9 #include "SDL_thread.h" | |
10 | |
11 /* Are we done yet? */ | |
12 static int done = 0; | |
13 | |
14 /* Is the cursor visible? */ | |
15 static int visible = 1; | |
16 | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
17 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
18 static void quit(int rc) |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
19 { |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
20 SDL_Quit(); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
21 exit(rc); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
22 } |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
23 |
0 | 24 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp) |
25 { | |
26 SDL_Surface *icon; | |
27 Uint8 *pixels; | |
28 Uint8 *mask; | |
29 int mlen, i; | |
30 | |
31 *maskp = NULL; | |
32 | |
33 /* Load the icon surface */ | |
34 icon = SDL_LoadBMP(file); | |
35 if ( icon == NULL ) { | |
36 fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError()); | |
37 return(NULL); | |
38 } | |
39 | |
40 /* Check width and height */ | |
41 if ( (icon->w%8) != 0 ) { | |
42 fprintf(stderr, "Icon width must be a multiple of 8!\n"); | |
43 SDL_FreeSurface(icon); | |
44 return(NULL); | |
45 } | |
46 if ( icon->format->palette == NULL ) { | |
47 fprintf(stderr, "Icon must have a palette!\n"); | |
48 SDL_FreeSurface(icon); | |
49 return(NULL); | |
50 } | |
51 | |
52 /* Set the colorkey */ | |
53 SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels)); | |
54 | |
55 /* Create the mask */ | |
56 pixels = (Uint8 *)icon->pixels; | |
57 printf("Transparent pixel: (%d,%d,%d)\n", | |
58 icon->format->palette->colors[*pixels].r, | |
59 icon->format->palette->colors[*pixels].g, | |
60 icon->format->palette->colors[*pixels].b); | |
61 mlen = icon->w*icon->h; | |
62 mask = (Uint8 *)malloc(mlen/8); | |
63 if ( mask == NULL ) { | |
64 fprintf(stderr, "Out of memory!\n"); | |
65 SDL_FreeSurface(icon); | |
66 return(NULL); | |
67 } | |
68 memset(mask, 0, mlen/8); | |
69 for ( i=0; i<mlen; ) { | |
70 if ( pixels[i] != *pixels ) | |
71 mask[i/8] |= 0x01; | |
72 ++i; | |
73 if ( (i%8) != 0 ) | |
74 mask[i/8] <<= 1; | |
75 } | |
76 *maskp = mask; | |
77 return(icon); | |
78 } | |
79 | |
80 int FilterEvents(const SDL_Event *event) | |
81 { | |
82 static int reallyquit = 0; | |
83 | |
84 switch (event->type) { | |
85 | |
86 case SDL_ACTIVEEVENT: | |
87 /* See what happened */ | |
88 printf("App %s ", | |
89 event->active.gain ? "gained" : "lost"); | |
90 if ( event->active.state & SDL_APPACTIVE ) | |
91 printf("active "); | |
92 if ( event->active.state & SDL_APPMOUSEFOCUS ) | |
93 printf("mouse "); | |
94 if ( event->active.state & SDL_APPINPUTFOCUS ) | |
95 printf("input "); | |
96 printf("focus\n"); | |
97 | |
98 /* See if we are iconified or restored */ | |
99 if ( event->active.state & SDL_APPACTIVE ) { | |
100 printf("App has been %s\n", | |
101 event->active.gain ? | |
102 "restored" : "iconified"); | |
103 } | |
104 return(0); | |
105 | |
106 /* This is important! Queue it if we want to quit. */ | |
107 case SDL_QUIT: | |
108 if ( ! reallyquit ) { | |
109 reallyquit = 1; | |
110 printf("Quit requested\n"); | |
111 return(0); | |
112 } | |
113 printf("Quit demanded\n"); | |
114 return(1); | |
115 | |
116 /* Mouse and keyboard events go to threads */ | |
117 case SDL_MOUSEMOTION: | |
118 case SDL_MOUSEBUTTONDOWN: | |
119 case SDL_MOUSEBUTTONUP: | |
120 case SDL_KEYDOWN: | |
121 case SDL_KEYUP: | |
122 return(1); | |
123 | |
124 /* Drop all other events */ | |
125 default: | |
126 return(0); | |
127 } | |
128 } | |
129 | |
130 int HandleMouse(void *unused) | |
131 { | |
132 SDL_Event events[10]; | |
133 int i, found; | |
134 Uint32 mask; | |
135 | |
136 /* Handle mouse events here */ | |
137 mask = (SDL_MOUSEMOTIONMASK|SDL_MOUSEBUTTONDOWNMASK|SDL_MOUSEBUTTONUPMASK); | |
138 while ( ! done ) { | |
139 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask); | |
140 for ( i=0; i<found; ++i ) { | |
141 switch(events[i].type) { | |
142 /* We want to toggle visibility on buttonpress */ | |
143 case SDL_MOUSEBUTTONDOWN: | |
144 case SDL_MOUSEBUTTONUP: | |
145 if ( events[i].button.state == SDL_PRESSED ) { | |
146 visible = !visible; | |
147 SDL_ShowCursor(visible); | |
148 } | |
149 printf("Mouse button %d has been %s\n", | |
150 events[i].button.button, | |
151 (events[i].button.state == SDL_PRESSED) ? | |
152 "pressed" : "released"); | |
153 break; | |
154 /* Show relative mouse motion */ | |
155 case SDL_MOUSEMOTION: | |
156 printf("Mouse relative motion: {%d,%d}\n", | |
157 events[i].motion.xrel, events[i].motion.yrel); | |
158 break; | |
159 } | |
160 } | |
161 /* Give up some CPU to allow events to arrive */ | |
162 SDL_Delay(20); | |
163 } | |
164 return(0); | |
165 } | |
166 | |
167 int HandleKeyboard(void *unused) | |
168 { | |
169 SDL_Event events[10]; | |
170 int i, found; | |
171 Uint32 mask; | |
172 | |
173 /* Handle mouse events here */ | |
174 mask = (SDL_KEYDOWNMASK|SDL_KEYUPMASK); | |
175 while ( ! done ) { | |
176 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask); | |
177 for ( i=0; i<found; ++i ) { | |
178 switch(events[i].type) { | |
179 /* We want to toggle visibility on buttonpress */ | |
180 case SDL_KEYDOWN: | |
181 case SDL_KEYUP: | |
562
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
182 printf("Key '%c' has been %s\n", |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
183 events[i].key.keysym.unicode, |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
184 (events[i].key.state == SDL_PRESSED) ? |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
185 "pressed" : "released"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
186 |
0 | 187 /* Allow hitting <ESC> to quit the app */ |
188 if ( events[i].key.keysym.sym == SDLK_ESCAPE ) { | |
189 done = 1; | |
190 } | |
562
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
191 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
192 /* skip events now that aren't KEYUPs... */ |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
193 if (events[i].key.state == SDL_PRESSED) |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
194 break; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
195 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
196 if ( events[i].key.keysym.sym == SDLK_f ) { |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
197 int rc = 0; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
198 printf("attempting to toggle fullscreen...\n"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
199 rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface()); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
200 printf("SDL_WM_ToggleFullScreen returned %d.\n", rc); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
201 } |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
202 |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
203 if ( events[i].key.keysym.sym == SDLK_g ) { |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
204 SDL_GrabMode m; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
205 m = SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON ? |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
206 SDL_GRAB_OFF : SDL_GRAB_ON; |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
207 printf("attempting to toggle input grab to %s...\n", |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
208 m == SDL_GRAB_ON ? "ON" : "OFF"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
209 SDL_WM_GrabInput(m); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
210 printf("attempt finished.\n"); |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
211 } |
cb40b26523a5
Added some code to toggle fullscreen and input grab for testing... --ryan.
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
212 |
0 | 213 break; |
214 } | |
215 } | |
216 /* Give up some CPU to allow events to arrive */ | |
217 SDL_Delay(20); | |
218 } | |
219 return(0); | |
220 } | |
221 | |
222 int main(int argc, char *argv[]) | |
223 { | |
224 SDL_Surface *screen; | |
225 SDL_Surface *icon; | |
226 Uint8 *icon_mask; | |
227 int i, parsed; | |
228 Uint8 *buffer; | |
229 SDL_Color palette[256]; | |
230 Uint32 init_flags; | |
231 Uint8 video_bpp; | |
232 Uint32 video_flags; | |
233 SDL_Thread *mouse_thread; | |
234 SDL_Thread *keybd_thread; | |
235 | |
236 /* Set the options, based on command line arguments */ | |
237 init_flags = SDL_INIT_VIDEO; | |
238 video_bpp = 8; | |
239 video_flags = SDL_SWSURFACE; | |
240 parsed = 1; | |
241 while ( parsed ) { | |
242 /* If the threaded option is enabled, and the SDL library hasn't | |
243 been compiled with threaded events enabled, then the mouse and | |
244 keyboard won't respond. | |
245 */ | |
246 if ( (argc >= 2) && (strcmp(argv[1], "-threaded") == 0) ) { | |
247 init_flags |= SDL_INIT_EVENTTHREAD; | |
248 argc -= 1; | |
249 argv += 1; | |
250 printf("Running with threaded events\n"); | |
251 } else | |
252 if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) { | |
253 video_flags |= SDL_FULLSCREEN; | |
254 argc -= 1; | |
255 argv += 1; | |
256 } else | |
257 if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) { | |
258 video_bpp = atoi(argv[2]); | |
259 argc -= 2; | |
260 argv += 2; | |
261 } else { | |
262 parsed = 0; | |
263 } | |
264 } | |
265 | |
266 /* Initialize SDL with the requested flags */ | |
267 if ( SDL_Init(init_flags) < 0 ) { | |
268 fprintf(stderr, | |
269 "Couldn't initialize SDL: %s\n", SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
270 return(1); |
0 | 271 } |
272 | |
273 /* Set the icon -- this must be done before the first mode set */ | |
274 icon = LoadIconSurface("icon.bmp", &icon_mask); | |
275 if ( icon != NULL ) { | |
276 SDL_WM_SetIcon(icon, icon_mask); | |
277 } | |
278 if ( icon_mask != NULL ) | |
279 free(icon_mask); | |
280 | |
281 /* Initialize the display */ | |
282 screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags); | |
283 if ( screen == NULL ) { | |
284 fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n", | |
285 video_bpp, SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
286 quit(1); |
0 | 287 } |
288 printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ? | |
289 "fullscreen" : "windowed"); | |
290 | |
291 /* Enable printable characters */ | |
292 SDL_EnableUNICODE(1); | |
293 | |
294 /* Set an event filter that discards everything but QUIT */ | |
295 SDL_SetEventFilter(FilterEvents); | |
296 | |
297 /* Create the event handling threads */ | |
298 mouse_thread = SDL_CreateThread(HandleMouse, NULL); | |
299 keybd_thread = SDL_CreateThread(HandleKeyboard, NULL); | |
300 | |
301 /* Set the surface pixels and refresh! */ | |
302 for ( i=0; i<256; ++i ) { | |
303 palette[i].r = 255-i; | |
304 palette[i].g = 255-i; | |
305 palette[i].b = 255-i; | |
306 } | |
307 SDL_SetColors(screen, palette, 0, 256); | |
308 if ( SDL_LockSurface(screen) < 0 ) { | |
309 fprintf(stderr, "Couldn't lock display surface: %s\n", | |
310 SDL_GetError()); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
311 quit(2); |
0 | 312 } |
313 buffer = (Uint8 *)screen->pixels; | |
314 for ( i=0; i<screen->h; ++i ) { | |
315 memset(buffer,(i*255)/screen->h, | |
316 screen->w*screen->format->BytesPerPixel); | |
317 buffer += screen->pitch; | |
318 } | |
319 SDL_UnlockSurface(screen); | |
320 SDL_UpdateRect(screen, 0, 0, 0, 0); | |
321 | |
322 /* Loop, waiting for QUIT */ | |
323 while ( ! done ) { | |
324 if ( ! (init_flags & SDL_INIT_EVENTTHREAD) ) { | |
325 SDL_PumpEvents(); /* Needed when event thread is off */ | |
326 } | |
327 if ( SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK) ) { | |
328 done = 1; | |
329 } | |
330 /* Give up some CPU so the events can accumulate */ | |
331 SDL_Delay(20); | |
332 } | |
333 SDL_WaitThread(mouse_thread, NULL); | |
334 SDL_WaitThread(keybd_thread, NULL); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
562
diff
changeset
|
335 SDL_Quit(); |
0 | 336 return(0); |
337 } |