Mercurial > sdl-ios-xcode
annotate test/testpalette.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 | aff0170f9f1b |
rev | line source |
---|---|
0 | 1 /* |
2 * testpalette.c | |
3 * | |
4 * A simple test of runtime palette modification for animation | |
5 * (using the SDL_SetPalette() API). | |
6 */ | |
7 | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <math.h> | |
12 | |
13 /* This isn't in the Windows headers */ | |
14 #ifndef M_PI | |
15 #define M_PI 3.14159265358979323846 | |
16 #endif | |
17 | |
18 #include <SDL.h> | |
19 | |
20 /* screen size */ | |
21 #define SCRW 640 | |
22 #define SCRH 480 | |
23 | |
24 #define NBOATS 5 | |
25 #define SPEED 2 | |
26 | |
27 #ifndef MIN | |
28 #define MIN(a, b) ((a) < (b) ? (a) : (b)) | |
29 #endif | |
30 #ifndef MAX | |
31 #define MAX(a, b) ((a) > (b) ? (a) : (b)) | |
32 #endif | |
33 | |
34 /* | |
35 * wave colours: Made by taking a narrow cross-section of a wave picture | |
36 * in Gimp, saving in PPM ascii format and formatting with Emacs macros. | |
37 */ | |
38 static SDL_Color wavemap[] = { | |
39 {0,2,103}, {0,7,110}, {0,13,117}, {0,19,125}, | |
40 {0,25,133}, {0,31,141}, {0,37,150}, {0,43,158}, | |
41 {0,49,166}, {0,55,174}, {0,61,182}, {0,67,190}, | |
42 {0,73,198}, {0,79,206}, {0,86,214}, {0,96,220}, | |
43 {5,105,224}, {12,112,226}, {19,120,227}, {26,128,229}, | |
44 {33,135,230}, {40,143,232}, {47,150,234}, {54,158,236}, | |
45 {61,165,238}, {68,173,239}, {75,180,241}, {82,188,242}, | |
46 {89,195,244}, {96,203,246}, {103,210,248}, {112,218,250}, | |
47 {124,224,250}, {135,226,251}, {146,229,251}, {156,231,252}, | |
48 {167,233,252}, {178,236,252}, {189,238,252}, {200,240,252}, | |
49 {211,242,252}, {222,244,252}, {233,247,252}, {242,249,252}, | |
50 {237,250,252}, {209,251,252}, {174,251,252}, {138,252,252}, | |
51 {102,251,252}, {63,250,252}, {24,243,252}, {7,225,252}, | |
52 {4,203,252}, {3,181,252}, {2,158,252}, {1,136,251}, | |
53 {0,111,248}, {0,82,234}, {0,63,213}, {0,50,192}, | |
54 {0,39,172}, {0,28,152}, {0,17,132}, {0,7,114} | |
55 }; | |
56 | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
57 /* 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:
0
diff
changeset
|
58 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:
0
diff
changeset
|
59 { |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
60 SDL_Quit(); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
61 exit(rc); |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
62 } |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
63 |
0 | 64 static void sdlerr(char *when) |
65 { | |
66 fprintf(stderr, "SDL error: %s: %s\n", when, 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:
0
diff
changeset
|
67 quit(1); |
0 | 68 } |
69 | |
70 /* create a background surface */ | |
71 static SDL_Surface *make_bg(SDL_Surface *screen, int startcol) | |
72 { | |
73 int i; | |
74 SDL_Surface *bg = SDL_CreateRGBSurface(SDL_SWSURFACE, screen->w, screen->h, | |
75 8, 0, 0, 0, 0); | |
76 if(!bg) | |
77 sdlerr("creating background surface"); | |
78 | |
79 /* set the palette to the logical screen palette so that blits | |
80 won't be translated */ | |
81 SDL_SetColors(bg, screen->format->palette->colors, 0, 256); | |
82 | |
83 /* Make a wavy background pattern using colours 0-63 */ | |
84 if(SDL_LockSurface(bg) < 0) | |
85 sdlerr("locking background"); | |
86 for(i = 0; i < SCRH; i++) { | |
87 Uint8 *p = (Uint8 *)bg->pixels + i * bg->pitch; | |
88 int j, d; | |
89 d = 0; | |
90 for(j = 0; j < SCRW; j++) { | |
91 int v = MAX(d, -2); | |
92 v = MIN(v, 2); | |
93 if(i > 0) | |
94 v += p[-bg->pitch] + 65 - startcol; | |
95 p[j] = startcol + (v & 63); | |
96 d += ((rand() >> 3) % 3) - 1; | |
97 } | |
98 } | |
99 SDL_UnlockSurface(bg); | |
100 return(bg); | |
101 } | |
102 | |
103 /* | |
104 * Return a surface flipped horisontally. Only works for 8bpp; | |
105 * extension to arbitrary bitness is left as an exercise for the reader. | |
106 */ | |
107 static SDL_Surface *hflip(SDL_Surface *s) | |
108 { | |
109 int i; | |
110 SDL_Surface *z = SDL_CreateRGBSurface(SDL_SWSURFACE, s->w, s->h, 8, | |
111 0, 0, 0, 0); | |
112 /* copy palette */ | |
113 SDL_SetColors(z, s->format->palette->colors, | |
114 0, s->format->palette->ncolors); | |
115 if(SDL_LockSurface(s) < 0 || SDL_LockSurface(z) < 0) | |
116 sdlerr("locking flip images"); | |
117 | |
118 for(i = 0; i < s->h; i++) { | |
119 int j; | |
120 Uint8 *from = (Uint8 *)s->pixels + i * s->pitch; | |
121 Uint8 *to = (Uint8 *)z->pixels + i * z->pitch + s->w - 1; | |
122 for(j = 0; j < s->w; j++) | |
123 to[-j] = from[j]; | |
124 } | |
125 | |
126 SDL_UnlockSurface(z); | |
127 SDL_UnlockSurface(s); | |
128 return z; | |
129 } | |
130 | |
131 int main(int argc, char **argv) | |
132 { | |
133 SDL_Color cmap[256]; | |
134 SDL_Surface *screen; | |
135 SDL_Surface *bg; | |
136 SDL_Surface *boat[2]; | |
137 unsigned vidflags = 0; | |
138 unsigned start; | |
139 int fade_max = 400; | |
140 int fade_level, fade_dir; | |
141 int boatcols, frames, i, red; | |
142 int boatx[NBOATS], boaty[NBOATS], boatdir[NBOATS]; | |
143 int gamma_fade = 0; | |
144 int gamma_ramp = 0; | |
145 | |
146 if(SDL_Init(SDL_INIT_VIDEO) < 0) | |
147 sdlerr("initialising SDL"); | |
148 | |
149 while(--argc) { | |
150 ++argv; | |
151 if(strcmp(*argv, "-hw") == 0) | |
152 vidflags |= SDL_HWSURFACE; | |
153 else if(strcmp(*argv, "-fullscreen") == 0) | |
154 vidflags |= SDL_FULLSCREEN; | |
155 else if(strcmp(*argv, "-nofade") == 0) | |
156 fade_max = 1; | |
157 else if(strcmp(*argv, "-gamma") == 0) | |
158 gamma_fade = 1; | |
159 else if(strcmp(*argv, "-gammaramp") == 0) | |
160 gamma_ramp = 1; | |
161 else { | |
162 fprintf(stderr, | |
163 "usage: testpalette " | |
164 " [-hw] [-fullscreen] [-nofade] [-gamma] [-gammaramp]\n"); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
165 quit(1); |
0 | 166 } |
167 } | |
168 | |
169 /* Ask explicitly for 8bpp and a hardware palette */ | |
170 if(!(screen = SDL_SetVideoMode(SCRW, SCRH, 8, vidflags | SDL_HWPALETTE))) { | |
171 fprintf(stderr, "error setting %dx%d 8bpp indexed mode: %s\n", | |
172 SCRW, SCRH, 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:
0
diff
changeset
|
173 quit(1); |
0 | 174 } |
175 | |
176 if(!(boat[0] = SDL_LoadBMP("sail.bmp"))) | |
177 sdlerr("loading sail.bmp"); | |
178 /* We've chosen magenta (#ff00ff) as colour key for the boat */ | |
179 SDL_SetColorKey(boat[0], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
180 SDL_MapRGB(boat[0]->format, 0xff, 0x00, 0xff)); | |
181 boatcols = boat[0]->format->palette->ncolors; | |
182 boat[1] = hflip(boat[0]); | |
183 SDL_SetColorKey(boat[1], SDL_SRCCOLORKEY | SDL_RLEACCEL, | |
184 SDL_MapRGB(boat[1]->format, 0xff, 0x00, 0xff)); | |
185 | |
186 /* | |
187 * First set the physical screen palette to black, so the user won't | |
188 * see our initial drawing on the screen. | |
189 */ | |
190 memset(cmap, 0, sizeof(cmap)); | |
191 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, 256); | |
192 | |
193 /* | |
194 * Proper palette management is important when playing games with the | |
195 * colormap. We have divided the palette as follows: | |
196 * | |
197 * index 0..(boatcols-1): used for the boat | |
198 * index boatcols..(boatcols+63): used for the waves | |
199 */ | |
200 SDL_SetPalette(screen, SDL_LOGPAL, | |
201 boat[0]->format->palette->colors, 0, boatcols); | |
202 SDL_SetPalette(screen, SDL_LOGPAL, wavemap, boatcols, 64); | |
203 | |
204 /* | |
205 * Now the logical screen palette is set, and will remain unchanged. | |
206 * The boats already have the same palette so fast blits can be used. | |
207 */ | |
208 memcpy(cmap, screen->format->palette->colors, 256 * sizeof(SDL_Color)); | |
209 | |
210 /* save the index of the red colour for later */ | |
211 red = SDL_MapRGB(screen->format, 0xff, 0x00, 0x00); | |
212 | |
213 bg = make_bg(screen, boatcols); /* make a nice wavy background surface */ | |
214 | |
215 /* initial screen contents */ | |
216 if(SDL_BlitSurface(bg, NULL, screen, NULL) < 0) | |
217 sdlerr("blitting background to screen"); | |
218 SDL_Flip(screen); /* actually put the background on screen */ | |
219 | |
220 /* determine initial boat placements */ | |
221 for(i = 0; i < NBOATS; i++) { | |
222 boatx[i] = (rand() % (SCRW + boat[0]->w)) - boat[0]->w; | |
223 boaty[i] = i * (SCRH - boat[0]->h) / (NBOATS - 1); | |
224 boatdir[i] = ((rand() >> 5) & 1) * 2 - 1; | |
225 } | |
226 | |
227 start = SDL_GetTicks(); | |
228 frames = 0; | |
229 fade_dir = 1; | |
230 fade_level = 0; | |
231 do { | |
232 SDL_Event e; | |
233 SDL_Rect updates[NBOATS]; | |
234 SDL_Rect r; | |
235 int redphase; | |
236 | |
237 /* A small event loop: just exit on any key or mouse button event */ | |
238 while(SDL_PollEvent(&e)) { | |
239 if(e.type == SDL_KEYDOWN || e.type == SDL_QUIT | |
240 || e.type == SDL_MOUSEBUTTONDOWN) { | |
241 if(fade_dir < 0) | |
242 fade_level = 0; | |
243 fade_dir = -1; | |
244 } | |
245 } | |
246 | |
247 /* move boats */ | |
248 for(i = 0; i < NBOATS; i++) { | |
249 int old_x = boatx[i]; | |
250 /* update boat position */ | |
251 boatx[i] += boatdir[i] * SPEED; | |
252 if(boatx[i] <= -boat[0]->w || boatx[i] >= SCRW) | |
253 boatdir[i] = -boatdir[i]; | |
254 | |
255 /* paint over the old boat position */ | |
256 r.x = old_x; | |
257 r.y = boaty[i]; | |
258 r.w = boat[0]->w; | |
259 r.h = boat[0]->h; | |
260 if(SDL_BlitSurface(bg, &r, screen, &r) < 0) | |
261 sdlerr("blitting background"); | |
262 | |
263 /* construct update rectangle (bounding box of old and new pos) */ | |
264 updates[i].x = MIN(old_x, boatx[i]); | |
265 updates[i].y = boaty[i]; | |
266 updates[i].w = boat[0]->w + SPEED; | |
267 updates[i].h = boat[0]->h; | |
268 /* clip update rectangle to screen */ | |
269 if(updates[i].x < 0) { | |
270 updates[i].w += updates[i].x; | |
271 updates[i].x = 0; | |
272 } | |
273 if(updates[i].x + updates[i].w > SCRW) | |
274 updates[i].w = SCRW - updates[i].x; | |
275 } | |
276 | |
277 for(i = 0; i < NBOATS; i++) { | |
278 /* paint boat on new position */ | |
279 r.x = boatx[i]; | |
280 r.y = boaty[i]; | |
281 if(SDL_BlitSurface(boat[(boatdir[i] + 1) / 2], NULL, | |
282 screen, &r) < 0) | |
283 sdlerr("blitting boat"); | |
284 } | |
285 | |
286 /* cycle wave palette */ | |
287 for(i = 0; i < 64; i++) | |
288 cmap[boatcols + ((i + frames) & 63)] = wavemap[i]; | |
289 | |
290 if(fade_dir) { | |
291 /* Fade the entire palette in/out */ | |
292 fade_level += fade_dir; | |
293 | |
294 if(gamma_fade) { | |
295 /* Fade linearly in gamma level (lousy) */ | |
296 float level = (float)fade_level / fade_max; | |
297 if(SDL_SetGamma(level, level, level) < 0) | |
298 sdlerr("setting gamma"); | |
299 | |
300 } else if(gamma_ramp) { | |
301 /* Fade using gamma ramp (better) */ | |
302 Uint16 ramp[256]; | |
303 for(i = 0; i < 256; i++) | |
304 ramp[i] = (i * fade_level / fade_max) << 8; | |
305 if(SDL_SetGammaRamp(ramp, ramp, ramp) < 0) | |
306 sdlerr("setting gamma ramp"); | |
307 | |
308 } else { | |
309 /* Fade using direct palette manipulation (best) */ | |
310 memcpy(cmap, screen->format->palette->colors, | |
311 boatcols * sizeof(SDL_Color)); | |
312 for(i = 0; i < boatcols + 64; i++) { | |
313 cmap[i].r = cmap[i].r * fade_level / fade_max; | |
314 cmap[i].g = cmap[i].g * fade_level / fade_max; | |
315 cmap[i].b = cmap[i].b * fade_level / fade_max; | |
316 } | |
317 } | |
318 if(fade_level == fade_max) | |
319 fade_dir = 0; | |
320 } | |
321 | |
322 /* pulse the red colour (done after the fade, for a night effect) */ | |
323 redphase = frames % 64; | |
324 cmap[red].r = (int)(255 * sin(redphase * M_PI / 63)); | |
325 | |
326 SDL_SetPalette(screen, SDL_PHYSPAL, cmap, 0, boatcols + 64); | |
327 | |
328 /* update changed areas of the screen */ | |
329 SDL_UpdateRects(screen, NBOATS, updates); | |
330 frames++; | |
331 } while(fade_level > 0); | |
332 | |
333 printf("%d frames, %.2f fps\n", | |
334 frames, 1000.0 * frames / (SDL_GetTicks() - start)); | |
1151
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
335 |
be9c9c8f6d53
Removed atexit() from most of the test programs; atexit(SDL_Quit) isn't safe
Ryan C. Gordon <icculus@icculus.org>
parents:
0
diff
changeset
|
336 SDL_Quit(); |
0 | 337 return 0; |
338 } | |
339 |