- Slap *a bit* of sense in the way we use region objects and handles, avoiding a massive orgy of handle allocations, locks, leaks and so on.
The motto here being "if you don't need a valid user-mode handle, then chances are that you don't need one at all."
CORE-8506 #resolve #comment Stale region handles should not be passed anymore to user-mode apps now.

svn path=/trunk/; revision=64177
This commit is contained in:
Jérôme Gardou 2014-09-17 09:54:27 +00:00
parent 726e4806e9
commit 215e0d90a1
18 changed files with 600 additions and 508 deletions

View file

@ -52,41 +52,31 @@ IntEngWndUpdateClipObj(
XCLIPOBJ* Clip,
PWND Window)
{
HRGN hVisRgn;
PROSRGNDATA visRgn;
TRACE("IntEngWndUpdateClipObj\n");
hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
if (hVisRgn != NULL)
visRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE);
if (visRgn != NULL)
{
visRgn = RGNOBJAPI_Lock(hVisRgn, NULL);
if (visRgn != NULL)
if (visRgn->rdh.nCount > 0)
{
if (visRgn->rdh.nCount > 0)
IntEngUpdateClipRegion(Clip, visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound);
TRACE("Created visible region with %lu rects\n", visRgn->rdh.nCount);
TRACE(" BoundingRect: %d, %d %d, %d\n",
visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
{
IntEngUpdateClipRegion(Clip, visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound);
TRACE("Created visible region with %lu rects\n", visRgn->rdh.nCount);
TRACE(" BoundingRect: %d, %d %d, %d\n",
visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top,
visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom);
ULONG i;
for (i = 0; i < visRgn->rdh.nCount; i++)
{
ULONG i;
for (i = 0; i < visRgn->rdh.nCount; i++)
{
TRACE(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1,
visRgn->Buffer[i].left, visRgn->Buffer[i].top,
visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
}
TRACE(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1,
visRgn->Buffer[i].left, visRgn->Buffer[i].top,
visRgn->Buffer[i].right, visRgn->Buffer[i].bottom);
}
}
RGNOBJAPI_Unlock(visRgn);
}
else
{
WARN("Couldn't lock visible region of window DC\n");
}
GreDeleteObject(hVisRgn);
REGION_Delete(visRgn);
}
else
{

View file

@ -477,7 +477,7 @@ NtGdiSelectClipPath(
HDC hDC,
int Mode)
{
HRGN hrgnPath;
PREGION RgnPath;
PPATH pPath;
BOOL success = FALSE;
PDC_ATTR pdcattr;
@ -507,21 +507,31 @@ NtGdiSelectClipPath(
}
/* Construct a region from the path */
else if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnPath))
RgnPath = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!RgnPath)
{
PREGION prgnPath = REGION_LockRgn(hrgnPath);
ASSERT(prgnPath);
success = IntGdiExtSelectClipRgn(pdc, prgnPath, Mode) != ERROR;
REGION_UnlockRgn(prgnPath);
GreDeleteObject( hrgnPath );
/* Empty the path */
if (success)
PATH_EmptyPath(pPath);
/* FIXME: Should this function delete the path even if it failed? */
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
DC_UnlockDc(pdc);
return FALSE;
}
if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, RgnPath))
{
EngSetLastError(ERROR_CAN_NOT_COMPLETE);
REGION_Delete(RgnPath);
DC_UnlockDc(pdc);
return FALSE;
}
success = IntGdiExtSelectClipRgn(pdc, RgnPath, Mode) != ERROR;
REGION_Delete(RgnPath);
/* Empty the path */
if (success)
PATH_EmptyPath(pPath);
/* FIXME: Should this function delete the path even if it failed? */
PATH_UnlockPath(pPath);
DC_UnlockDc(pdc);

View file

@ -458,8 +458,24 @@ NtGdiPolyPolyDraw( IN HDC hDC,
/* Special handling for GdiPolyPolyRgn */
if (iFunc == GdiPolyPolyRgn)
{
PREGION Rgn;
HRGN hRgn;
hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC);
Rgn = REGION_AllocUserRgnWithHandle(0);
if (!Rgn)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
ExFreePoolWithTag(pTemp, TAG_SHAPE);
return 0;
}
hRgn = Rgn->BaseObject.hHmgr;
if (!IntSetPolyPolygonRgn(SafePoints, SafeCounts, Count, hDC ? 1 : 2, Rgn))
{
/* EngSetLastError ? */
GreDeleteObject(hRgn);
hRgn = NULL;
}
RGNOBJAPI_Unlock(Rgn);
ExFreePoolWithTag(pTemp, TAG_SHAPE);
return (ULONG_PTR)hRgn;
}

View file

@ -98,7 +98,7 @@ PATH_FillPath(
//SIZE ptViewportExt, ptWindowExt;
//POINTL ptViewportOrg, ptWindowOrg;
XFORM xform;
HRGN hrgn;
PREGION Rgn;
PDC_ATTR pdcattr = dc->pdcattr;
if (pPath->state != PATH_Closed)
@ -107,61 +107,72 @@ PATH_FillPath(
return FALSE;
}
if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgn))
/* Allocate a temporary region */
Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!Rgn)
{
/* Since PaintRgn interprets the region as being in logical coordinates
* but the points we store for the path are already in device
* coordinates, we have to set the mapping mode to MM_TEXT temporarily.
* Using SaveDC to save information about the mapping mode / world
* transform would be easier but would require more overhead, especially
* now that SaveDC saves the current path.
*/
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Save the information about the old mapping mode */
//mapMode = pdcattr->iMapMode;
//ptViewportExt = pdcattr->szlViewportExt;
//ptViewportOrg = pdcattr->ptlViewportOrg;
//ptWindowExt = pdcattr->szlWindowExt;
//ptWindowOrg = pdcattr->ptlWindowOrg;
if (!PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
{
/* EngSetLastError ? */
REGION_Delete(Rgn);
return FALSE;
}
/* Save world transform
* NB: The Windows documentation on world transforms would lead one to
* believe that this has to be done only in GM_ADVANCED; however, my
* tests show that resetting the graphics mode to GM_COMPATIBLE does
* not reset the world transform.
*/
MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
/* Since PaintRgn interprets the region as being in logical coordinates
* but the points we store for the path are already in device
* coordinates, we have to set the mapping mode to MM_TEXT temporarily.
* Using SaveDC to save information about the mapping mode / world
* transform would be easier but would require more overhead, especially
* now that SaveDC saves the current path.
*/
/* Set MM_TEXT */
/* Save the information about the old mapping mode */
//mapMode = pdcattr->iMapMode;
//ptViewportExt = pdcattr->szlViewportExt;
//ptViewportOrg = pdcattr->ptlViewportOrg;
//ptWindowExt = pdcattr->szlWindowExt;
//ptWindowOrg = pdcattr->ptlWindowOrg;
/* Save world transform
* NB: The Windows documentation on world transforms would lead one to
* believe that this has to be done only in GM_ADVANCED; however, my
* tests show that resetting the graphics mode to GM_COMPATIBLE does
* not reset the world transform.
*/
MatrixS2XForm(&xform, &dc->pdcattr->mxWorldToPage);
/* Set MM_TEXT */
// IntGdiSetMapMode(dc, MM_TEXT);
// pdcattr->ptlViewportOrg.x = 0;
// pdcattr->ptlViewportOrg.y = 0;
// pdcattr->ptlWindowOrg.x = 0;
// pdcattr->ptlWindowOrg.y = 0;
// graphicsMode = pdcattr->iGraphicsMode;
// graphicsMode = pdcattr->iGraphicsMode;
// pdcattr->iGraphicsMode = GM_ADVANCED;
// IntGdiModifyWorldTransform(dc, &xform, MWT_IDENTITY);
// pdcattr->iGraphicsMode = graphicsMode;
/* Paint the region */
IntGdiPaintRgn(dc, hrgn);
GreDeleteObject(hrgn);
/* Restore the old mapping mode */
/* Paint the region */
IntGdiPaintRgn(dc, Rgn);
REGION_Delete(Rgn);
/* Restore the old mapping mode */
// IntGdiSetMapMode(dc, mapMode);
// pdcattr->szlViewportExt = ptViewportExt;
// pdcattr->ptlViewportOrg = ptViewportOrg;
// pdcattr->szlWindowExt = ptWindowExt;
// pdcattr->ptlWindowOrg = ptWindowOrg;
/* Go to GM_ADVANCED temporarily to restore the world transform */
//graphicsMode = pdcattr->iGraphicsMode;
/* Go to GM_ADVANCED temporarily to restore the world transform */
//graphicsMode = pdcattr->iGraphicsMode;
// pdcattr->iGraphicsMode = GM_ADVANCED;
// IntGdiModifyWorldTransform(dc, &xform, MWT_MAX+1);
// pdcattr->iGraphicsMode = graphicsMode;
return TRUE;
}
return FALSE;
return TRUE;
}
/* PATH_InitGdiPath
@ -1221,14 +1232,14 @@ FASTCALL
PATH_PathToRegion(
PPATH pPath,
INT nPolyFillMode,
HRGN *pHrgn)
PREGION Rgn)
{
int numStrokes, iStroke, i;
PULONG pNumPointsInStroke;
HRGN hrgn = 0;
BOOL Ret;
ASSERT(pPath != NULL);
ASSERT(pHrgn != NULL);
ASSERT(Rgn != NULL);
PATH_FlattenPath(pPath);
@ -1268,23 +1279,18 @@ PATH_PathToRegion(
pNumPointsInStroke[iStroke]++;
}
/* Create a region from the strokes */
hrgn = IntCreatePolyPolygonRgn(pPath->pPoints,
pNumPointsInStroke,
numStrokes,
nPolyFillMode);
if (hrgn == (HRGN)0)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
/* Fill the region with the strokes */
Ret = IntSetPolyPolygonRgn(pPath->pPoints,
pNumPointsInStroke,
numStrokes,
nPolyFillMode,
Rgn);
/* Free memory for number-of-points-in-stroke array */
ExFreePoolWithTag(pNumPointsInStroke, TAG_PATH);
/* Success! */
*pHrgn = hrgn;
return TRUE;
return Ret;
}
/* PATH_EmptyPath
@ -2675,6 +2681,7 @@ NtGdiPathToRegion(HDC hDC)
{
PPATH pPath;
HRGN hrgnRval = 0;
PREGION Rgn;
DC *pDc;
PDC_ATTR pdcattr;
@ -2703,9 +2710,25 @@ NtGdiPathToRegion(HDC hDC)
}
else
{
/* Create the region and fill it with the path strokes */
Rgn = REGION_AllocUserRgnWithHandle(1);
if (!Rgn)
{
PATH_UnlockPath(pPath);
DC_UnlockDc(pDc);
}
hrgnRval = Rgn->BaseObject.hHmgr;
/* FIXME: Should we empty the path even if conversion failed? */
if (PATH_PathToRegion(pPath, pdcattr->jFillMode, &hrgnRval))
if (PATH_PathToRegion(pPath, pdcattr->jFillMode, Rgn))
{
PATH_EmptyPath(pPath);
}
else
{
GreDeleteObject(hrgnRval);
hrgnRval = NULL;
}
RGNOBJAPI_Unlock(Rgn);
}
PATH_UnlockPath(pPath);

