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
67extern HINSTANCE aygshell;
68#endif
69
70/* Initialization/Query functions */
71static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat);
72static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
73SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
74static int DIB_SetColors(_THIS, int firstcolor, int ncolors,
75			 SDL_Color *colors);
76static void DIB_CheckGamma(_THIS);
77void DIB_SwapGamma(_THIS);
78void DIB_QuitGamma(_THIS);
79int DIB_SetGammaRamp(_THIS, Uint16 *ramp);
80int DIB_GetGammaRamp(_THIS, Uint16 *ramp);
81static void DIB_VideoQuit(_THIS);
82
83/* Hardware surface functions */
84static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface);
85static int DIB_LockHWSurface(_THIS, SDL_Surface *surface);
86static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface);
87static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface);
88
89/* Windows message handling functions */
90static void DIB_GrabStaticColors(HWND window);
91static void DIB_ReleaseStaticColors(HWND window);
92static void DIB_Activate(_THIS, BOOL active, BOOL minimized);
93static void DIB_RealizePalette(_THIS);
94static void DIB_PaletteChanged(_THIS, HWND window);
95static void DIB_WinPAINT(_THIS, HDC hdc);
96
97static void DIB_GetWinPos(_THIS, int* px, int *py);
98static void DIB_SetWinPos(_THIS, int  x, int  y);
99static int  DIB_IsWinVisible(_THIS, int recenter);
100static int  DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi);
101static int  DIB_GetMonitorRect(_THIS, SDL_Rect*  rect);
102
103/* helper fn */
104static int DIB_SussScreenDepth();
105
106/* DIB driver bootstrap functions */
107
108static int DIB_Available(void)
109{
110	return(1);
111}
112
113static 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
126static 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
206VideoBootStrap WINDIB_bootstrap = {
207	"windib", "Win95/98/NT/2000/CE GDI",
208	DIB_Available, DIB_CreateDevice
209};
210
211static 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
221static 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
267static 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
288int 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 */
398SDL_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*/
415static 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 */
477static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects);
478
479SDL_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 */
865static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface)
866{
867	return(-1);
868}
869static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface)
870{
871	return;
872}
873static int DIB_LockHWSurface(_THIS, SDL_Surface *surface)
874{
875	return(0);
876}
877static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface)
878{
879	return;
880}
881
882static 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
901static 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
916static 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
937int 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
1009static 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}
1024void 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}
1043void 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
1063int 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
1094int 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
1111void 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 */
1179static 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}
1192static 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}
1202static 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}
1214static 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}
1230static 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 */
1238static 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
1252static 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
1260static 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
1266typedef struct {
1267    int   result;
1268    int   first;
1269    RECT  wrect;
1270    RECT  primary;
1271} VisibilityData;
1272
1273
1274BOOL 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
1297static 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
1323static 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
1347typedef struct {
1348    int   first;
1349    RECT  wrect;
1350	long  bestArea;
1351	RECT  bestRect;
1352	RECT  primary;
1353} ProximityData;
1354
1355BOOL 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
1393static 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
1418void DX5_SoundFocus(HWND hwnd)
1419{
1420	return;
1421}
1422#endif
1423