test/threadwin.c
author Sam Lantinga <slouken@libsdl.org>
Mon, 07 Mar 2011 22:06:12 -0800
changeset 5451 6535fdf7cf45
parent 5123 dc0dfdd58f27
child 5535 96594ac5fd1a
permissions -rw-r--r--
The msimg library isn't needed anymore.
     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(void *userdata, 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 
   137     /* Handle mouse events here */
   138     while (!done) {
   139         found = SDL_PeepEvents(events, 10, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEBUTTONUP);
   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
   168 HandleKeyboard(void *unused)
   169 {
   170     SDL_Event events[10];
   171     int i, found;
   172 
   173     /* Handle mouse events here */
   174     while (!done) {
   175         found = SDL_PeepEvents(events, 10, SDL_GETEVENT, SDL_KEYDOWN, SDL_KEYUP);
   176         for (i = 0; i < found; ++i) {
   177             switch (events[i].type) {
   178                 /* We want to toggle visibility on buttonpress */
   179             case SDL_KEYDOWN:
   180             case SDL_KEYUP:
   181                 printf("Key '%c' (keysym==%d) has been %s\n",
   182                        events[i].key.keysym.unicode,
   183                        (int) events[i].key.keysym.sym,
   184                        (events[i].key.state == SDL_PRESSED) ?
   185                        "pressed" : "released");
   186 
   187                 /* Allow hitting <ESC> to quit the app */
   188                 if (events[i].key.keysym.sym == SDLK_ESCAPE) {
   189                     done = 1;
   190                 }
   191 
   192                 /* skip events now that aren't KEYUPs... */
   193                 if (events[i].key.state == SDL_PRESSED)
   194                     break;
   195 
   196                 if (events[i].key.keysym.sym == SDLK_f) {
   197                     int rc = 0;
   198                     printf("attempting to toggle fullscreen...\n");
   199                     rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
   200                     printf("SDL_WM_ToggleFullScreen returned %d.\n", rc);
   201                 }
   202 
   203                 if (events[i].key.keysym.sym == SDLK_g) {
   204                     SDL_GrabMode m;
   205                     m = SDL_WM_GrabInput(SDL_GRAB_QUERY) ==
   206                         SDL_GRAB_ON ? SDL_GRAB_OFF : SDL_GRAB_ON;
   207                     printf
   208                         ("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
   224 main(int argc, char *argv[])
   225 {
   226     SDL_Surface *screen;
   227     SDL_Surface *icon;
   228     Uint8 *icon_mask;
   229     int i, parsed;
   230     Uint8 *buffer;
   231     SDL_Color palette[256];
   232     Uint32 init_flags;
   233     Uint8 video_bpp;
   234     Uint32 video_flags;
   235     SDL_Thread *mouse_thread;
   236     SDL_Thread *keybd_thread;
   237 
   238     /* Set the options, based on command line arguments */
   239     init_flags = SDL_INIT_VIDEO;
   240     video_bpp = 8;
   241     video_flags = SDL_SWSURFACE;
   242     parsed = 1;
   243     while (parsed) {
   244         if ((argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0)) {
   245             video_flags |= SDL_FULLSCREEN;
   246             argc -= 1;
   247             argv += 1;
   248         } else if ((argc >= 3) && (strcmp(argv[1], "-bpp") == 0)) {
   249             video_bpp = atoi(argv[2]);
   250             argc -= 2;
   251             argv += 2;
   252         } else {
   253             parsed = 0;
   254         }
   255     }
   256 
   257     /* Initialize SDL with the requested flags */
   258     if (SDL_Init(init_flags) < 0) {
   259         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
   260         return (1);
   261     }
   262 
   263     /* Set the icon -- this must be done before the first mode set */
   264     icon = LoadIconSurface("icon.bmp", &icon_mask);
   265     if (icon != NULL) {
   266         SDL_WM_SetIcon(icon, icon_mask);
   267     }
   268     if (icon_mask != NULL)
   269         free(icon_mask);
   270 
   271     /* Initialize the display */
   272     screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags);
   273     if (screen == NULL) {
   274         fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
   275                 video_bpp, SDL_GetError());
   276         quit(1);
   277     }
   278     printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
   279            "fullscreen" : "windowed");
   280 
   281     /* Enable printable characters */
   282     SDL_EnableUNICODE(1);
   283 
   284     /* Set an event filter that discards everything but QUIT */
   285     SDL_SetEventFilter(FilterEvents, NULL);
   286 
   287     /* Create the event handling threads */
   288     mouse_thread = SDL_CreateThread(HandleMouse, NULL);
   289     keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
   290 
   291     /* Set the surface pixels and refresh! */
   292     for (i = 0; i < 256; ++i) {
   293         palette[i].r = 255 - i;
   294         palette[i].g = 255 - i;
   295         palette[i].b = 255 - i;
   296     }
   297     SDL_SetColors(screen, palette, 0, 256);
   298     if (SDL_LockSurface(screen) < 0) {
   299         fprintf(stderr, "Couldn't lock display surface: %s\n",
   300                 SDL_GetError());
   301         quit(2);
   302     }
   303     buffer = (Uint8 *) screen->pixels;
   304     for (i = 0; i < screen->h; ++i) {
   305         memset(buffer, (i * 255) / screen->h,
   306                screen->w * screen->format->BytesPerPixel);
   307         buffer += screen->pitch;
   308     }
   309     SDL_UnlockSurface(screen);
   310     SDL_UpdateRect(screen, 0, 0, 0, 0);
   311 
   312     /* Loop, waiting for QUIT */
   313     while (!done) {
   314         SDL_PumpEvents();
   315 
   316         if (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUIT, SDL_QUIT)) {
   317             done = 1;
   318         }
   319         /* Give up some CPU so the events can accumulate */
   320         SDL_Delay(20);
   321     }
   322     SDL_WaitThread(mouse_thread, NULL);
   323     SDL_WaitThread(keybd_thread, NULL);
   324     SDL_Quit();
   325     return (0);
   326 }