SDL-1.2.14
[sdl_omap.git] / test / threadwin.c
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
17 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
18 static void quit(int rc)
19 {
20         SDL_Quit();
21         exit(rc);
22 }
23
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 SDLCALL 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 SDLCALL 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 SDLCALL 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:
182                                 printf("Key '%c' (keysym==%d) has been %s\n",
183                                                 events[i].key.keysym.unicode,
184                                                 (int) events[i].key.keysym.sym,
185                                         (events[i].key.state == SDL_PRESSED) ?
186                                                 "pressed" : "released");
187
188                                 /* Allow hitting <ESC> to quit the app */
189                                 if ( events[i].key.keysym.sym == SDLK_ESCAPE ) {
190                                         done = 1;
191                                 }
192
193                                         /* skip events now that aren't KEYUPs... */
194                                         if (events[i].key.state == SDL_PRESSED)
195                                                 break;
196
197                                 if ( events[i].key.keysym.sym == SDLK_f ) {
198                                                 int rc = 0;
199                                                 printf("attempting to toggle fullscreen...\n");
200                                                 rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
201                         printf("SDL_WM_ToggleFullScreen returned %d.\n", rc);
202                                 }
203
204                                 if ( events[i].key.keysym.sym == SDLK_g ) {
205                                                 SDL_GrabMode m;
206                                                 m = SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON ?
207                                                                 SDL_GRAB_OFF : SDL_GRAB_ON;
208                                                 printf("attempting to toggle input grab to %s...\n",
209                                 m == SDL_GRAB_ON ? "ON" : "OFF");
210                         SDL_WM_GrabInput(m);
211                                                 printf("attempt finished.\n");
212                                 }
213
214                                 break;
215                         }
216                 }
217                 /* Give up some CPU to allow events to arrive */
218                 SDL_Delay(20);
219         }
220         return(0);
221 }
222
223 int main(int argc, char *argv[])
224 {
225         SDL_Surface *screen;
226         SDL_Surface *icon;
227         Uint8 *icon_mask;
228         int i, parsed;
229         Uint8 *buffer;
230         SDL_Color palette[256];
231         Uint32 init_flags;
232         Uint8  video_bpp;
233         Uint32 video_flags;
234         SDL_Thread *mouse_thread;
235         SDL_Thread *keybd_thread;
236
237         /* Set the options, based on command line arguments */
238         init_flags = SDL_INIT_VIDEO;
239         video_bpp = 8;
240         video_flags = SDL_SWSURFACE;
241         parsed = 1;
242         while ( parsed ) {
243                 /* If the threaded option is enabled, and the SDL library hasn't
244                    been compiled with threaded events enabled, then the mouse and
245                    keyboard won't respond.
246                  */
247                 if ( (argc >= 2) && (strcmp(argv[1], "-threaded") == 0) ) {
248                         init_flags |= SDL_INIT_EVENTTHREAD;
249                         argc -= 1;
250                         argv += 1;
251                         printf("Running with threaded events\n");
252                 } else
253                 if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) {
254                         video_flags |= SDL_FULLSCREEN;
255                         argc -= 1;
256                         argv += 1;
257                 } else
258                 if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) {
259                         video_bpp = atoi(argv[2]);
260                         argc -= 2;
261                         argv += 2;
262                 } else {
263                         parsed = 0;
264                 }
265         }
266
267         /* Initialize SDL with the requested flags */
268         if ( SDL_Init(init_flags) < 0 ) {
269                 fprintf(stderr,
270                         "Couldn't initialize SDL: %s\n", SDL_GetError());
271                 return(1);
272         }
273
274         /* Set the icon -- this must be done before the first mode set */
275         icon = LoadIconSurface("icon.bmp", &icon_mask);
276         if ( icon != NULL ) {
277                 SDL_WM_SetIcon(icon, icon_mask);
278         }
279         if ( icon_mask != NULL )
280                 free(icon_mask);
281
282         /* Initialize the display */
283         screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags);
284         if (  screen == NULL ) {
285                 fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
286                                                 video_bpp, SDL_GetError());
287                 quit(1);
288         }
289         printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
290                                                 "fullscreen" : "windowed");
291
292         /* Enable printable characters */
293         SDL_EnableUNICODE(1);
294
295         /* Set an event filter that discards everything but QUIT */
296         SDL_SetEventFilter(FilterEvents);
297
298         /* Create the event handling threads */
299         mouse_thread = SDL_CreateThread(HandleMouse, NULL);
300         keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
301
302         /* Set the surface pixels and refresh! */
303         for ( i=0; i<256; ++i ) {
304                 palette[i].r = 255-i;
305                 palette[i].g = 255-i;
306                 palette[i].b = 255-i;
307         }
308         SDL_SetColors(screen, palette, 0, 256);
309         if ( SDL_LockSurface(screen) < 0 ) {
310                 fprintf(stderr, "Couldn't lock display surface: %s\n",
311                                                         SDL_GetError());
312                 quit(2);
313         }
314         buffer = (Uint8 *)screen->pixels;
315         for ( i=0; i<screen->h; ++i ) {
316                 memset(buffer,(i*255)/screen->h,
317                                 screen->w*screen->format->BytesPerPixel);
318                 buffer += screen->pitch;
319         }
320         SDL_UnlockSurface(screen);
321         SDL_UpdateRect(screen, 0, 0, 0, 0);
322
323         /* Loop, waiting for QUIT */
324         while ( ! done ) {
325                 if ( ! (init_flags & SDL_INIT_EVENTTHREAD) ) {
326                         SDL_PumpEvents(); /* Needed when event thread is off */
327                 }
328                 if ( SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK) ) {
329                         done = 1;
330                 }
331                 /* Give up some CPU so the events can accumulate */
332                 SDL_Delay(20);
333         }
334         SDL_WaitThread(mouse_thread, NULL);
335         SDL_WaitThread(keybd_thread, NULL);
336         SDL_Quit();
337         return(0);
338 }