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