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