| 1 | /* |
| 2 | *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. |
| 3 | * |
| 4 | *Permission is hereby granted, free of charge, to any person obtaining |
| 5 | * a copy of this software and associated documentation files (the |
| 6 | *"Software"), to deal in the Software without restriction, including |
| 7 | *without limitation the rights to use, copy, modify, merge, publish, |
| 8 | *distribute, sublicense, and/or sell copies of the Software, and to |
| 9 | *permit persons to whom the Software is furnished to do so, subject to |
| 10 | *the following conditions: |
| 11 | * |
| 12 | *The above copyright notice and this permission notice shall be |
| 13 | *included in all copies or substantial portions of the Software. |
| 14 | * |
| 15 | *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 | *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 | *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 | *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR |
| 19 | *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
| 20 | *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 21 | *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 22 | * |
| 23 | *Except as contained in this notice, the name of the XFree86 Project |
| 24 | *shall not be used in advertising or otherwise to promote the sale, use |
| 25 | *or other dealings in this Software without prior written authorization |
| 26 | *from the XFree86 Project. |
| 27 | * |
| 28 | * Authors: Dakshinamurthy Karra |
| 29 | * Suhaib M Siddiqi |
| 30 | * Peter Busch |
| 31 | * Harold L Hunt II |
| 32 | */ |
| 33 | |
| 34 | #ifdef HAVE_XWIN_CONFIG_H |
| 35 | #include <xwin-config.h> |
| 36 | #endif |
| 37 | #include "win.h" |
| 38 | |
| 39 | /* |
| 40 | * Local function prototypes |
| 41 | */ |
| 42 | |
| 43 | static Bool |
| 44 | winAllocateFBPrimaryDD(ScreenPtr pScreen); |
| 45 | |
| 46 | static Bool |
| 47 | winCloseScreenPrimaryDD(ScreenPtr pScreen); |
| 48 | |
| 49 | static Bool |
| 50 | winInitVisualsPrimaryDD(ScreenPtr pScreen); |
| 51 | |
| 52 | static Bool |
| 53 | winAdjustVideoModePrimaryDD(ScreenPtr pScreen); |
| 54 | |
| 55 | static Bool |
| 56 | winActivateAppPrimaryDD(ScreenPtr pScreen); |
| 57 | |
| 58 | static Bool |
| 59 | winHotKeyAltTabPrimaryDD(ScreenPtr pScreen); |
| 60 | |
| 61 | /* |
| 62 | * Create a DirectDraw primary surface |
| 63 | */ |
| 64 | |
| 65 | static Bool |
| 66 | winAllocateFBPrimaryDD(ScreenPtr pScreen) |
| 67 | { |
| 68 | winScreenPriv(pScreen); |
| 69 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 70 | HRESULT ddrval = DD_OK; |
| 71 | DDSURFACEDESC ddsd; |
| 72 | DDSURFACEDESC *pddsdPrimary = NULL; |
| 73 | DDSURFACEDESC *pddsdOffscreen = NULL; |
| 74 | RECT rcClient; |
| 75 | |
| 76 | ErrorF("winAllocateFBPrimaryDD\n"); |
| 77 | |
| 78 | /* Get client area location in screen coords */ |
| 79 | GetClientRect(pScreenPriv->hwndScreen, &rcClient); |
| 80 | MapWindowPoints(pScreenPriv->hwndScreen, |
| 81 | HWND_DESKTOP, (LPPOINT) &rcClient, 2); |
| 82 | |
| 83 | /* Create a DirectDraw object, store the address at lpdd */ |
| 84 | ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL); |
| 85 | if (ddrval != DD_OK) |
| 86 | FatalError("winAllocateFBPrimaryDD - Could not start DirectDraw\n"); |
| 87 | |
| 88 | /* Get a DirectDraw2 interface pointer */ |
| 89 | ddrval = IDirectDraw_QueryInterface(pScreenPriv->pdd, |
| 90 | &IID_IDirectDraw2, |
| 91 | (LPVOID *) &pScreenPriv->pdd2); |
| 92 | if (FAILED(ddrval)) { |
| 93 | ErrorF("winAllocateFBShadowDD - Failed DD2 query: %08x\n", |
| 94 | (unsigned int) ddrval); |
| 95 | return FALSE; |
| 96 | } |
| 97 | |
| 98 | ErrorF("winAllocateFBPrimaryDD - Created and initialized DD\n"); |
| 99 | |
| 100 | /* Are we windowed or fullscreen? */ |
| 101 | if (pScreenInfo->fFullScreen) { |
| 102 | /* Full screen mode */ |
| 103 | ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2, |
| 104 | pScreenPriv->hwndScreen, |
| 105 | DDSCL_FULLSCREEN |
| 106 | | DDSCL_EXCLUSIVE); |
| 107 | if (FAILED(ddrval)) |
| 108 | FatalError("winAllocateFBPrimaryDD - Could not set " |
| 109 | "cooperative level\n"); |
| 110 | |
| 111 | /* Change the video mode to the mode requested */ |
| 112 | ddrval = IDirectDraw2_SetDisplayMode(pScreenPriv->pdd2, |
| 113 | pScreenInfo->dwWidth, |
| 114 | pScreenInfo->dwHeight, |
| 115 | pScreenInfo->dwBPP, |
| 116 | pScreenInfo->dwRefreshRate, 0); |
| 117 | if (FAILED(ddrval)) |
| 118 | FatalError("winAllocateFBPrimaryDD - Could not set " |
| 119 | "full screen display mode\n"); |
| 120 | } |
| 121 | else { |
| 122 | /* Windowed mode */ |
| 123 | ddrval = IDirectDraw2_SetCooperativeLevel(pScreenPriv->pdd2, |
| 124 | pScreenPriv->hwndScreen, |
| 125 | DDSCL_NORMAL); |
| 126 | if (FAILED(ddrval)) |
| 127 | FatalError("winAllocateFBPrimaryDD - Could not set " |
| 128 | "cooperative level\n"); |
| 129 | } |
| 130 | |
| 131 | /* Describe the primary surface */ |
| 132 | ZeroMemory(&ddsd, sizeof(ddsd)); |
| 133 | ddsd.dwSize = sizeof(ddsd); |
| 134 | ddsd.dwFlags = DDSD_CAPS; |
| 135 | ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; |
| 136 | |
| 137 | /* Create the primary surface */ |
| 138 | ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2, |
| 139 | &ddsd, &pScreenPriv->pddsPrimary, NULL); |
| 140 | if (FAILED(ddrval)) |
| 141 | FatalError("winAllocateFBPrimaryDD - Could not create primary " |
| 142 | "surface %08x\n", (unsigned int) ddrval); |
| 143 | |
| 144 | ErrorF("winAllocateFBPrimaryDD - Created primary\n"); |
| 145 | |
| 146 | /* Allocate a DD surface description for our screen privates */ |
| 147 | pddsdPrimary = pScreenPriv->pddsdPrimary = malloc(sizeof(DDSURFACEDESC)); |
| 148 | if (pddsdPrimary == NULL) |
| 149 | FatalError("winAllocateFBPrimaryDD - Could not allocate surface " |
| 150 | "description memory\n"); |
| 151 | ZeroMemory(pddsdPrimary, sizeof(*pddsdPrimary)); |
| 152 | pddsdPrimary->dwSize = sizeof(*pddsdPrimary); |
| 153 | |
| 154 | /* Describe the offscreen surface to be created */ |
| 155 | /* |
| 156 | * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, |
| 157 | * as drawing, locking, and unlocking take forever |
| 158 | * with video memory surfaces. In addition, |
| 159 | * video memory is a somewhat scarce resource, |
| 160 | * so you shouldn't be allocating video memory when |
| 161 | * you have the option of using system memory instead. |
| 162 | */ |
| 163 | ZeroMemory(&ddsd, sizeof(ddsd)); |
| 164 | ddsd.dwSize = sizeof(ddsd); |
| 165 | ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; |
| 166 | ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; |
| 167 | ddsd.dwHeight = pScreenInfo->dwHeight; |
| 168 | ddsd.dwWidth = pScreenInfo->dwWidth; |
| 169 | |
| 170 | /* Create the shadow surface */ |
| 171 | ddrval = IDirectDraw2_CreateSurface(pScreenPriv->pdd2, |
| 172 | &ddsd, |
| 173 | &pScreenPriv->pddsOffscreen, NULL); |
| 174 | if (ddrval != DD_OK) |
| 175 | FatalError("winAllocateFBPrimaryDD - Could not create shadow " |
| 176 | "surface\n"); |
| 177 | |
| 178 | ErrorF("winAllocateFBPrimaryDD - Created offscreen\n"); |
| 179 | |
| 180 | /* Allocate a DD surface description for our screen privates */ |
| 181 | pddsdOffscreen = pScreenPriv->pddsdOffscreen |
| 182 | = malloc(sizeof(DDSURFACEDESC)); |
| 183 | if (pddsdOffscreen == NULL) |
| 184 | FatalError("winAllocateFBPrimaryDD - Could not allocate surface " |
| 185 | "description memory\n"); |
| 186 | ZeroMemory(pddsdOffscreen, sizeof(*pddsdOffscreen)); |
| 187 | pddsdOffscreen->dwSize = sizeof(*pddsdOffscreen); |
| 188 | |
| 189 | ErrorF("winAllocateFBPrimaryDD - Locking primary\n"); |
| 190 | |
| 191 | /* Lock the primary surface */ |
| 192 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary, |
| 193 | pScreenInfo-> |
| 194 | fFullScreen ? NULL : &rcClient, |
| 195 | pddsdPrimary, DDLOCK_WAIT, NULL); |
| 196 | if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL) |
| 197 | FatalError("winAllocateFBPrimaryDD - Could not lock " |
| 198 | "primary surface\n"); |
| 199 | |
| 200 | ErrorF("winAllocateFBPrimaryDD - Locked primary\n"); |
| 201 | |
| 202 | /* We don't know how to deal with anything other than RGB */ |
| 203 | if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB)) |
| 204 | FatalError("winAllocateFBPrimaryDD - Color format other than RGB\n"); |
| 205 | |
| 206 | /* Grab the pitch from the surface desc */ |
| 207 | pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8) |
| 208 | / pScreenInfo->dwBPP; |
| 209 | |
| 210 | /* Save the pointer to our surface memory */ |
| 211 | pScreenInfo->pfb = pddsdPrimary->lpSurface; |
| 212 | |
| 213 | /* Grab the color depth and masks from the surface description */ |
| 214 | pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask; |
| 215 | pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask; |
| 216 | pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask; |
| 217 | |
| 218 | ErrorF("winAllocateFBPrimaryDD - Returning\n"); |
| 219 | |
| 220 | return TRUE; |
| 221 | } |
| 222 | |
| 223 | static void |
| 224 | winFreeFBPrimaryDD(ScreenPtr pScreen) |
| 225 | { |
| 226 | winScreenPriv(pScreen); |
| 227 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 228 | |
| 229 | /* Free the offscreen surface, if there is one */ |
| 230 | if (pScreenPriv->pddsOffscreen) { |
| 231 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL); |
| 232 | IDirectDrawSurface2_Release(pScreenPriv->pddsOffscreen); |
| 233 | pScreenPriv->pddsOffscreen = NULL; |
| 234 | } |
| 235 | |
| 236 | /* Release the primary surface, if there is one */ |
| 237 | if (pScreenPriv->pddsPrimary) { |
| 238 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL); |
| 239 | IDirectDrawSurface2_Release(pScreenPriv->pddsPrimary); |
| 240 | pScreenPriv->pddsPrimary = NULL; |
| 241 | } |
| 242 | |
| 243 | /* Free the DirectDraw object, if there is one */ |
| 244 | if (pScreenPriv->pdd) { |
| 245 | IDirectDraw2_RestoreDisplayMode(pScreenPriv->pdd); |
| 246 | IDirectDraw2_Release(pScreenPriv->pdd); |
| 247 | pScreenPriv->pdd = NULL; |
| 248 | } |
| 249 | |
| 250 | /* Invalidate the ScreenInfo's fb pointer */ |
| 251 | pScreenInfo->pfb = NULL; |
| 252 | } |
| 253 | |
| 254 | static Bool |
| 255 | winInitScreenPrimaryDD(ScreenPtr pScreen) |
| 256 | { |
| 257 | return winAllocateFBPrimaryDD(pScreen); |
| 258 | } |
| 259 | |
| 260 | /* |
| 261 | * Call the wrapped CloseScreen function. |
| 262 | * |
| 263 | * Free our resources and private structures. |
| 264 | */ |
| 265 | |
| 266 | static Bool |
| 267 | winCloseScreenPrimaryDD(ScreenPtr pScreen) |
| 268 | { |
| 269 | winScreenPriv(pScreen); |
| 270 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 271 | Bool fReturn; |
| 272 | |
| 273 | ErrorF("winCloseScreenPrimaryDD - Freeing screen resources\n"); |
| 274 | |
| 275 | /* Flag that the screen is closed */ |
| 276 | pScreenPriv->fClosed = TRUE; |
| 277 | pScreenPriv->fActive = FALSE; |
| 278 | |
| 279 | /* Call the wrapped CloseScreen procedure */ |
| 280 | WIN_UNWRAP(CloseScreen); |
| 281 | if (pScreen->CloseScreen) |
| 282 | fReturn = (*pScreen->CloseScreen) (pScreen); |
| 283 | |
| 284 | /* Delete the window property */ |
| 285 | RemoveProp(pScreenPriv->hwndScreen, WIN_SCR_PROP); |
| 286 | |
| 287 | winFreeFBPrimaryDD(pScreen); |
| 288 | |
| 289 | /* Delete tray icon, if we have one */ |
| 290 | if (!pScreenInfo->fNoTrayIcon) |
| 291 | winDeleteNotifyIcon(pScreenPriv); |
| 292 | |
| 293 | /* Free the exit confirmation dialog box, if it exists */ |
| 294 | if (g_hDlgExit != NULL) { |
| 295 | DestroyWindow(g_hDlgExit); |
| 296 | g_hDlgExit = NULL; |
| 297 | } |
| 298 | |
| 299 | /* Kill our window */ |
| 300 | if (pScreenPriv->hwndScreen) { |
| 301 | DestroyWindow(pScreenPriv->hwndScreen); |
| 302 | pScreenPriv->hwndScreen = NULL; |
| 303 | } |
| 304 | |
| 305 | /* Kill our screeninfo's pointer to the screen */ |
| 306 | pScreenInfo->pScreen = NULL; |
| 307 | |
| 308 | /* Free the screen privates for this screen */ |
| 309 | free((pointer) pScreenPriv); |
| 310 | |
| 311 | return fReturn; |
| 312 | } |
| 313 | |
| 314 | /* |
| 315 | * Tell mi what sort of visuals we need. |
| 316 | * |
| 317 | * Generally we only need one visual, as our screen can only |
| 318 | * handle one format at a time, I believe. You may want |
| 319 | * to verify that last sentence. |
| 320 | */ |
| 321 | |
| 322 | static Bool |
| 323 | winInitVisualsPrimaryDD(ScreenPtr pScreen) |
| 324 | { |
| 325 | winScreenPriv(pScreen); |
| 326 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 327 | DWORD dwRedBits, dwGreenBits, dwBlueBits; |
| 328 | |
| 329 | /* Count the number of ones in each color mask */ |
| 330 | dwRedBits = winCountBits(pScreenPriv->dwRedMask); |
| 331 | dwGreenBits = winCountBits(pScreenPriv->dwGreenMask); |
| 332 | dwBlueBits = winCountBits(pScreenPriv->dwBlueMask); |
| 333 | |
| 334 | /* Store the maximum number of ones in a color mask as the bitsPerRGB */ |
| 335 | if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) |
| 336 | pScreenPriv->dwBitsPerRGB = dwRedBits; |
| 337 | else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) |
| 338 | pScreenPriv->dwBitsPerRGB = dwGreenBits; |
| 339 | else |
| 340 | pScreenPriv->dwBitsPerRGB = dwBlueBits; |
| 341 | |
| 342 | ErrorF("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n", |
| 343 | (unsigned int) pScreenPriv->dwRedMask, |
| 344 | (unsigned int) pScreenPriv->dwGreenMask, |
| 345 | (unsigned int) pScreenPriv->dwBlueMask, |
| 346 | (int) pScreenPriv->dwBitsPerRGB); |
| 347 | |
| 348 | /* Create a single visual according to the Windows screen depth */ |
| 349 | switch (pScreenInfo->dwDepth) { |
| 350 | case 24: |
| 351 | case 16: |
| 352 | case 15: |
| 353 | if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth, |
| 354 | TrueColorMask, |
| 355 | pScreenPriv->dwBitsPerRGB, |
| 356 | TrueColor, |
| 357 | pScreenPriv->dwRedMask, |
| 358 | pScreenPriv->dwGreenMask, |
| 359 | pScreenPriv->dwBlueMask)) { |
| 360 | ErrorF("winInitVisualsPrimaryDD - " |
| 361 | "miSetVisualTypesAndMasks failed\n"); |
| 362 | return FALSE; |
| 363 | } |
| 364 | break; |
| 365 | |
| 366 | case 8: |
| 367 | #if CYGDEBUG |
| 368 | winDebug("winInitVisuals - Calling miSetVisualTypesAndMasks\n"); |
| 369 | #endif /* CYGDEBUG */ |
| 370 | if (!miSetVisualTypesAndMasks(pScreenInfo->dwDepth, |
| 371 | PseudoColorMask, |
| 372 | pScreenPriv->dwBitsPerRGB, |
| 373 | PseudoColor, |
| 374 | pScreenPriv->dwRedMask, |
| 375 | pScreenPriv->dwGreenMask, |
| 376 | pScreenPriv->dwBlueMask)) { |
| 377 | ErrorF("winInitVisualsPrimaryDD - " |
| 378 | "miSetVisualTypesAndMasks failed\n"); |
| 379 | return FALSE; |
| 380 | } |
| 381 | #if CYGDEBUG |
| 382 | winDebug("winInitVisualsPrimaryDD - Returned from " |
| 383 | "miSetVisualTypesAndMasks\n"); |
| 384 | #endif /* CYGDEBUG */ |
| 385 | break; |
| 386 | |
| 387 | default: |
| 388 | ErrorF("winInitVisualsPrimaryDD - Unknown screen depth\n"); |
| 389 | return FALSE; |
| 390 | } |
| 391 | |
| 392 | ErrorF("winInitVisualsPrimaryDD - Returning\n"); |
| 393 | |
| 394 | return TRUE; |
| 395 | } |
| 396 | |
| 397 | static Bool |
| 398 | winAdjustVideoModePrimaryDD(ScreenPtr pScreen) |
| 399 | { |
| 400 | winScreenPriv(pScreen); |
| 401 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 402 | HDC hdc = NULL; |
| 403 | DWORD dwBPP; |
| 404 | |
| 405 | /* We're in serious trouble if we can't get a DC */ |
| 406 | hdc = GetDC(NULL); |
| 407 | if (hdc == NULL) { |
| 408 | ErrorF("winAdjustVideoModePrimaryDD - GetDC failed\n"); |
| 409 | return FALSE; |
| 410 | } |
| 411 | |
| 412 | /* Query GDI for current display depth */ |
| 413 | dwBPP = GetDeviceCaps(hdc, BITSPIXEL); |
| 414 | |
| 415 | /* DirectDraw can only change the depth in fullscreen mode */ |
| 416 | if (!(pScreenInfo->fFullScreen && (pScreenInfo->dwBPP != WIN_DEFAULT_BPP))) { |
| 417 | /* Otherwise, We'll use GDI's depth */ |
| 418 | pScreenInfo->dwBPP = dwBPP; |
| 419 | } |
| 420 | |
| 421 | /* Release our DC */ |
| 422 | ReleaseDC(NULL, hdc); |
| 423 | |
| 424 | return TRUE; |
| 425 | } |
| 426 | |
| 427 | /* |
| 428 | * We need to blit our offscreen fb to |
| 429 | * the screen when we are activated, and we need to point |
| 430 | * the fb code back to the primary surface memory. |
| 431 | */ |
| 432 | |
| 433 | static Bool |
| 434 | winActivateAppPrimaryDD(ScreenPtr pScreen) |
| 435 | { |
| 436 | winScreenPriv(pScreen); |
| 437 | RECT rcSrc, rcClient; |
| 438 | HRESULT ddrval = DD_OK; |
| 439 | |
| 440 | /* Check for errors */ |
| 441 | if (pScreenPriv == NULL |
| 442 | || pScreenPriv->pScreenInfo == NULL |
| 443 | || pScreenPriv->pddsPrimary == NULL |
| 444 | || pScreenPriv->pddsOffscreen == NULL) |
| 445 | return FALSE; |
| 446 | |
| 447 | /* Check for do-nothing */ |
| 448 | if (!pScreenPriv->fActive) |
| 449 | return TRUE; |
| 450 | |
| 451 | /* We are activating */ |
| 452 | ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsOffscreen); |
| 453 | if (ddrval == DD_OK) { |
| 454 | IDirectDrawSurface2_Unlock(pScreenPriv->pddsOffscreen, NULL); |
| 455 | /* |
| 456 | * We don't check for an error from Unlock, because it |
| 457 | * doesn't matter if the Unlock failed. |
| 458 | */ |
| 459 | } |
| 460 | |
| 461 | /* Restore both surfaces, just cause I like it that way */ |
| 462 | IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen); |
| 463 | IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary); |
| 464 | |
| 465 | /* Get client area in screen coords */ |
| 466 | GetClientRect(pScreenPriv->hwndScreen, &rcClient); |
| 467 | MapWindowPoints(pScreenPriv->hwndScreen, |
| 468 | HWND_DESKTOP, (LPPOINT) &rcClient, 2); |
| 469 | |
| 470 | /* Setup a source rectangle */ |
| 471 | rcSrc.left = 0; |
| 472 | rcSrc.top = 0; |
| 473 | rcSrc.right = pScreenPriv->pScreenInfo->dwWidth; |
| 474 | rcSrc.bottom = pScreenPriv->pScreenInfo->dwHeight; |
| 475 | |
| 476 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsPrimary, |
| 477 | &rcClient, |
| 478 | pScreenPriv->pddsOffscreen, |
| 479 | &rcSrc, DDBLT_WAIT, NULL); |
| 480 | if (ddrval != DD_OK) |
| 481 | FatalError("winActivateAppPrimaryDD () - Failed blitting offscreen " |
| 482 | "surface to primary surface %08x\n", (unsigned int) ddrval); |
| 483 | |
| 484 | /* Lock the primary surface */ |
| 485 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsPrimary, |
| 486 | &rcClient, |
| 487 | pScreenPriv->pddsdPrimary, |
| 488 | DDLOCK_WAIT, NULL); |
| 489 | if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL) |
| 490 | FatalError("winActivateAppPrimaryDD () - Could not lock " |
| 491 | "primary surface\n"); |
| 492 | |
| 493 | /* Notify FB of the new memory pointer */ |
| 494 | winUpdateFBPointer(pScreen, pScreenPriv->pddsdPrimary->lpSurface); |
| 495 | |
| 496 | /* |
| 497 | * Register the Alt-Tab combo as a hotkey so we can copy |
| 498 | * the primary framebuffer before the display mode changes |
| 499 | */ |
| 500 | RegisterHotKey(pScreenPriv->hwndScreen, 1, MOD_ALT, 9); |
| 501 | |
| 502 | return TRUE; |
| 503 | } |
| 504 | |
| 505 | /* |
| 506 | * Handle the Alt+Tab hotkey. |
| 507 | * |
| 508 | * We need to save the primary fb to an offscreen fb when |
| 509 | * we get deactivated, and point the fb code at the offscreen |
| 510 | * fb for the duration of the deactivation. |
| 511 | */ |
| 512 | |
| 513 | static Bool |
| 514 | winHotKeyAltTabPrimaryDD(ScreenPtr pScreen) |
| 515 | { |
| 516 | winScreenPriv(pScreen); |
| 517 | HRESULT ddrval = DD_OK; |
| 518 | |
| 519 | ErrorF("\nwinHotKeyAltTabPrimaryDD\n\n"); |
| 520 | |
| 521 | /* Alt+Tab was pressed, we will lose focus very soon */ |
| 522 | pScreenPriv->fActive = FALSE; |
| 523 | |
| 524 | /* Check for error conditions */ |
| 525 | if (pScreenPriv->pddsPrimary == NULL || pScreenPriv->pddsOffscreen == NULL) |
| 526 | return FALSE; |
| 527 | |
| 528 | /* Did we loose the primary surface? */ |
| 529 | ddrval = IDirectDrawSurface2_IsLost(pScreenPriv->pddsPrimary); |
| 530 | if (ddrval == DD_OK) { |
| 531 | ddrval = IDirectDrawSurface2_Unlock(pScreenPriv->pddsPrimary, NULL); |
| 532 | if (FAILED(ddrval)) |
| 533 | FatalError("winHotKeyAltTabPrimaryDD - Failed unlocking primary " |
| 534 | "surface\n"); |
| 535 | } |
| 536 | |
| 537 | /* Blit the primary surface to the offscreen surface */ |
| 538 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen, NULL, /* should be rcDest */ |
| 539 | pScreenPriv->pddsPrimary, |
| 540 | NULL, DDBLT_WAIT, NULL); |
| 541 | if (ddrval == DDERR_SURFACELOST) { |
| 542 | IDirectDrawSurface2_Restore(pScreenPriv->pddsOffscreen); |
| 543 | IDirectDrawSurface2_Restore(pScreenPriv->pddsPrimary); |
| 544 | |
| 545 | /* Blit the primary surface to the offscreen surface */ |
| 546 | ddrval = IDirectDrawSurface2_Blt(pScreenPriv->pddsOffscreen, |
| 547 | NULL, |
| 548 | pScreenPriv->pddsPrimary, |
| 549 | NULL, DDBLT_WAIT, NULL); |
| 550 | if (FAILED(ddrval)) |
| 551 | FatalError("winHotKeyAltTabPrimaryDD - Failed blitting primary " |
| 552 | "surface to offscreen surface: %08x\n", |
| 553 | (unsigned int) ddrval); |
| 554 | } |
| 555 | else { |
| 556 | FatalError("winHotKeyAltTabPrimaryDD - Unknown error from " |
| 557 | "Blt: %08dx\n", (unsigned int) ddrval); |
| 558 | } |
| 559 | |
| 560 | /* Lock the offscreen surface */ |
| 561 | ddrval = IDirectDrawSurface2_Lock(pScreenPriv->pddsOffscreen, |
| 562 | NULL, |
| 563 | pScreenPriv->pddsdOffscreen, |
| 564 | DDLOCK_WAIT, NULL); |
| 565 | if (ddrval != DD_OK || pScreenPriv->pddsdPrimary->lpSurface == NULL) |
| 566 | FatalError("winHotKeyAltTabPrimaryDD - Could not lock " |
| 567 | "offscreen surface\n"); |
| 568 | |
| 569 | /* Notify FB of the new memory pointer */ |
| 570 | winUpdateFBPointer(pScreen, pScreenPriv->pddsdOffscreen->lpSurface); |
| 571 | |
| 572 | /* Unregister our hotkey */ |
| 573 | UnregisterHotKey(pScreenPriv->hwndScreen, 1); |
| 574 | |
| 575 | return TRUE; |
| 576 | } |
| 577 | |
| 578 | /* Set engine specific functions */ |
| 579 | Bool |
| 580 | winSetEngineFunctionsPrimaryDD(ScreenPtr pScreen) |
| 581 | { |
| 582 | winScreenPriv(pScreen); |
| 583 | winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; |
| 584 | |
| 585 | /* Set our pointers */ |
| 586 | pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD; |
| 587 | pScreenPriv->pwinFreeFB = winFreeFBPrimaryDD; |
| 588 | pScreenPriv->pwinShadowUpdate = |
| 589 | (winShadowUpdateProcPtr) (void (*)(void)) NoopDDA; |
| 590 | pScreenPriv->pwinInitScreen = winInitScreenPrimaryDD; |
| 591 | pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD; |
| 592 | pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD; |
| 593 | pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD; |
| 594 | if (pScreenInfo->fFullScreen) |
| 595 | pScreenPriv->pwinCreateBoundingWindow = |
| 596 | winCreateBoundingWindowFullScreen; |
| 597 | else |
| 598 | pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; |
| 599 | pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; |
| 600 | pScreenPriv->pwinBltExposedRegions = |
| 601 | (winBltExposedRegionsProcPtr) (void (*)(void)) NoopDDA; |
| 602 | pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD; |
| 603 | pScreenPriv->pwinRedrawScreen = NULL; |
| 604 | pScreenPriv->pwinRealizeInstalledPalette = NULL; |
| 605 | pScreenPriv->pwinInstallColormap = NULL; |
| 606 | pScreenPriv->pwinStoreColors = NULL; |
| 607 | pScreenPriv->pwinCreateColormap = NULL; |
| 608 | pScreenPriv->pwinDestroyColormap = NULL; |
| 609 | pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD; |
| 610 | pScreenPriv->pwinCreatePrimarySurface = |
| 611 | (winCreatePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; |
| 612 | pScreenPriv->pwinReleasePrimarySurface = |
| 613 | (winReleasePrimarySurfaceProcPtr) (void (*)(void)) NoopDDA; |
| 614 | #ifdef XWIN_MULTIWINDOW |
| 615 | pScreenPriv->pwinFinishCreateWindowsWindow = |
| 616 | (winFinishCreateWindowsWindowProcPtr) (void (*)(void)) NoopDDA; |
| 617 | #endif |
| 618 | |
| 619 | return TRUE; |
| 620 | } |