Home | History | Annotate | Download | only in windib
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2006 Sam Lantinga
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Lesser General Public
      7     License as published by the Free Software Foundation; either
      8     version 2.1 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Lesser General Public License for more details.
     14 
     15     You should have received a copy of the GNU Lesser General Public
     16     License along with this library; if not, write to the Free Software
     17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     18 
     19     Sam Lantinga
     20     slouken (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 #define WIN32_LEAN_AND_MEAN
     25 #include <windows.h>
     26 
     27 /* Not yet in the mingw32 cross-compile headers */
     28 #ifndef CDS_FULLSCREEN
     29 #define CDS_FULLSCREEN	4
     30 #endif
     31 
     32 #include "SDL_syswm.h"
     33 #include "../SDL_sysvideo.h"
     34 #include "../SDL_pixels_c.h"
     35 #include "../../events/SDL_sysevents.h"
     36 #include "../../events/SDL_events_c.h"
     37 #include "SDL_dibvideo.h"
     38 #include "../wincommon/SDL_syswm_c.h"
     39 #include "../wincommon/SDL_sysmouse_c.h"
     40 #include "SDL_dibevents_c.h"
     41 #include "../wincommon/SDL_wingl_c.h"
     42 
     43 #ifdef _WIN32_WCE
     44 #define NO_GETDIBITS
     45 #define NO_GAMMA_SUPPORT
     46   #if _WIN32_WCE < 420
     47     #define NO_CHANGEDISPLAYSETTINGS
     48   #else
     49     #define ChangeDisplaySettings(lpDevMode, dwFlags) ChangeDisplaySettingsEx(NULL, (lpDevMode), 0, (dwFlags), 0)
     50   #endif
     51 #endif
     52 #ifndef WS_MAXIMIZE
     53 #define WS_MAXIMIZE	0
     54 #endif
     55 #ifndef WS_THICKFRAME
     56 #define WS_THICKFRAME	0
     57 #endif
     58 #ifndef SWP_NOCOPYBITS
     59 #define SWP_NOCOPYBITS	0
     60 #endif
     61 #ifndef PC_NOCOLLAPSE
     62 #define PC_NOCOLLAPSE	0
     63 #endif
     64 
     65 #ifdef _WIN32_WCE
     66 // defined and used in SDL_sysevents.c
     67 extern HINSTANCE aygshell;
     68 #endif
     69 
     70 /* Initialization/Query functions */
     71 static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
     72 static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
     73 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
     74 static int DIB_SetColors(_THIS, int firstcolor, int ncolors,
     75 			 SDL_Color *colors);
     76 static void DIB_CheckGamma(_THIS);
     77 void DIB_SwapGamma(_THIS);
     78 void DIB_QuitGamma(_THIS);
     79 int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
     80 int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
     81 static void DIB_VideoQuit(_THIS);
     82 
     83 /* Hardware surface functions */
     84 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);
     85 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);
     86 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);
     87 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
     88 
     89 /* Windows message handling functions */
     90 static void DIB_GrabStaticColors(HWND window);
     91 static void DIB_ReleaseStaticColors(HWND window);
     92 static void DIB_Activate(_THIS, BOOL active, BOOL minimized);
     93 static void DIB_RealizePalette(_THIS);
     94 static void DIB_PaletteChanged(_THIS, HWND window);
     95 static void DIB_WinPAINT(_THIS, HDC hdc);
     96 
     97 static void DIB_GetWinPos(_THIS, int* px, int *py);
     98 static void DIB_SetWinPos(_THIS, int  x, int  y);
     99 static int  DIB_IsWinVisible(_THIS, int recenter);
    100 static int  DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi);
    101 static int  DIB_GetMonitorRect(_THIS, SDL_Rect*  rect);
    102 
    103 /* helper fn */
    104 static int DIB_SussScreenDepth();
    105 
    106 /* DIB driver bootstrap functions */
    107 
    108 static int DIB_Available(void)
    109 {
    110 	return(1);
    111 }
    112 
    113 static void DIB_DeleteDevice(SDL_VideoDevice *device)
    114 {
    115 	if ( device ) {
    116 		if ( device->hidden ) {
    117 			SDL_free(device->hidden);
    118 		}
    119 		if ( device->gl_data ) {
    120 			SDL_free(device->gl_data);
    121 		}
    122 		SDL_free(device);
    123 	}
    124 }
    125 
    126 static SDL_VideoDevice *DIB_CreateDevice(int devindex)
    127 {
    128 	SDL_VideoDevice *device;
    129 
    130 	/* Initialize all variables that we clean on shutdown */
    131 	device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice));
    132 	if ( device ) {
    133 		SDL_memset(device, 0, (sizeof *device));
    134 		device->hidden = (struct SDL_PrivateVideoData *)
    135 				SDL_malloc((sizeof *device->hidden));
    136 		device->gl_data = (struct SDL_PrivateGLData *)
    137 				SDL_malloc((sizeof *device->gl_data));
    138 	}
    139 	if ( (device == NULL) || (device->hidden == NULL) ||
    140 		                 (device->gl_data == NULL) ) {
    141 		SDL_OutOfMemory();
    142 		DIB_DeleteDevice(device);
    143 		return(NULL);
    144 	}
    145 	SDL_memset(device->hidden, 0, (sizeof *device->hidden));
    146 	SDL_memset(device->gl_data, 0, (sizeof *device->gl_data));
    147 
    148 	/* Set the function pointers */
    149 	device->VideoInit = DIB_VideoInit;
    150 	device->ListModes = DIB_ListModes;
    151 	device->SetVideoMode = DIB_SetVideoMode;
    152 	device->UpdateMouse = WIN_UpdateMouse;
    153 	device->SetColors = DIB_SetColors;
    154 	device->UpdateRects = NULL;
    155 	device->VideoQuit = DIB_VideoQuit;
    156 	device->AllocHWSurface = DIB_AllocHWSurface;
    157 	device->CheckHWBlit = NULL;
    158 	device->FillHWRect = NULL;
    159 	device->SetHWColorKey = NULL;
    160 	device->SetHWAlpha = NULL;
    161 	device->LockHWSurface = DIB_LockHWSurface;
    162 	device->UnlockHWSurface = DIB_UnlockHWSurface;
    163 	device->FlipHWSurface = NULL;
    164 	device->FreeHWSurface = DIB_FreeHWSurface;
    165 	device->SetGammaRamp = DIB_SetGammaRamp;
    166 	device->GetGammaRamp = DIB_GetGammaRamp;
    167 #if SDL_VIDEO_OPENGL
    168 	device->GL_LoadLibrary = WIN_GL_LoadLibrary;
    169 	device->GL_GetProcAddress = WIN_GL_GetProcAddress;
    170 	device->GL_GetAttribute = WIN_GL_GetAttribute;
    171 	device->GL_MakeCurrent = WIN_GL_MakeCurrent;
    172 	device->GL_SwapBuffers = WIN_GL_SwapBuffers;
    173 #endif
    174 	device->SetCaption = WIN_SetWMCaption;
    175 	device->SetIcon = WIN_SetWMIcon;
    176 	device->IconifyWindow = WIN_IconifyWindow;
    177 	device->GrabInput = WIN_GrabInput;
    178 	device->GetWMInfo = WIN_GetWMInfo;
    179 	device->FreeWMCursor = WIN_FreeWMCursor;
    180 	device->CreateWMCursor = WIN_CreateWMCursor;
    181 	device->ShowWMCursor = WIN_ShowWMCursor;
    182 	device->WarpWMCursor = WIN_WarpWMCursor;
    183 	device->CheckMouseMode = WIN_CheckMouseMode;
    184 	device->InitOSKeymap = DIB_InitOSKeymap;
    185 	device->PumpEvents = DIB_PumpEvents;
    186 
    187     device->GetWindowPos = DIB_GetWinPos;
    188     device->SetWindowPos = DIB_SetWinPos;
    189     device->IsWindowVisible = DIB_IsWinVisible;
    190     device->GetMonitorDPI = DIB_GetMonitorDPI;
    191     device->GetMonitorRect = DIB_GetMonitorRect;
    192 
    193 	/* Set up the windows message handling functions */
    194 	WIN_Activate = DIB_Activate;
    195 	WIN_RealizePalette = DIB_RealizePalette;
    196 	WIN_PaletteChanged = DIB_PaletteChanged;
    197 	WIN_WinPAINT = DIB_WinPAINT;
    198 	HandleMessage = DIB_HandleMessage;
    199 
    200 	device->free = DIB_DeleteDevice;
    201 
    202 	/* We're finally ready */
    203 	return device;
    204 }
    205 
    206 VideoBootStrap WINDIB_bootstrap = {
    207 	"windib", "Win95/98/NT/2000/CE GDI",
    208 	DIB_Available, DIB_CreateDevice
    209 };
    210 
    211 static int cmpmodes(const void *va, const void *vb)
    212 {
    213     SDL_Rect *a = *(SDL_Rect **)va;
    214     SDL_Rect *b = *(SDL_Rect **)vb;
    215     if ( a->w == b->w )
    216         return b->h - a->h;
    217     else
    218         return b->w - a->w;
    219 }
    220 
    221 static int DIB_AddMode(_THIS, int bpp, int w, int h)
    222 {
    223 	SDL_Rect *mode;
    224 	int i, index;
    225 	int next_mode;
    226 
    227 	/* Check to see if we already have this mode */
    228 	if ( bpp < 8 ) {  /* Not supported */
    229 		return(0);
    230 	}
    231 	index = ((bpp+7)/8)-1;
    232 	for ( i=0; i<SDL_nummodes[index]; ++i ) {
    233 		mode = SDL_modelist[index][i];
    234 		if ( (mode->w == w) && (mode->h == h) ) {
    235 			return(0);
    236 		}
    237 	}
    238 
    239 	/* Set up the new video mode rectangle */
    240 	mode = (SDL_Rect *)SDL_malloc(sizeof *mode);
    241 	if ( mode == NULL ) {
    242 		SDL_OutOfMemory();
    243 		return(-1);
    244 	}
    245 	mode->x = 0;
    246 	mode->y = 0;
    247 	mode->w = w;
    248 	mode->h = h;
    249 
    250 	/* Allocate the new list of modes, and fill in the new mode */
    251 	next_mode = SDL_nummodes[index];
    252 	SDL_modelist[index] = (SDL_Rect **)
    253 	       SDL_realloc(SDL_modelist[index], (1+next_mode+1)*sizeof(SDL_Rect *));
    254 	if ( SDL_modelist[index] == NULL ) {
    255 		SDL_OutOfMemory();
    256 		SDL_nummodes[index] = 0;
    257 		SDL_free(mode);
    258 		return(-1);
    259 	}
    260 	SDL_modelist[index][next_mode] = mode;
    261 	SDL_modelist[index][next_mode+1] = NULL;
    262 	SDL_nummodes[index]++;
    263 
    264 	return(0);
    265 }
    266 
    267 static void DIB_CreatePalette(_THIS, int bpp)
    268 {
    269 /*	RJR: March 28, 2000
    270 	moved palette creation here from "DIB_VideoInit" */
    271 
    272 	LOGPALETTE *palette;
    273 	HDC hdc;
    274 	int ncolors;
    275 
    276 	ncolors = (1 << bpp);
    277 	palette = (LOGPALETTE *)SDL_malloc(sizeof(*palette)+
    278 				ncolors*sizeof(PALETTEENTRY));
    279 	palette->palVersion = 0x300;
    280 	palette->palNumEntries = ncolors;
    281 	hdc = GetDC(SDL_Window);
    282 	GetSystemPaletteEntries(hdc, 0, ncolors, palette->palPalEntry);
    283 	ReleaseDC(SDL_Window, hdc);
    284 	screen_pal = CreatePalette(palette);
    285 	screen_logpal = palette;
    286 }
    287 
    288 int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat)
    289 {
    290 	const char *env = NULL;
    291 #ifndef NO_CHANGEDISPLAYSETTINGS
    292 	int i;
    293 	DEVMODE settings;
    294 #endif
    295 
    296 	/* Create the window */
    297 	if ( DIB_CreateWindow(this) < 0 ) {
    298 		return(-1);
    299 	}
    300 
    301 #if !SDL_AUDIO_DISABLED
    302 	DX5_SoundFocus(SDL_Window);
    303 #endif
    304 
    305 	/* Determine the screen depth */
    306 	vformat->BitsPerPixel = DIB_SussScreenDepth();
    307 	switch (vformat->BitsPerPixel) {
    308 		case 15:
    309 			vformat->Rmask = 0x00007c00;
    310 			vformat->Gmask = 0x000003e0;
    311 			vformat->Bmask = 0x0000001f;
    312 			vformat->BitsPerPixel = 16;
    313 			break;
    314 		case 16:
    315 			vformat->Rmask = 0x0000f800;
    316 			vformat->Gmask = 0x000007e0;
    317 			vformat->Bmask = 0x0000001f;
    318 			break;
    319 		case 24:
    320 		case 32:
    321 			/* GDI defined as 8-8-8 */
    322 			vformat->Rmask = 0x00ff0000;
    323 			vformat->Gmask = 0x0000ff00;
    324 			vformat->Bmask = 0x000000ff;
    325 			break;
    326 		default:
    327 			break;
    328 	}
    329 
    330 	/* See if gamma is supported on this screen */
    331 	DIB_CheckGamma(this);
    332 
    333 #ifndef NO_CHANGEDISPLAYSETTINGS
    334 
    335 	settings.dmSize = sizeof(DEVMODE);
    336 	settings.dmDriverExtra = 0;
    337 #ifdef _WIN32_WCE
    338 	settings.dmFields = DM_DISPLAYQUERYORIENTATION;
    339 	this->hidden->supportRotation = ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL) == DISP_CHANGE_SUCCESSFUL;
    340 #endif
    341 	/* Query for the desktop resolution */
    342 	EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &SDL_desktop_mode);
    343 	this->info.current_w = SDL_desktop_mode.dmPelsWidth;
    344 	this->info.current_h = SDL_desktop_mode.dmPelsHeight;
    345 
    346 	/* Query for the list of available video modes */
    347 	for ( i=0; EnumDisplaySettings(NULL, i, &settings); ++i ) {
    348 		DIB_AddMode(this, settings.dmBitsPerPel,
    349 			settings.dmPelsWidth, settings.dmPelsHeight);
    350 #ifdef _WIN32_WCE
    351 		if( this->hidden->supportRotation )
    352 			DIB_AddMode(this, settings.dmBitsPerPel,
    353 				settings.dmPelsHeight, settings.dmPelsWidth);
    354 #endif
    355 	}
    356 	/* Sort the mode lists */
    357 	for ( i=0; i<NUM_MODELISTS; ++i ) {
    358 		if ( SDL_nummodes[i] > 0 ) {
    359 			SDL_qsort(SDL_modelist[i], SDL_nummodes[i], sizeof *SDL_modelist[i], cmpmodes);
    360 		}
    361 	}
    362 #else
    363 	// WinCE and fullscreen mode:
    364 	// We use only vformat->BitsPerPixel that allow SDL to
    365 	// emulate other bpp (8, 32) and use triple buffer,
    366 	// because SDL surface conversion is much faster than the WinCE one.
    367 	// Although it should be tested on devices with graphics accelerator.
    368 
    369 	DIB_AddMode(this, vformat->BitsPerPixel,
    370 			GetDeviceCaps(GetDC(NULL), HORZRES),
    371 			GetDeviceCaps(GetDC(NULL), VERTRES));
    372 
    373 #endif /* !NO_CHANGEDISPLAYSETTINGS */
    374 
    375 	/* Grab an identity palette if we are in a palettized mode */
    376 	if ( vformat->BitsPerPixel <= 8 ) {
    377 	/*	RJR: March 28, 2000
    378 		moved palette creation to "DIB_CreatePalette" */
    379 		DIB_CreatePalette(this, vformat->BitsPerPixel);
    380 	}
    381 
    382 	/* Fill in some window manager capabilities */
    383 	this->info.wm_available = 1;
    384 
    385 #ifdef _WIN32_WCE
    386 	this->hidden->origRotation = -1;
    387 #endif
    388 
    389 	/* Allow environment override of screensaver disable. */
    390 	env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER");
    391 	this->hidden->allow_screensaver = ( (env && SDL_atoi(env)) ? 1 : 0 );
    392 
    393 	/* We're done! */
    394 	return(0);
    395 }
    396 
    397 /* We support any format at any dimension */
    398 SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    399 {
    400 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    401 		return(SDL_modelist[((format->BitsPerPixel+7)/8)-1]);
    402 	} else {
    403 		return((SDL_Rect **)-1);
    404 	}
    405 }
    406 
    407 
    408 /*
    409   Helper fn to work out which screen depth windows is currently using.
    410   15 bit mode is considered 555 format, 16 bit is 565.
    411   returns 0 for unknown mode.
    412   (Derived from code in sept 1999 Windows Developer Journal
    413   http://www.wdj.com/code/archive.html)
    414 */
    415 static int DIB_SussScreenDepth()
    416 {
    417 #ifdef NO_GETDIBITS
    418 	int depth;
    419 	HDC hdc;
    420 
    421 	hdc = GetDC(SDL_Window);
    422 	depth = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL);
    423 	ReleaseDC(SDL_Window, hdc);
    424 	return(depth);
    425 #else
    426     int depth;
    427     int dib_size;
    428     LPBITMAPINFOHEADER dib_hdr;
    429     HDC hdc;
    430     HBITMAP hbm;
    431 
    432     /* Allocate enough space for a DIB header plus palette (for
    433      * 8-bit modes) or bitfields (for 16- and 32-bit modes)
    434      */
    435     dib_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
    436     dib_hdr = (LPBITMAPINFOHEADER) SDL_malloc(dib_size);
    437     SDL_memset(dib_hdr, 0, dib_size);
    438     dib_hdr->biSize = sizeof(BITMAPINFOHEADER);
    439 
    440     /* Get a device-dependent bitmap that's compatible with the
    441        screen.
    442      */
    443     hdc = GetDC(NULL);
    444     hbm = CreateCompatibleBitmap( hdc, 1, 1 );
    445 
    446     /* Convert the DDB to a DIB.  We need to call GetDIBits twice:
    447      * the first call just fills in the BITMAPINFOHEADER; the
    448      * second fills in the bitfields or palette.
    449      */
    450     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
    451     GetDIBits(hdc, hbm, 0, 1, NULL, (LPBITMAPINFO) dib_hdr, DIB_RGB_COLORS);
    452     DeleteObject(hbm);
    453     ReleaseDC(NULL, hdc);
    454 
    455     depth = 0;
    456     switch( dib_hdr->biBitCount )
    457     {
    458     case 8:     depth = 8; break;
    459     case 24:    depth = 24; break;
    460     case 32:    depth = 32; break;
    461     case 16:
    462         if( dib_hdr->biCompression == BI_BITFIELDS ) {
    463             /* check the red mask */
    464             switch( ((DWORD*)((char*)dib_hdr + dib_hdr->biSize))[0] ) {
    465                 case 0xf800: depth = 16; break;   /* 565 */
    466                 case 0x7c00: depth = 15; break;   /* 555 */
    467             }
    468         }
    469     }
    470     SDL_free(dib_hdr);
    471     return depth;
    472 #endif /* NO_GETDIBITS */
    473 }
    474 
    475 
    476 /* Various screen update functions available */
    477 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
    478 
    479 SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
    480 				int width, int height, int bpp, Uint32 flags)
    481 {
    482 	SDL_Surface *video;
    483 	int prev_w, prev_h;
    484 	Uint32 prev_flags;
    485 	DWORD style;
    486 	const DWORD directstyle =
    487 			(WS_POPUP);
    488 	const DWORD windowstyle =
    489 			(WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX);
    490 	const DWORD resizestyle =
    491 			(WS_THICKFRAME|WS_MAXIMIZEBOX);
    492 	int binfo_size;
    493 	BITMAPINFO *binfo;
    494 	HDC hdc;
    495 	RECT bounds;
    496 	int x, y;
    497 	Uint32 Rmask, Gmask, Bmask;
    498 
    499 	/* Clean up any GL context that may be hanging around */
    500 	if ( current->flags & SDL_OPENGL ) {
    501 		WIN_GL_ShutDown(this);
    502 	}
    503 	SDL_resizing = 1;
    504 
    505 	/* Recalculate the bitmasks if necessary */
    506 	if ( bpp == current->format->BitsPerPixel ) {
    507 		video = current;
    508 	} else {
    509 		switch (bpp) {
    510 			case 15:
    511 			case 16:
    512 				if ( DIB_SussScreenDepth() == 15 ) {
    513 					/* 5-5-5 */
    514 					Rmask = 0x00007c00;
    515 					Gmask = 0x000003e0;
    516 					Bmask = 0x0000001f;
    517 				} else {
    518 					/* 5-6-5 */
    519 					Rmask = 0x0000f800;
    520 					Gmask = 0x000007e0;
    521 					Bmask = 0x0000001f;
    522 				}
    523 				break;
    524 			case 24:
    525 			case 32:
    526 				/* GDI defined as 8-8-8 */
    527 				Rmask = 0x00ff0000;
    528 				Gmask = 0x0000ff00;
    529 				Bmask = 0x000000ff;
    530 				break;
    531 			default:
    532 				Rmask = 0x00000000;
    533 				Gmask = 0x00000000;
    534 				Bmask = 0x00000000;
    535 				break;
    536 		}
    537 		video = SDL_CreateRGBSurface(SDL_SWSURFACE,
    538 					0, 0, bpp, Rmask, Gmask, Bmask, 0);
    539 		if ( video == NULL ) {
    540 			SDL_OutOfMemory();
    541 			return(NULL);
    542 		}
    543 	}
    544 
    545 	/* Fill in part of the video surface */
    546 	prev_flags = video->flags;
    547 	prev_w = video->w;
    548 	prev_h = video->h;
    549 	video->flags = 0;	/* Clear flags */
    550 	video->w = width;
    551 	video->h = height;
    552 	video->pitch = SDL_CalculatePitch(video);
    553 
    554 	/* Small fix for WinCE/Win32 - when activating window
    555 	   SDL_VideoSurface is equal to zero, so activating code
    556 	   is not called properly for fullscreen windows because
    557 	   macros WINDIB_FULLSCREEN uses SDL_VideoSurface
    558 	*/
    559 	SDL_VideoSurface = video;
    560 
    561 #if defined(_WIN32_WCE)
    562 	if ( flags & SDL_FULLSCREEN )
    563 		video->flags |= SDL_FULLSCREEN;
    564 #endif
    565 
    566 #ifndef NO_CHANGEDISPLAYSETTINGS
    567 	/* Set fullscreen mode if appropriate */
    568 	if ( (flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    569 		DEVMODE settings;
    570 		BOOL changed;
    571 
    572 		SDL_memset(&settings, 0, sizeof(DEVMODE));
    573 		settings.dmSize = sizeof(DEVMODE);
    574 
    575 #ifdef _WIN32_WCE
    576 		// try to rotate screen to fit requested resolution
    577 		if( this->hidden->supportRotation )
    578 		{
    579 			DWORD rotation;
    580 
    581 			// ask current mode
    582 			settings.dmFields = DM_DISPLAYORIENTATION;
    583 			ChangeDisplaySettingsEx(NULL, &settings, NULL, CDS_TEST, NULL);
    584 			rotation = settings.dmDisplayOrientation;
    585 
    586 			if( (width > GetDeviceCaps(GetDC(NULL), HORZRES))
    587 				&& (height < GetDeviceCaps(GetDC(NULL), VERTRES)))
    588 			{
    589 				switch( rotation )
    590 				{
    591 				case DMDO_0:
    592 					settings.dmDisplayOrientation = DMDO_90;
    593 					break;
    594 				case DMDO_270:
    595 					settings.dmDisplayOrientation = DMDO_180;
    596 					break;
    597 				}
    598 				if( settings.dmDisplayOrientation != rotation )
    599 				{
    600 					// go to landscape
    601 					this->hidden->origRotation = rotation;
    602 					ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
    603 				}
    604 			}
    605 			if( (width < GetDeviceCaps(GetDC(NULL), HORZRES))
    606 				&& (height > GetDeviceCaps(GetDC(NULL), VERTRES)))
    607 			{
    608 				switch( rotation )
    609 				{
    610 				case DMDO_90:
    611 					settings.dmDisplayOrientation = DMDO_0;
    612 					break;
    613 				case DMDO_180:
    614 					settings.dmDisplayOrientation = DMDO_270;
    615 					break;
    616 				}
    617 				if( settings.dmDisplayOrientation != rotation )
    618 				{
    619 					// go to portrait
    620 					this->hidden->origRotation = rotation;
    621 					ChangeDisplaySettingsEx(NULL,&settings,NULL,CDS_RESET,NULL);
    622 				}
    623 			}
    624 
    625 		}
    626 #endif
    627 
    628 #ifndef _WIN32_WCE
    629 		settings.dmBitsPerPel = video->format->BitsPerPixel;
    630 		settings.dmPelsWidth = width;
    631 		settings.dmPelsHeight = height;
    632 		settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
    633 		if ( width <= (int)SDL_desktop_mode.dmPelsWidth &&
    634 		     height <= (int)SDL_desktop_mode.dmPelsHeight ) {
    635 			settings.dmDisplayFrequency = SDL_desktop_mode.dmDisplayFrequency;
    636 			settings.dmFields |= DM_DISPLAYFREQUENCY;
    637 		}
    638 		changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
    639 		if ( ! changed && (settings.dmFields & DM_DISPLAYFREQUENCY) ) {
    640 			settings.dmFields &= ~DM_DISPLAYFREQUENCY;
    641 			changed = (ChangeDisplaySettings(&settings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
    642 		}
    643 #else
    644 		changed = 1;
    645 #endif
    646 		if ( changed ) {
    647 			video->flags |= SDL_FULLSCREEN;
    648 			SDL_fullscreen_mode = settings;
    649 		}
    650 
    651 	}
    652 #endif /* !NO_CHANGEDISPLAYSETTINGS */
    653 
    654 	/* Reset the palette and create a new one if necessary */
    655 	if ( grab_palette ) {
    656 		DIB_ReleaseStaticColors(SDL_Window);
    657 		grab_palette = FALSE;
    658 	}
    659 	if ( screen_pal != NULL ) {
    660 	/*	RJR: March 28, 2000
    661 		delete identity palette if switching from a palettized mode */
    662 		DeleteObject(screen_pal);
    663 		screen_pal = NULL;
    664 	}
    665 	if ( screen_logpal != NULL ) {
    666 		SDL_free(screen_logpal);
    667 		screen_logpal = NULL;
    668 	}
    669 
    670 	if ( bpp <= 8 )
    671 	{
    672 	/*	RJR: March 28, 2000
    673 		create identity palette switching to a palettized mode */
    674 		DIB_CreatePalette(this, bpp);
    675 	}
    676 
    677 	style = GetWindowLong(SDL_Window, GWL_STYLE);
    678 	style &= ~(resizestyle|WS_MAXIMIZE);
    679 	if ( (video->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    680 		style &= ~windowstyle;
    681 		style |= directstyle;
    682 	} else {
    683 #ifndef NO_CHANGEDISPLAYSETTINGS
    684 		if ( (prev_flags & SDL_FULLSCREEN) == SDL_FULLSCREEN ) {
    685 			ChangeDisplaySettings(NULL, 0);
    686 		}
    687 #endif
    688 		if ( flags & SDL_NOFRAME ) {
    689 			style &= ~windowstyle;
    690 			style |= directstyle;
    691 			video->flags |= SDL_NOFRAME;
    692 		} else {
    693 			style &= ~directstyle;
    694 			style |= windowstyle;
    695 			if ( flags & SDL_RESIZABLE ) {
    696 				style |= resizestyle;
    697 				video->flags |= SDL_RESIZABLE;
    698 			}
    699 		}
    700 #if WS_MAXIMIZE
    701 		if (IsZoomed(SDL_Window)) style |= WS_MAXIMIZE;
    702 #endif
    703 	}
    704 
    705 	/* DJM: Don't piss of anyone who has setup his own window */
    706 	if ( !SDL_windowid )
    707 		SetWindowLong(SDL_Window, GWL_STYLE, style);
    708 
    709 	/* Delete the old bitmap if necessary */
    710 	if ( screen_bmp != NULL ) {
    711 		DeleteObject(screen_bmp);
    712 	}
    713 	if ( ! (flags & SDL_OPENGL) ) {
    714 		BOOL is16bitmode = (video->format->BytesPerPixel == 2);
    715 
    716 		/* Suss out the bitmap info header */
    717 		binfo_size = sizeof(*binfo);
    718 		if( is16bitmode ) {
    719 			/* 16bit modes, palette area used for rgb bitmasks */
    720 			binfo_size += 3*sizeof(DWORD);
    721 		} else if ( video->format->palette ) {
    722 			binfo_size += video->format->palette->ncolors *
    723 							sizeof(RGBQUAD);
    724 		}
    725 		binfo = (BITMAPINFO *)SDL_malloc(binfo_size);
    726 		if ( ! binfo ) {
    727 			if ( video != current ) {
    728 				SDL_FreeSurface(video);
    729 			}
    730 			SDL_OutOfMemory();
    731 			return(NULL);
    732 		}
    733 
    734 		binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    735 		binfo->bmiHeader.biWidth = video->w;
    736 		binfo->bmiHeader.biHeight = -video->h;	/* -ve for topdown bitmap */
    737 		binfo->bmiHeader.biPlanes = 1;
    738 		binfo->bmiHeader.biSizeImage = video->h * video->pitch;
    739 		binfo->bmiHeader.biXPelsPerMeter = 0;
    740 		binfo->bmiHeader.biYPelsPerMeter = 0;
    741 		binfo->bmiHeader.biClrUsed = 0;
    742 		binfo->bmiHeader.biClrImportant = 0;
    743 		binfo->bmiHeader.biBitCount = video->format->BitsPerPixel;
    744 
    745 		if ( is16bitmode ) {
    746 			/* BI_BITFIELDS tells CreateDIBSection about the rgb masks in the palette */
    747 			binfo->bmiHeader.biCompression = BI_BITFIELDS;
    748 			((Uint32*)binfo->bmiColors)[0] = video->format->Rmask;
    749 			((Uint32*)binfo->bmiColors)[1] = video->format->Gmask;
    750 			((Uint32*)binfo->bmiColors)[2] = video->format->Bmask;
    751 		} else {
    752 			binfo->bmiHeader.biCompression = BI_RGB;	/* BI_BITFIELDS for 565 vs 555 */
    753 			if ( video->format->palette ) {
    754 				SDL_memset(binfo->bmiColors, 0,
    755 					video->format->palette->ncolors*sizeof(RGBQUAD));
    756 			}
    757 		}
    758 
    759 		/* Create the offscreen bitmap buffer */
    760 		hdc = GetDC(SDL_Window);
    761 		screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS,
    762 					(void **)(&video->pixels), NULL, 0);
    763 		ReleaseDC(SDL_Window, hdc);
    764 		SDL_free(binfo);
    765 		if ( screen_bmp == NULL ) {
    766 			if ( video != current ) {
    767 				SDL_FreeSurface(video);
    768 			}
    769 			SDL_SetError("Couldn't create DIB section");
    770 			return(NULL);
    771 		}
    772 		this->UpdateRects = DIB_NormalUpdate;
    773 
    774 		/* Set video surface flags */
    775 		if ( screen_pal && (flags & (SDL_FULLSCREEN|SDL_HWPALETTE)) ) {
    776 			grab_palette = TRUE;
    777 		}
    778 		/* BitBlt() maps colors for us */
    779 		video->flags |= SDL_HWPALETTE;
    780 	}
    781 #ifndef _WIN32_WCE
    782 	/* Resize the window */
    783 	if ( !SDL_windowid && !IsZoomed(SDL_Window) ) {
    784 #else
    785 	if ( !SDL_windowid ) {
    786 #endif
    787 		HWND top;
    788 		UINT swp_flags;
    789 		const char *window = NULL;
    790 		const char *center = NULL;
    791 
    792 		if ( video->w != prev_w || video->h != prev_h ) {
    793 			window = SDL_getenv("SDL_VIDEO_WINDOW_POS");
    794 			center = SDL_getenv("SDL_VIDEO_CENTERED");
    795 			if ( window ) {
    796 				if ( SDL_sscanf(window, "%d,%d", &x, &y) == 2 ) {
    797 					SDL_windowX = x;
    798 					SDL_windowY = y;
    799 				}
    800 				if ( SDL_strcmp(window, "center") == 0 ) {
    801 					center = window;
    802 				}
    803 			}
    804 		}
    805 		swp_flags = (SWP_NOCOPYBITS | SWP_SHOWWINDOW);
    806 
    807 		bounds.left = SDL_windowX;
    808 		bounds.top = SDL_windowY;
    809 		bounds.right = SDL_windowX+video->w;
    810 		bounds.bottom = SDL_windowY+video->h;
    811 #ifndef _WIN32_WCE
    812 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), (GetMenu(SDL_Window) != NULL), 0);
    813 #else
    814 		// The bMenu parameter must be FALSE; menu bars are not supported
    815 		AdjustWindowRectEx(&bounds, GetWindowLong(SDL_Window, GWL_STYLE), 0, 0);
    816 #endif
    817 		width = bounds.right-bounds.left;
    818 		height = bounds.bottom-bounds.top;
    819 		if ( (flags & SDL_FULLSCREEN) ) {
    820 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
    821 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
    822 		} else if ( center ) {
    823 			x = (GetSystemMetrics(SM_CXSCREEN)-width)/2;
    824 			y = (GetSystemMetrics(SM_CYSCREEN)-height)/2;
    825 		} else if ( SDL_windowX || SDL_windowY || window ) {
    826 			x = bounds.left;
    827 			y = bounds.top;
    828 		} else {
    829 			x = y = -1;
    830 			swp_flags |= SWP_NOMOVE;
    831 		}
    832 		if ( flags & SDL_FULLSCREEN ) {
    833 			top = HWND_TOPMOST;
    834 		} else {
    835 			top = HWND_NOTOPMOST;
    836 		}
    837 		SetWindowPos(SDL_Window, top, x, y, width, height, swp_flags);
    838 		if ( !(flags & SDL_FULLSCREEN) ) {
    839 			SDL_windowX = SDL_bounds.left;
    840 			SDL_windowY = SDL_bounds.top;
    841 		}
    842 		SetForegroundWindow(SDL_Window);
    843 	}
    844 	SDL_resizing = 0;
    845 
    846 	/* Set up for OpenGL */
    847 	if ( flags & SDL_OPENGL ) {
    848 		if ( WIN_GL_SetupWindow(this) < 0 ) {
    849 			return(NULL);
    850 		}
    851 		video->flags |= SDL_OPENGL;
    852 	}
    853 
    854 	/* JC 14 Mar 2006
    855 		Flush the message loop or this can cause big problems later
    856 		Especially if the user decides to use dialog boxes or assert()!
    857 	*/
    858 	WIN_FlushMessageQueue();
    859 
    860 	/* We're live! */
    861 	return(video);
    862 }
    863 
    864 /* We don't actually allow hardware surfaces in the DIB driver */
    865 static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
    866 {
    867 	return(-1);
    868 }
    869 static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
    870 {
    871 	return;
    872 }
    873 static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
    874 {
    875 	return(0);
    876 }
    877 static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
    878 {
    879 	return;
    880 }
    881 
    882 static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects)
    883 {
    884 	HDC hdc, mdc;
    885 	int i;
    886 
    887 	hdc = GetDC(SDL_Window);
    888 	if ( screen_pal ) {
    889 		SelectPalette(hdc, screen_pal, FALSE);
    890 	}
    891 	mdc = CreateCompatibleDC(hdc);
    892 	SelectObject(mdc, screen_bmp);
    893 	for ( i=0; i<numrects; ++i ) {
    894 		BitBlt(hdc, rects[i].x, rects[i].y, rects[i].w, rects[i].h,
    895 					mdc, rects[i].x, rects[i].y, SRCCOPY);
    896 	}
    897 	DeleteDC(mdc);
    898 	ReleaseDC(SDL_Window, hdc);
    899 }
    900 
    901 static int FindPaletteIndex(LOGPALETTE *pal, BYTE r, BYTE g, BYTE b)
    902 {
    903 	PALETTEENTRY *entry;
    904 	int i;
    905 	int nentries = pal->palNumEntries;
    906 
    907 	for ( i = 0; i < nentries; ++i ) {
    908 		entry = &pal->palPalEntry[i];
    909 		if ( entry->peRed == r && entry->peGreen == g && entry->peBlue == b ) {
    910 			return i;
    911 		}
    912 	}
    913 	return -1;
    914 }
    915 
    916 static BOOL CheckPaletteEntry(LOGPALETTE *pal, int index, BYTE r, BYTE g, BYTE b)
    917 {
    918 	PALETTEENTRY *entry;
    919 	BOOL moved = 0;
    920 
    921 	entry = &pal->palPalEntry[index];
    922 	if ( entry->peRed != r || entry->peGreen != g || entry->peBlue != b ) {
    923 		int found = FindPaletteIndex(pal, r, g, b);
    924 		if ( found >= 0 ) {
    925 			pal->palPalEntry[found] = *entry;
    926 		}
    927 		entry->peRed = r;
    928 		entry->peGreen = g;
    929 		entry->peBlue = b;
    930 		moved = 1;
    931 	}
    932 	entry->peFlags = 0;
    933 
    934 	return moved;
    935 }
    936 
    937 int DIB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
    938 {
    939 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
    940 	HDC hdc, mdc;
    941 	RGBQUAD *pal;
    942 #else
    943 	HDC hdc;
    944 #endif
    945 	int i;
    946 	int moved_entries = 0;
    947 
    948 	/* Update the display palette */
    949 	hdc = GetDC(SDL_Window);
    950 	if ( screen_pal ) {
    951 		PALETTEENTRY *entry;
    952 
    953 		for ( i=0; i<ncolors; ++i ) {
    954 			entry = &screen_logpal->palPalEntry[firstcolor+i];
    955 			entry->peRed   = colors[i].r;
    956 			entry->peGreen = colors[i].g;
    957 			entry->peBlue  = colors[i].b;
    958 			entry->peFlags = PC_NOCOLLAPSE;
    959 		}
    960 #ifdef SYSPAL_NOSTATIC
    961 		/* Check to make sure black and white are in position */
    962 		if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
    963 			moved_entries += CheckPaletteEntry(screen_logpal, 0, 0x00, 0x00, 0x00);
    964 			moved_entries += CheckPaletteEntry(screen_logpal, screen_logpal->palNumEntries-1, 0xff, 0xff, 0xff);
    965 		}
    966 		/* FIXME:
    967 		   If we don't have full access to the palette, what we
    968 		   really want to do is find the 236 most diverse colors
    969 		   in the desired palette, set those entries (10-245) and
    970 		   then map everything into the new system palette.
    971 		 */
    972 #endif
    973 
    974 #ifndef _WIN32_WCE
    975 		/* Copy the entries into the system palette */
    976 		UnrealizeObject(screen_pal);
    977 #endif
    978 		SetPaletteEntries(screen_pal, 0, screen_logpal->palNumEntries, screen_logpal->palPalEntry);
    979 		SelectPalette(hdc, screen_pal, FALSE);
    980 		RealizePalette(hdc);
    981 	}
    982 
    983 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
    984 	/* Copy palette colors into DIB palette */
    985 	pal = SDL_stack_alloc(RGBQUAD, ncolors);
    986 	for ( i=0; i<ncolors; ++i ) {
    987 		pal[i].rgbRed = colors[i].r;
    988 		pal[i].rgbGreen = colors[i].g;
    989 		pal[i].rgbBlue = colors[i].b;
    990 		pal[i].rgbReserved = 0;
    991 	}
    992 
    993 	/* Set the DIB palette and update the display */
    994 	mdc = CreateCompatibleDC(hdc);
    995 	SelectObject(mdc, screen_bmp);
    996 	SetDIBColorTable(mdc, firstcolor, ncolors, pal);
    997 	if ( moved_entries || !grab_palette ) {
    998 		BitBlt(hdc, 0, 0, this->screen->w, this->screen->h,
    999 		       mdc, 0, 0, SRCCOPY);
   1000 	}
   1001 	DeleteDC(mdc);
   1002 	SDL_stack_free(pal);
   1003 #endif
   1004 	ReleaseDC(SDL_Window, hdc);
   1005 	return(1);
   1006 }
   1007 
   1008 
   1009 static void DIB_CheckGamma(_THIS)
   1010 {
   1011 #ifndef NO_GAMMA_SUPPORT
   1012 	HDC hdc;
   1013 	WORD ramp[3*256];
   1014 
   1015 	/* If we fail to get gamma, disable gamma control */
   1016 	hdc = GetDC(SDL_Window);
   1017 	if ( ! GetDeviceGammaRamp(hdc, ramp) ) {
   1018 		this->GetGammaRamp = NULL;
   1019 		this->SetGammaRamp = NULL;
   1020 	}
   1021 	ReleaseDC(SDL_Window, hdc);
   1022 #endif /* !NO_GAMMA_SUPPORT */
   1023 }
   1024 void DIB_SwapGamma(_THIS)
   1025 {
   1026 #ifndef NO_GAMMA_SUPPORT
   1027 	HDC hdc;
   1028 
   1029 	if ( gamma_saved ) {
   1030 		hdc = GetDC(SDL_Window);
   1031 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1032 			/* About to leave active state, restore gamma */
   1033 			SetDeviceGammaRamp(hdc, gamma_saved);
   1034 		} else {
   1035 			/* About to enter active state, set game gamma */
   1036 			GetDeviceGammaRamp(hdc, gamma_saved);
   1037 			SetDeviceGammaRamp(hdc, this->gamma);
   1038 		}
   1039 		ReleaseDC(SDL_Window, hdc);
   1040 	}
   1041 #endif /* !NO_GAMMA_SUPPORT */
   1042 }
   1043 void DIB_QuitGamma(_THIS)
   1044 {
   1045 #ifndef NO_GAMMA_SUPPORT
   1046 	if ( gamma_saved ) {
   1047 		/* Restore the original gamma if necessary */
   1048 		if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1049 			HDC hdc;
   1050 
   1051 			hdc = GetDC(SDL_Window);
   1052 			SetDeviceGammaRamp(hdc, gamma_saved);
   1053 			ReleaseDC(SDL_Window, hdc);
   1054 		}
   1055 
   1056 		/* Free the saved gamma memory */
   1057 		SDL_free(gamma_saved);
   1058 		gamma_saved = 0;
   1059 	}
   1060 #endif /* !NO_GAMMA_SUPPORT */
   1061 }
   1062 
   1063 int DIB_SetGammaRamp(_THIS, Uint16 *ramp)
   1064 {
   1065 #ifdef NO_GAMMA_SUPPORT
   1066 	SDL_SetError("SDL compiled without gamma ramp support");
   1067 	return -1;
   1068 #else
   1069 	HDC hdc;
   1070 	BOOL succeeded;
   1071 
   1072 	/* Set the ramp for the display */
   1073 	if ( ! gamma_saved ) {
   1074 		gamma_saved = (WORD *)SDL_malloc(3*256*sizeof(*gamma_saved));
   1075 		if ( ! gamma_saved ) {
   1076 			SDL_OutOfMemory();
   1077 			return -1;
   1078 		}
   1079 		hdc = GetDC(SDL_Window);
   1080 		GetDeviceGammaRamp(hdc, gamma_saved);
   1081 		ReleaseDC(SDL_Window, hdc);
   1082 	}
   1083 	if ( SDL_GetAppState() & SDL_APPINPUTFOCUS ) {
   1084 		hdc = GetDC(SDL_Window);
   1085 		succeeded = SetDeviceGammaRamp(hdc, ramp);
   1086 		ReleaseDC(SDL_Window, hdc);
   1087 	} else {
   1088 		succeeded = TRUE;
   1089 	}
   1090 	return succeeded ? 0 : -1;
   1091 #endif /* !NO_GAMMA_SUPPORT */
   1092 }
   1093 
   1094 int DIB_GetGammaRamp(_THIS, Uint16 *ramp)
   1095 {
   1096 #ifdef NO_GAMMA_SUPPORT
   1097 	SDL_SetError("SDL compiled without gamma ramp support");
   1098 	return -1;
   1099 #else
   1100 	HDC hdc;
   1101 	BOOL succeeded;
   1102 
   1103 	/* Get the ramp from the display */
   1104 	hdc = GetDC(SDL_Window);
   1105 	succeeded = GetDeviceGammaRamp(hdc, ramp);
   1106 	ReleaseDC(SDL_Window, hdc);
   1107 	return succeeded ? 0 : -1;
   1108 #endif /* !NO_GAMMA_SUPPORT */
   1109 }
   1110 
   1111 void DIB_VideoQuit(_THIS)
   1112 {
   1113 	int i, j;
   1114 
   1115 	/* Destroy the window and everything associated with it */
   1116 	if ( SDL_Window ) {
   1117 		/* Delete the screen bitmap (also frees screen->pixels) */
   1118 		if ( this->screen ) {
   1119 			if ( grab_palette ) {
   1120 				DIB_ReleaseStaticColors(SDL_Window);
   1121 			}
   1122 #ifndef NO_CHANGEDISPLAYSETTINGS
   1123 			if ( this->screen->flags & SDL_FULLSCREEN ) {
   1124 				ChangeDisplaySettings(NULL, 0);
   1125 				ShowWindow(SDL_Window, SW_HIDE);
   1126 			}
   1127 #endif
   1128 			if ( this->screen->flags & SDL_OPENGL ) {
   1129 				WIN_GL_ShutDown(this);
   1130 			}
   1131 			this->screen->pixels = NULL;
   1132 		}
   1133 		if ( screen_pal != NULL ) {
   1134 			DeleteObject(screen_pal);
   1135 			screen_pal = NULL;
   1136 		}
   1137 		if ( screen_logpal != NULL ) {
   1138 			SDL_free(screen_logpal);
   1139 			screen_logpal = NULL;
   1140 		}
   1141 		if ( screen_bmp ) {
   1142 			DeleteObject(screen_bmp);
   1143 			screen_bmp = NULL;
   1144 		}
   1145 		if ( screen_icn ) {
   1146 			DestroyIcon(screen_icn);
   1147 			screen_icn = NULL;
   1148 		}
   1149 		DIB_QuitGamma(this);
   1150 		DIB_DestroyWindow(this);
   1151 
   1152 		SDL_Window = NULL;
   1153 
   1154 #if defined(_WIN32_WCE)
   1155 
   1156 // Unload wince aygshell library to prevent leak
   1157 		if( aygshell )
   1158 		{
   1159 			FreeLibrary(aygshell);
   1160 			aygshell = NULL;
   1161 		}
   1162 #endif
   1163 	}
   1164 
   1165 	for ( i=0; i < SDL_arraysize(SDL_modelist); ++i ) {
   1166 		if ( !SDL_modelist[i] ) {
   1167 			continue;
   1168 		}
   1169 		for ( j=0; SDL_modelist[i][j]; ++j ) {
   1170 			SDL_free(SDL_modelist[i][j]);
   1171 		}
   1172 		SDL_free(SDL_modelist[i]);
   1173 		SDL_modelist[i] = NULL;
   1174 		SDL_nummodes[i] = 0;
   1175 	}
   1176 }
   1177 
   1178 /* Exported for the windows message loop only */
   1179 static void DIB_GrabStaticColors(HWND window)
   1180 {
   1181 #ifdef SYSPAL_NOSTATIC
   1182 	HDC hdc;
   1183 
   1184 	hdc = GetDC(window);
   1185 	SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC256);
   1186 	if ( GetSystemPaletteUse(hdc) != SYSPAL_NOSTATIC256 ) {
   1187 		SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
   1188 	}
   1189 	ReleaseDC(window, hdc);
   1190 #endif
   1191 }
   1192 static void DIB_ReleaseStaticColors(HWND window)
   1193 {
   1194 #ifdef SYSPAL_NOSTATIC
   1195 	HDC hdc;
   1196 
   1197 	hdc = GetDC(window);
   1198 	SetSystemPaletteUse(hdc, SYSPAL_STATIC);
   1199 	ReleaseDC(window, hdc);
   1200 #endif
   1201 }
   1202 static void DIB_Activate(_THIS, BOOL active, BOOL minimized)
   1203 {
   1204 	if ( grab_palette ) {
   1205 		if ( !active ) {
   1206 			DIB_ReleaseStaticColors(SDL_Window);
   1207 			DIB_RealizePalette(this);
   1208 		} else if ( !minimized ) {
   1209 			DIB_GrabStaticColors(SDL_Window);
   1210 			DIB_RealizePalette(this);
   1211 		}
   1212 	}
   1213 }
   1214 static void DIB_RealizePalette(_THIS)
   1215 {
   1216 	if ( screen_pal != NULL ) {
   1217 		HDC hdc;
   1218 
   1219 		hdc = GetDC(SDL_Window);
   1220 #ifndef _WIN32_WCE
   1221 		UnrealizeObject(screen_pal);
   1222 #endif
   1223 		SelectPalette(hdc, screen_pal, FALSE);
   1224 		if ( RealizePalette(hdc) ) {
   1225 			InvalidateRect(SDL_Window, NULL, FALSE);
   1226 		}
   1227 		ReleaseDC(SDL_Window, hdc);
   1228 	}
   1229 }
   1230 static void DIB_PaletteChanged(_THIS, HWND window)
   1231 {
   1232 	if ( window != SDL_Window ) {
   1233 		DIB_RealizePalette(this);
   1234 	}
   1235 }
   1236 
   1237 /* Exported for the windows message loop only */
   1238 static void DIB_WinPAINT(_THIS, HDC hdc)
   1239 {
   1240 	HDC mdc;
   1241 
   1242 	if ( screen_pal ) {
   1243 		SelectPalette(hdc, screen_pal, FALSE);
   1244 	}
   1245 	mdc = CreateCompatibleDC(hdc);
   1246 	SelectObject(mdc, screen_bmp);
   1247 	BitBlt(hdc, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h,
   1248 							mdc, 0, 0, SRCCOPY);
   1249 	DeleteDC(mdc);
   1250 }
   1251 
   1252 static void DIB_GetWinPos(_THIS, int* px, int *py)
   1253 {
   1254 	RECT  rect;
   1255 	GetWindowRect(SDL_Window, &rect);
   1256 	*px = rect.left;
   1257 	*py = rect.top;
   1258 }
   1259 
   1260 static void DIB_SetWinPos(_THIS, int  x, int  y)
   1261 {
   1262     SetWindowPos(SDL_Window, HWND_TOPMOST,
   1263                  x, y, 0, 0, SWP_NOSIZE|SWP_NOZORDER);
   1264 }
   1265 
   1266 typedef struct {
   1267     int   result;
   1268     int   first;
   1269     RECT  wrect;
   1270     RECT  primary;
   1271 } VisibilityData;
   1272 
   1273 
   1274 BOOL CALLBACK visibility_cb(HMONITOR  hMonitor,
   1275                             HDC       hdcMonitor,
   1276                             LPRECT    mrect,
   1277                             LPARAM    dwData)
   1278 {
   1279     VisibilityData*  data = (VisibilityData*)dwData;
   1280 
   1281     if ( data->first ) {
   1282         data->first   = 0;
   1283         data->primary = mrect[0];
   1284     }
   1285 
   1286     if ( data->wrect.left   >= mrect->left   &&
   1287          data->wrect.right  <= mrect->right  &&
   1288          data->wrect.top    >= mrect->top    &&
   1289          data->wrect.bottom <= mrect->bottom )
   1290     {
   1291         data->result = 1;
   1292         return FALSE;
   1293     }
   1294     return TRUE;
   1295 }
   1296 
   1297 static int  DIB_IsWinVisible(_THIS, int  recenter)
   1298 {
   1299     VisibilityData  data;
   1300     data.result = 0;
   1301     data.first  = 1;
   1302 
   1303     GetWindowRect(SDL_Window, &data.wrect);
   1304 
   1305     EnumDisplayMonitors(NULL, NULL, visibility_cb, (LPARAM)&data);
   1306 
   1307     if ( !data.result && recenter ) {
   1308         int  new_x = 10;
   1309         int  new_y = 10;
   1310 
   1311         if ( !data.first ) {
   1312             int  primary_w = data.primary.right  - data.primary.left;
   1313             int  primary_h = data.primary.bottom - data.primary.top;
   1314 
   1315             new_x = data.primary.left + (primary_w - this->screen->w)/2;
   1316             new_y = data.primary.top  + (primary_h - this->screen->h)/2;
   1317         }
   1318         DIB_SetWinPos(this, new_x, new_y);
   1319     }
   1320     return  data.result;
   1321 }
   1322 
   1323 static int  DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi)
   1324 {
   1325     HDC  displayDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
   1326     int  xdpi, ydpi;
   1327 
   1328     if (displayDC == NULL) {
   1329         return -1;
   1330     }
   1331     xdpi = GetDeviceCaps( displayDC, LOGPIXELSX );
   1332     ydpi = GetDeviceCaps( displayDC, LOGPIXELSY );
   1333 
   1334     DeleteDC(displayDC);
   1335 
   1336     /* sanity checks */
   1337     if (xdpi < 20 || xdpi > 400 || ydpi < 20 || ydpi > 400) {
   1338         return -1;
   1339     }
   1340 
   1341     *xDpi = xdpi;
   1342     *yDpi = ydpi;
   1343     return 0;
   1344 }
   1345 
   1346 
   1347 typedef struct {
   1348     int   first;
   1349     RECT  wrect;
   1350 	long  bestArea;
   1351 	RECT  bestRect;
   1352 	RECT  primary;
   1353 } ProximityData;
   1354 
   1355 BOOL CALLBACK proximity_cb(HMONITOR  hMonitor,
   1356                            HDC       hdcMonitor,
   1357                            LPRECT    mrect,
   1358                            LPARAM    dwData)
   1359 {
   1360     ProximityData*  data = (ProximityData*)dwData;
   1361     int   x1, y1, x2, y2, area;
   1362 
   1363 	x1 = mrect->left;
   1364 	x2 = mrect->right;
   1365 	y1 = mrect->top;
   1366 	y2 = mrect->bottom;
   1367 
   1368 	if (data->first) {
   1369 		data->primary = mrect[0];
   1370 	}
   1371 
   1372 	if (x1 < data->wrect.left)
   1373 		x1 = data->wrect.left;
   1374     if (x2 > data->wrect.right)
   1375 		x2 = data->wrect.right;
   1376 	if (y1 < data->wrect.top)
   1377 		y1 = data->wrect.top;
   1378 	if (y2 > data->wrect.bottom)
   1379 		y2 = data->wrect.bottom;
   1380 
   1381 	if (x1 >= x2 || y1 >= y2)
   1382 		return TRUE;
   1383 
   1384 	area = (x2-x1)*(y2-y1);
   1385 	if (data->first || area > data->bestArea) {
   1386 		data->first    = 0;
   1387 		data->bestRect = mrect[0];
   1388 		data->bestArea = area;
   1389 	}
   1390     return TRUE;
   1391 }
   1392 
   1393 static int  DIB_GetMonitorRect(_THIS, SDL_Rect*  rect)
   1394 {
   1395     ProximityData  data;
   1396 	RECT*          sr;
   1397 
   1398     data.first  = 1;
   1399     GetWindowRect(SDL_Window, &data.wrect);
   1400 
   1401     EnumDisplayMonitors(NULL, NULL, proximity_cb, (LPARAM)&data);
   1402 
   1403 	if (data.first)
   1404 		return -1;
   1405 
   1406 	sr = &data.bestRect;
   1407 
   1408 	rect->x = sr->left;
   1409 	rect->y = sr->top;
   1410 	rect->w = sr->right - sr->left;
   1411 	rect->h = sr->bottom - sr->top;
   1412 
   1413 	return 0;
   1414 }
   1415 
   1416 /* Stub in case DirectX isn't available */
   1417 #if !SDL_AUDIO_DRIVER_DSOUND
   1418 void DX5_SoundFocus(HWND hwnd)
   1419 {
   1420 	return;
   1421 }
   1422 #endif
   1423