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