test/threadwin.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 28 May 2006 13:04:16 +0000
branchSDL-1.3
changeset 1662 782fd950bd46
parent 1659 14717b52abc0
child 1668 4da1ee79c9af
permissions -rw-r--r--
Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API.

WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid.

The code is now run through a consistent indent format:
indent -i4 -nut -nsc -br -ce

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