View file

@ -67,7 +67,7 @@ BOOL FASTCALL PATH_PolyPolygon ( PDC dc, const POINT* pts, const INT* counts, UI
BOOL FASTCALL PATH_PolyPolyline( PDC dc, const POINT* pts, const DWORD* counts, DWORD polylines);
BOOL FASTCALL PATH_Rectangle (PDC dc, INT x1, INT y1, INT x2, INT y2);
BOOL FASTCALL PATH_RoundRect(DC *dc, INT x1, INT y1, INT x2, INT y2, INT ell_width, INT ell_height);
BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, HRGN *pHrgn);
BOOL FASTCALL PATH_PathToRegion (PPATH pPath, INT nPolyFillMode, PREGION Rgn);
BOOL FASTCALL PATH_ExtTextOut(PDC dc,INT x,INT y,UINT flags,const RECTL *lprc,LPCWSTR str,UINT count,const INT *dx);
BOOL FASTCALL PATH_AddEntry (PPATH pPath, const POINT *pPoint, BYTE flags);

View file

@ -1956,46 +1956,35 @@ REGION_CreateFrameRgn(
}
static
BOOL FASTCALL
REGION_LPTODP(
PDC dc,
HRGN hDest,
HRGN hSrc)
_In_ PDC dc,
_Inout_ PREGION RgnDest,
_In_ PREGION RgnSrc)
{
RECTL *pCurRect, *pEndRect;
PROSRGNDATA srcObj = NULL;
PROSRGNDATA destObj = NULL;
RECTL tmpRect;
BOOL ret = FALSE;
PDC_ATTR pdcattr;
if (!dc)
return ret;
return FALSE;
pdcattr = dc->pdcattr;
if (pdcattr->iMapMode == MM_TEXT) // Requires only a translation
{
if (NtGdiCombineRgn(hDest, hSrc, 0, RGN_COPY) == ERROR)
goto done;
if (IntGdiCombineRgn(RgnDest, RgnSrc, 0, RGN_COPY) == ERROR)
return FALSE;
NtGdiOffsetRgn(hDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x,
IntGdiOffsetRgn(RgnDest, pdcattr->ptlViewportOrg.x - pdcattr->ptlWindowOrg.x,
pdcattr->ptlViewportOrg.y - pdcattr->ptlWindowOrg.y);
ret = TRUE;
goto done;
return TRUE;
}
if ( !(srcObj = RGNOBJAPI_Lock(hSrc, NULL)) )
goto done;
if ( !(destObj = RGNOBJAPI_Lock(hDest, NULL)) )
{
RGNOBJAPI_Unlock(srcObj);
goto done;
}
EMPTY_REGION(destObj);
EMPTY_REGION(RgnDest);
pEndRect = srcObj->Buffer + srcObj->rdh.nCount;
for (pCurRect = srcObj->Buffer; pCurRect < pEndRect; pCurRect++)
pEndRect = RgnSrc->Buffer + RgnSrc->rdh.nCount;
for (pCurRect = RgnSrc->Buffer; pCurRect < pEndRect; pCurRect++)
{
tmpRect = *pCurRect;
tmpRect.left = XLPTODP(pdcattr, tmpRect.left);
@ -2016,15 +2005,10 @@ REGION_LPTODP(
tmpRect.bottom = tmp;
}
REGION_UnionRectWithRgn(destObj, &tmpRect);
REGION_UnionRectWithRgn(RgnDest, &tmpRect);
}
ret = TRUE;
RGNOBJAPI_Unlock(srcObj);
RGNOBJAPI_Unlock(destObj);
done:
return ret;
return TRUE;
}
PROSRGNDATA
@ -2236,7 +2220,7 @@ IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
PREGION prgn;
/* Allocate a region, witout a handle */
prgn = (PREGION)GDIOBJ_AllocateObject(GDIObjType_RGN_TYPE, sizeof(REGION), 0);
prgn = (PREGION)GDIOBJ_AllocateObject(GDIObjType_RGN_TYPE, sizeof(REGION), BASEFLAG_LOOKASIDE);
if (!prgn)
{
return NULL;
@ -2250,31 +2234,6 @@ IntSysCreateRectpRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
return prgn;
}
HRGN
FASTCALL
IntSysCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
{
PREGION prgn;
HRGN hrgn;
/* Allocate a region, witout a handle */
prgn = (PREGION)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_REGION, sizeof(REGION));
if (!prgn)
{
return NULL;
}
/* Initialize it */
prgn->Buffer = &prgn->rdh.rcBound;
REGION_SetRectRgn(prgn, LeftRect, TopRect, RightRect, BottomRect);
hrgn = prgn->BaseObject.hHmgr;
prgn->prgnattr = &prgn->rgnattr;
REGION_UnlockRgn(prgn);
return hrgn;
}
VOID NTAPI
REGION_vCleanup(PVOID ObjectBody)
{
@ -2479,44 +2438,42 @@ BOOL
FASTCALL
IntGdiPaintRgn(
PDC dc,
HRGN hRgn
PREGION Rgn
)
{
HRGN tmpVisRgn;
PROSRGNDATA visrgn;
PROSRGNDATA VisRgn;
XCLIPOBJ ClipRegion;
BOOL bRet = FALSE;
POINTL BrushOrigin;
SURFACE *psurf;
PDC_ATTR pdcattr;
if (!dc) return FALSE;
if (!dc || !Rgn)
return FALSE;
pdcattr = dc->pdcattr;
ASSERT(!(pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)));
if (!(tmpVisRgn = IntSysCreateRectRgn(0, 0, 0, 0))) return FALSE;
// Transform region into device co-ords
if (!REGION_LPTODP(dc, tmpVisRgn, hRgn) ||
NtGdiOffsetRgn(tmpVisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
VisRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!VisRgn)
{
GreDeleteObject(tmpVisRgn);
return FALSE;
}
visrgn = RGNOBJAPI_Lock(tmpVisRgn, NULL);
if (visrgn == NULL)
// Transform region into device co-ords
if (!REGION_LPTODP(dc, VisRgn, Rgn) ||
IntGdiOffsetRgn(VisRgn, dc->ptlDCOrig.x, dc->ptlDCOrig.y) == ERROR)
{
GreDeleteObject(tmpVisRgn);
REGION_Delete(VisRgn);
return FALSE;
}
if (dc->prgnRao)
IntGdiCombineRgn(visrgn, visrgn, dc->prgnRao, RGN_AND);
IntGdiCombineRgn(VisRgn, VisRgn, dc->prgnRao, RGN_AND);
IntEngInitClipObj(&ClipRegion);
IntEngUpdateClipRegion(&ClipRegion, visrgn->rdh.nCount, visrgn->Buffer, &visrgn->rdh.rcBound );
IntEngUpdateClipRegion(&ClipRegion, VisRgn->rdh.nCount, VisRgn->Buffer, &VisRgn->rdh.rcBound );
BrushOrigin.x = pdcattr->ptlBrushOrigin.x;
BrushOrigin.y = pdcattr->ptlBrushOrigin.y;
@ -2529,8 +2486,7 @@ IntGdiPaintRgn(
&BrushOrigin,
0xFFFF); // FIXME: Don't know what to put here
RGNOBJAPI_Unlock(visrgn);
GreDeleteObject(tmpVisRgn);
REGION_Delete(VisRgn);
IntEngFreeClipResources(&ClipRegion);
// Fill the region
@ -3129,16 +3085,15 @@ REGION_CreateETandAET(
}
}
HRGN FASTCALL
IntCreatePolyPolygonRgn(
BOOL FASTCALL
IntSetPolyPolygonRgn(
POINT *Pts,
PULONG Count,
INT nbpolygons,
INT mode
INT mode,
PREGION Rgn
)
{
HRGN hrgn;
ROSRGNDATA *region;
EdgeTableEntry *pAET; /* Active Edge Table */
INT y; /* Current scanline */
int iPts = 0; /* Number of pts in buffer */
@ -3158,10 +3113,6 @@ IntCreatePolyPolygonRgn(
if (mode == 0 || mode > 2) return 0;
if (!(region = REGION_AllocUserRgnWithHandle(nbpolygons)))
return 0;
hrgn = region->BaseObject.hHmgr;
/* Special case a rectangle */
if (((nbpolygons == 1) && ((*Count == 4) ||
@ -3175,18 +3126,19 @@ IntCreatePolyPolygonRgn(
(Pts[2].x == Pts[3].x) &&
(Pts[3].y == Pts[0].y))))
{
RGNOBJAPI_Unlock(region);
NtGdiSetRectRgn(hrgn, min(Pts[0].x, Pts[2].x), min(Pts[0].y, Pts[2].y),
max(Pts[0].x, Pts[2].x), max(Pts[0].y, Pts[2].y));
return hrgn;
REGION_SetRectRgn(Rgn,
min(Pts[0].x, Pts[2].x),
min(Pts[0].y, Pts[2].y),
max(Pts[0].x, Pts[2].x),
max(Pts[0].y, Pts[2].y));
return TRUE;
}
for (poly = total = 0; poly < nbpolygons; poly++)
total += Count[poly];
if (! (pETEs = ExAllocatePoolWithTag(PagedPool, sizeof(EdgeTableEntry) * total, TAG_REGION)) )
{
GreDeleteObject(hrgn);
return 0;
return FALSE;
}
pts = FirstPtBlock.pts;
REGION_CreateETandAET(Count, nbpolygons, Pts, &ET, &AET, pETEs, &SLLBlock);
@ -3230,7 +3182,7 @@ IntCreatePolyPolygonRgn(
{
DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION);
return 0;
return FALSE;
}
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
@ -3289,8 +3241,7 @@ IntCreatePolyPolygonRgn(
{
DPRINT1("Can't alloc tPB\n");
ExFreePoolWithTag(pETEs, TAG_REGION);
GreDeleteObject(hrgn);
return 0;
return FALSE;
}
curPtBlock->next = tmpPtBlock;
curPtBlock = tmpPtBlock;
@ -3315,7 +3266,7 @@ IntCreatePolyPolygonRgn(
}
}
REGION_FreeStorage(SLLBlock.next);
REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, Rgn);
for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;)
{
@ -3324,8 +3275,7 @@ IntCreatePolyPolygonRgn(
curPtBlock = tmpPtBlock;
}
ExFreePoolWithTag(pETEs, TAG_REGION);
RGNOBJAPI_Unlock(region);
return hrgn;
return TRUE;
}
BOOL
@ -3432,6 +3382,8 @@ NtGdiCreateRectRgn(INT LeftRect, INT TopRect, INT RightRect, INT BottomRect)
REGION_SetRectRgn(pRgn, LeftRect, TopRect, RightRect, BottomRect);
RGNOBJAPI_Unlock(pRgn);
DPRINT1("Returning %p.\n", hRgn);
return hRgn;
}
@ -3762,7 +3714,7 @@ NtGdiFrameRgn(
HRGN FrameRgn;
BOOL Ret;
if (!(FrameRgn = IntSysCreateRectRgn(0, 0, 0, 0)))
if (!(FrameRgn = NtGdiCreateRectRgn(0, 0, 0, 0)))
{
return FALSE;
}

View file

@ -40,8 +40,8 @@ VOID FASTCALL IntGdiReleaseRaoRgn(PDC);
VOID FASTCALL IntGdiReleaseVisRgn(PDC);
INT APIENTRY IntGdiGetRgnBox(HRGN, RECTL*);
BOOL FASTCALL IntGdiPaintRgn(PDC, HRGN );
HRGN FASTCALL IntCreatePolyPolygonRgn(PPOINT, PULONG, INT, INT);
BOOL FASTCALL IntGdiPaintRgn(PDC, PREGION );
BOOL FASTCALL IntSetPolyPolygonRgn(PPOINT, PULONG, INT, INT, PREGION);
INT FASTCALL IntGdiOffsetRgn(PROSRGNDATA,INT,INT);
BOOL FASTCALL IntRectInRegion(HRGN,LPRECTL);
@ -49,13 +49,9 @@ INT FASTCALL IntGdiCombineRgn(PROSRGNDATA, PROSRGNDATA, PROSRGNDATA, INT);
INT FASTCALL REGION_Complexity(PROSRGNDATA);
PROSRGNDATA FASTCALL RGNOBJAPI_Lock(HRGN,PRGN_ATTR *);
VOID FASTCALL RGNOBJAPI_Unlock(PROSRGNDATA);
HRGN FASTCALL IntSysCreateRectRgn(INT,INT,INT,INT);
PROSRGNDATA FASTCALL IntSysCreateRectpRgn(INT,INT,INT,INT);
BOOL FASTCALL IntGdiSetRegionOwner(HRGN,DWORD);
#define IntSysCreateRectRgnIndirect(prc) \
IntSysCreateRectRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)
#define IntSysCreateRectpRgnIndirect(prc) \
IntSysCreateRectpRgn((prc)->left, (prc)->top, (prc)->right, (prc)->bottom)

View file

@ -1010,16 +1010,20 @@ IntDefWindowProc(
case WM_SYNCPAINT:
{
HRGN hRgn;
PREGION Rgn;
Wnd->state &= ~WNDS_SYNCPAINTPENDING;
ERR("WM_SYNCPAINT\n");
hRgn = IntSysCreateRectRgn(0, 0, 0, 0);
if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION)
Rgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (Rgn)
{
if (!wParam) wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
co_UserRedrawWindow(Wnd, NULL, hRgn, wParam);
if (co_UserGetUpdateRgn(Wnd, Rgn, FALSE) != NULLREGION)
{
if (!wParam)
wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
co_UserRedrawWindow(Wnd, NULL, Rgn, wParam);
}
REGION_Delete(Rgn);
}
GreDeleteObject(hRgn);
return 0;
}

View file

@ -752,19 +752,19 @@ VOID APIENTRY
UserRedrawDesktop()
{
PWND Window = NULL;
HRGN hRgn;
PREGION Rgn;
Window = UserGetDesktopWindow();
hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow);
Rgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
IntInvalidateWindows( Window,
hRgn,
Rgn,
RDW_FRAME |
RDW_ERASE |
RDW_INVALIDATE |
RDW_ALLCHILDREN);
GreDeleteObject(hRgn);
REGION_Delete(Rgn);
}

View file

@ -652,7 +652,6 @@ IntDispatchMessage(PMSG pMsg)
LRESULT retval = 0;
PTHREADINFO pti;
PWND Window = NULL;
HRGN hrgn;
BOOL DoCallBack = TRUE;
if (pMsg->hwnd)
@ -743,11 +742,12 @@ IntDispatchMessage(PMSG pMsg)
if (pMsg->message == WM_PAINT)
{
PREGION Rgn;
Window->state2 &= ~WNDS2_WMPAINTSENT;
/* send a WM_NCPAINT and WM_ERASEBKGND if the non-client area is still invalid */
hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
co_UserGetUpdateRgn( Window, hrgn, TRUE );
GreDeleteObject(hrgn);
Rgn = IntSysCreateRectpRgn( 0, 0, 0, 0 );
co_UserGetUpdateRgn( Window, Rgn, TRUE );
REGION_Delete(Rgn);
}
return retval;

View file

@ -258,7 +258,11 @@ UserUpdateMonitorSize(IN HDEV hDev)
}
/* ...and create new one */
pMonitor->hrgnMonitor = IntSysCreateRectRgnIndirect(&pMonitor->rcMonitor);
pMonitor->hrgnMonitor = NtGdiCreateRectRgn(
pMonitor->rcMonitor.left,
pMonitor->rcMonitor.top,
pMonitor->rcMonitor.right,
pMonitor->rcMonitor.bottom);
if (pMonitor->hrgnMonitor)
IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);

