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