|
|
/****************************** Module Header ******************************\
* Module Name: sprite.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * Windows Layering (Sprite) support. * * History: * 12/05/97 vadimg created \***************************************************************************/
#include "precomp.h"
#pragma hdrstop
#ifdef MOUSE_IP
#define MOUSE_SONAR_RADIUS_INIT 100
#define MOUSE_SONAR_LINE_WIDTH 4
#define MOUSE_SONAR_RADIUS_DELTA 20
#define MOUSE_SONAR_RADIUS_TIMER 50
#define COLORKEY_COLOR RGB(255, 0, 255)
VOID DrawSonar(HDC hdc);
#endif
#ifdef REDIRECTION
/***************************************************************************\
* UserGetRedirectionBitmap * \***************************************************************************/ HBITMAP UserGetRedirectionBitmap( HWND hwnd) { HBITMAP hbm; PWND pwnd;
EnterCrit();
if ((pwnd = RevalidateHwnd(hwnd)) == NULL) { return NULL; }
hbm = GetRedirectionBitmap(pwnd);
LeaveCrit();
return hbm; }
/***************************************************************************\
* SetRedirectionMode * \***************************************************************************/ BOOL SetRedirectionMode( PBWL pbwl, PPROCESSINFO ppi) { HWND *phwnd; PWND pwndT; BOOL fRet = TRUE;
for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) {
if ((pwndT = RevalidateHwnd(*phwnd)) == NULL) { continue; }
if (TestWF(pwndT, WFVISIBLE) && (ppi == NULL || GETPTI(pwndT)->ppi != ppi)) { if (SetRedirectedWindow(pwndT, REDIRECT_EXTREDIRECTED)) { SetWF(pwndT, WEFEXTREDIRECTED); } else { fRet = FALSE; break; } } }
return fRet; }
/***************************************************************************\
* UnsetRedirectionMode * \***************************************************************************/ VOID UnsetRedirectionMode( PBWL pbwl, PPROCESSINFO ppi) { HWND *phwnd; PWND pwndT;
for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { if ((pwndT = RevalidateHwnd(*phwnd)) == NULL) { continue; }
if (TestWF(pwndT, WFVISIBLE) && ppi == NULL || GETPTI(pwndT)->ppi != ppi) { UnsetRedirectedWindow(pwndT, REDIRECT_EXTREDIRECTED); ClrWF(pwndT, WEFEXTREDIRECTED); } } }
/***************************************************************************\
* xxxSetRedirectionMode * \***************************************************************************/ BOOL xxxSetRedirectionMode( BOOL fEnable, PDESKTOP pDesk, PTHREADINFO pti, PPROCESSINFO ppi) { PBWL pbwl; PWND pwndDesktop = pDesk->pDeskInfo->spwnd;
pbwl = BuildHwndList(pwndDesktop->spwndChild, BWL_ENUMLIST, pti); if (pbwl == NULL) { return FALSE; }
if (fEnable) { if (!SetRedirectionMode(pbwl, ppi)) { UnsetRedirectionMode(pbwl, ppi); } } else { UnsetRedirectionMode(pbwl, ppi); } FreeHwndList(pbwl);
GreEnableDirectDrawRedirection(gpDispInfo->hDev, fEnable); xxxBroadcastDisplaySettingsChange(PtiCurrent()->rpdesk, FALSE);
pwndDesktop = PtiCurrent()->rpdesk->pDeskInfo->spwnd; BEGINATOMICCHECK(); xxxInternalInvalidate(pwndDesktop, HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); ENDATOMICCHECK();
return TRUE; }
/***************************************************************************\
* xxxSetProcessRedirectionMode * \***************************************************************************/ BOOL xxxSetProcessRedirectionMode( BOOL fEnable, PPROCESSINFO ppi) { PTHREADINFO pti = ppi->ptiList; TL tl;
while (pti != NULL) { ThreadLockPti(PtiCurrent(), pti, &tl); if (!xxxSetRedirectionMode(fEnable, pti->rpdesk, pti, NULL)) { ThreadUnlockPti(PtiCurrent(), &tl); return FALSE; } pti = pti->ptiSibling; ThreadUnlockPti(PtiCurrent(), &tl); }
return TRUE; }
/***************************************************************************\
* xxxSetDesktopRedirectionMode * \***************************************************************************/ BOOL xxxSetDesktopRedirectionMode( BOOL fEnable, PDESKTOP pDesk, PPROCESSINFO ppi) { return xxxSetRedirectionMode(fEnable, pDesk, NULL, ppi); }
#endif
/***************************************************************************\
* IncrementRedirectedCount * \***************************************************************************/ VOID IncrementRedirectedCount( PWND pwnd) { if (TestWF(pwnd, WFVISIBLE)) { gnVisibleRedirectedCount++; if (gnVisibleRedirectedCount == 1) { InternalSetTimer(gTermIO.spwndDesktopOwner, IDSYS_LAYER, 100, xxxSystemTimerProc, TMRF_SYSTEM | TMRF_PTIWINDOW); } } }
/***************************************************************************\
* DecrementRedirectedCount * \***************************************************************************/ VOID DecrementRedirectedCount( PWND pwnd) { if (TestWF(pwnd, WFVISIBLE)) { if (gnVisibleRedirectedCount > 0) { gnVisibleRedirectedCount--; if (gnVisibleRedirectedCount == 0) { _KillSystemTimer(gTermIO.spwndDesktopOwner, IDSYS_LAYER); } } } }
/***************************************************************************\
* CreateRedirectionBitmap * * 10/1/1998 vadimg created \***************************************************************************/ HBITMAP CreateRedirectionBitmap( PWND pwnd) { HBITMAP hbm;
UserAssert(pwnd->rcWindow.right >= pwnd->rcWindow.left); UserAssert(pwnd->rcWindow.bottom >= pwnd->rcWindow.top);
/*
* Make sure the (0,0) case doesn't fail, since the window really * can be sized this way. */ if ((hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, max(pwnd->rcWindow.right - pwnd->rcWindow.left, 1), max(pwnd->rcWindow.bottom - pwnd->rcWindow.top, 1) | CCB_NOVIDEOMEMORY)) == NULL) { RIPMSG0(RIP_WARNING, "CreateRedirectionBitmap: bitmap create failed"); return NULL; }
if (!GreSetBitmapOwner(hbm, OBJECT_OWNER_PUBLIC) || !GreMarkUndeletableBitmap(hbm) || !SetRedirectionBitmap(pwnd, hbm)) { RIPMSG0(RIP_WARNING, "CreateRedirectionBitmap: bitmap set failed"); GreMarkDeletableBitmap(hbm); GreDeleteObject(hbm); return NULL; }
SetWF(pwnd, WEFPREDIRECTED);
/*
* Force the window to redraw if we could recreate the bitmap since * the redirection bitmap we just allocated doesn't contain anything * yet. */ BEGINATOMICCHECK(); xxxInternalInvalidate(pwnd, HRGN_FULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN); ENDATOMICCHECK();
IncrementRedirectedCount(pwnd);
return hbm; }
/***************************************************************************\
* ConvertRedirectionDCs * * 11/19/1998 vadimg created \***************************************************************************/ VOID ConvertRedirectionDCs( PWND pwnd, HBITMAP hbm) { PDCE pdce;
GreLockDisplay(gpDispInfo->hDev);
for (pdce = gpDispInfo->pdceFirst; pdce != NULL; pdce = pdce->pdceNext) { if (pdce->DCX_flags & DCX_DESTROYTHIS) { continue; }
if (!(pdce->DCX_flags & DCX_INUSE)) { continue; }
if (!_IsDescendant(pwnd, pdce->pwndOrg)) { continue; }
/*
* Only normal DCs can be redirected. Redirection on monitor * specific DCs is not supported. */ if (pdce->pMonitor != NULL) { continue; }
SET_OR_CLEAR_FLAG(pdce->DCX_flags, DCX_REDIRECTED, (hbm != NULL));
UserVerify(GreSelectRedirectionBitmap(pdce->hdc, hbm));
InvalidateDce(pdce); }
GreUnlockDisplay(gpDispInfo->hDev); }
/***************************************************************************\
* UpdateRedirectedDC * * 11/19/1998 vadimg created \***************************************************************************/ VOID UpdateRedirectedDC( PDCE pdce) { RECT rcBounds; PWND pwnd; SIZE size; POINT pt; HBITMAP hbm, hbmOld; PREDIRECT prdr;
UserAssert(pdce->DCX_flags & DCX_REDIRECTED);
/*
* Check to see if any drawing has been done into this DC * that should be transferred to the sprite. */ if (!GreGetBounds(pdce->hdc, &rcBounds, 0)) { return; }
pwnd = GetStyleWindow(pdce->pwndOrg, WEFPREDIRECTED); UserAssert(pwnd); prdr = (PREDIRECT)_GetProp(pwnd, PROP_LAYER, TRUE);
#ifdef REDIRECTION
BEGINATOMICCHECK(); xxxWindowEvent(EVENT_SYSTEM_REDIRECTEDPAINT, pwnd, MAKELONG(rcBounds.left, rcBounds.top), MAKELONG(rcBounds.right, rcBounds.bottom), WEF_ASYNC); ENDATOMICCHECK(); #endif
if (TestWF(pwnd, WEFCOMPOSITED)) { if (TestWF(pwnd, WEFPCOMPOSITING)) { UnionRect(&prdr->rcUpdate, &prdr->rcUpdate, &rcBounds); } else { HRGN hrgn;
OffsetRect(&rcBounds, pwnd->rcWindow.left, pwnd->rcWindow.top); hrgn = GreCreateRectRgnIndirect(&rcBounds);
BEGINATOMICCHECK(); xxxInternalInvalidate(pwnd, hrgn, RDW_ALLCHILDREN | RDW_INVALIDATE | RDW_ERASE | RDW_FRAME); ENDATOMICCHECK();
GreDeleteObject(hrgn); } } else if (TestWF(pwnd, WEFLAYERED)) { hbm = prdr->hbm;
hbmOld = GreSelectBitmap(ghdcMem, hbm);
size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left; size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top;
pt.x = pt.y = 0; GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, NULL, &size, ghdcMem, &pt, 0, NULL, ULW_DEFAULT_ATTRIBUTES, &rcBounds);
GreSelectBitmap(ghdcMem, hbmOld); } }
/***************************************************************************\
* DeleteRedirectionBitmap * \***************************************************************************/ VOID DeleteRedirectionBitmap( PWND pwnd, HBITMAP hbm) { GreMarkDeletableBitmap(hbm); GreDeleteObject(hbm); DecrementRedirectedCount(pwnd); }
/***************************************************************************\
* RemoveRedirectionBitmap * * 9/23/1998 vadimg created \***************************************************************************/ VOID RemoveRedirectionBitmap( PWND pwnd) { HBITMAP hbm;
/*
* Delete the backing bitmap for this layered window. */ if ((hbm = GetRedirectionBitmap(pwnd)) == NULL) { return; }
UserAssert(TestWF(pwnd, WEFPREDIRECTED)); ClrWF(pwnd, WEFPREDIRECTED);
ConvertRedirectionDCs(pwnd, NULL); SetRedirectionBitmap(pwnd, NULL); DeleteRedirectionBitmap(pwnd, hbm); }
/***************************************************************************\
* _GetLayeredWindowAttributes * * 3/14/2000 jstall created \***************************************************************************/ BOOL _GetLayeredWindowAttributes( PWND pwnd, COLORREF *pcrKey, BYTE *pbAlpha, DWORD *pdwFlags) { BLENDFUNCTION bf;
UserAssert(pcrKey != NULL); UserAssert(pbAlpha != NULL); UserAssert(pdwFlags != NULL);
if (!TestWF(pwnd, WEFLAYERED)) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "GetLayeredWindowAttributes: not a sprite 0x%p", pwnd); return FALSE; }
/*
* Check that the window has a redirection bitmap and is marked as * layered through WS_EX_LAYERED. If the window is layered through * UpdateLayeredWindow, this function should fail. */ if ((GetRedirectionFlags(pwnd) & REDIRECT_LAYER) == 0 || !TestWF(pwnd, WEFLAYERED)) {
return FALSE; }
if (GreGetSpriteAttributes(gpDispInfo->hDev, PtoHq(pwnd), NULL, pcrKey, &bf, pdwFlags)) { *pbAlpha = bf.SourceConstantAlpha;
return TRUE; }
return FALSE; }
/***************************************************************************\
* _SetLayeredWindowAttributes * * 9/24/1998 vadimg created \***************************************************************************/ BOOL _SetLayeredWindowAttributes( PWND pwnd, COLORREF crKey, BYTE bAlpha, DWORD dwFlags) { BOOL bRet; BLENDFUNCTION blend; HBITMAP hbm;
if (!TestWF(pwnd, WEFLAYERED)) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "SetLayeredWindowAttributes: not a sprite 0x%p", pwnd); return FALSE; }
if ((hbm = GetRedirectionBitmap(pwnd)) == NULL) { if (!SetRedirectedWindow(pwnd, REDIRECT_LAYER)) { return FALSE; } }
blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.AlphaFormat = 0; blend.SourceConstantAlpha = bAlpha;
dwFlags |= ULW_NEW_ATTRIBUTES; // Notify gdi that these are new attributes
if (hbm != NULL) { HBITMAP hbmOld; SIZE size; POINT ptSrc = {0,0};
hbmOld = GreSelectBitmap(ghdcMem, hbm);
size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left; size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top;
bRet = GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, NULL, &size, ghdcMem, &ptSrc, crKey, &blend, dwFlags, NULL);
GreSelectBitmap(ghdcMem, hbmOld); } else { bRet = GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, NULL, NULL, NULL, NULL, NULL, crKey, &blend, dwFlags, NULL); }
return bRet; }
/***************************************************************************\
* RecreateRedirectionBitmap * * 10/1/1998 vadimg created \***************************************************************************/ BOOL RecreateRedirectionBitmap( PWND pwnd) { HBITMAP hbm, hbmNew, hbmMem, hbmMem2; BITMAP bm, bmNew; int cx, cy; PDCE pdce;
/*
* No need to do anything if this layered window doesn't have * a redirection bitmap. */ if ((hbm = GetRedirectionBitmap(pwnd)) == NULL) { return FALSE; }
UserAssert(TestWF(pwnd, WEFPREDIRECTED));
/*
* Try to create a new redirection bitmap with the new size. If failed, * delete the old one and remove it from the window property list. */ if ((hbmNew = CreateRedirectionBitmap(pwnd)) == NULL) { RemoveRedirectionBitmap(pwnd); return FALSE; }
/*
* Make sure that the display is locked, so that nobody can be drawing * into the redirection DCs while we're switching bitmaps under them. */ UserAssert(GreIsDisplayLocked(gpDispInfo->hDev));
/*
* Get the size of the old bitmap to know how much to copy. */ GreExtGetObjectW(hbm, sizeof(bm), (LPSTR)&bm); GreExtGetObjectW(hbmNew, sizeof(bmNew), (LPSTR)&bmNew);
/*
* Copy the bitmap from the old bitmap into the new one. */ hbmMem = GreSelectBitmap(ghdcMem, hbm); hbmMem2 = GreSelectBitmap(ghdcMem2, hbmNew);
cx = min(bm.bmWidth, bmNew.bmWidth); cy = min(bm.bmHeight, bmNew.bmHeight);
GreBitBlt(ghdcMem2, 0, 0, cx, cy, ghdcMem, 0, 0, SRCCOPY | NOMIRRORBITMAP, 0);
/*
* Find layered DCs that are in use corresponding to this window and * replace the old redirection bitmap by the new one. */ for (pdce = gpDispInfo->pdceFirst; pdce != NULL; pdce = pdce->pdceNext) { if (pdce->DCX_flags & DCX_DESTROYTHIS) { continue; }
if (!(pdce->DCX_flags & DCX_REDIRECTED) || !(pdce->DCX_flags & DCX_INUSE)) { continue; }
if (!_IsDescendant(pwnd, pdce->pwndOrg)) { continue; }
UserVerify(GreSelectRedirectionBitmap(pdce->hdc, hbmNew)); }
GreSelectBitmap(ghdcMem, hbmMem); GreSelectBitmap(ghdcMem2, hbmMem2);
/*
* Finally, delete the old redirection bitmap. */ DeleteRedirectionBitmap(pwnd, hbm);
return TRUE; }
/***************************************************************************\
* ResetRedirectedWindows * \***************************************************************************/ VOID ResetRedirectedWindows( VOID) { PHE phe, pheMax; PWND pwnd;
GreLockDisplay(gpDispInfo->hDev);
pheMax = &gSharedInfo.aheList[giheLast]; for (phe = gSharedInfo.aheList; phe <= pheMax; phe++) { if (phe->bType != TYPE_WINDOW) { continue; }
pwnd = (PWND)phe->phead; if (!TestWF(pwnd, WEFPREDIRECTED)) { continue; }
RecreateRedirectionBitmap(pwnd);
/*
* Recreate the sprite so the surfaces are at the proper color depth. */ if (TestWF(pwnd, WEFLAYERED)) { COLORREF cr; BLENDFUNCTION blend; DWORD dwFlags;
GreGetSpriteAttributes(gpDispInfo->hDev, PtoHq(pwnd), NULL, &cr, &blend, &dwFlags);
GreDeleteSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL);
if (GreCreateSprite(gpDispInfo->hDev, PtoHq(pwnd), &pwnd->rcWindow)) { _SetLayeredWindowAttributes(pwnd, cr, blend.SourceConstantAlpha, dwFlags); } else { RemoveRedirectionBitmap(pwnd); ClrWF(pwnd, WEFLAYERED); } } }
GreUnlockDisplay(gpDispInfo->hDev); }
/***************************************************************************\
* UnsetLayeredWindow * * 1/30/1998 vadimg created \***************************************************************************/ VOID UnsetLayeredWindow( PWND pwnd) { HWND hwnd = PtoHq(pwnd);
UnsetRedirectedWindow(pwnd, REDIRECT_LAYER);
/*
* If the window is still visible, leave the sprite bits on the screen. */ if (TestWF(pwnd, WFVISIBLE)) { GreUpdateSprite(gpDispInfo->hDev, hwnd, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL, ULW_NOREPAINT, NULL); }
/*
* Delete the sprite object. */ if (!GreDeleteSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL)) { RIPMSG1(RIP_WARNING, "xxxSetLayeredWindow failed 0x%p", pwnd); } ClrWF(pwnd, WEFLAYERED);
/*
* Make sure the window gets painted if visible. * * RAID 143578. * Should consider to jiggle the mouse. Remove IDC_NOMOUSE when * SetFMouseMoved and thus InvalidateDCCache don't leave crit. * This is because the hit-testing by a window may change when it * transitions the layering state. */ if (TestWF(pwnd, WFVISIBLE)) { BEGINATOMICCHECK(); zzzInvalidateDCCache(pwnd, IDC_DEFAULT | IDC_NOMOUSE); ENDATOMICCHECK(); } }
/***************************************************************************\
* xxxSetLayeredWindow * * 12/05/97 vadimg wrote \***************************************************************************/ HANDLE xxxSetLayeredWindow( PWND pwnd, BOOL fRepaintBehind) { HANDLE hsprite; SIZE size;
CheckLock(pwnd);
#ifndef CHILD_LAYERING
if (!FTopLevel(pwnd)) { RIPMSG1(RIP_WARNING, "xxxSetLayeredWindow: not top-level 0x%p", pwnd); return NULL; } #endif
UserAssertMsg1(!TestWF(pwnd, WEFLAYERED), "xxxSetLayeredWindow: already layered 0x%p", pwnd);
size.cx = pwnd->rcWindow.right - pwnd->rcWindow.left; size.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top;
hsprite = GreCreateSprite(gpDispInfo->hDev, PtoHq(pwnd), &pwnd->rcWindow); if (hsprite == NULL) { RIPMSG1(RIP_WARNING, "xxxSetLayeredWindow failed 0x%p", pwnd); return NULL; }
SetWF(pwnd, WEFLAYERED); TrackLayeredZorder(pwnd);
/*
* Invalidate the DC cache because changing the sprite status * may change the visrgn for some windows. * * RAID 143578. * Should jiggle the mouse. Remove IDC_NOMOUSE when * SetFMouseMoved and thus InvalidateDCCache don't leave crit. * This is because the hit-testing by a window may change when it * transitions the layering state. */ BEGINATOMICCHECK(); zzzInvalidateDCCache(pwnd, IDC_DEFAULT | IDC_NOMOUSE); ENDATOMICCHECK();
/*
* For the dynamic promotion to a sprite, put the proper bits into * the sprite itself by doing ULW with the current screen content * and into the background by invalidating windows behind. There * might be some dirty bits if the window is partially obscured, but * they will be refreshed as soon as the app calls ULW on its own. */ if (TestWF(pwnd, WFVISIBLE)) { if (fRepaintBehind) { POINT pt;
pt.x = pwnd->rcWindow.left; pt.y = pwnd->rcWindow.top;
_UpdateLayeredWindow(pwnd, gpDispInfo->hdcScreen, &pt, &size, gpDispInfo->hdcScreen, &pt, 0, NULL, ULW_OPAQUE); } } else { /*
* No need to repaint behind if the window is still invisible. */ fRepaintBehind = FALSE; }
/*
* This must be done after the DC cache is invalidated, because * the xxxUpdateWindows call will redraw some stuff. */ if (fRepaintBehind) { HRGN hrgn = GreCreateRectRgnIndirect(&pwnd->rcWindow); xxxRedrawWindow(NULL, NULL, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN); xxxUpdateWindows(pwnd, hrgn); GreDeleteObject(hrgn); } return hsprite; }
/***************************************************************************\
* UserVisrgnFromHwnd * * Calculate a non-clipchildren visrgn for sprites. This function must be * called while inside the USER critical section. * * 12/05/97 vadimg wrote \***************************************************************************/
BOOL UserVisrgnFromHwnd(HRGN *phrgn, HWND hwnd) { PWND pwnd; DWORD dwFlags; RECT rcWindow; BOOL fRet;
CheckCritIn();
if ((pwnd = RevalidateHwnd(hwnd)) == NULL) { RIPMSG0(RIP_WARNING, "VisrgnFromHwnd: invalid hwnd"); return FALSE; }
/*
* So that we don't have to recompute the layered window's visrgn * every time the layered window is moved, we compute the visrgn once * as if the layered window covered the entire screen. GDI will * automatically intersect with this region whenever the sprite moves. */ rcWindow = pwnd->rcWindow; pwnd->rcWindow = gpDispInfo->rcScreen;
/*
* Since we use DCX_WINDOW, only rcWindow needs to be faked and saved. * Never specify DCX_REDIRECTEDBITMAP here. See comments in CalcVisRgn(). */ dwFlags = DCX_WINDOW | DCX_LOCKWINDOWUPDATE; if (TestWF(pwnd, WFCLIPSIBLINGS)) dwFlags |= DCX_CLIPSIBLINGS;
fRet = CalcVisRgn(phrgn, pwnd, pwnd, dwFlags);
pwnd->rcWindow = rcWindow;
return fRet; }
/***************************************************************************\
* SetRectRelative \***************************************************************************/
void SetRectRelative(PRECT prc, int dx, int dy, int dcx, int dcy) { prc->left += dx; prc->top += dy; prc->right += (dx + dcx); prc->bottom += (dy + dcy); }
/***************************************************************************\
* xxxUpdateLayeredWindow * * 1/20/1998 vadimg created \***************************************************************************/
BOOL _UpdateLayeredWindow( PWND pwnd, HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags) { int dx, dy, dcx, dcy; BOOL fMove = FALSE, fSize = FALSE;
/*
* Verify that we're called with a real layered window. */ if (!TestWF(pwnd, WEFLAYERED) || GetRedirectionBitmap(pwnd) != NULL) { RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "_UpdateLayeredWindow: can't call on window 0x%p", pwnd); return FALSE; }
if (!GreUpdateSprite(gpDispInfo->hDev, PtoHq(pwnd), NULL, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags, NULL)) { RIPMSG1(RIP_WARNING, "_UpdateLayeredWindow: !UpdateSprite 0x%p", pwnd); return FALSE; }
/*
* Figure out relative adjustments in position and size. */ if (pptDst != NULL) { dx = pptDst->x - pwnd->rcWindow.left; dy = pptDst->y - pwnd->rcWindow.top; if (dx != 0 || dy != 0) { fMove = TRUE; } } else { dx = 0; dy = 0; } if (psize != NULL) { dcx = psize->cx - (pwnd->rcWindow.right - pwnd->rcWindow.left); dcy = psize->cy - (pwnd->rcWindow.bottom - pwnd->rcWindow.top); if (dcx != 0 || dcy != 0) { fSize = TRUE; } } else { dcx = 0; dcy = 0; }
if (fMove || fSize) { /*
* Adjust the client rect position and size relative to * the window rect. */ SetRectRelative(&pwnd->rcWindow, dx, dy, dcx, dcy); SetRectRelative(&pwnd->rcClient, dx, dy, dcx, dcy);
/*
* Since the client rect could be smaller than the window * rect make sure the client rect doesn't underflow! */ if ((dcx < 0) && (pwnd->rcClient.left < pwnd->rcWindow.left)) { pwnd->rcClient.left = pwnd->rcWindow.left; pwnd->rcClient.right = pwnd->rcWindow.left; } if ((dcy < 0) && (pwnd->rcClient.top < pwnd->rcWindow.top)) { pwnd->rcClient.top = pwnd->rcWindow.top; pwnd->rcClient.bottom = pwnd->rcWindow.top; }
/*
* RAID 143578. * The shape of the layered window may have changed and thus * ideally we should jiggle the mouse. Currently, that would * make us leave the critical section which we don't want to do. * * SetFMouseMoved(); */ }
return TRUE; }
/***************************************************************************\
* DeleteFadeSprite \***************************************************************************/
PWND DeleteFadeSprite(void) { PWND pwnd = NULL;
if (gfade.dwFlags & FADE_WINDOW) { if ((pwnd = RevalidateHwnd(gfade.hsprite)) != NULL) { if (TestWF(pwnd, WEFLAYERED)) { UnsetLayeredWindow(pwnd); } } else { RIPMSG0(RIP_WARNING, "DeleteFadeSprite: hwnd no longer valid"); } } else { GreDeleteSprite(gpDispInfo->hDev, NULL, gfade.hsprite); } gfade.hsprite = NULL; return pwnd; }
/***************************************************************************\
* UpdateFade * * 2/16/1998 vadimg created \***************************************************************************/
void UpdateFade(POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, BLENDFUNCTION *pblend) { PWND pwnd;
if (gfade.dwFlags & FADE_WINDOW) { if ((pwnd = RevalidateHwnd(gfade.hsprite)) != NULL) { _UpdateLayeredWindow(pwnd, NULL, pptDst, psize, hdcSrc, pptSrc, 0, pblend, ULW_ALPHA); } } else { #ifdef MOUSE_IP
DWORD dwShape = ULW_ALPHA;
if (gfade.dwFlags & FADE_COLORKEY) { dwShape = ULW_COLORKEY; } GreUpdateSprite(gpDispInfo->hDev, NULL, gfade.hsprite, NULL, pptDst, psize, hdcSrc, pptSrc, gfade.crColorKey, pblend, dwShape, NULL); #else
GreUpdateSprite(gpDispInfo->hDev, NULL, gfade.hsprite, NULL, pptDst, psize, hdcSrc, pptSrc, 0, pblend, ULW_ALPHA, NULL); #endif
} }
/***************************************************************************\
* CreateFade * * 2/5/1998 vadimg created \***************************************************************************/
HDC CreateFade(PWND pwnd, RECT *prc, DWORD dwTime, DWORD dwFlags) { SIZE size;
/*
* Bail if there is a fade animation going on already. */ if (gfade.hbm != NULL) { RIPMSG0(RIP_WARNING, "CreateFade: failed, fade not available"); return NULL; }
/*
* Create a cached compatible DC. */ if (gfade.hdc == NULL) { gfade.hdc = GreCreateCompatibleDC(gpDispInfo->hdcScreen); if (gfade.hdc == NULL) { return NULL; } } else { /*
* Reset the hdc before reusing it. */ GreSetLayout(gfade.hdc , -1, 0); }
/*
* A windowed fade must have window position and size, so * prc passed in is disregarded. */ UserAssert((pwnd == NULL) || (prc == NULL));
if (pwnd != NULL) { prc = &pwnd->rcWindow; }
size.cx = prc->right - prc->left; size.cy = prc->bottom - prc->top;
if (pwnd == NULL) { gfade.hsprite = GreCreateSprite(gpDispInfo->hDev, NULL, prc); } else { gfade.dwFlags |= FADE_WINDOW; gfade.hsprite = HWq(pwnd);
BEGINATOMICCHECK(); xxxSetLayeredWindow(pwnd, FALSE); ENDATOMICCHECK(); }
if (gfade.hsprite == NULL) return FALSE;
/*
* Create a compatible bitmap for this size animation. */ gfade.hbm = GreCreateCompatibleBitmap(gpDispInfo->hdcScreen, size.cx, size.cy); if (gfade.hbm == NULL) { DeleteFadeSprite(); return NULL; }
GreSelectBitmap(gfade.hdc, gfade.hbm);
/*
* Mirror the hdc if it will be used to fade a mirrored window. */ if ((pwnd != NULL) && TestWF(pwnd, WEFLAYOUTRTL)) { GreSetLayout(gfade.hdc , -1, LAYOUT_RTL); }
/*
* Since this isn't necessarily the first animation and the hdc could * be set to public, make sure the owner is the current process. This * way this process will be able to draw into it. */ GreSetDCOwner(gfade.hdc, OBJECT_OWNER_CURRENT);
/*
* Initialize all other fade animation data. */ gfade.ptDst.x = prc->left; gfade.ptDst.y = prc->top; gfade.size.cx = size.cx; gfade.size.cy = size.cy; gfade.dwTime = dwTime; gfade.dwFlags |= dwFlags; #ifdef MOUSE_IP
if (gfade.dwFlags & FADE_COLORKEY) { gfade.crColorKey = COLORKEY_COLOR; } else { gfade.crColorKey = 0; } #endif
return gfade.hdc; }
/***************************************************************************\
* ShowFade * * GDI says that for alpha fade-out it's more efficient to do the first * show as opaque alpha instead of using ULW_OPAQUE. \***************************************************************************/
#define ALPHASTART 40
VOID ShowFade( VOID) { BLENDFUNCTION blend; POINT ptSrc; BOOL fShow;
UserAssert(gfade.hdc != NULL); UserAssert(gfade.hbm != NULL);
if (gfade.dwFlags & FADE_SHOWN) { return; }
fShow = (gfade.dwFlags & FADE_SHOW); ptSrc.x = ptSrc.y = 0; blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.AlphaFormat = 0; blend.SourceConstantAlpha = fShow ? ALPHASTART : (255 - ALPHASTART); UpdateFade(&gfade.ptDst, &gfade.size, gfade.hdc, &ptSrc, &blend);
gfade.dwFlags |= FADE_SHOWN; }
/***************************************************************************\
* StartFade * * 2/5/1998 vadimg created \***************************************************************************/ VOID StartFade( VOID) { DWORD dwTimer = 10; DWORD dwElapsed;
UserAssert(gfade.hdc != NULL); UserAssert(gfade.hbm != NULL);
/*
* Set dc and bitmap to public so the desktop thread can use them. */ GreSetDCOwner(gfade.hdc, OBJECT_OWNER_PUBLIC); GreSetBitmapOwner(gfade.hbm, OBJECT_OWNER_PUBLIC);
/*
* If it's not already shown, do the initial update that makes copy of * the source. All other updates will only need to change the alpha value. */ ShowFade();
/*
* Get the start time for the fade animation. */ dwElapsed = (gfade.dwTime * ALPHASTART + 255) / 255; gfade.dwStart = NtGetTickCount() - dwElapsed;
/*
* Set the timer in the desktop thread. This will insure that the * animation is smooth and won't get stuck if the current thread hangs. */ #ifdef MOUSE_IP
if (gfade.dwFlags & FADE_SONAR) { /*
* Sonar requires slower timer. */ dwTimer = MOUSE_SONAR_RADIUS_TIMER; } #endif
InternalSetTimer(gTermIO.spwndDesktopOwner, IDSYS_FADE, dwTimer, xxxSystemTimerProc, TMRF_SYSTEM | TMRF_PTIWINDOW); }
/***************************************************************************\
* StopFade * * 2/5/1998 vadimg created \***************************************************************************/ VOID StopFade( VOID) { DWORD dwRop = SRCCOPY; PWND pwnd;
UserAssert(gfade.hdc != NULL); UserAssert(gfade.hbm != NULL);
/*
* Stop the fade animation timer. */ _KillSystemTimer(gTermIO.spwndDesktopOwner, IDSYS_FADE);
pwnd = DeleteFadeSprite();
/*
* If showing and the animation isn't completed, blt the last frame. */ if (!(gfade.dwFlags & FADE_COMPLETED) && (gfade.dwFlags & FADE_SHOW)) { int x, y; HDC hdc;
/*
* For a windowed fade, make sure we observe the current visrgn. */ if (pwnd != NULL) { hdc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_CACHE); x = 0; y = 0; } else { hdc = gpDispInfo->hdcScreen; x = gfade.ptDst.x; y = gfade.ptDst.y; }
/*
* If the destination DC is RTL mirrored, then BitBlt call should mirror the * content, since we want the menu to preserve it text (i.e. not to * be flipped). [samera] */ if (GreGetLayout(hdc) & LAYOUT_RTL) { dwRop |= NOMIRRORBITMAP; } GreBitBlt(hdc, x, y, gfade.size.cx, gfade.size.cy, gfade.hdc, 0, 0, dwRop, 0); _ReleaseDC(hdc); }
/*
* Clean up the animation data. */ GreSelectBitmap(gfade.hdc, GreGetStockObject(PRIV_STOCK_BITMAP)); GreCleanDC(gfade.hdc); GreSetDCOwner(gfade.hdc, OBJECT_OWNER_PUBLIC); GreDeleteObject(gfade.hbm);
gfade.hbm = NULL; gfade.dwFlags = 0; }
/***************************************************************************\
* AnimateFade * * 2/5/1998 vadimg created \***************************************************************************/ VOID AnimateFade( VOID) { DWORD dwTimeElapsed; BLENDFUNCTION blend; BYTE bAlpha; BOOL fShow;
UserAssert(gfade.hdc != NULL); UserAssert(gfade.hbm != NULL);
dwTimeElapsed = NtGetTickCount() - gfade.dwStart;
/*
* If exceeding the allowed time, stop the animation now. */ if (dwTimeElapsed > gfade.dwTime) { StopFade(); return; }
fShow = (gfade.dwFlags & FADE_SHOW);
/*
* Calculate new alpha value based on time elapsed. */ if (fShow) { bAlpha = (BYTE)((255 * dwTimeElapsed) / gfade.dwTime); } else { bAlpha = (BYTE)(255 * (gfade.dwTime - dwTimeElapsed) / gfade.dwTime); }
blend.BlendOp = AC_SRC_OVER; blend.BlendFlags = 0; blend.AlphaFormat = 0; blend.SourceConstantAlpha = bAlpha;
#ifdef MOUSE_IP
if (gfade.dwFlags & FADE_SONAR) { DrawSonar(gfade.hdc); UpdateFade(&gfade.ptDst, &gfade.size, gfade.hdc, (LPPOINT)&gZero.pt, NULL); giSonarRadius -= MOUSE_SONAR_RADIUS_DELTA; } else { UpdateFade(NULL, NULL, NULL, NULL, &blend); }
/*
* Check if finished animating the fade. */ if ((fShow && bAlpha == 255) || (!fShow && bAlpha == 0) || ((gfade.dwFlags & FADE_SONAR) && giSonarRadius < 0)) { gfade.dwFlags |= FADE_COMPLETED; StopFade(); } #else
UpdateFade(NULL, NULL, NULL, NULL, &blend);
/*
* Check if finished animating the fade. */ if ((fShow && bAlpha == 255) || (!fShow && bAlpha == 0)) { gfade.dwFlags |= FADE_COMPLETED; StopFade(); } #endif
}
/***************************************************************************\
* SetRedirectedWindow * * 1/27/99 vadimg wrote \***************************************************************************/ BOOL SetRedirectedWindow( PWND pwnd, UINT uFlags) { HBITMAP hbmNew = NULL; PREDIRECT prdr; PCLS pcls;
if (!TestWF(pwnd, WEFPREDIRECTED)) { /*
* Setup the window for Redirection. This will create a new bitmap to * redirect drawing into, and then converting all HDC's to that window * to draw into that bitmap. The contents of the bitmap will be copied * to the screen in UpdateRedirectedDC(). */
UserAssert(GetRedirectionBitmap(pwnd) == NULL);
/*
* NOTE: We can only redirect windows that don't use CS_CLASSDC or * CS_PARENTDC. This is because we need to setup a new to draw into * that is not the screen HDC. When we do this, we explicitely mark * the DC with DCX_REDIRECTED. * * In the case of CS_CLASSDC or CS_PARENTDC, that DC may be shared * between a redirected window and a non-redirected window, causing a * conflict. * * This is not a problem for CS_OWNDC, since the window has its own * HDC that will not be shared. It does however require that we setup * redirection after this HDC is already built. This behavior was * changed in Whistler (NT 5.1). */
pcls = pwnd->pcls; if (TestCF2(pcls, CFPARENTDC) || TestCF2(pcls, CFCLASSDC)) { RIPMSG0(RIP_WARNING, "Cannot enable redirection on CS_PARENTDC, or CS_CLASSDC window"); return FALSE; }
if ((hbmNew = CreateRedirectionBitmap(pwnd)) == NULL) { return FALSE; }
ConvertRedirectionDCs(pwnd, hbmNew); }
prdr = _GetProp(pwnd, PROP_LAYER, TRUE); prdr->uFlags |= uFlags;
#if DBG
prdr->pwnd = pwnd; #endif
return TRUE; }
/***************************************************************************\
* UnsetRedirectedWindow * * 1/27/1999 vadimg created \***************************************************************************/ VOID UnsetRedirectedWindow( PWND pwnd, UINT uFlags) { if (TestWF(pwnd, WEFPREDIRECTED)) { PREDIRECT prdr = _GetProp(pwnd, PROP_LAYER, TRUE);
prdr->uFlags &= ~uFlags;
if (prdr->uFlags != 0) { return; }
RemoveRedirectionBitmap(pwnd); } }
#ifdef CHILD_LAYERING
/***************************************************************************\
* GetNextLayeredWindow * * Preorder traversal of the window tree to find the next layering window * below in zorder than pwnd. We need this because sprites are stored in a * linked list. Note that this algorithm is iterative which is cool! \***************************************************************************/ PWND GetNextLayeredWindow( PWND pwnd) { while (TRUE) { if (pwnd->spwndChild != NULL) { pwnd = pwnd->spwndChild; } else if (pwnd->spwndNext != NULL) { pwnd = pwnd->spwndNext; } else {
do { pwnd = pwnd->spwndParent;
if (pwnd == NULL) { return NULL; }
} while (pwnd->spwndNext == NULL);
pwnd = pwnd->spwndNext; }
if (TestWF(pwnd, WEFLAYERED)) { return pwnd; } } } #endif
/***************************************************************************\
* GetStyleWindow * \***************************************************************************/ PWND GetStyleWindow( PWND pwnd, DWORD dwStyle) { while (pwnd != NULL) { if (TestWF(pwnd, dwStyle)) { break; }
pwnd = pwnd->spwndParent; }
return pwnd; }
/***************************************************************************\
* TrackLayeredZorder * * Unlike USER, GDI stores sprites from bottom to top. \***************************************************************************/ VOID TrackLayeredZorder( PWND pwnd) { #ifdef CHILD_LAYERING
PWND pwndT = GetNextLayeredWindow(pwnd);
#else
PWND pwndT = pwnd->spwndNext;
while (pwndT != NULL) { if (TestWF(pwndT, WEFLAYERED)) { break; }
pwndT = pwndT->spwndNext; }
#endif
GreZorderSprite(gpDispInfo->hDev, PtoHq(pwnd), PtoH(pwndT)); }
/***************************************************************************\
* GetRedirectionBitmap * \***************************************************************************/ HBITMAP GetRedirectionBitmap( PWND pwnd) { PREDIRECT prdr = _GetProp(pwnd, PROP_LAYER, TRUE);
if (prdr != NULL) { return prdr->hbm; }
return NULL; }
/***************************************************************************\
* SetRedirectionBitmap * \***************************************************************************/ BOOL SetRedirectionBitmap( PWND pwnd, HBITMAP hbm) { PREDIRECT prdr;
if (hbm == NULL) { prdr = (PREDIRECT)InternalRemoveProp(pwnd, PROP_LAYER, TRUE); if (prdr != NULL) { UserFreePool(prdr); } } else { prdr = _GetProp(pwnd, PROP_LAYER, TRUE); if (prdr == NULL) { if ((prdr = (PREDIRECT)UserAllocPool(sizeof(REDIRECT), TAG_REDIRECT)) == NULL) { return FALSE; }
if (!InternalSetProp(pwnd, PROP_LAYER, (HANDLE)prdr, PROPF_INTERNAL)) { UserFreePool(prdr); return FALSE; } } else { DeleteMaybeSpecialRgn(prdr->hrgnComp); }
prdr->hbm = hbm; prdr->uFlags = 0; prdr->hrgnComp = NULL; SetRectEmpty(&prdr->rcUpdate); }
return TRUE; }
#ifdef MOUSE_IP
CONST RECT grcSonar = {0, 0, MOUSE_SONAR_RADIUS_INIT * 2, MOUSE_SONAR_RADIUS_INIT * 2};
VOID DrawSonar( HDC hdc) { HBRUSH hbrBackground; HBRUSH hbrRing, hbrOld; HPEN hpen, hpenOld;
hbrBackground = GreCreateSolidBrush(COLORKEY_COLOR); if (hbrBackground == NULL) { RIPMSG0(RIP_WARNING, "DrawSonar: failed to create background brush."); return; } FillRect(hdc, &grcSonar, hbrBackground);
/*
* Pen for the edges. */ hpen = GreCreatePen(PS_SOLID, 0, RGB(255, 255, 255), NULL); if (hpen == NULL) { RIPMSG0(RIP_WARNING, "DrawSonar: failed to create pen."); goto return1; } hpenOld = GreSelectPen(hdc, hpen);
/*
* Draw the ring. */ hbrRing = GreCreateSolidBrush(RGB(128, 128, 128)); if (hbrRing == NULL) { goto return2; } hbrOld = GreSelectBrush(hdc, hbrRing);
NtGdiEllipse(hdc, MOUSE_SONAR_RADIUS_INIT - giSonarRadius, MOUSE_SONAR_RADIUS_INIT - giSonarRadius, MOUSE_SONAR_RADIUS_INIT + giSonarRadius, MOUSE_SONAR_RADIUS_INIT + giSonarRadius);
/*
* Draw innter hollow area (this draws inner edge as well). */ GreSelectBrush(hdc, hbrBackground); NtGdiEllipse(hdc, MOUSE_SONAR_RADIUS_INIT - giSonarRadius + MOUSE_SONAR_LINE_WIDTH, MOUSE_SONAR_RADIUS_INIT - giSonarRadius + MOUSE_SONAR_LINE_WIDTH, MOUSE_SONAR_RADIUS_INIT + giSonarRadius - MOUSE_SONAR_LINE_WIDTH, MOUSE_SONAR_RADIUS_INIT + giSonarRadius - MOUSE_SONAR_LINE_WIDTH);
/*
* Clean up things. */ GreSelectBrush(hdc, hbrOld); UserAssert(hbrRing); GreDeleteObject(hbrRing); return2: GreSelectPen(hdc, hpenOld); if (hpen) { GreDeleteObject(hpen); }
return1: if (hbrBackground) { GreDeleteObject(hbrBackground); } }
/***************************************************************************\
* SonarAction * \***************************************************************************/ BOOL StartSonar( VOID) { HDC hdc; RECT rc;
UserAssert(TestUP(MOUSESONAR));
gptSonarCenter = gpsi->ptCursor;
/*
* LATER: Is this the right thing? */ if (gfade.dwFlags) { /*
* Some other animation is going on. * Stop it first. */ UserAssert(!TestFadeFlags(FADE_SONAR)); StopSonar(); UserAssert(gfade.dwFlags == 0); }
rc.left = gptSonarCenter.x - MOUSE_SONAR_RADIUS_INIT; rc.right = gptSonarCenter.x + MOUSE_SONAR_RADIUS_INIT; rc.top = gptSonarCenter.y - MOUSE_SONAR_RADIUS_INIT; rc.bottom = gptSonarCenter.y + MOUSE_SONAR_RADIUS_INIT;
giSonarRadius = MOUSE_SONAR_RADIUS_INIT;
hdc = CreateFade(NULL, &rc, CMS_SONARTIMEOUT, FADE_SONAR | FADE_COLORKEY); if (hdc == NULL) { RIPMSG0(RIP_WARNING, "StartSonar: failed to create a new sonar."); return FALSE; }
/*
* Start sonar animation. */ DrawSonar(hdc); StartFade(); AnimateFade();
return TRUE; }
VOID StopSonar( VOID) { UserAssert(TestUP(MOUSESONAR));
StopFade(); giSonarRadius = -1; }
#endif // MOUSE_IP
/***************************************************************************\
* GetRedirectionFlags * * GetRedirectionFlags returns the current redirection flags for a given * window. * * 2/8/2000 JStall created \***************************************************************************/ UINT GetRedirectionFlags( PWND pwnd) { PREDIRECT prdr = _GetProp(pwnd, PROP_LAYER, TRUE); if (prdr != NULL) { return prdr->uFlags; }
return 0; }
/***************************************************************************\
* xxxPrintWindow * * xxxPrintWindow uses redirection to get a complete bitmap of a window. If * the window already has a redirection bitmap, the bits will be directly * copied. If the window doesn't have a redirection bitmap, it will be * temporarily redirected, forcibly redrawn, and then returned to its * previous state. * * 2/8/2000 JStall created \***************************************************************************/ BOOL xxxPrintWindow( PWND pwnd, HDC hdcBlt, UINT nFlags) { HDC hdcSrc; SIZE sizeBmpPxl; POINT ptOffsetPxl; BOOL fTempRedir; BOOL fSuccess;
CheckLock(pwnd);
/*
* Determine the area of the window to copy. */ if ((nFlags & PW_CLIENTONLY) != 0) { /*
* Only get the client area */ ptOffsetPxl.x = pwnd->rcWindow.left - pwnd->rcClient.left; ptOffsetPxl.y = pwnd->rcWindow.top - pwnd->rcClient.top; sizeBmpPxl.cx = pwnd->rcClient.right - pwnd->rcClient.left; sizeBmpPxl.cy = pwnd->rcClient.bottom - pwnd->rcClient.top; } else { /*
* Return the entire window */ ptOffsetPxl.x = 0; ptOffsetPxl.y = 0; sizeBmpPxl.cx = pwnd->rcWindow.right - pwnd->rcWindow.left; sizeBmpPxl.cy = pwnd->rcWindow.bottom - pwnd->rcWindow.top; }
/*
* Redirect the window so that we can get the bits. Since this flag never * is turned on outside this function call, always safe to turn it on here. */ fTempRedir = (GetRedirectionFlags(pwnd) == 0);
if (!SetRedirectedWindow(pwnd, REDIRECT_PRINT)) { /*
* Unable to redirect the window, so can't get the bits. */
fSuccess = FALSE; goto Done; } else { fSuccess = TRUE; }
if (fTempRedir) { xxxUpdateWindow(pwnd); }
hdcSrc = _GetDCEx(pwnd, NULL, DCX_WINDOW | DCX_CACHE); GreBitBlt(hdcBlt, 0, 0, sizeBmpPxl.cx, sizeBmpPxl.cy, hdcSrc, ptOffsetPxl.x, ptOffsetPxl.y, SRCCOPY | NOMIRRORBITMAP, 0); _ReleaseDC(hdcSrc);
/*
* Cleanup */ UnsetRedirectedWindow(pwnd, REDIRECT_PRINT);
Done: return fSuccess; }
/***************************************************************************\
* xxxEnumTurnOffCompositing * * xxxEnumTurnOffCompositing() is called for each window, giving an * opportunity to turn off WS_EX_COMPOSITED for that window. * * 8/21/2000 JStall created \***************************************************************************/
BOOL APIENTRY xxxEnumTurnOffCompositing(PWND pwnd, LPARAM lParam) { CheckLock(pwnd);
UNREFERENCED_PARAMETER(lParam);
if (TestWF(pwnd, WEFCOMPOSITED)) { DWORD dwStyle = (pwnd->ExStyle & ~WS_EX_COMPOSITED) & WS_EX_ALLVALID; xxxSetWindowStyle(pwnd, GWL_EXSTYLE, dwStyle); }
return TRUE; }
/***************************************************************************\
* xxxTurnOffCompositing * * xxxTurnOffCompositing() turns off WS_EX_COMPOSITED for (optionally a * PWND and) its children. This is used when reparenting under * a parent-chain that has WS_EX_COMPOSITED already turned on. If we don't * turn off WS_EX_COMPOSITED for the children, it takes extra bitmaps and the * compositing will not properly work. * * 8/21/2000 JStall created \***************************************************************************/ VOID xxxTurnOffCompositing( PWND pwndStart, BOOL fChild) { TL tlpwnd; UINT nFlags = BWL_ENUMCHILDREN;
CheckLock(pwndStart);
/*
* If they want to skip over the wnd itself and start with this WND's * child, we need to get and lock that child. We will unlock it when * finished. We also need to mark BWL_ENUMLIST so that we will enumerate * all of the children. */ if (fChild) { pwndStart = pwndStart->spwndChild; if (pwndStart == NULL) { return; } nFlags |= BWL_ENUMLIST;
ThreadLockAlways(pwndStart, &tlpwnd); }
/*
* Enumerate the windows. */ xxxInternalEnumWindow(pwndStart, xxxEnumTurnOffCompositing, 0, nFlags);
if (fChild) { ThreadUnlock(&tlpwnd); } }
|