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