View file

@ -56,7 +56,7 @@ IntIntersectWithParents(PWND Child, RECTL *WindowRect)
}
BOOL FASTCALL
IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse)
{
PWND ParentWnd = Child;
@ -81,7 +81,7 @@ IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse)
return FALSE;
IntInvalidateWindows( ParentWnd,
hValidateRgn,
ValidateRgn,
RDW_VALIDATE | RDW_NOCHILDREN);
}
@ -177,9 +177,21 @@ IntCalcWindowRgn(PWND Wnd, BOOL Client)
HRGN hRgnWindow;
if (Client)
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
{
hRgnWindow = NtGdiCreateRectRgn(
Wnd->rcClient.left,
Wnd->rcClient.top,
Wnd->rcClient.right,
Wnd->rcClient.bottom);
}
else
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
{
hRgnWindow = NtGdiCreateRectRgn(
Wnd->rcWindow.left,
Wnd->rcWindow.top,
Wnd->rcWindow.right,
Wnd->rcWindow.bottom);
}
if (Wnd->hrgnClip != NULL && !(Wnd->style & WS_MINIMIZE))
{
@ -302,8 +314,16 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
{
if (Wnd->hrgnUpdate)
{
if (!IntValidateParent(Wnd, Wnd->hrgnUpdate, Recurse))
return;
PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
if (RgnUpdate)
{
if (!IntValidateParent(Wnd, RgnUpdate, Recurse))
{
RGNOBJAPI_Unlock(RgnUpdate);
return;
}
RGNOBJAPI_Unlock(RgnUpdate);
}
}
if (Flags & RDW_UPDATENOW)
@ -397,7 +417,7 @@ co_IntPaintWindows(PWND Wnd, ULONG Flags, BOOL Recurse)
* co_WinPosSetWindowPos, IntValidateParent, co_UserRedrawWindow.
*/
VOID FASTCALL
IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
IntInvalidateWindows(PWND Wnd, PREGION Rgn, ULONG Flags)
{
INT RgnType;
BOOL HadPaintMessage;
@ -412,11 +432,14 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
*/
if (0 != (Flags & RDW_INVALIDATE) && 0 == (Flags & RDW_FRAME))
{
HRGN hRgnClient;
PREGION RgnClient;
hRgnClient = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnClient, RGN_AND);
GreDeleteObject(hRgnClient);
RgnClient = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
if (RgnClient)
{
RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClient, RGN_AND);
REGION_Delete(RgnClient);
}
}
/*
@ -425,21 +448,27 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (!Wnd->hrgnClip || (Wnd->style & WS_MINIMIZE))
{
HRGN hRgnWindow;
hRgnWindow = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
RgnType = NtGdiCombineRgn(hRgn, hRgn, hRgnWindow, RGN_AND);
GreDeleteObject(hRgnWindow);
PREGION RgnWindow = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
if (RgnWindow)
{
RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnWindow, RGN_AND);
REGION_Delete(RgnWindow);
}
}
else
{
NtGdiOffsetRgn( hRgn,
-Wnd->rcWindow.left,
-Wnd->rcWindow.top);
RgnType = NtGdiCombineRgn(hRgn, hRgn, Wnd->hrgnClip, RGN_AND);
NtGdiOffsetRgn( hRgn,
Wnd->rcWindow.left,
Wnd->rcWindow.top);
PREGION RgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
if (RgnClip)
{
IntGdiOffsetRgn( Rgn,
-Wnd->rcWindow.left,
-Wnd->rcWindow.top);
RgnType = IntGdiCombineRgn(Rgn, Rgn, RgnClip, RGN_AND);
IntGdiOffsetRgn( Rgn,
Wnd->rcWindow.left,
Wnd->rcWindow.top);
RGNOBJAPI_Unlock(RgnClip);
}
}
/*
@ -462,6 +491,8 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Flags & RDW_INVALIDATE && RgnType != NULLREGION)
{
PREGION RgnUpdate;
Wnd->state &= ~WNDS_NONCPAINT;
/* If not the same thread set it dirty. */
@ -479,16 +510,21 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Wnd->hrgnUpdate == NULL)
{
Wnd->hrgnUpdate = IntSysCreateRectRgn(0, 0, 0, 0);
Wnd->hrgnUpdate = NtGdiCreateRectRgn(0, 0, 0, 0);
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_PUBLIC);
}
if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
hRgn, RGN_OR) == NULLREGION)
RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
if (RgnUpdate)
{
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL;
RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_OR);
RGNOBJAPI_Unlock(RgnUpdate);
if (RgnType == NULLREGION)
{
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL;
}
}
Flags |= RDW_FRAME; // For children.
}
@ -511,13 +547,20 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
if (Wnd->hrgnUpdate != NULL)
{
if (NtGdiCombineRgn(Wnd->hrgnUpdate, Wnd->hrgnUpdate,
hRgn, RGN_DIFF) == NULLREGION)
{
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL;
}
PREGION RgnUpdate = RGNOBJAPI_Lock(Wnd->hrgnUpdate, NULL);
if (RgnUpdate)
{
RgnType = IntGdiCombineRgn(RgnUpdate, RgnUpdate, Rgn, RGN_DIFF);
RGNOBJAPI_Unlock(RgnUpdate);
if(RgnType == NULLREGION)
{
IntGdiSetRegionOwner(Wnd->hrgnUpdate, GDI_OBJ_HMGR_POWNED);
GreDeleteObject(Wnd->hrgnUpdate);
Wnd->hrgnUpdate = NULL;
}
}
}
if (Wnd->hrgnUpdate == NULL)
@ -541,10 +584,13 @@ IntInvalidateWindows(PWND Wnd, HRGN hRgn, ULONG Flags)
/*
* Recursive call to update children hrgnUpdate
*/
HRGN hRgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(hRgnTemp, hRgn, 0, RGN_COPY);
IntInvalidateWindows(Child, hRgnTemp, Flags);
GreDeleteObject(hRgnTemp);
PREGION RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (RgnTemp)
{
IntGdiCombineRgn(RgnTemp, Rgn, 0, RGN_COPY);
IntInvalidateWindows(Child, RgnTemp, Flags);
REGION_Delete(RgnTemp);
}
}
}
}
@ -602,10 +648,10 @@ BOOL FASTCALL
co_UserRedrawWindow(
PWND Window,
const RECTL* UpdateRect,
HRGN UpdateRgn,
PREGION UpdateRgn,
ULONG Flags)
{
HRGN hRgn = NULL;
PREGION TmpRgn = NULL;
TRACE("co_UserRedrawWindow start\n");
/*
@ -626,35 +672,37 @@ co_UserRedrawWindow(
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE)) // Both are OKAY!
{
if (UpdateRgn != NULL)
if (UpdateRgn)
{
hRgn = IntSysCreateRectRgn(0, 0, 0, 0);
if (NtGdiCombineRgn(hRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
{
GreDeleteObject(hRgn);
hRgn = NULL;
}
else
NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top);
TmpRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (IntGdiCombineRgn(TmpRgn, UpdateRgn, NULL, RGN_COPY) == NULLREGION)
{
REGION_Delete(TmpRgn);
TmpRgn = NULL;
}
else
{
IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
}
}
else if (UpdateRect != NULL)
{
if (!RECTL_bIsEmptyRect(UpdateRect))
{
hRgn = IntSysCreateRectRgnIndirect((RECTL *)UpdateRect);
NtGdiOffsetRgn(hRgn, Window->rcClient.left, Window->rcClient.top);
TmpRgn = IntSysCreateRectpRgnIndirect(UpdateRect);
IntGdiOffsetRgn(TmpRgn, Window->rcClient.left, Window->rcClient.top);
}
}
else if ((Flags & (RDW_INVALIDATE | RDW_FRAME)) == (RDW_INVALIDATE | RDW_FRAME) ||
(Flags & (RDW_VALIDATE | RDW_NOFRAME)) == (RDW_VALIDATE | RDW_NOFRAME))
{
if (!RECTL_bIsEmptyRect(&Window->rcWindow))
hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow);
TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcWindow);
}
else
{
if (!RECTL_bIsEmptyRect(&Window->rcClient))
hRgn = IntSysCreateRectRgnIndirect(&Window->rcClient);
TmpRgn = IntSysCreateRectpRgnIndirect(&Window->rcClient);
}
}
@ -664,9 +712,9 @@ co_UserRedrawWindow(
*/
if (Flags & (RDW_INVALIDATE | RDW_VALIDATE | RDW_INTERNALPAINT | RDW_NOINTERNALPAINT) &&
hRgn != NULL)
TmpRgn != NULL)
{
IntInvalidateWindows(Window, hRgn, Flags);
IntInvalidateWindows(Window, TmpRgn, Flags);
}
/*
@ -685,9 +733,9 @@ co_UserRedrawWindow(
* Cleanup ;-)
*/
if (hRgn != NULL)
if (TmpRgn != NULL)
{
GreDeleteObject(hRgn);
REGION_Delete(TmpRgn);
}
TRACE("co_UserRedrawWindow exit\n");
@ -991,7 +1039,7 @@ IntBeginPaint(PWND Window, PPAINTSTRUCT Ps)
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
if (Child->hrgnUpdate == NULL && Child->state & WNDS_SENDNCPAINT) // Helped fixing test_redrawnow.
IntInvalidateWindows(Child, Window->hrgnUpdate, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
IntInvalidateWindows(Child, NULL, RDW_FRAME | RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
}
@ -1157,33 +1205,39 @@ Exit:
}
INT FASTCALL
co_UserGetUpdateRgn(PWND Window, HRGN hRgn, BOOL bErase)
co_UserGetUpdateRgn(PWND Window, PREGION Rgn, BOOL bErase)
{
int RegionType;
RECTL Rect;
int RegionType;
RECTL Rect;
PREGION UpdateRgn;
ASSERT_REFS_CO(Window);
ASSERT_REFS_CO(Window);
Window->state &= ~WNDS_UPDATEDIRTY;
Window->state &= ~WNDS_UPDATEDIRTY;
if (Window->hrgnUpdate == NULL)
{
RegionType = (NtGdiSetRectRgn(hRgn, 0, 0, 0, 0) ? NULLREGION : ERROR);
}
else
{
Rect = Window->rcClient;
IntIntersectWithParents(Window, &Rect);
NtGdiSetRectRgn(hRgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = NtGdiCombineRgn(hRgn, hRgn, Window->hrgnUpdate, RGN_AND);
NtGdiOffsetRgn(hRgn, -Window->rcClient.left, -Window->rcClient.top);
}
if (Window->hrgnUpdate == NULL)
{
REGION_SetRectRgn(Rgn, 0, 0, 0, 0);
return NULLREGION;
}
UpdateRgn = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
if (!UpdateRgn)
return ERROR;
Rect = Window->rcClient;
IntIntersectWithParents(Window, &Rect);
REGION_SetRectRgn(Rgn, Rect.left, Rect.top, Rect.right, Rect.bottom);
RegionType = IntGdiCombineRgn(Rgn, Rgn, UpdateRgn, RGN_AND);
IntGdiOffsetRgn(Rgn, -Window->rcClient.left, -Window->rcClient.top);
if (bErase && RegionType != NULLREGION && RegionType != ERROR)
{
co_UserRedrawWindow(Window, NULL, NULL, RDW_ERASENOW | RDW_NOCHILDREN);
}
RGNOBJAPI_Unlock(UpdateRgn);
return RegionType;
}
@ -1201,6 +1255,7 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
PWND Window;
INT ret;
USER_REFERENCE_ENTRY Ref;
PREGION Rgn = NULL;
TRACE("Enter NtUserGetUpdateRgn\n");
UserEnterExclusive();
@ -1210,13 +1265,19 @@ NtUserGetUpdateRgn(HWND hWnd, HRGN hRgn, BOOL bErase)
RETURN(ERROR);
}
Rgn = RGNOBJAPI_Lock(hRgn, NULL);
if (!Rgn)
RETURN(ERROR);
UserRefObjectCo(Window, &Ref);
ret = co_UserGetUpdateRgn(Window, hRgn, bErase);
ret = co_UserGetUpdateRgn(Window, Rgn, bErase);
UserDerefObjectCo(Window);
RETURN(ret);
CLEANUP:
if (Rgn)
RGNOBJAPI_Unlock(Rgn);
TRACE("Leave NtUserGetUpdateRgn, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
@ -1327,6 +1388,7 @@ NtUserRedrawWindow(
BOOL Ret;
USER_REFERENCE_ENTRY Ref;
NTSTATUS Status = STATUS_SUCCESS;
PREGION RgnUpdate = NULL;
DECLARE_RETURN(BOOL);
TRACE("Enter NtUserRedrawWindow\n");
@ -1365,11 +1427,21 @@ NtUserRedrawWindow(
RETURN( FALSE);
}
if (hrgnUpdate)
{
RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnUpdate)
{
EngSetLastError(ERROR_INVALID_HANDLE);
RETURN(FALSE);
}
}
UserRefObjectCo(Wnd, &Ref);
Ret = co_UserRedrawWindow( Wnd,
lprcUpdate ? &SafeUpdateRect : NULL,
hrgnUpdate,
RgnUpdate,
flags);
UserDerefObjectCo(Wnd);
@ -1377,6 +1449,8 @@ NtUserRedrawWindow(
RETURN( Ret);
CLEANUP:
if (RgnUpdate)
RGNOBJAPI_Unlock(RgnUpdate);
TRACE("Leave NtUserRedrawWindow, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
@ -1390,7 +1464,7 @@ UserScrollDC(
INT dy,
const RECTL *prcScroll,
const RECTL *prcClip,
HRGN hrgnUpdate,
PREGION RgnUpdate,
RECTL *prcUpdate)
{
PDC pDC;
@ -1435,10 +1509,9 @@ UserScrollDC(
/* Calculate the region that was invalidated by moving or
could not be copied, because it was not visible */
if (hrgnUpdate || prcUpdate)
if (RgnUpdate || prcUpdate)
{
HRGN hrgnOwn, hrgnTmp;
PREGION prgnTmp;
PREGION RgnOwn, RgnTmp;
pDC = DC_LockDc(hDC);
if (!pDC)
@ -1450,44 +1523,38 @@ UserScrollDC(
rcDst = rcScroll;
RECTL_vOffsetRect(&rcDst, dx, dy);
RECTL_bIntersectRect(&rcDst, &rcDst, &rcClip);
if (hrgnUpdate)
if (RgnUpdate)
{
hrgnOwn = hrgnUpdate;
if (!NtGdiSetRectRgn(hrgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom))
{
DC_UnlockDc(pDC);
return ERROR;
}
RgnOwn = RgnUpdate;
REGION_SetRectRgn(RgnOwn, rcDst.left, rcDst.top, rcDst.right, rcDst.bottom);
}
else
{
hrgnOwn = IntSysCreateRectRgnIndirect(&rcDst);
RgnOwn = IntSysCreateRectpRgnIndirect(&rcDst);
}
/* Add the source rect */
hrgnTmp = IntSysCreateRectRgnIndirect(&rcSrc);
NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_OR);
RgnTmp = IntSysCreateRectpRgnIndirect(&rcSrc);
IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_OR);
/* Substract the part of the dest that was visible in source */
prgnTmp = RGNOBJAPI_Lock(hrgnTmp, NULL);
IntGdiCombineRgn(prgnTmp, prgnTmp, pDC->prgnVis, RGN_AND);
RGNOBJAPI_Unlock(prgnTmp);
NtGdiOffsetRgn(hrgnTmp, dx, dy);
Result = NtGdiCombineRgn(hrgnOwn, hrgnOwn, hrgnTmp, RGN_DIFF);
IntGdiCombineRgn(RgnTmp, RgnTmp, pDC->prgnVis, RGN_AND);
IntGdiOffsetRgn(RgnTmp, dx, dy);
Result = IntGdiCombineRgn(RgnOwn, RgnOwn, RgnTmp, RGN_DIFF);
/* DO NOT Unlock DC while messing with prgnVis! */
DC_UnlockDc(pDC);
GreDeleteObject(hrgnTmp);
REGION_Delete(RgnTmp);
if (prcUpdate)
{
IntGdiGetRgnBox(hrgnOwn, prcUpdate);
REGION_GetRgnBox(RgnOwn, prcUpdate);
}
if (!hrgnUpdate)
if (!RgnUpdate)
{
GreDeleteObject(hrgnOwn);
REGION_Delete(RgnOwn);
}
}
else
@ -1516,6 +1583,7 @@ NtUserScrollDC(
RECTL rcScroll, rcClip, rcUpdate;
NTSTATUS Status = STATUS_SUCCESS;
DWORD Result;
PREGION RgnUpdate = NULL;
TRACE("Enter NtUserScrollDC\n");
UserEnterExclusive();
@ -1548,12 +1616,19 @@ NtUserScrollDC(
RETURN(FALSE);
}
if (hrgnUpdate)
{
RgnUpdate = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnUpdate)
RETURN(FALSE);
}
Result = UserScrollDC( hDC,
dx,
dy,
prcUnsafeScroll? &rcScroll : 0,
prcUnsafeClip? &rcClip : 0,
hrgnUpdate,
RgnUpdate,
prcUnsafeUpdate? &rcUpdate : NULL);
if(Result == ERROR)
{
@ -1583,6 +1658,8 @@ NtUserScrollDC(
RETURN(TRUE);
CLEANUP:
if (RgnUpdate)
RGNOBJAPI_Unlock(RgnUpdate);
TRACE("Leave NtUserScrollDC, ret=%lu\n",_ret_);
UserLeave();
END_CLEANUP;
@ -1610,7 +1687,7 @@ NtUserScrollWindowEx(
INT Result;
PWND Window = NULL, CaretWnd;
HDC hDC;
HRGN hrgnOwn = NULL, hrgnTemp, hrgnWinupd = NULL;
PREGION RgnOwn = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret;
DWORD dcxflags = 0;
int rdw_flags;
@ -1668,11 +1745,15 @@ NtUserScrollWindowEx(
if (hrgnUpdate)
{
hrgnOwn = hrgnUpdate;
RgnOwn = RGNOBJAPI_Lock(hrgnUpdate, NULL);
if (!RgnOwn)
{
RETURN(ERROR);
}
bOwnRgn = FALSE;
}
else
hrgnOwn = IntSysCreateRectRgn(0, 0, 0, 0);
RgnOwn = IntSysCreateRectpRgn(0, 0, 0, 0);
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
if (flags & SW_SCROLLWNDDCE)
@ -1709,7 +1790,7 @@ NtUserScrollWindowEx(
dy,
&rcScroll,
&rcClip,
hrgnOwn,
RgnOwn,
prcUnsafeUpdate? &rcUpdate : NULL);
UserReleaseDC(Window, hDC, FALSE);
@ -1719,22 +1800,29 @@ NtUserScrollWindowEx(
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/
hrgnTemp = IntSysCreateRectRgn(0, 0, 0, 0);
if (co_UserGetUpdateRgn(Window, hrgnTemp, FALSE) != NULLREGION)
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (RgnTemp)
{
HRGN hrgnClip = IntSysCreateRectRgnIndirect(&rcClip);
if (!bOwnRgn)
{
hrgnWinupd = IntSysCreateRectRgn( 0, 0, 0, 0);
NtGdiCombineRgn( hrgnWinupd, hrgnTemp, 0, RGN_COPY);
}
NtGdiOffsetRgn(hrgnTemp, dx, dy);
NtGdiCombineRgn(hrgnTemp, hrgnTemp, hrgnClip, RGN_AND);
if (!bOwnRgn) NtGdiCombineRgn( hrgnWinupd, hrgnWinupd, hrgnTemp, RGN_OR );
co_UserRedrawWindow(Window, NULL, hrgnTemp, rdw_flags );
GreDeleteObject(hrgnClip);
if (co_UserGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
{
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
if (RgnClip)
{
if (!bOwnRgn)
{
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
}
IntGdiOffsetRgn(RgnTemp, dx, dy);
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
if (!bOwnRgn)
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
REGION_Delete(RgnClip);
}
}
REGION_Delete(RgnTemp);
}
GreDeleteObject(hrgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
@ -1766,7 +1854,7 @@ NtUserScrollWindowEx(
if (flags & (SW_INVALIDATE | SW_ERASE))
{
co_UserRedrawWindow(Window, NULL, hrgnOwn, rdw_flags |
co_UserRedrawWindow(Window, NULL, RgnOwn, rdw_flags |
((flags & SW_ERASE) ? RDW_ERASENOW : 0) |
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : 0));
}
@ -1805,15 +1893,19 @@ NtUserScrollWindowEx(
RETURN(Result);
CLEANUP:
if (hrgnWinupd && !bOwnRgn)
if (RgnWinupd && !bOwnRgn)
{
NtGdiCombineRgn( hrgnOwn, hrgnOwn, hrgnWinupd, RGN_OR);
GreDeleteObject(hrgnWinupd);
IntGdiCombineRgn( RgnOwn, RgnOwn, RgnWinupd, RGN_OR);
REGION_Delete(RgnWinupd);
}
if (hrgnOwn && !hrgnUpdate)
if (RgnOwn && !hrgnUpdate)
{
GreDeleteObject(hrgnOwn);
REGION_Delete(RgnOwn);
}
else if (RgnOwn)
{
RGNOBJAPI_Unlock(RgnOwn);
}
if (Window)

View file

@ -1,12 +1,12 @@
#pragma once
BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, HRGN UpdateRgn, ULONG Flags);
VOID FASTCALL IntInvalidateWindows(PWND Window, HRGN hRgn, ULONG Flags);
BOOL FASTCALL co_UserRedrawWindow(PWND Wnd, const RECTL* UpdateRect, PREGION UpdateRgn, ULONG Flags);
VOID FASTCALL IntInvalidateWindows(PWND Window, PREGION Rgn, ULONG Flags);
BOOL FASTCALL IntGetPaintMessage(PWND Window, UINT MsgFilterMin, UINT MsgFilterMax, PTHREADINFO Thread, MSG *Message, BOOL Remove);
INT FASTCALL UserRealizePalette(HDC);
INT FASTCALL co_UserGetUpdateRgn(PWND, HRGN, BOOL);
INT FASTCALL co_UserGetUpdateRgn(PWND, PREGION, BOOL);
VOID FASTCALL co_IntPaintWindows(PWND Window, ULONG Flags, BOOL Recurse);
BOOL FASTCALL IntValidateParent(PWND Child, HRGN hValidateRgn, BOOL Recurse);
BOOL FASTCALL IntValidateParent(PWND Child, PREGION ValidateRgn, BOOL Recurse);
BOOL FASTCALL IntIsWindowDirty(PWND);
BOOL FASTCALL IntEndPaint(PWND,PPAINTSTRUCT);
HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);

View file

@ -793,8 +793,15 @@ NtUserCallHwndParamLock(
switch (Routine)
{
case TWOPARAM_ROUTINE_VALIDATERGN:
Ret = (DWORD)co_UserRedrawWindow( Window, NULL, (HRGN)Param, RDW_VALIDATE);
break;
{
PREGION Rgn = RGNOBJAPI_Lock((HRGN)Param, NULL);
if (Rgn)
{
Ret = (DWORD)co_UserRedrawWindow( Window, NULL, Rgn, RDW_VALIDATE);
RGNOBJAPI_Unlock(Rgn);
}
break;
}
}
UserDerefObjectCo(Window);

View file

@ -9,14 +9,14 @@
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserWinpos);
HRGN FASTCALL
PREGION FASTCALL
VIS_ComputeVisibleRegion(
PWND Wnd,
BOOLEAN ClientArea,
BOOLEAN ClipChildren,
BOOLEAN ClipSiblings)
{
HRGN VisRgn, ClipRgn;
PREGION VisRgn, ClipRgn;
PWND PreviousWindow, CurrentWindow, CurrentSibling;
if (!Wnd || !(Wnd->style & WS_VISIBLE))
@ -28,11 +28,11 @@ VIS_ComputeVisibleRegion(
if (ClientArea)
{
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcClient);
}
else
{
VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
VisRgn = IntSysCreateRectpRgnIndirect(&Wnd->rcWindow);
}
/*
@ -48,19 +48,21 @@ VIS_ComputeVisibleRegion(
if (!VerifyWnd(CurrentWindow))
{
ERR("ATM the Current Window or Parent is dead! %p\n",CurrentWindow);
if (VisRgn) GreDeleteObject(VisRgn);
if (VisRgn)
REGION_Delete(VisRgn);
return NULL;
}
if (!(CurrentWindow->style & WS_VISIBLE))
{
if (VisRgn) GreDeleteObject(VisRgn);
if (VisRgn)
REGION_Delete(VisRgn);
return NULL;
}
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
GreDeleteObject(ClipRgn);
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcClient);
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
REGION_Delete(ClipRgn);
if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
(PreviousWindow == Wnd && ClipSiblings))
@ -72,16 +74,21 @@ VIS_ComputeVisibleRegion(
if ((CurrentSibling->style & WS_VISIBLE) &&
!(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
{
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentSibling->rcWindow);
/* Combine it with the window region if available */
if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
{
NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
PREGION SiblingClipRgn = RGNOBJAPI_Lock(CurrentSibling->hrgnClip, NULL);
if (SiblingClipRgn)
{
IntGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
IntGdiCombineRgn(ClipRgn, ClipRgn, SiblingClipRgn, RGN_AND);
IntGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
RGNOBJAPI_Unlock(SiblingClipRgn);
}
}
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
GreDeleteObject(ClipRgn);
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
REGION_Delete(ClipRgn);
}
CurrentSibling = CurrentSibling->spwndNext;
}
@ -99,16 +106,20 @@ VIS_ComputeVisibleRegion(
if ((CurrentWindow->style & WS_VISIBLE) &&
!(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
{
ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
ClipRgn = IntSysCreateRectpRgnIndirect(&CurrentWindow->rcWindow);
/* Combine it with the window region if available */
if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
{
NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
PREGION CurrentRgnClip = RGNOBJAPI_Lock(CurrentWindow->hrgnClip, NULL);
if (CurrentRgnClip)
{
IntGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
IntGdiCombineRgn(ClipRgn, ClipRgn, CurrentRgnClip, RGN_AND);
IntGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
}
}
NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
GreDeleteObject(ClipRgn);
IntGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
REGION_Delete(ClipRgn);
}
CurrentWindow = CurrentWindow->spwndNext;
}
@ -116,9 +127,14 @@ VIS_ComputeVisibleRegion(
if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
{
NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
PREGION WndRgnClip = RGNOBJAPI_Lock(Wnd->hrgnClip, NULL);
if (WndRgnClip)
{
IntGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
IntGdiCombineRgn(VisRgn, VisRgn, WndRgnClip, RGN_AND);
IntGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
RGNOBJAPI_Unlock(WndRgnClip);
}
}
return VisRgn;
@ -127,9 +143,8 @@ VIS_ComputeVisibleRegion(
VOID FASTCALL
co_VIS_WindowLayoutChanged(
PWND Wnd,
HRGN NewlyExposed)
PREGION NewlyExposed)
{
HRGN Temp;
PWND Parent;
USER_REFERENCE_ENTRY Ref;
@ -138,20 +153,23 @@ co_VIS_WindowLayoutChanged(
Parent = Wnd->spwndParent;
if(Parent)
{
Temp = IntSysCreateRectRgn(0, 0, 0, 0);
PREGION TempRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
NtGdiOffsetRgn(Temp,
Wnd->rcWindow.left - Parent->rcClient.left,
Wnd->rcWindow.top - Parent->rcClient.top);
if (!TempRgn)
return;
UserRefObjectCo(Parent, &Ref);
co_UserRedrawWindow(Parent, NULL, Temp,
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
RDW_ALLCHILDREN);
UserDerefObjectCo(Parent);
IntGdiCombineRgn(TempRgn, NewlyExposed, NULL, RGN_COPY);
IntGdiOffsetRgn(TempRgn,
Wnd->rcWindow.left - Parent->rcClient.left,
Wnd->rcWindow.top - Parent->rcClient.top);
GreDeleteObject(Temp);
UserRefObjectCo(Parent, &Ref);
co_UserRedrawWindow(Parent, NULL, TempRgn,
RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
RDW_ALLCHILDREN);
UserDerefObjectCo(Parent);
REGION_Delete(TempRgn);
}
}

View file

@ -9,7 +9,7 @@
#pragma once
HRGN FASTCALL VIS_ComputeVisibleRegion(PWND Window, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings);
VOID FASTCALL co_VIS_WindowLayoutChanged(PWND Window, HRGN UncoveredRgn);
PREGION FASTCALL VIS_ComputeVisibleRegion(PWND Window, BOOLEAN ClientArea, BOOLEAN ClipChildren, BOOLEAN ClipSiblings);
VOID FASTCALL co_VIS_WindowLayoutChanged(PWND Window, PREGION UncoveredRgn);
/* EOF */

View file

@ -69,24 +69,10 @@ static
PREGION FASTCALL
DceGetVisRgn(PWND Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{
PREGION RetRgn;
HRGN hVisRgn;
hVisRgn = VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS));
RetRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (hVisRgn != NULL)
{
PREGION VisRgn = REGION_LockRgn(hVisRgn);
IntGdiCombineRgn(RetRgn, VisRgn, NULL, RGN_COPY);
REGION_UnlockRgn(VisRgn);
GreDeleteObject(hVisRgn);
}
return RetRgn;
return VIS_ComputeVisibleRegion( Window,
0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS));
}
PDCE FASTCALL
@ -582,11 +568,19 @@ UserGetDCEx(PWND Wnd OPTIONAL, HANDLE ClipRegion, ULONG Flags)
{
if (!(Flags & DCX_WINDOW))
{
Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
Dce->hrgnClip = NtGdiCreateRectRgn(
Wnd->rcClient.left,
Wnd->rcClient.top,
Wnd->rcClient.right,
Wnd->rcClient.bottom);
}
else
{
Dce->hrgnClip = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
Dce->hrgnClip = NtGdiCreateRectRgn(
Wnd->rcWindow.left,
Wnd->rcWindow.top,
Wnd->rcWindow.right,
Wnd->rcWindow.bottom);
}
Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
bUpdateVisRgn = TRUE;

View file

@ -1652,13 +1652,10 @@ co_WinPosSetWindowPos(
RECTL NewWindowRect;
RECTL NewClientRect;
RECTL valid_rects[2];
PROSRGNDATA VisRgn;
HRGN VisBefore = NULL;
HRGN VisBeforeJustClient = NULL;
HRGN VisAfter = NULL;
HRGN DirtyRgn = NULL;
HRGN ExposedRgn = NULL;
HRGN CopyRgn = NULL;
PREGION VisBefore = NULL;
PREGION VisBeforeJustClient = NULL;
PREGION VisAfter = NULL;
PREGION CopyRgn = NULL;
ULONG WvrFlags = 0;
RECTL OldWindowRect, OldClientRect;
int RgnType;
@ -1736,20 +1733,16 @@ co_WinPosSetWindowPos(
{
VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisBefore != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBefore, NULL)) &&
REGION_Complexity(VisRgn) == NULLREGION )
REGION_Complexity(VisBefore) == NULLREGION )
{
RGNOBJAPI_Unlock(VisRgn);
GreDeleteObject(VisBefore);
REGION_Delete(VisBefore);
VisBefore = NULL;
}
else if(VisRgn)
else if(VisBefore)
{
RGNOBJAPI_Unlock(VisRgn);
NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
IntGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
}
/* Calculate the non client area for resizes, as this is used in the copy region */
@ -1757,20 +1750,16 @@ co_WinPosSetWindowPos(
{
VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisBeforeJustClient != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBeforeJustClient, NULL)) &&
REGION_Complexity(VisRgn) == NULLREGION )
REGION_Complexity(VisBeforeJustClient) == NULLREGION )
{
RGNOBJAPI_Unlock(VisRgn);
GreDeleteObject(VisBeforeJustClient);
REGION_Delete(VisBeforeJustClient);
VisBeforeJustClient = NULL;
}
else if(VisRgn)
else if(VisBeforeJustClient)
{
RGNOBJAPI_Unlock(VisRgn);
NtGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
IntGdiOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
}
}
}
@ -1843,20 +1832,16 @@ co_WinPosSetWindowPos(
/* Determine the new visible region */
VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
(Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
VisRgn = NULL;
if ( VisAfter != NULL &&
(VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisAfter, NULL)) &&
REGION_Complexity(VisRgn) == NULLREGION )
REGION_Complexity(VisAfter) == NULLREGION )
{
RGNOBJAPI_Unlock(VisRgn);
GreDeleteObject(VisAfter);
REGION_Delete(VisAfter);
VisAfter = NULL;
}
else if(VisRgn)
else if(VisAfter)
{
RGNOBJAPI_Unlock(VisRgn);
NtGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
IntGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
}
/*
@ -1882,21 +1867,26 @@ co_WinPosSetWindowPos(
* region...)
*/
CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (WinPos.flags & SWP_NOSIZE)
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
else if (VisBeforeJustClient != NULL)
{
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
GreDeleteObject(VisBeforeJustClient);
RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
REGION_Delete(VisBeforeJustClient);
}
/* No use in copying bits which are in the update region. */
if (Window->hrgnUpdate != NULL)
{
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->hrgnUpdate, RGN_DIFF);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
PREGION RgnUpdate = RGNOBJAPI_Lock(Window->hrgnUpdate, NULL);
if (RgnUpdate)
{
IntGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF);
IntGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
RGNOBJAPI_Unlock(RgnUpdate);
}
}
/*
@ -1904,21 +1894,17 @@ co_WinPosSetWindowPos(
* there's nothing to copy. Also, it's no use copying bits onto
* themselves.
*/
if ( (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(CopyRgn, NULL)) &&
REGION_GetRgnBox(VisRgn, &CopyRect) == NULLREGION)
if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
{
/* Nothing to copy, clean up */
RGNOBJAPI_Unlock(VisRgn);
GreDeleteObject(CopyRgn);
REGION_Delete(CopyRgn);
CopyRgn = NULL;
}
else if (OldWindowRect.left != NewWindowRect.left ||
OldWindowRect.top != NewWindowRect.top)
{
if(VisRgn)
{
RGNOBJAPI_Unlock(VisRgn);
}
HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
PREGION DcRgnObj = RGNOBJAPI_Lock(DcRgn, NULL);
/*
* Small trick here: there is no function to bitblt a region. So
@ -1929,9 +1915,11 @@ co_WinPosSetWindowPos(
* Since NtUserGetDCEx takes ownership of the clip region, we need
* to create a copy of CopyRgn and pass that. We need CopyRgn later
*/
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY);
IntGdiOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top);
RGNOBJAPI_Unlock(DcRgnObj);
Dc = UserGetDCEx( Window,
CopyRgn,
DcRgn,
DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
NtGdiBitBlt( Dc,
CopyRect.left, CopyRect.top,
@ -1946,11 +1934,7 @@ co_WinPosSetWindowPos(
UserReleaseDC(Window, Dc, FALSE);
IntValidateParent(Window, CopyRgn, FALSE);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
}
else if(VisRgn)
{
RGNOBJAPI_Unlock(VisRgn);
GreDeleteObject(DcRgn);
}
}
else
@ -1961,78 +1945,84 @@ co_WinPosSetWindowPos(
/* We need to redraw what wasn't visible before */
if (VisAfter != NULL)
{
DirtyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
if (CopyRgn != NULL)
PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (DirtyRgn)
{
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
}
else
{
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
}
if (RgnType != ERROR && RgnType != NULLREGION)
{
/* old code
NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
IntInvalidateWindows( Window,
DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
GreDeleteObject(DirtyRgn);
*/
PWND Parent = Window->spwndParent;
NtGdiOffsetRgn( DirtyRgn,
Window->rcWindow.left,
Window->rcWindow.top);
if ( (Window->style & WS_CHILD) &&
(Parent) &&
!(Parent->style & WS_CLIPCHILDREN))
{
IntInvalidateWindows( Parent,
DirtyRgn,
RDW_ERASE | RDW_INVALIDATE);
co_IntPaintWindows(Parent, RDW_ERASENOW, FALSE);
}
else
{
if (CopyRgn != NULL)
{
RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
}
else
{
RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
}
if (RgnType != ERROR && RgnType != NULLREGION)
{
/* old code
NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
IntInvalidateWindows( Window,
DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
GreDeleteObject(DirtyRgn);
*/
PWND Parent = Window->spwndParent;
IntGdiOffsetRgn( DirtyRgn,
Window->rcWindow.left,
Window->rcWindow.top);
if ( (Window->style & WS_CHILD) &&
(Parent) &&
!(Parent->style & WS_CLIPCHILDREN))
{
IntInvalidateWindows( Parent,
DirtyRgn,
RDW_ERASE | RDW_INVALIDATE);
co_IntPaintWindows(Parent, RDW_ERASENOW, FALSE);
}
else
{
IntInvalidateWindows( Window,
DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
REGION_Delete(DirtyRgn);
}
GreDeleteObject(DirtyRgn);
}
if (CopyRgn != NULL)
{
GreDeleteObject(CopyRgn);
REGION_Delete(CopyRgn);
}
/* Expose what was covered before but not covered anymore */
if (VisBefore != NULL)
{
ExposedRgn = IntSysCreateRectRgn(0, 0, 0, 0);
RgnType = NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
NtGdiOffsetRgn( ExposedRgn,
OldWindowRect.left - NewWindowRect.left,
OldWindowRect.top - NewWindowRect.top);
if (VisAfter != NULL)
RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
if (RgnType != ERROR && RgnType != NULLREGION)
PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
if (ExposedRgn)
{
co_VIS_WindowLayoutChanged(Window, ExposedRgn);
RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
IntGdiOffsetRgn( ExposedRgn,
OldWindowRect.left - NewWindowRect.left,
OldWindowRect.top - NewWindowRect.top);
if (VisAfter != NULL)
RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
if (RgnType != ERROR && RgnType != NULLREGION)
{
co_VIS_WindowLayoutChanged(Window, ExposedRgn);
}
REGION_Delete(ExposedRgn);
}
GreDeleteObject(ExposedRgn);
GreDeleteObject(VisBefore);
REGION_Delete(VisBefore);
}
if (VisAfter != NULL)
{
GreDeleteObject(VisAfter);
REGION_Delete(VisAfter);
}
}
@ -3112,7 +3102,7 @@ NtUserSetWindowRgn(
HRGN hRgn,
BOOL bRedraw)
{
HRGN hrgnCopy;
HRGN hrgnCopy = NULL;
PWND Window;
INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
BOOLEAN Ret = FALSE;
@ -3132,7 +3122,7 @@ NtUserSetWindowRgn(
{
if (GreIsHandleValid(hRgn))
{
hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0);
hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0);
/* The coordinates of a window's window region are relative to the
upper-left corner of the window, not the client area of the window. */
NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
@ -3140,10 +3130,6 @@ NtUserSetWindowRgn(
else
RETURN( 0);
}
else
{
hrgnCopy = NULL;
}
if (Window->hrgnClip)
{