test/testwm.c
author Patrice Mandin <patmandin@gmail.com>
Thu, 19 Jan 2006 21:28:52 +0000
changeset 1257 448a9a64537b
parent 1151 be9c9c8f6d53
child 1284 08e3393e9ffb
permissions -rw-r--r--
[PATCH] SDL_GetVideoMode() does not find best mode, part 2

Following commit 1.51, I come accross a problem when SDL must choose between
several video modes that could suit the one asked.

If I ask 320x240 with this list:
768x480 768x240 640x400 640x200 384x480 384x240 320x400 320x200

The smallest selectables modes are 384x240 and 320x400. And SDL choose the later
in this list, but 384x240 is more suitable. So I added a check to compare
the pixel count (surface) of modes, and select the one which has the smallest
pixel count.

In my example, 384x240 has 92160 pixels, and 320x400 has 128000 pixels. So now
SDL will choose 384x240 for the asked 320x240 mode.
     1 
     2 /* Test out the window manager interaction functions */
     3 
     4 #include <stdio.h>
     5 #include <stdlib.h>
     6 #include <string.h>
     7 
     8 #include "SDL.h"
     9 
    10 /* Is the cursor visible? */
    11 static int visible = 1;
    12 
    13 static Uint8  video_bpp;
    14 static Uint32 video_flags;
    15 
    16 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    17 static void quit(int rc)
    18 {
    19 	SDL_Quit();
    20 	exit(rc);
    21 }
    22 
    23 int SetVideoMode(int w, int h)
    24 {
    25 	SDL_Surface *screen;
    26 	int i;
    27 	Uint8 *buffer;
    28 	SDL_Color palette[256];
    29 
    30 	screen = SDL_SetVideoMode(w, h, video_bpp, video_flags);
    31 	if (  screen == NULL ) {
    32 		fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n",
    33 					w, h, video_bpp, SDL_GetError());
    34 		return(-1);
    35 	}
    36 	printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
    37 						"fullscreen" : "windowed");
    38 
    39 	/* Set the surface pixels and refresh! */
    40 	for ( i=0; i<256; ++i ) {
    41 		palette[i].r = 255-i;
    42 		palette[i].g = 255-i;
    43 		palette[i].b = 255-i;
    44 	}
    45 	SDL_SetColors(screen, palette, 0, 256);
    46 	if ( SDL_LockSurface(screen) < 0 ) {
    47 		fprintf(stderr, "Couldn't lock display surface: %s\n",
    48 							SDL_GetError());
    49 		return(-1);
    50 	}
    51 	buffer = (Uint8 *)screen->pixels;
    52 	for ( i=0; i<screen->h; ++i ) {
    53 		memset(buffer,(i*255)/screen->h,
    54 				screen->w*screen->format->BytesPerPixel);
    55 		buffer += screen->pitch;
    56 	}
    57 	SDL_UnlockSurface(screen);
    58 	SDL_UpdateRect(screen, 0, 0, 0, 0);
    59 
    60 	return(0);
    61 }
    62 
    63 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp)
    64 {
    65 	SDL_Surface *icon;
    66 	Uint8       *pixels;
    67 	Uint8       *mask;
    68 	int          mlen, i, j;
    69 
    70 	*maskp = NULL;
    71 
    72 	/* Load the icon surface */
    73 	icon = SDL_LoadBMP(file);
    74 	if ( icon == NULL ) {
    75 		fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
    76 		return(NULL);
    77 	}
    78 
    79 	/* Check width and height 
    80 	if ( (icon->w%8) != 0 ) {
    81 		fprintf(stderr, "Icon width must be a multiple of 8!\n");
    82 		SDL_FreeSurface(icon);
    83 		return(NULL);
    84 	}
    85 */
    86     
    87     
    88 	if ( icon->format->palette == NULL ) {
    89 		fprintf(stderr, "Icon must have a palette!\n");
    90 		SDL_FreeSurface(icon);
    91 		return(NULL);
    92 	}
    93 
    94 	/* Set the colorkey */
    95 	SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels));
    96 
    97 	/* Create the mask */
    98 	pixels = (Uint8 *)icon->pixels;
    99 	printf("Transparent pixel: (%d,%d,%d)\n",
   100 				icon->format->palette->colors[*pixels].r,
   101 				icon->format->palette->colors[*pixels].g,
   102 				icon->format->palette->colors[*pixels].b);
   103 	mlen = (icon->w*icon->h + 7) / 8;
   104 	mask = (Uint8 *)malloc(mlen);
   105 	if ( mask == NULL ) {
   106 		fprintf(stderr, "Out of memory!\n");
   107 		SDL_FreeSurface(icon);
   108 		return(NULL);
   109 	}
   110 	memset(mask, 0, mlen);
   111 	for ( i=0; i < icon->h; i++)
   112         for (j=0; j < icon->w; j++) {
   113             int pindex = i * icon->pitch + j;
   114             int mindex = i * icon->w + j;
   115             if ( pixels[pindex] != *pixels )
   116                 mask[mindex>>3] |= 1 << (7 - (mindex & 7));
   117         }
   118 	*maskp = mask;
   119 	return(icon);
   120 }
   121 
   122 void HotKey_ToggleFullScreen(void)
   123 {
   124 	SDL_Surface *screen;
   125 
   126 	screen = SDL_GetVideoSurface();
   127 	if ( SDL_WM_ToggleFullScreen(screen) ) {
   128 		printf("Toggled fullscreen mode - now %s\n",
   129 		    (screen->flags&SDL_FULLSCREEN) ? "fullscreen" : "windowed");
   130 	} else {
   131 		printf("Unable to toggle fullscreen mode\n");
   132 		video_flags ^= SDL_FULLSCREEN;
   133 		SetVideoMode(screen->w, screen->h);
   134 	}
   135 }
   136 
   137 void HotKey_ToggleGrab(void)
   138 {
   139 	SDL_GrabMode mode;
   140 
   141 	printf("Ctrl-G: toggling input grab!\n");
   142 	mode = SDL_WM_GrabInput(SDL_GRAB_QUERY);
   143 	if ( mode == SDL_GRAB_ON ) {
   144 		printf("Grab was on\n");
   145 	} else {
   146 		printf("Grab was off\n");
   147 	}
   148 	mode = SDL_WM_GrabInput(mode ? SDL_GRAB_OFF : SDL_GRAB_ON);
   149 	if ( mode == SDL_GRAB_ON ) {
   150 		printf("Grab is now on\n");
   151 	} else {
   152 		printf("Grab is now off\n");
   153 	}
   154 }
   155 
   156 void HotKey_Iconify(void)
   157 {
   158 	printf("Ctrl-Z: iconifying window!\n");
   159 	SDL_WM_IconifyWindow();
   160 }
   161 
   162 void HotKey_Quit(void)
   163 {
   164 	SDL_Event event;
   165 
   166 	printf("Posting internal quit request\n");
   167 	event.type = SDL_USEREVENT;
   168 	SDL_PushEvent(&event);
   169 }
   170 
   171 int FilterEvents(const SDL_Event *event)
   172 {
   173 	static int reallyquit = 0;
   174 
   175 	switch (event->type) {
   176 
   177 		case SDL_ACTIVEEVENT:
   178 			/* See what happened */
   179 			printf("App %s ",
   180 				event->active.gain ? "gained" : "lost");
   181 			if ( event->active.state & SDL_APPACTIVE )
   182 				printf("active ");
   183 			if ( event->active.state & SDL_APPMOUSEFOCUS )
   184 				printf("mouse ");
   185 			if ( event->active.state & SDL_APPINPUTFOCUS )
   186 				printf("input ");
   187 			printf("focus\n");
   188 
   189 			/* See if we are iconified or restored */
   190 			if ( event->active.state & SDL_APPACTIVE ) {
   191 				printf("App has been %s\n",
   192 					event->active.gain ?
   193 						 "restored" : "iconified");
   194 			}
   195 			return(0);
   196 
   197 		/* We want to toggle visibility on buttonpress */
   198 		case SDL_MOUSEBUTTONDOWN:
   199 		case SDL_MOUSEBUTTONUP:
   200 			if ( event->button.state == SDL_PRESSED ) {
   201 				visible = !visible;
   202 				SDL_ShowCursor(visible);
   203 			}
   204 			printf("Mouse button %d has been %s\n",
   205 				event->button.button,
   206 				(event->button.state == SDL_PRESSED) ?
   207 						"pressed" : "released");
   208 			return(0);
   209 
   210 		/* Show relative mouse motion */
   211 		case SDL_MOUSEMOTION:
   212 #if 0
   213 			printf("Mouse relative motion: {%d,%d}\n",
   214 				event->motion.xrel, event->motion.yrel);
   215 #endif
   216 			return(0);
   217 
   218 		case SDL_KEYDOWN:
   219 			if ( event->key.keysym.sym == SDLK_ESCAPE ) {
   220 				HotKey_Quit();
   221 			}
   222 			if ( (event->key.keysym.sym == SDLK_g) &&
   223 			     (event->key.keysym.mod & KMOD_CTRL) ) {
   224 				HotKey_ToggleGrab();
   225 			}
   226 			if ( (event->key.keysym.sym == SDLK_z) &&
   227 			     (event->key.keysym.mod & KMOD_CTRL) ) {
   228 				HotKey_Iconify();
   229 			}
   230 			if ( (event->key.keysym.sym == SDLK_RETURN) &&
   231 			     (event->key.keysym.mod & KMOD_ALT) ) {
   232 				HotKey_ToggleFullScreen();
   233 			}
   234 			return(0);
   235 
   236 		/* Pass the video resize event through .. */
   237 		case SDL_VIDEORESIZE:
   238 			return(1);
   239 
   240 		/* This is important!  Queue it if we want to quit. */
   241 		case SDL_QUIT:
   242 			if ( ! reallyquit ) {
   243 				reallyquit = 1;
   244 				printf("Quit requested\n");
   245 				return(0);
   246 			}
   247 			printf("Quit demanded\n");
   248 			return(1);
   249 
   250 		/* This will never happen because events queued directly
   251 		   to the event queue are not filtered.
   252 		 */
   253 		case SDL_USEREVENT:
   254 			return(1);
   255 
   256 		/* Drop all other events */
   257 		default:
   258 			return(0);
   259 	}
   260 }
   261 
   262 int main(int argc, char *argv[])
   263 {
   264 	SDL_Event event;
   265 	char *title;
   266 	SDL_Surface *icon;
   267 	Uint8 *icon_mask;
   268 	int parsed;
   269 	int w, h;
   270 
   271 	if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
   272 		fprintf(stderr,
   273 			"Couldn't initialize SDL: %s\n", SDL_GetError());
   274 		return(1);
   275 	}
   276 
   277 	/* Check command line arguments */
   278 	w = 640;
   279 	h = 480;
   280 	video_bpp = 8;
   281 	video_flags = SDL_SWSURFACE;
   282 	parsed = 1;
   283 	while ( parsed ) {
   284 		if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) {
   285 			video_flags |= SDL_FULLSCREEN;
   286 			argc -= 1;
   287 			argv += 1;
   288 		} else
   289 		if ( (argc >= 2) && (strcmp(argv[1], "-resize") == 0) ) {
   290 			video_flags |= SDL_RESIZABLE;
   291 			argc -= 1;
   292 			argv += 1;
   293 		} else
   294 		if ( (argc >= 2) && (strcmp(argv[1], "-noframe") == 0) ) {
   295 			video_flags |= SDL_NOFRAME;
   296 			argc -= 1;
   297 			argv += 1;
   298 		} else
   299 		if ( (argc >= 3) && (strcmp(argv[1], "-width") == 0) ) {
   300 			w = atoi(argv[2]);
   301 			argc -= 2;
   302 			argv += 2;
   303 		} else
   304 		if ( (argc >= 3) && (strcmp(argv[1], "-height") == 0) ) {
   305 			h = atoi(argv[2]);
   306 			argc -= 2;
   307 			argv += 2;
   308 		} else
   309 		if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) {
   310 			video_bpp = atoi(argv[2]);
   311 			argc -= 2;
   312 			argv += 2;
   313 		} else {
   314 			parsed = 0;
   315 		}
   316 	}
   317 
   318 	/* Set the icon -- this must be done before the first mode set */
   319 	icon = LoadIconSurface("icon.bmp", &icon_mask);
   320 	if ( icon != NULL ) {
   321 		SDL_WM_SetIcon(icon, icon_mask);
   322 	}
   323 	if ( icon_mask != NULL )
   324 		free(icon_mask);
   325 
   326 	/* Set the title bar */
   327 	if ( argv[1] == NULL )
   328 		title = "Testing  1.. 2.. 3...";
   329 	else
   330 		title = argv[1];
   331 	SDL_WM_SetCaption(title, "testwm");
   332 
   333 	/* See if it's really set */
   334 	SDL_WM_GetCaption(&title, NULL);
   335 	if ( title )
   336 		printf("Title was set to: %s\n", title);
   337 	else
   338 		printf("No window title was set!\n");
   339 
   340 	/* Initialize the display */
   341 	if ( SetVideoMode(w, h) < 0 ) {
   342 		quit(1);
   343 	}
   344 
   345 	/* Set an event filter that discards everything but QUIT */
   346 	SDL_SetEventFilter(FilterEvents);
   347 
   348 	/* Ignore key up events, they don't even get filtered */
   349 	SDL_EventState(SDL_KEYUP, SDL_IGNORE);
   350 
   351 	/* Loop, waiting for QUIT */
   352 	while ( SDL_WaitEvent(&event) ) {
   353 		switch (event.type) {
   354 			case SDL_VIDEORESIZE:
   355 				printf("Got a resize event: %dx%d\n",
   356 				       event.resize.w, event.resize.h);
   357 				SetVideoMode(event.resize.w, event.resize.h);
   358 				break;
   359 			case SDL_USEREVENT:
   360 				printf("Handling internal quit request\n");
   361 				/* Fall through to the quit handler */
   362 			case SDL_QUIT:
   363 				printf("Bye bye..\n");
   364 				quit(0);
   365 			default:
   366 				/* This should never happen */
   367 				printf("Warning: Event %d wasn't filtered\n",
   368 								event.type);
   369 				break;
   370 		}
   371 	}
   372 	printf("SDL_WaitEvent() error: %s\n", SDL_GetError());
   373 	SDL_Quit();
   374 	return(255);
   375 }