• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@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 
DIB_Available(void)108 static int DIB_Available(void)
109 {
110 	return(1);
111 }
112 
DIB_DeleteDevice(SDL_VideoDevice * device)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 
DIB_CreateDevice(int devindex)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 
cmpmodes(const void * va,const void * vb)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 
DIB_AddMode(_THIS,int bpp,int w,int h)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 
DIB_CreatePalette(_THIS,int bpp)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 
DIB_VideoInit(_THIS,SDL_PixelFormat * vformat)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 */
DIB_ListModes(_THIS,SDL_PixelFormat * format,Uint32 flags)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 */
DIB_SussScreenDepth()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 
DIB_SetVideoMode(_THIS,SDL_Surface * current,int width,int height,int bpp,Uint32 flags)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