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