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 (at) 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 108 static int DIB_Available(void) 109 { 110 return(1); 111 } 112 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 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 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 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 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 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 */ 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 */ 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 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