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