test/threadwin.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. LoadIconSurface
  2. FilterEvents
  3. HandleMouse
  4. HandleKeyboard
  5. main

   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 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp)
     /* [<][>][^][v][top][bottom][index][help] */
  18 {
  19         SDL_Surface *icon;
  20         Uint8       *pixels;
  21         Uint8       *mask;
  22         int          mlen, i;
  23 
  24         *maskp = NULL;
  25 
  26         /* Load the icon surface */
  27         icon = SDL_LoadBMP(file);
  28         if ( icon == NULL ) {
  29                 fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
  30                 return(NULL);
  31         }
  32 
  33         /* Check width and height */
  34         if ( (icon->w%8) != 0 ) {
  35                 fprintf(stderr, "Icon width must be a multiple of 8!\n");
  36                 SDL_FreeSurface(icon);
  37                 return(NULL);
  38         }
  39         if ( icon->format->palette == NULL ) {
  40                 fprintf(stderr, "Icon must have a palette!\n");
  41                 SDL_FreeSurface(icon);
  42                 return(NULL);
  43         }
  44 
  45         /* Set the colorkey */
  46         SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels));
  47 
  48         /* Create the mask */
  49         pixels = (Uint8 *)icon->pixels;
  50         printf("Transparent pixel: (%d,%d,%d)\n",
  51                                 icon->format->palette->colors[*pixels].r,
  52                                 icon->format->palette->colors[*pixels].g,
  53                                 icon->format->palette->colors[*pixels].b);
  54         mlen = icon->w*icon->h;
  55         mask = (Uint8 *)malloc(mlen/8);
  56         if ( mask == NULL ) {
  57                 fprintf(stderr, "Out of memory!\n");
  58                 SDL_FreeSurface(icon);
  59                 return(NULL);
  60         }
  61         memset(mask, 0, mlen/8);
  62         for ( i=0; i<mlen; ) {
  63                 if ( pixels[i] != *pixels )
  64                         mask[i/8] |= 0x01;
  65                 ++i;
  66                 if ( (i%8) != 0 )
  67                         mask[i/8] <<= 1;
  68         }
  69         *maskp = mask;
  70         return(icon);
  71 }
  72 
  73 int FilterEvents(const SDL_Event *event)
     /* [<][>][^][v][top][bottom][index][help] */
  74 {
  75         static int reallyquit = 0;
  76 
  77         switch (event->type) {
  78 
  79                 case SDL_ACTIVEEVENT:
  80                         /* See what happened */
  81                         printf("App %s ",
  82                                 event->active.gain ? "gained" : "lost");
  83                         if ( event->active.state & SDL_APPACTIVE )
  84                                 printf("active ");
  85                         if ( event->active.state & SDL_APPMOUSEFOCUS )
  86                                 printf("mouse ");
  87                         if ( event->active.state & SDL_APPINPUTFOCUS )
  88                                 printf("input ");
  89                         printf("focus\n");
  90 
  91                         /* See if we are iconified or restored */
  92                         if ( event->active.state & SDL_APPACTIVE ) {
  93                                 printf("App has been %s\n",
  94                                         event->active.gain ?
  95                                                  "restored" : "iconified");
  96                         }
  97                         return(0);
  98 
  99                 /* This is important!  Queue it if we want to quit. */
 100                 case SDL_QUIT:
 101                         if ( ! reallyquit ) {
 102                                 reallyquit = 1;
 103                                 printf("Quit requested\n");
 104                                 return(0);
 105                         }
 106                         printf("Quit demanded\n");
 107                         return(1);
 108 
 109                 /* Mouse and keyboard events go to threads */
 110                 case SDL_MOUSEMOTION:
 111                 case SDL_MOUSEBUTTONDOWN:
 112                 case SDL_MOUSEBUTTONUP:
 113                 case SDL_KEYDOWN:
 114                 case SDL_KEYUP:
 115                         return(1);
 116 
 117                 /* Drop all other events */
 118                 default:
 119                         return(0);
 120         }
 121 }
 122 
 123 int HandleMouse(void *unused)
     /* [<][>][^][v][top][bottom][index][help] */
 124 {
 125         SDL_Event events[10];
 126         int i, found;
 127         Uint32 mask;
 128 
 129         /* Handle mouse events here */
 130         mask = (SDL_MOUSEMOTIONMASK|SDL_MOUSEBUTTONDOWNMASK|SDL_MOUSEBUTTONUPMASK);
 131         while ( ! done ) {
 132                 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
 133                 for ( i=0; i<found; ++i ) {
 134                         switch(events[i].type) {
 135                                 /* We want to toggle visibility on buttonpress */
 136                                 case SDL_MOUSEBUTTONDOWN:
 137                                 case SDL_MOUSEBUTTONUP:
 138                                         if ( events[i].button.state == SDL_PRESSED ) {
 139                                                 visible = !visible;
 140                                                 SDL_ShowCursor(visible);
 141                                         }
 142                                         printf("Mouse button %d has been %s\n",
 143                                                 events[i].button.button,
 144                                                 (events[i].button.state == SDL_PRESSED) ?
 145                                                 "pressed" : "released");
 146                                         break;
 147                                 /* Show relative mouse motion */
 148                                 case SDL_MOUSEMOTION:
 149                                         printf("Mouse relative motion: {%d,%d}\n",
 150                                                         events[i].motion.xrel, events[i].motion.yrel);
 151                                         break;
 152                         }
 153                 }
 154                 /* Give up some CPU to allow events to arrive */
 155                 SDL_Delay(20);
 156         }
 157         return(0);
 158 }
 159 
 160 int HandleKeyboard(void *unused)
     /* [<][>][^][v][top][bottom][index][help] */
 161 {
 162         SDL_Event events[10];
 163         int i, found;
 164         Uint32 mask;
 165 
 166         /* Handle mouse events here */
 167         mask = (SDL_KEYDOWNMASK|SDL_KEYUPMASK);
 168         while ( ! done ) {
 169                 found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
 170                 for ( i=0; i<found; ++i ) {
 171                         switch(events[i].type) {
 172                             /* We want to toggle visibility on buttonpress */
 173                             case SDL_KEYDOWN:
 174                             case SDL_KEYUP:
 175                                 /* Allow hitting <ESC> to quit the app */
 176                                 if ( events[i].key.keysym.sym == SDLK_ESCAPE ) {
 177                                         done = 1;
 178                                 }
 179                                 printf("Key '%c' has been %s\n",
 180                                                 events[i].key.keysym.unicode,
 181                                         (events[i].key.state == SDL_PRESSED) ?
 182                                                 "pressed" : "released");
 183                                 break;
 184                         }
 185                 }
 186                 /* Give up some CPU to allow events to arrive */
 187                 SDL_Delay(20);
 188         }
 189         return(0);
 190 }
 191 
 192 int main(int argc, char *argv[])
     /* [<][>][^][v][top][bottom][index][help] */
 193 {
 194         SDL_Surface *screen;
 195         SDL_Surface *icon;
 196         Uint8 *icon_mask;
 197         int i, parsed;
 198         Uint8 *buffer;
 199         SDL_Color palette[256];
 200         Uint32 init_flags;
 201         Uint8  video_bpp;
 202         Uint32 video_flags;
 203         SDL_Thread *mouse_thread;
 204         SDL_Thread *keybd_thread;
 205 
 206         /* Set the options, based on command line arguments */
 207         init_flags = SDL_INIT_VIDEO;
 208         video_bpp = 8;
 209         video_flags = SDL_SWSURFACE;
 210         parsed = 1;
 211         while ( parsed ) {
 212                 /* If the threaded option is enabled, and the SDL library hasn't
 213                    been compiled with threaded events enabled, then the mouse and
 214                    keyboard won't respond.
 215                  */
 216                 if ( (argc >= 2) && (strcmp(argv[1], "-threaded") == 0) ) {
 217                         init_flags |= SDL_INIT_EVENTTHREAD;
 218                         argc -= 1;
 219                         argv += 1;
 220                         printf("Running with threaded events\n");
 221                 } else
 222                 if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) {
 223                         video_flags |= SDL_FULLSCREEN;
 224                         argc -= 1;
 225                         argv += 1;
 226                 } else
 227                 if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) {
 228                         video_bpp = atoi(argv[2]);
 229                         argc -= 2;
 230                         argv += 2;
 231                 } else {
 232                         parsed = 0;
 233                 }
 234         }
 235 
 236         /* Initialize SDL with the requested flags */
 237         if ( SDL_Init(init_flags) < 0 ) {
 238                 fprintf(stderr,
 239                         "Couldn't initialize SDL: %s\n", SDL_GetError());
 240                 exit(1);
 241         }
 242         atexit(SDL_Quit);
 243 
 244         /* Set the icon -- this must be done before the first mode set */
 245         icon = LoadIconSurface("icon.bmp", &icon_mask);
 246         if ( icon != NULL ) {
 247                 SDL_WM_SetIcon(icon, icon_mask);
 248         }
 249         if ( icon_mask != NULL )
 250                 free(icon_mask);
 251 
 252         /* Initialize the display */
 253         screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags);
 254         if (  screen == NULL ) {
 255                 fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
 256                                                 video_bpp, SDL_GetError());
 257                 exit(1);
 258         }
 259         printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
 260                                                 "fullscreen" : "windowed");
 261 
 262         /* Enable printable characters */
 263         SDL_EnableUNICODE(1);
 264 
 265         /* Set an event filter that discards everything but QUIT */
 266         SDL_SetEventFilter(FilterEvents);
 267 
 268         /* Create the event handling threads */
 269         mouse_thread = SDL_CreateThread(HandleMouse, NULL);
 270         keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
 271 
 272         /* Set the surface pixels and refresh! */
 273         for ( i=0; i<256; ++i ) {
 274                 palette[i].r = 255-i;
 275                 palette[i].g = 255-i;
 276                 palette[i].b = 255-i;
 277         }
 278         SDL_SetColors(screen, palette, 0, 256);
 279         if ( SDL_LockSurface(screen) < 0 ) {
 280                 fprintf(stderr, "Couldn't lock display surface: %s\n",
 281                                                         SDL_GetError());
 282                 exit(2);
 283         }
 284         buffer = (Uint8 *)screen->pixels;
 285         for ( i=0; i<screen->h; ++i ) {
 286                 memset(buffer,(i*255)/screen->h,
 287                                 screen->w*screen->format->BytesPerPixel);
 288                 buffer += screen->pitch;
 289         }
 290         SDL_UnlockSurface(screen);
 291         SDL_UpdateRect(screen, 0, 0, 0, 0);
 292 
 293         /* Loop, waiting for QUIT */
 294         while ( ! done ) {
 295                 if ( ! (init_flags & SDL_INIT_EVENTTHREAD) ) {
 296                         SDL_PumpEvents(); /* Needed when event thread is off */
 297                 }
 298                 if ( SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK) ) {
 299                         done = 1;
 300                 }
 301                 /* Give up some CPU so the events can accumulate */
 302                 SDL_Delay(20);
 303         }
 304         SDL_WaitThread(mouse_thread, NULL);
 305         SDL_WaitThread(keybd_thread, NULL);
 306         return(0);
 307 }

/* [<][>][^][v][top][bottom][index][help] */