test/testwm.c
author Ryan C. Gordon <icculus@icculus.org>
Fri, 03 Jun 2011 16:03:10 -0400
changeset 5547 4ccecd0901e2
parent 5535 96594ac5fd1a
permissions -rw-r--r--
Assert code's stdio interface was reading from the wrong variable.

Thanks to Frank Zago for the catch.
     1 /*
     2   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     3 
     4   This software is provided 'as-is', without any express or implied
     5   warranty.  In no event will the authors be held liable for any damages
     6   arising from the use of this software.
     7 
     8   Permission is granted to anyone to use this software for any purpose,
     9   including commercial applications, and to alter it and redistribute it
    10   freely.
    11 */
    12 
    13 /* Test out the window manager interaction functions */
    14 
    15 #include <stdio.h>
    16 #include <stdlib.h>
    17 #include <string.h>
    18 
    19 #include "SDL.h"
    20 
    21 /* Is the cursor visible? */
    22 static int visible = 1;
    23 
    24 static Uint8 video_bpp;
    25 static Uint32 video_flags;
    26 
    27 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    28 static void
    29 quit(int rc)
    30 {
    31     SDL_Quit();
    32     exit(rc);
    33 }
    34 
    35 int
    36 SetVideoMode(int w, int h)
    37 {
    38     SDL_Surface *screen;
    39     int i;
    40     Uint8 *buffer;
    41     SDL_Color palette[256];
    42 
    43     screen = SDL_SetVideoMode(w, h, video_bpp, video_flags);
    44     if (screen == NULL) {
    45         fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
    46                 w, h, video_bpp, SDL_GetError());
    47         return (-1);
    48     }
    49     printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
    50            "fullscreen" : "windowed");
    51 
    52     /* Set the surface pixels and refresh! */
    53     for (i = 0; i < 256; ++i) {
    54         palette[i].r = 255 - i;
    55         palette[i].g = 255 - i;
    56         palette[i].b = 255 - i;
    57     }
    58     SDL_SetColors(screen, palette, 0, 256);
    59     if (SDL_LockSurface(screen) < 0) {
    60         fprintf(stderr, "Couldn't lock display surface: %s\n",
    61                 SDL_GetError());
    62         return (-1);
    63     }
    64     buffer = (Uint8 *) screen->pixels;
    65     for (i = 0; i < screen->h; ++i) {
    66         memset(buffer, (i * 255) / screen->h,
    67                screen->w * screen->format->BytesPerPixel);
    68         buffer += screen->pitch;
    69     }
    70     SDL_UnlockSurface(screen);
    71     SDL_UpdateRect(screen, 0, 0, 0, 0);
    72 
    73     return (0);
    74 }
    75 
    76 SDL_Surface *
    77 LoadIconSurface(char *file, Uint8 ** maskp)
    78 {
    79     SDL_Surface *icon;
    80     Uint8 *pixels;
    81     Uint8 *mask;
    82     int mlen, i, j;
    83 
    84     *maskp = NULL;
    85 
    86     /* Load the icon surface */
    87     icon = SDL_LoadBMP(file);
    88     if (icon == NULL) {
    89         fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
    90         return (NULL);
    91     }
    92 
    93     /* Check width and height 
    94        if ( (icon->w%8) != 0 ) {
    95        fprintf(stderr, "Icon width must be a multiple of 8!\n");
    96        SDL_FreeSurface(icon);
    97        return(NULL);
    98        }
    99      */
   100 
   101 
   102     if (icon->format->palette == NULL) {
   103         fprintf(stderr, "Icon must have a palette!\n");
   104         SDL_FreeSurface(icon);
   105         return (NULL);
   106     }
   107 
   108     /* Set the colorkey */
   109     SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *) icon->pixels));
   110 
   111     /* Create the mask */
   112     pixels = (Uint8 *) icon->pixels;
   113     printf("Transparent pixel: (%d,%d,%d)\n",
   114            icon->format->palette->colors[*pixels].r,
   115            icon->format->palette->colors[*pixels].g,
   116            icon->format->palette->colors[*pixels].b);
   117     mlen = (icon->w * icon->h + 7) / 8;
   118     mask = (Uint8 *) malloc(mlen);
   119     if (mask == NULL) {
   120         fprintf(stderr, "Out of memory!\n");
   121         SDL_FreeSurface(icon);
   122         return (NULL);
   123     }
   124     memset(mask, 0, mlen);
   125     for (i = 0; i < icon->h; i++)
   126         for (j = 0; j < icon->w; j++) {
   127             int pindex = i * icon->pitch + j;
   128             int mindex = i * icon->w + j;
   129             if (pixels[pindex] != *pixels)
   130                 mask[mindex >> 3] |= 1 << (7 - (mindex & 7));
   131         }
   132     *maskp = mask;
   133     return (icon);
   134 }
   135 
   136 void
   137 HotKey_ToggleFullScreen(void)
   138 {
   139     SDL_Surface *screen;
   140 
   141     screen = SDL_GetVideoSurface();
   142     if (SDL_WM_ToggleFullScreen(screen)) {
   143         printf("Toggled fullscreen mode - now %s\n",
   144                (screen->flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed");
   145     } else {
   146         printf("Unable to toggle fullscreen mode\n");
   147         video_flags ^= SDL_FULLSCREEN;
   148         SetVideoMode(screen->w, screen->h);
   149     }
   150 }
   151 
   152 void
   153 HotKey_ToggleGrab(void)
   154 {
   155     SDL_GrabMode mode;
   156 
   157     printf("Ctrl-G: toggling input grab!\n");
   158     mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
   159     if (mode == SDL_GRAB_ON) {
   160         printf("Grab was on\n");
   161     } else {
   162         printf("Grab was off\n");
   163     }
   164     mode = SDL_WM_GrabInput(mode ? SDL_GRAB_OFF : SDL_GRAB_ON);
   165     if (mode == SDL_GRAB_ON) {
   166         printf("Grab is now on\n");
   167     } else {
   168         printf("Grab is now off\n");
   169     }
   170 }
   171 
   172 void
   173 HotKey_Iconify(void)
   174 {
   175     printf("Ctrl-Z: iconifying window!\n");
   176     SDL_WM_IconifyWindow();
   177 }
   178 
   179 void
   180 HotKey_Quit(void)
   181 {
   182     SDL_Event event;
   183 
   184     printf("Posting internal quit request\n");
   185     event.type = SDL_USEREVENT;
   186     SDL_PushEvent(&event);
   187 }
   188 
   189 
   190 static void
   191 print_modifiers(void)
   192 {
   193     int mod;
   194     printf(" modifiers:");
   195     mod = SDL_GetModState();
   196     if(!mod) {
   197         printf(" (none)");
   198         return;
   199     }
   200     if(mod & KMOD_LSHIFT)
   201         printf(" LSHIFT");
   202     if(mod & KMOD_RSHIFT)
   203         printf(" RSHIFT");
   204     if(mod & KMOD_LCTRL)
   205         printf(" LCTRL");
   206     if(mod & KMOD_RCTRL)
   207         printf(" RCTRL");
   208     if(mod & KMOD_LALT)
   209         printf(" LALT");
   210     if(mod & KMOD_RALT)
   211         printf(" RALT");
   212     if(mod & KMOD_LMETA)
   213         printf(" LMETA");
   214     if(mod & KMOD_RMETA)
   215         printf(" RMETA");
   216     if(mod & KMOD_NUM)
   217         printf(" NUM");
   218     if(mod & KMOD_CAPS)
   219         printf(" CAPS");
   220     if(mod & KMOD_MODE)
   221         printf(" MODE");
   222 }
   223 
   224 static void PrintKey(const SDL_Keysym *sym, int pressed)
   225 {
   226     /* Print the keycode, name and state */
   227     if ( sym->sym ) {
   228         printf("Key %s:  %d-%s ", pressed ?  "pressed" : "released",
   229                     sym->sym, SDL_GetKeyName(sym->sym));
   230     } else {
   231         printf("Unknown Key (scancode = %d) %s ", sym->scancode,
   232                     pressed ?  "pressed" : "released");
   233     }
   234 
   235     /* Print the translated character, if one exists */
   236     if ( sym->unicode ) {
   237         /* Is it a control-character? */
   238         if ( sym->unicode < ' ' ) {
   239             printf(" (^%c)", sym->unicode+'@');
   240         } else {
   241 #ifdef UNICODE
   242             printf(" (%c)", sym->unicode);
   243 #else
   244             /* This is a Latin-1 program, so only show 8-bits */
   245             if ( !(sym->unicode & 0xFF00) )
   246                 printf(" (%c)", sym->unicode);
   247             else
   248                 printf(" (0x%X)", sym->unicode);
   249 #endif
   250         }
   251     }
   252     print_modifiers();
   253     printf("\n");
   254 }
   255 
   256 
   257 static int (SDLCALL * old_filterfunc) (void *, SDL_Event *);
   258 static void *old_filterdata;
   259 
   260 int SDLCALL
   261 FilterEvents(void *userdata, SDL_Event * event)
   262 {
   263     static int reallyquit = 0;
   264 
   265     if (old_filterfunc) {
   266         old_filterfunc(old_filterdata, event);
   267     }
   268 
   269     switch (event->type) {
   270 
   271     case SDL_ACTIVEEVENT:
   272         /* See what happened */
   273         printf("App %s ", event->active.gain ? "gained" : "lost");
   274         if (event->active.state & SDL_APPACTIVE)
   275             printf("active ");
   276         if (event->active.state & SDL_APPINPUTFOCUS)
   277             printf("input ");
   278         if (event->active.state & SDL_APPMOUSEFOCUS)
   279             printf("mouse ");
   280         printf("focus\n");
   281 
   282         /* See if we are iconified or restored */
   283         if (event->active.state & SDL_APPACTIVE) {
   284             printf("App has been %s\n",
   285                    event->active.gain ? "restored" : "iconified");
   286         }
   287         return (0);
   288 
   289         /* We want to toggle visibility on buttonpress */
   290     case SDL_MOUSEBUTTONDOWN:
   291     case SDL_MOUSEBUTTONUP:
   292         if (event->button.state == SDL_PRESSED) {
   293             visible = !visible;
   294             SDL_ShowCursor(visible);
   295         }
   296         printf("Mouse button %d has been %s at %d,%d\n",
   297                event->button.button,
   298                (event->button.state == SDL_PRESSED) ? "pressed" : "released",
   299                event->button.x, event->button.y);
   300         return (0);
   301 
   302         /* Show relative mouse motion */
   303     case SDL_MOUSEMOTION:
   304 #if 0
   305         printf("Mouse motion: {%d,%d} (%d,%d)\n",
   306                event->motion.x, event->motion.y,
   307                event->motion.xrel, event->motion.yrel);
   308 #endif
   309         return (0);
   310 
   311     case SDL_KEYDOWN:
   312         PrintKey(&event->key.keysym, 1);
   313         if (event->key.keysym.sym == SDLK_ESCAPE) {
   314             HotKey_Quit();
   315         }
   316         if ((event->key.keysym.sym == SDLK_g) &&
   317             (event->key.keysym.mod & KMOD_CTRL)) {
   318             HotKey_ToggleGrab();
   319         }
   320         if ((event->key.keysym.sym == SDLK_z) &&
   321             (event->key.keysym.mod & KMOD_CTRL)) {
   322             HotKey_Iconify();
   323         }
   324         if ((event->key.keysym.sym == SDLK_RETURN) &&
   325             (event->key.keysym.mod & (KMOD_ALT|KMOD_META))) {
   326             HotKey_ToggleFullScreen();
   327         }
   328         return (0);
   329 
   330 	case SDL_KEYUP:
   331 		PrintKey(&event->key.keysym, 0);
   332 		return(0);
   333 
   334         /* Pass the video resize event through .. */
   335     case SDL_VIDEORESIZE:
   336         return (1);
   337 
   338         /* This is important!  Queue it if we want to quit. */
   339     case SDL_QUIT:
   340         if (!reallyquit) {
   341             reallyquit = 1;
   342             printf("Quit requested\n");
   343             return (0);
   344         }
   345         printf("Quit demanded\n");
   346         return (1);
   347 
   348         /* This will never happen because events queued directly
   349            to the event queue are not filtered.
   350          */
   351     case SDL_USEREVENT:
   352         return (1);
   353 
   354         /* Drop all other events */
   355     default:
   356         return (0);
   357     }
   358 }
   359 
   360 int
   361 main(int argc, char *argv[])
   362 {
   363     SDL_Event event;
   364     const char *title;
   365     SDL_Surface *icon;
   366     Uint8 *icon_mask;
   367     int parsed;
   368     int w, h;
   369 
   370     if (SDL_Init(SDL_INIT_VIDEO) < 0) {
   371         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
   372         return (1);
   373     }
   374 
   375     /* Check command line arguments */
   376     w = 640;
   377     h = 480;
   378     video_bpp = 8;
   379     video_flags = SDL_SWSURFACE;
   380     parsed = 1;
   381     while (parsed) {
   382         if ((argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0)) {
   383             video_flags |= SDL_FULLSCREEN;
   384             argc -= 1;
   385             argv += 1;
   386         } else if ((argc >= 2) && (strcmp(argv[1], "-resize") == 0)) {
   387             video_flags |= SDL_RESIZABLE;
   388             argc -= 1;
   389             argv += 1;
   390         } else if ((argc >= 2) && (strcmp(argv[1], "-noframe") == 0)) {
   391             video_flags |= SDL_NOFRAME;
   392             argc -= 1;
   393             argv += 1;
   394         } else if ((argc >= 3) && (strcmp(argv[1], "-width") == 0)) {
   395             w = atoi(argv[2]);
   396             argc -= 2;
   397             argv += 2;
   398         } else if ((argc >= 3) && (strcmp(argv[1], "-height") == 0)) {
   399             h = atoi(argv[2]);
   400             argc -= 2;
   401             argv += 2;
   402         } else if ((argc >= 3) && (strcmp(argv[1], "-bpp") == 0)) {
   403             video_bpp = atoi(argv[2]);
   404             argc -= 2;
   405             argv += 2;
   406         } else {
   407             parsed = 0;
   408         }
   409     }
   410 
   411     /* Set the icon -- this must be done before the first mode set */
   412     icon = LoadIconSurface("icon.bmp", &icon_mask);
   413     if (icon != NULL) {
   414         SDL_WM_SetIcon(icon, icon_mask);
   415     }
   416     if (icon_mask != NULL)
   417         free(icon_mask);
   418 
   419     /* Set the title bar */
   420     if (argv[1] == NULL)
   421         title = "Testing  1.. 2.. 3...";
   422     else
   423         title = argv[1];
   424     SDL_WM_SetCaption(title, "testwm");
   425 
   426     /* See if it's really set */
   427     SDL_WM_GetCaption(&title, NULL);
   428     if (title)
   429         printf("Title was set to: %s\n", title);
   430     else
   431         printf("No window title was set!\n");
   432 
   433     /* Initialize the display */
   434     if (SetVideoMode(w, h) < 0) {
   435         quit(1);
   436     }
   437 
   438     /* Set an event filter that discards everything but QUIT */
   439     SDL_GetEventFilter(&old_filterfunc, &old_filterdata);
   440     SDL_SetEventFilter(FilterEvents, NULL);
   441 
   442     /* Loop, waiting for QUIT */
   443     while (SDL_WaitEvent(&event)) {
   444         switch (event.type) {
   445         case SDL_VIDEORESIZE:
   446             printf("Got a resize event: %dx%d\n",
   447                    event.resize.w, event.resize.h);
   448             SetVideoMode(event.resize.w, event.resize.h);
   449             break;
   450         case SDL_USEREVENT:
   451             printf("Handling internal quit request\n");
   452             /* Fall through to the quit handler */
   453         case SDL_QUIT:
   454             printf("Bye bye..\n");
   455             quit(0);
   456         default:
   457             /* This should never happen */
   458             printf("Warning: Event %d wasn't filtered\n", event.type);
   459             break;
   460         }
   461     }
   462     printf("SDL_WaitEvent() error: %s\n", SDL_GetError());
   463     SDL_Quit();
   464     return (255);
   465 }