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 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 88extern HINSTANCE aygshell; 89#endif 90 91/* Initialization/Query functions */ 92static int DIB_VideoInit(_THIS, SDL_PixelFormat *vformat); 93static SDL_Rect **DIB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags); 94SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); 95static int DIB_SetColors(_THIS, int firstcolor, int ncolors, 96 SDL_Color *colors); 97static void DIB_CheckGamma(_THIS); 98void DIB_SwapGamma(_THIS); 99void DIB_QuitGamma(_THIS); 100int DIB_SetGammaRamp(_THIS, Uint16 *ramp); 101int DIB_GetGammaRamp(_THIS, Uint16 *ramp); 102static void DIB_VideoQuit(_THIS); 103 104/* Hardware surface functions */ 105static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface); 106static int DIB_LockHWSurface(_THIS, SDL_Surface *surface); 107static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface); 108static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface); 109 110/* Windows message handling functions */ 111static void DIB_GrabStaticColors(HWND window); 112static void DIB_ReleaseStaticColors(HWND window); 113static void DIB_Activate(_THIS, BOOL active, BOOL minimized); 114static void DIB_RealizePalette(_THIS); 115static void DIB_PaletteChanged(_THIS, HWND window); 116static void DIB_WinPAINT(_THIS, HDC hdc); 117 118static void DIB_GetWinPos(_THIS, int* px, int *py); 119static void DIB_SetWinPos(_THIS, int x, int y); 120static int DIB_IsWinVisible(_THIS, int recenter); 121static int DIB_GetMonitorDPI(_THIS, int* xDpi, int *yDpi); 122static int DIB_GetMonitorRect(_THIS, SDL_Rect* rect); 123 124/* helper fn */ 125static int DIB_SussScreenDepth(); 126 127/* DIB driver bootstrap functions */ 128 129static int DIB_Available(void) 130{ 131 return(1); 132} 133 134static 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 150static 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 240VideoBootStrap WINDIB_bootstrap = { 241 "windib", "Win95/98/NT/2000/CE GDI", 242 DIB_Available, DIB_CreateDevice 243}; 244 245static 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 255static 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 301static 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 322int 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 */ 442SDL_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*/ 459static 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 */ 521static void DIB_NormalUpdate(_THIS, int numrects, SDL_Rect *rects); 522 523static 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 595SDL_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 */ 942static int DIB_AllocHWSurface(_THIS, SDL_Surface *surface) 943{ 944 return(-1); 945} 946static void DIB_FreeHWSurface(_THIS, SDL_Surface *surface) 947{ 948 return; 949} 950static int DIB_LockHWSurface(_THIS, SDL_Surface *surface) 951{ 952 return(0); 953} 954static void DIB_UnlockHWSurface(_THIS, SDL_Surface *surface) 955{ 956 return; 957} 958 959static 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 978static 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 993static 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 1014int 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 1086static 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} 1101void 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} 1120void 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 1140int 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 1171int 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 1188void 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 */ 1256static 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} 1269static 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} 1279static 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} 1291static 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} 1307static 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 */ 1315static 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 1329static 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 1337static 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 1343typedef struct { 1344 int result; 1345 int first; 1346 RECT wrect; 1347 RECT primary; 1348} VisibilityData; 1349 1350 1351BOOL 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 1374static 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 1400static 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 1424typedef struct { 1425 int first; 1426 RECT wrect; 1427 long bestArea; 1428 RECT bestRect; 1429 RECT primary; 1430} ProximityData; 1431 1432BOOL 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 1470static 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 1495void DX5_SoundFocus(HWND hwnd) 1496{ 1497 return; 1498} 1499#endif 1500