diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/hw/xwin/winpfbdd.c | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/hw/xwin/winpfbdd.c')
-rw-r--r-- | xorg-server/hw/xwin/winpfbdd.c | 684 |
1 files changed, 684 insertions, 0 deletions
diff --git a/xorg-server/hw/xwin/winpfbdd.c b/xorg-server/hw/xwin/winpfbdd.c new file mode 100644 index 000000000..13fc1058d --- /dev/null +++ b/xorg-server/hw/xwin/winpfbdd.c @@ -0,0 +1,684 @@ +/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + * + *Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + *"Software"), to deal in the Software without restriction, including + *without limitation the rights to use, copy, modify, merge, publish, + *distribute, sublicense, and/or sell copies of the Software, and to + *permit persons to whom the Software is furnished to do so, subject to + *the following conditions: + * + *The above copyright notice and this permission notice shall be + *included in all copies or substantial portions of the Software. + * + *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR + *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + *Except as contained in this notice, the name of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Dakshinamurthy Karra + * Suhaib M Siddiqi + * Peter Busch + * Harold L Hunt II + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" + + +/* + * External symbols + */ + +extern const GUID _IID_IDirectDraw2; +extern HWND g_hDlgExit; + + +/* + * Local function prototypes + */ + +static Bool +winAllocateFBPrimaryDD (ScreenPtr pScreen); + +static Bool +winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen); + +static Bool +winInitVisualsPrimaryDD (ScreenPtr pScreen); + +static Bool +winAdjustVideoModePrimaryDD (ScreenPtr pScreen); + +static Bool +winActivateAppPrimaryDD (ScreenPtr pScreen); + +static Bool +winHotKeyAltTabPrimaryDD (ScreenPtr pScreen); + + +/* + * Create a DirectDraw primary surface + */ + +static Bool +winAllocateFBPrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + HRESULT ddrval = DD_OK; + DDSURFACEDESC ddsd; + DDSURFACEDESC *pddsdPrimary = NULL; + DDSURFACEDESC *pddsdOffscreen = NULL; + RECT rcClient; + + ErrorF ("winAllocateFBPrimaryDD\n"); + + /* Get client area location in screen coords */ + GetClientRect (pScreenPriv->hwndScreen, &rcClient); + MapWindowPoints (pScreenPriv->hwndScreen, + HWND_DESKTOP, + (LPPOINT)&rcClient, 2); + + /* Create a DirectDraw object, store the address at lpdd */ + ddrval = (*g_fpDirectDrawCreate) (NULL, &pScreenPriv->pdd, NULL); + if (ddrval != DD_OK) + FatalError ("winAllocateFBPrimaryDD - Could not start DirectDraw\n"); + + /* Get a DirectDraw2 interface pointer */ + ddrval = IDirectDraw_QueryInterface (pScreenPriv->pdd, + &IID_IDirectDraw2, + (LPVOID*) &pScreenPriv->pdd2); + if (FAILED (ddrval)) + { + ErrorF ("winAllocateFBShadowDD - Failed DD2 query: %08x\n", + (unsigned int) ddrval); + return FALSE; + } + + + ErrorF ("winAllocateFBPrimaryDD - Created and initialized DD\n"); + + /* Are we windowed or fullscreen? */ + if (pScreenInfo->fFullScreen) + { + /* Full screen mode */ + ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, + pScreenPriv->hwndScreen, + DDSCL_FULLSCREEN + | DDSCL_EXCLUSIVE); + if (FAILED (ddrval)) + FatalError ("winAllocateFBPrimaryDD - Could not set " + "cooperative level\n"); + + /* Change the video mode to the mode requested */ + ddrval = IDirectDraw2_SetDisplayMode (pScreenPriv->pdd2, + pScreenInfo->dwWidth, + pScreenInfo->dwHeight, + pScreenInfo->dwBPP, + pScreenInfo->dwRefreshRate, + 0); + if (FAILED (ddrval)) + FatalError ("winAllocateFBPrimaryDD - Could not set " + "full screen display mode\n"); + } + else + { + /* Windowed mode */ + ddrval = IDirectDraw2_SetCooperativeLevel (pScreenPriv->pdd2, + pScreenPriv->hwndScreen, + DDSCL_NORMAL); + if (FAILED (ddrval)) + FatalError ("winAllocateFBPrimaryDD - Could not set " + "cooperative level\n"); + } + + /* Describe the primary surface */ + ZeroMemory (&ddsd, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS; + ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + + /* Create the primary surface */ + ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, + &ddsd, + &pScreenPriv->pddsPrimary, + NULL); + if (FAILED (ddrval)) + FatalError ("winAllocateFBPrimaryDD - Could not create primary " + "surface %08x\n", (unsigned int) ddrval); + + ErrorF ("winAllocateFBPrimaryDD - Created primary\n"); + + /* Allocate a DD surface description for our screen privates */ + pddsdPrimary = pScreenPriv->pddsdPrimary + = malloc (sizeof (DDSURFACEDESC)); + if (pddsdPrimary == NULL) + FatalError ("winAllocateFBPrimaryDD - Could not allocate surface " + "description memory\n"); + ZeroMemory (pddsdPrimary, sizeof (*pddsdPrimary)); + pddsdPrimary->dwSize = sizeof (*pddsdPrimary); + + /* Describe the offscreen surface to be created */ + /* + * NOTE: Do not use a DDSCAPS_VIDEOMEMORY surface, + * as drawing, locking, and unlocking take forever + * with video memory surfaces. In addition, + * video memory is a somewhat scarce resource, + * so you shouldn't be allocating video memory when + * you have the option of using system memory instead. + */ + ZeroMemory (&ddsd, sizeof (ddsd)); + ddsd.dwSize = sizeof (ddsd); + ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + ddsd.dwHeight = pScreenInfo->dwHeight; + ddsd.dwWidth = pScreenInfo->dwWidth; + + /* Create the shadow surface */ + ddrval = IDirectDraw2_CreateSurface (pScreenPriv->pdd2, + &ddsd, + &pScreenPriv->pddsOffscreen, + NULL); + if (ddrval != DD_OK) + FatalError ("winAllocateFBPrimaryDD - Could not create shadow " + "surface\n"); + + ErrorF ("winAllocateFBPrimaryDD - Created offscreen\n"); + + /* Allocate a DD surface description for our screen privates */ + pddsdOffscreen = pScreenPriv->pddsdOffscreen + = malloc (sizeof (DDSURFACEDESC)); + if (pddsdOffscreen == NULL) + FatalError ("winAllocateFBPrimaryDD - Could not allocate surface " + "description memory\n"); + ZeroMemory (pddsdOffscreen, sizeof (*pddsdOffscreen)); + pddsdOffscreen->dwSize = sizeof (*pddsdOffscreen); + + ErrorF ("winAllocateFBPrimaryDD - Locking primary\n"); + + /* Lock the primary surface */ + ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary, + pScreenInfo->fFullScreen ? NULL:&rcClient, + pddsdPrimary, + DDLOCK_WAIT, + NULL); + if (ddrval != DD_OK || pddsdPrimary->lpSurface == NULL) + FatalError ("winAllocateFBPrimaryDD - Could not lock " + "primary surface\n"); + + ErrorF ("winAllocateFBPrimaryDD - Locked primary\n"); + + /* We don't know how to deal with anything other than RGB */ + if (!(pddsdPrimary->ddpfPixelFormat.dwFlags & DDPF_RGB)) + FatalError ("winAllocateFBPrimaryDD - Color format other than RGB\n"); + + /* Grab the pitch from the surface desc */ + pScreenInfo->dwStride = (pddsdPrimary->u1.lPitch * 8) + / pScreenInfo->dwBPP; + + /* Save the pointer to our surface memory */ + pScreenInfo->pfb = pddsdPrimary->lpSurface; + + /* Grab the color depth and masks from the surface description */ + pScreenPriv->dwRedMask = pddsdPrimary->ddpfPixelFormat.u2.dwRBitMask; + pScreenPriv->dwGreenMask = pddsdPrimary->ddpfPixelFormat.u3.dwGBitMask; + pScreenPriv->dwBlueMask = pddsdPrimary->ddpfPixelFormat.u4.dwBBitMask; + + ErrorF ("winAllocateFBPrimaryDD - Returning\n"); + + return TRUE; +} + + +/* + * Call the wrapped CloseScreen function. + * + * Free our resources and private structures. + */ + +static Bool +winCloseScreenPrimaryDD (int nIndex, ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + Bool fReturn; + + ErrorF ("winCloseScreenPrimaryDD - Freeing screen resources\n"); + + /* Flag that the screen is closed */ + pScreenPriv->fClosed = TRUE; + pScreenPriv->fActive = FALSE; + + /* Call the wrapped CloseScreen procedure */ + WIN_UNWRAP(CloseScreen); + fReturn = (*pScreen->CloseScreen) (nIndex, pScreen); + + /* Delete the window property */ + RemoveProp (pScreenPriv->hwndScreen, WIN_SCR_PROP); + + /* Free the offscreen surface, if there is one */ + if (pScreenPriv->pddsOffscreen) + { + IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, NULL); + IDirectDrawSurface2_Release (pScreenPriv->pddsOffscreen); + pScreenPriv->pddsOffscreen = NULL; + } + + /* Release the primary surface, if there is one */ + if (pScreenPriv->pddsPrimary) + { + IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, NULL); + IDirectDrawSurface2_Release (pScreenPriv->pddsPrimary); + pScreenPriv->pddsPrimary = NULL; + } + + /* Free the DirectDraw object, if there is one */ + if (pScreenPriv->pdd) + { + IDirectDraw2_RestoreDisplayMode (pScreenPriv->pdd); + IDirectDraw2_Release (pScreenPriv->pdd); + pScreenPriv->pdd = NULL; + } + + /* Delete tray icon, if we have one */ + if (!pScreenInfo->fNoTrayIcon) + winDeleteNotifyIcon (pScreenPriv); + + /* Free the exit confirmation dialog box, if it exists */ + if (g_hDlgExit != NULL) + { + DestroyWindow (g_hDlgExit); + g_hDlgExit = NULL; + } + + /* Kill our window */ + if (pScreenPriv->hwndScreen) + { + DestroyWindow (pScreenPriv->hwndScreen); + pScreenPriv->hwndScreen = NULL; + } + + /* Kill our screeninfo's pointer to the screen */ + pScreenInfo->pScreen = NULL; + + /* Invalidate the ScreenInfo's fb pointer */ + pScreenInfo->pfb = NULL; + + /* Free the screen privates for this screen */ + free ((pointer) pScreenPriv); + + return fReturn; +} + + +/* + * Tell mi what sort of visuals we need. + * + * Generally we only need one visual, as our screen can only + * handle one format at a time, I believe. You may want + * to verify that last sentence. + */ + +static Bool +winInitVisualsPrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + DWORD dwRedBits, dwGreenBits, dwBlueBits; + + /* Count the number of ones in each color mask */ + dwRedBits = winCountBits (pScreenPriv->dwRedMask); + dwGreenBits = winCountBits (pScreenPriv->dwGreenMask); + dwBlueBits = winCountBits (pScreenPriv->dwBlueMask); + + /* Store the maximum number of ones in a color mask as the bitsPerRGB */ + if (dwRedBits > dwGreenBits && dwRedBits > dwBlueBits) + pScreenPriv->dwBitsPerRGB = dwRedBits; + else if (dwGreenBits > dwRedBits && dwGreenBits > dwBlueBits) + pScreenPriv->dwBitsPerRGB = dwGreenBits; + else + pScreenPriv->dwBitsPerRGB = dwBlueBits; + + ErrorF ("winInitVisualsPrimaryDD - Masks: %08x %08x %08x bpRGB: %d\n", + (unsigned int) pScreenPriv->dwRedMask, + (unsigned int) pScreenPriv->dwGreenMask, + (unsigned int) pScreenPriv->dwBlueMask, + (int) pScreenPriv->dwBitsPerRGB); + + /* Create a single visual according to the Windows screen depth */ + switch (pScreenInfo->dwDepth) + { + case 24: + case 16: + case 15: + if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, + TrueColorMask, + pScreenPriv->dwBitsPerRGB, + TrueColor, + pScreenPriv->dwRedMask, + pScreenPriv->dwGreenMask, + pScreenPriv->dwBlueMask)) + { + ErrorF ("winInitVisualsPrimaryDD - " + "miSetVisualTypesAndMasks failed\n"); + return FALSE; + } + break; + + case 8: +#if CYGDEBUG + winDebug ("winInitVisuals - Calling miSetVisualTypesAndMasks\n"); +#endif /* CYGDEBUG */ + if (!miSetVisualTypesAndMasks (pScreenInfo->dwDepth, + PseudoColorMask, + pScreenPriv->dwBitsPerRGB, + PseudoColor, + pScreenPriv->dwRedMask, + pScreenPriv->dwGreenMask, + pScreenPriv->dwBlueMask)) + { + ErrorF ("winInitVisualsPrimaryDD - " + "miSetVisualTypesAndMasks failed\n"); + return FALSE; + } +#if CYGDEBUG + winDebug ("winInitVisualsPrimaryDD - Returned from " + "miSetVisualTypesAndMasks\n"); +#endif /* CYGDEBUG */ + break; + + default: + ErrorF ("winInitVisualsPrimaryDD - Unknown screen depth\n"); + return FALSE; + } + + ErrorF ("winInitVisualsPrimaryDD - Returning\n"); + + return TRUE; +} + + +static Bool +winAdjustVideoModePrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + HDC hdc = NULL; + DWORD dwBPP; + + /* We're in serious trouble if we can't get a DC */ + hdc = GetDC (NULL); + if (hdc == NULL) + { + ErrorF ("winAdjustVideoModePrimaryDD - GetDC failed\n"); + return FALSE; + } + + /* Query GDI for current display depth */ + dwBPP = GetDeviceCaps (hdc, BITSPIXEL); + + /* DirectDraw can only change the depth in fullscreen mode */ + if (pScreenInfo->dwBPP == WIN_DEFAULT_BPP) + { + /* No -depth parameter passed, let the user know the depth being used */ + ErrorF ("winAdjustVideoModePrimaryDD - Using Windows display " + "depth of %d bits per pixel\n", (int) dwBPP); + + /* Use GDI's depth */ + pScreenInfo->dwBPP = dwBPP; + } + else if (pScreenInfo->fFullScreen + && pScreenInfo->dwBPP != dwBPP) + { + /* FullScreen, and GDI depth differs from -depth parameter */ + ErrorF ("winAdjustVideoModePrimaryDD - FullScreen, using command " + "line depth: %d\n", (int) pScreenInfo->dwBPP); + } + else if (dwBPP != pScreenInfo->dwBPP) + { + /* Windowed, and GDI depth differs from -depth parameter */ + ErrorF ("winAdjustVideoModePrimaryDD - Windowed, command line " + "depth: %d, using depth: %d\n", + (int) pScreenInfo->dwBPP, (int) dwBPP); + + /* We'll use GDI's depth */ + pScreenInfo->dwBPP = dwBPP; + } + + /* Release our DC */ + ReleaseDC (NULL, hdc); + + return TRUE; +} + + +/* + * We need to blit our offscreen fb to + * the screen when we are activated, and we need to point + * the fb code back to the primary surface memory. + */ + +static Bool +winActivateAppPrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + RECT rcSrc, rcClient; + HRESULT ddrval = DD_OK; + + /* Check for errors */ + if (pScreenPriv == NULL + || pScreenPriv->pddsPrimary == NULL + || pScreenPriv->pddsOffscreen == NULL) + return FALSE; + + /* Check for do-nothing */ + if (!pScreenPriv->fActive) + return TRUE; + + /* We are activating */ + ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsOffscreen); + if (ddrval == DD_OK) + { + IDirectDrawSurface2_Unlock (pScreenPriv->pddsOffscreen, + NULL); + /* + * We don't check for an error from Unlock, because it + * doesn't matter if the Unlock failed. + */ + } + + /* Restore both surfaces, just cause I like it that way */ + IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen); + IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); + + /* Get client area in screen coords */ + GetClientRect (pScreenPriv->hwndScreen, &rcClient); + MapWindowPoints (pScreenPriv->hwndScreen, + HWND_DESKTOP, + (LPPOINT)&rcClient, 2); + + /* Setup a source rectangle */ + rcSrc.left = 0; + rcSrc.top = 0; + rcSrc.right = pScreenInfo->dwWidth; + rcSrc.bottom = pScreenInfo->dwHeight; + + ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsPrimary, + &rcClient, + pScreenPriv->pddsOffscreen, + &rcSrc, + DDBLT_WAIT, + NULL); + if (ddrval != DD_OK) + FatalError ("winActivateAppPrimaryDD () - Failed blitting offscreen " + "surface to primary surface %08x\n", (unsigned int) ddrval); + + /* Lock the primary surface */ + ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsPrimary, + &rcClient, + pScreenPriv->pddsdPrimary, + DDLOCK_WAIT, + NULL); + if (ddrval != DD_OK + || pScreenPriv->pddsdPrimary->lpSurface == NULL) + FatalError ("winActivateAppPrimaryDD () - Could not lock " + "primary surface\n"); + + /* Notify FB of the new memory pointer */ + winUpdateFBPointer (pScreen, + pScreenPriv->pddsdPrimary->lpSurface); + + /* + * Register the Alt-Tab combo as a hotkey so we can copy + * the primary framebuffer before the display mode changes + */ + RegisterHotKey (pScreenPriv->hwndScreen, 1, MOD_ALT, 9); + + return TRUE; +} + + +/* + * Handle the Alt+Tab hotkey. + * + * We need to save the primary fb to an offscreen fb when + * we get deactivated, and point the fb code at the offscreen + * fb for the duration of the deactivation. + */ + +static Bool +winHotKeyAltTabPrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + RECT rcClient, rcSrc; + HRESULT ddrval = DD_OK; + + ErrorF ("\nwinHotKeyAltTabPrimaryDD\n\n"); + + /* Alt+Tab was pressed, we will lose focus very soon */ + pScreenPriv->fActive = FALSE; + + /* Check for error conditions */ + if (pScreenPriv->pddsPrimary == NULL + || pScreenPriv->pddsOffscreen == NULL) + return FALSE; + + /* Get client area in screen coords */ + GetClientRect (pScreenPriv->hwndScreen, &rcClient); + MapWindowPoints (pScreenPriv->hwndScreen, + HWND_DESKTOP, + (LPPOINT)&rcClient, 2); + + /* Did we loose the primary surface? */ + ddrval = IDirectDrawSurface2_IsLost (pScreenPriv->pddsPrimary); + if (ddrval == DD_OK) + { + ddrval = IDirectDrawSurface2_Unlock (pScreenPriv->pddsPrimary, + NULL); + if (FAILED (ddrval)) + FatalError ("winHotKeyAltTabPrimaryDD - Failed unlocking primary " + "surface\n"); + } + + /* Setup a source rectangle */ + rcSrc.left = 0; + rcSrc.top = 0; + rcSrc.right = pScreenInfo->dwWidth; + rcSrc.bottom = pScreenInfo->dwHeight; + + /* Blit the primary surface to the offscreen surface */ + ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen, + NULL, /* should be rcDest */ + pScreenPriv->pddsPrimary, + NULL, + DDBLT_WAIT, + NULL); + if (ddrval == DDERR_SURFACELOST) + { + IDirectDrawSurface2_Restore (pScreenPriv->pddsOffscreen); + IDirectDrawSurface2_Restore (pScreenPriv->pddsPrimary); + + /* Blit the primary surface to the offscreen surface */ + ddrval = IDirectDrawSurface2_Blt (pScreenPriv->pddsOffscreen, + NULL, + pScreenPriv->pddsPrimary, + NULL, + DDBLT_WAIT, + NULL); + if (FAILED (ddrval)) + FatalError ("winHotKeyAltTabPrimaryDD - Failed blitting primary " + "surface to offscreen surface: %08x\n", + (unsigned int) ddrval); + } + else + { + FatalError ("winHotKeyAltTabPrimaryDD - Unknown error from " + "Blt: %08dx\n", (unsigned int) ddrval); + } + + /* Lock the offscreen surface */ + ddrval = IDirectDrawSurface2_Lock (pScreenPriv->pddsOffscreen, + NULL, + pScreenPriv->pddsdOffscreen, + DDLOCK_WAIT, + NULL); + if (ddrval != DD_OK + || pScreenPriv->pddsdPrimary->lpSurface == NULL) + FatalError ("winHotKeyAltTabPrimaryDD - Could not lock " + "offscreen surface\n"); + + /* Notify FB of the new memory pointer */ + winUpdateFBPointer (pScreen, + pScreenPriv->pddsdOffscreen->lpSurface); + + /* Unregister our hotkey */ + UnregisterHotKey (pScreenPriv->hwndScreen, 1); + + return TRUE; +} + + +/* Set engine specific functions */ +Bool +winSetEngineFunctionsPrimaryDD (ScreenPtr pScreen) +{ + winScreenPriv(pScreen); + winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo; + + /* Set our pointers */ + pScreenPriv->pwinAllocateFB = winAllocateFBPrimaryDD; + pScreenPriv->pwinShadowUpdate + = (winShadowUpdateProcPtr) (void (*)(void))NoopDDA; + pScreenPriv->pwinCloseScreen = winCloseScreenPrimaryDD; + pScreenPriv->pwinInitVisuals = winInitVisualsPrimaryDD; + pScreenPriv->pwinAdjustVideoMode = winAdjustVideoModePrimaryDD; + if (pScreenInfo->fFullScreen) + pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowFullScreen; + else + pScreenPriv->pwinCreateBoundingWindow = winCreateBoundingWindowWindowed; + pScreenPriv->pwinFinishScreenInit = winFinishScreenInitFB; + pScreenPriv->pwinBltExposedRegions + = (winBltExposedRegionsProcPtr) (void (*)(void))NoopDDA; + pScreenPriv->pwinActivateApp = winActivateAppPrimaryDD; + pScreenPriv->pwinHotKeyAltTab = winHotKeyAltTabPrimaryDD; +#ifdef XWIN_MULTIWINDOW + pScreenPriv->pwinFinishCreateWindowsWindow = + (winFinishCreateWindowsWindowProcPtr) (void (*)(void))NoopDDA; +#endif + + return TRUE; +} |