test: update.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# update.c File Reference

`#include "precomp.h"`

Go to the source code of this file.

## Defines

#define | UW_ENUMCHILDREN 0x0001
#define | UW_RECURSED 0x0004
#define | RIR_OUTSIDE 0
#define | RIR_INTERSECT 1
#define | RIR_INSIDE 2
#define | RDW_IGNOREUPDATEDIRTY 0x8000
#define | RECTINREGION_BUG

## Functions

BOOL | xxxInvalidateRect (PWND pwnd, LPRECT lprcInvalid, BOOL fErase)
BOOL | xxxValidateRect (PWND pwnd, LPRECT lprcValid)
BOOL | xxxInvalidateRgn (PWND pwnd, HRGN hrgnInvalid, BOOL fErase)
BOOL | xxxValidateRgn (PWND pwnd, HRGN hrgnValid)
UINT | SmartRectInRegion (HRGN hrgn, LPRECT lprc)
VOID | PixieHack (PWND pwnd, LPRECT prcBounds)
BOOL | xxxRedrawWindow (PWND pwnd, LPRECT lprcUpdate, HRGN hrgnUpdate, DWORD flags)
BOOL | InternalInvalidate2 (PWND pwnd, HRGN hrgn, HRGN hrgnSubtract, LPRECT prcParents, DWORD flags)
VOID | InternalInvalidate3 (PWND pwnd, HRGN hrgn, DWORD flags)
BOOL | ValidateParents (PWND pwnd, BOOL fRecurse)
void | xxxUpdateWindow2 (PWND pwnd, DWORD flags)
void | xxxInternalUpdateWindow (PWND pwnd, DWORD flags)
VOID | xxxInternalInvalidate (PWND pwnd, HRGN hrgnUpdate, DWORD flags)
BOOL | xxxUpdateWindow (PWND pwnd)
int | _ExcludeUpdateRgn (HDC hdc, PWND pwnd)
BOOL | xxxGetUpdateRect (PWND pwnd, LPRECT lprc, BOOL fErase)
int | xxxGetUpdateRgn (PWND pwnd, HRGN hrgn, BOOL fErase)
BOOL | IntersectWithParents (PWND pwnd, LPRECT lprc)

## Define Documentation

#define RDW_IGNOREUPDATEDIRTY 0x8000

| Definition at line 28 of file update.c. Referenced by InternalInvalidate3(), and ValidateParents().

#define RECTINREGION_BUG

#define RIR_INSIDE 2

| Definition at line 26 of file update.c. Referenced by InternalInvalidate2(), and SmartRectInRegion().

#define RIR_INTERSECT 1

| Definition at line 25 of file update.c. Referenced by InternalInvalidate2(), and SmartRectInRegion().

#define RIR_OUTSIDE 0

| Definition at line 24 of file update.c. Referenced by InternalInvalidate2(), and SmartRectInRegion().

#define UW_ENUMCHILDREN 0x0001

| Definition at line 21 of file update.c. Referenced by xxxInternalInvalidate(), xxxUpdateWindow(), and xxxUpdateWindow2().

#define UW_RECURSED 0x0004

| Definition at line 22 of file update.c. Referenced by xxxUpdateWindow2().

## Function Documentation

int _ExcludeUpdateRgn | ( | HDC | hdc,
|  | PWND | pwnd
| ) |

Definition at line 1462 of file update.c.

References CopyRgn, FALSE, ghrgnInv1, gpDispInfo, HRGN_FULL, tagDISPLAYINFO::hrgnScreen, tagWND::hrgnUpdate, NULL, and SubtractRgn.

Referenced by NtUserExcludeUpdateRgn(), and UT_InvertCaret().

    01465 {
    01466     POINT pt;
    01467
    01468     if (pwnd->hrgnUpdate == NULL) {
    01469
    01470         RECT rc;
    01471
    01472         /*
    01473          * Pass FALSE for fXForm since &rc isn't used.
    01474          */
    01475         return GreGetClipBox(hdc, &rc, FALSE);
    01476
    01477     } else if (pwnd->hrgnUpdate == HRGN_FULL) {
    01478
    01479         return GreIntersectClipRect(hdc, 0, 0, 0, 0);
    01480
    01481     } else {
    01482
    01483         /*
    01484          * If no clip rgn exists, then subtract from a device-sized clip rgn.
    01485          * (GetClipRgn returns clip rgn in screen coordinates).
    01486          */
    01487         GreGetDCOrg(hdc, &pt);
    01488         if (GreGetRandomRgn(hdc, ghrgnInv1, 1) != 1) {
    01489             CopyRgn(ghrgnInv1, gpDispInfo->hrgnScreen);
    01490         } else {
    01491
    01492             /*
    01493              * Gets returned in dc coords - translate to screen.
    01494              */
    01495             GreOffsetRgn(ghrgnInv1, pt.x, pt.y);
    01496         }
    01497
    01498         SubtractRgn(ghrgnInv1, ghrgnInv1, pwnd->hrgnUpdate);
    01499
    01500         /*
    01501          * Map to dc coords before select
    01502          */
    01503         GreOffsetRgn(ghrgnInv1, -pt.x, -pt.y);
    01504
    01505         return GreExtSelectClipRgn(hdc, ghrgnInv1, RGN_COPY);
    01506     }
    01507 }

BOOL InternalInvalidate2 | ( | PWND | pwnd,
|  | HRGN | hrgn,
|  | HRGN | hrgnSubtract,
|  | LPRECT | prcParents,
|  | DWORD | flags
| ) |

Definition at line 400 of file update.c.

References BOOL, CopyRect, DWORD, FALSE, FLayeredOrRedirected(), GetAppCompatFlags(), GETPTI, ghrgnInv2, HRGN_FULL, tagWND::hrgnClip, InternalInvalidate3(), IntersectRect(), IntersectRgn, NULL, PixieHack(), tagWND::rcClient, tagWND::rcWindow, RDW_HASWINDOWRGN, RIR_INSIDE, RIR_INTERSECT, RIR_OUTSIDE, SetRectRgnIndirect(), SmartRectInRegion(), tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndParent, SubtractRgn, TestWF, TRUE, WEFTRANSPARENT, WFALWAYSSENDNCPAINT, WFCLIPCHILDREN, WFCLIPSIBLINGS, WFMINIMIZED, WFVISIBLE, and WFWIN31COMPAT.

Referenced by ValidateParents(), and xxxInternalInvalidate().

    00406 {
    00407     /*
    00408      * NOTE: Uses ghrgnInv2
    00409      */
    00410     RECT  rcOurShare;
    00411     DWORD flagsChildren;
    00412     PWND  pwndT;
    00413
    00414     /*
    00415      * This routine is called recursively down the parent/child chain.
    00416      * Remember if on the way one of the windows has a clipping region.
    00417      * This info is used later on to optimize out a loop in the common
    00418      * case.
    00419      */
    00420     if (pwnd->hrgnClip != NULL) {
    00421         flags |= RDW_HASWINDOWRGN;
    00422     }
    00423
    00424     /*
    00425      * If we recurse, make sure our children subtract themselves off.
    00426      */
    00427     flagsChildren = flags | RDW_SUBTRACTSELF;
    00428     CopyRect(&rcOurShare, &pwnd->rcWindow);
    00429
    00430     /*
    00431      * If we're invalidating, we only want to deal with the part of
    00432      * our window rectangle that intersects our parents.
    00433      * This way, we don't end up validating or invalidating more than our
    00434      * fair share. If we're completely obscured by our parents, then there is
    00435      * nothing to do.
    00436      *
    00437      * We don't perform this intersection if we're validating, because there
    00438      * are cases where a child and its update region may exist but be obscured
    00439      * by parents, and we want to make sure validation will work in these
    00440      * cases.  ScrollWindow() can cause this when children are offset, as can
    00441      * various 3.0 compatibility hacks.
    00442      */
    00443
    00444     if (flags & RDW_INVALIDATE) {
    00445         /*
    00446          * Don't subtract out any sprite windows from the invalid region.
    00447          * Behave as if it's not there.  However, always allow layered window
    00448          * invalidation when RDW_INVALIDATELAYERS is passed in.
    00449          */
    00450         if (FLayeredOrRedirected(pwnd) && !(flags & RDW_INVALIDATELAYERS))
    00451             return TRUE;
    00452
    00453         if (!IntersectRect(&rcOurShare, &rcOurShare, prcParents)) {
    00454
    00455             /*
    00456              * BACKWARD COMPATIBILITY HACK: If hrgn is (HRGN)1, we need to
    00457              * invalidate ALL child windows, even if they're not visible.  This
    00458              * is a bummer, because it'll result in all sorts of repaints that
    00459              * aren't necessary.
    00460              *
    00461              * Various apps, including WordStar for Windows and WaveEdit,
    00462              * depend on this behavior.  Here's how WaveEdit relies on this: it
    00463              * has a CS_HDREDRAW | CS_VREDRAW window, that moves its children
    00464              * around with MoveWindow( ..., fRedraw = FALSE).  The windows
    00465              * not part of the new client area didn't get invalidated.
    00466              */
    00467             if (!TestWF(pwnd, WFWIN31COMPAT) && (hrgn == HRGN_FULL)) {
    00468
    00469                 /*
    00470                  * For purposes of hit-testing, our share is our window
    00471                  * rectangle.  However, we don't want to diddle the region
    00472                  * passed to us, because by rights we're really clipped out!
    00473                  */
    00474                 flags &= ~RDW_SUBTRACTSELF;
    00475                 flagsChildren &= ~RDW_SUBTRACTSELF;
    00476
    00477             } else {
    00478                 return TRUE;
    00479             }
    00480         }
    00481
    00482         /*
    00483          * If our window rect doesn't intersect the valid/invalid region,
    00484          * nothing further to do.
    00485          */
    00486         if (hrgn > HRGN_FULL) {
    00487
    00488             switch (SmartRectInRegion(hrgn, &rcOurShare)) {
    00489             case RIR_OUTSIDE:
    00490                 return TRUE;
    00491
    00492             case RIR_INTERSECT:
    00493
    00494                 /*
    00495                  * The update region can be within the window rect but not
    00496                  * touch the window region; in this case we don't want this
    00497                  * update region to be distributed to this window. If this
    00498                  * is the case, return TRUE as if RIR_OUTSIDE.
    00499                  *
    00500                  * If RDW_HASWINDOWRGN is set, either this window or
    00501                  * one of its parents has a window clipping region. This
    00502                  * flag is just an optimization so that this loop isn't
    00503                  * executed all the time.
    00504                  *
    00505                  * A future optimization may be to calculate this parent
    00506                  * clipped region as part of recursion like prcParents is
    00507                  * calculated. It is not super important though because this
    00508                  * case rarely happens (a window with a region), and even
    00509                  * more rare, a regional window that is a child of a regional
    00510                  * window parent.
    00511                  */
    00512                 if (flags & RDW_HASWINDOWRGN) {
    00513
    00514                     /*
    00515                      * Clip to the window's clipping region and parents!
    00516                      * If we don't clip to parents, we may get a case where
    00517                      * a child clips out some update region that was meant to
    00518                      * go to a sibling of the parent.
    00519                      */
    00520                     SetRectRgnIndirect(ghrgnInv2, &rcOurShare);
    00521                     for (pwndT = pwnd; pwndT != NULL; pwndT = pwndT->spwndParent) {
    00522
    00523                         if (pwndT->hrgnClip != NULL) {
    00524
    00525                             /*
    00526                              * An error at this stage would possibly result
    00527                              * in more being subtracted out of the clipping
    00528                              * region that we'd like.
    00529                              */
    00530                             IntersectRgn(ghrgnInv2, ghrgnInv2, pwndT->hrgnClip);
    00531                         }
    00532                     }
    00533
    00534                     if (IntersectRgn(ghrgnInv2, ghrgnInv2, hrgn) == NULLREGION)
    00535                         return TRUE;
    00536                 }
    00537                 break;
    00538
    00539             case RIR_INSIDE:
    00540                 /*
    00541                  * If the rectangle is completely within hrgn, then we can use
    00542                  * HRGN_FULL, which is much faster and easier to deal with.
    00543                  *
    00544                  * COMPAT HACK:  There are some apps (PP, MSDRAW) that depend
    00545                  * on some weirdities of the 3.0 GetUpdateRect in order to
    00546                  * paint properly.  Since this stuff hinges on whether the
    00547                  * update region is 1 or a real region, we need to simulate
    00548                  * when 3.0 would generate a HRGN(1) update region.  The
    00549                  * following optimization was not made in 3.0, so we yank it
    00550                  * in 3.1 for these apps.  (win31 bugs 8235,10380)
    00551                  */
    00552                 if (!(GetAppCompatFlags(GETPTI(pwnd)) & GACF_NOHRGN1))
    00553                     hrgn = HRGN_FULL;
    00554                 break;
    00555             }
    00556         }
    00557     }
    00558
    00559     /*
    00560      * If not CLIPCHILDREN, go diddle the update region BEFORE our clipped
    00561      * children have done their thing to hrgnSubtract. Otherwise,
    00562      * we'll diddle after we recurse.
    00563      */
    00564     if (!TestWF(pwnd, WFCLIPCHILDREN)) {
    00565         InternalInvalidate3(pwnd, hrgn, flags);
    00566     }
    00567
    00568     /*
    00569      * If this is a GACF_ALWAYSSENDNCPAINT app, take care of it...
    00570      */
    00571     if (TestWF(pwnd, WFALWAYSSENDNCPAINT))
    00572         PixieHack(pwnd, &rcOurShare);
    00573
    00574     /*
    00575      * Recurse on our children if necessary.
    00576      *
    00577      * By default, our children are enumerated if we are not CLIPCHILDREN.
    00578      * Don't bother with children if we're minimized.
    00579      */
    00580     if ((pwnd->spwndChild != NULL) &&
    00581         !TestWF(pwnd, WFMINIMIZED) &&
    00582         !(flags & RDW_NOCHILDREN)  &&
    00583         ((flags & RDW_ALLCHILDREN) || !TestWF(pwnd, WFCLIPCHILDREN))) {
    00584
    00585         RECT rcChildrenShare;
    00586         PWND pwndChild;
    00587
    00588         /*
    00589          * If we're invalidating, make sure our children
    00590          * erase and frame themselves. Also, tell children to subtract
    00591          * themselves from hrgnSubtract.
    00592          */
    00593         if (flags & RDW_INVALIDATE) {
    00594             flagsChildren |= RDW_ERASE | RDW_FRAME;
    00595         }
    00596
    00597         /*
    00598          * Our children are clipped to our client rect, so reflect
    00599          * that in the rectangle we give them.
    00600          */
    00601         if (IntersectRect(&rcChildrenShare, &rcOurShare, &pwnd->rcClient) ||
    00602             (!TestWF(pwnd, WFWIN31COMPAT) && (hrgn == HRGN_FULL))) {
    00603
    00604             for (pwndChild = pwnd->spwndChild; pwndChild != NULL;
    00605                     pwndChild = pwndChild->spwndNext) {
    00606
    00607                 if (!TestWF(pwndChild, WFVISIBLE))
    00608                     continue;
    00609
    00610                 if (!InternalInvalidate2(pwndChild,
    00611                                          hrgn,
    00612                                          hrgnSubtract,
    00613                                          &rcChildrenShare,
    00614                                          flagsChildren)) {
    00615
    00616                     /*
    00617                      * The children swallowed the region:
    00618                      * If there are no update region related things
    00619                      * to do then we can just return with FALSE
    00620                      */
    00621                     if (!(flags & (RDW_INTERNALPAINT | RDW_NOINTERNALPAINT)))
    00622                         return FALSE;
    00623
    00624                     /*
    00625                      * We have to enumerate the rest of the children because
    00626                      * one of the RDW_NO/INTERNALPAINT bits is set.  Since
    00627                      * there's no longer any update region to worry about,
    00628                      * strip out the update region bits from the parent
    00629                      * and child fiags.  Also, tell the children not to
    00630                      * bother subtracting themselves from the region.
    00631                      */
    00632                     flags &= ~(RDW_INVALIDATE |
    00633                                RDW_ERASE      |
    00634                                RDW_FRAME      |
    00635                                RDW_VALIDATE   |
    00636                                RDW_NOERASE    |
    00637                                RDW_NOFRAME);
    00638
    00639                     flagsChildren &= ~(RDW_INVALIDATE |
    00640                                        RDW_ERASE      |
    00641                                        RDW_FRAME      |
    00642                                        RDW_VALIDATE   |
    00643                                        RDW_NOERASE    |
    00644                                        RDW_NOFRAME    |
    00645                                        RDW_SUBTRACTSELF);
    00646                 }
    00647             }
    00648         }
    00649     }
    00650
    00651     /*
    00652      * Go diddle the update region  (AFTER our clipped children may have
    00653      * done their thing to hrgnSubtract)
    00654      */
    00655     if (TestWF(pwnd, WFCLIPCHILDREN))
    00656         InternalInvalidate3(pwnd, hrgn, flags);
    00657
    00658     /*
    00659      * If we're invalidating and we're supposed to,
    00660      * try to subtract off our window area from the region.
    00661      *
    00662      * This way our parent and our siblings below us will not
    00663      * get any update region for areas that don't need one.
    00664      */
    00665     if (flags & RDW_SUBTRACTSELF) {
    00666
    00667         /*
    00668          * Subtract our visible region from the update rgn only if:
    00669          * a) we're not a transparent window
    00670          * b) we are clipsiblings
    00671          * c) we're validating OR our parent is clipchildren.
    00672          *
    00673          * The check for validation is a backward-compatibility hack: this
    00674          * is what 3.0 did, so this is what we do here.
    00675          *
    00676          * BACKWARD COMPATIBILITY HACK
    00677          *
    00678          * In 3.0, we subtracted this window from the update rgn if it
    00679          * was clipsiblings, even if the parent was not clipchildren.
    00680          * This causes a compatibility problem for Lotus Notes 3.1: it
    00681          * has a combobox dropdown in a dialog that is a WS_CLIPSIBLING
    00682          * sibling of the other dialog controls, which are not WS_CLIPSIBLINGs.
    00683          * The dialog is not WS_CLIPCHILDREN.  What happens is that a listbox
    00684          * underneath the dropdown also gets a paint msg (since we didn't
    00685          * do this subtraction), and, since it's not CLIPSIBLINGS, it
    00686          * obliterates the dropdown.
    00687          *
    00688          * This is a very obscure difference, and it's too late in the
    00689          * project to make this change now, so we're leaving the code as is
    00690          * and using a compatibility hack to enable the 3.0-compatible
    00691          * behavior.  It's quite likely that this code works the way it does
    00692          * for other compatibility reasons.  Sigh (neilk).
    00693          */
    00694         if (!TestWF(pwnd, WEFTRANSPARENT) &&
    00695             TestWF(pwnd, WFCLIPSIBLINGS)  &&
    00696             ((flags & RDW_VALIDATE) ||
    00697                  ((pwnd->spwndParent != NULL) &&
    00698                  (TestWF(pwnd->spwndParent, WFCLIPCHILDREN) ||
    00699                  (GetAppCompatFlags(GETPTI(pwnd)) & GACF_SUBTRACTCLIPSIBS))))) {
    00700
    00701             /*
    00702              * Intersect with our visible area.
    00703              *
    00704              * Don't worry about errors: an error will result in more, not less
    00705              * area being invalidated, which is okay.
    00706              */
    00707             SetRectRgnIndirect(ghrgnInv2, &rcOurShare);
    00708
    00709             /*
    00710              * If RDW_HASWINDOWRGN is set, either this window or
    00711              * one of its parents has a window clipping region. This
    00712              * flag is just an optimization so that this loop isn't
    00713              * executed all the time.
    00714              */
    00715             if (flags & RDW_HASWINDOWRGN) {
    00716
    00717                 /*
    00718                  * Clip to the window's clipping region and parents!
    00719                  * If we don't clip to parents, we may get a case where
    00720                  * a child clips out some update region that was meant to
    00721                  * go to a sibling of the parent.
    00722                  */
    00723                 for (pwndT = pwnd; pwndT != NULL; pwndT = pwndT->spwndParent) {
    00724
    00725                     if (pwndT->hrgnClip != NULL) {
    00726
    00727                         /*
    00728                          * An error at this stage would possibly result in more
    00729                          * being subtracted out of the clipping region that
    00730                          * we'd like.
    00731                          */
    00732                         IntersectRgn(ghrgnInv2, ghrgnInv2, pwndT->hrgnClip);
    00733                     }
    00734                 }
    00735             }
    00736
    00737
    00738 #if 1
    00739             /*
    00740              * TEMP HACK!!! RE-ENABLE this code when regions work again
    00741              */
    00742             if (SubtractRgn(hrgnSubtract, hrgnSubtract, ghrgnInv2) == NULLREGION)
    00743                 return FALSE;
    00744 #else
    00745             {
    00746             DWORD iRet;
    00747
    00748             iRet = SubtractRgn(hrgnSubtract, hrgnSubtract, ghrgnInv2);
    00749
    00750             if (iRet == NULLREGION)
    00751                 return FALSE;
    00752
    00753             if (iRet == SIMPLEREGION) {
    00754                 RECT rcSub;
    00755                 GreGetRgnBox(hrgnSubtract, &rcSub);
    00756                 if (rcSub.left > rcSub.right)
    00757                     return FALSE;
    00758             }
    00759             }
    00760 #endif
    00761
    00762
    00763
    00764         }
    00765     }
    00766
    00767     return TRUE;
    00768 }

VOID InternalInvalidate3 | ( | PWND | pwnd,
|  | HRGN | hrgn,
|  | DWORD | flags
| ) |

Definition at line 784 of file update.c.

References BOOL, CalcWindowRgn(), ClearHungFlag(), ClrWF, CopyRgn, CreateEmptyRgnPublic(), DecPaintCount(), DeleteMaybeSpecialRgn(), GETPTI, ghrgnInv2, HRGN_FULL, tagWND::hrgnUpdate, IncPaintCount(), NEEDSPAINT, NULL, PtiCurrent, RDW_IGNOREUPDATEDIRTY, SetHungFlag(), SetWF, SubtractRgn, TestWF, TRUE, UnionRgn, VOID(), WEFTRANSPARENT, WFDONTVALIDATE, WFINTERNALPAINT, WFNONCPAINT, WFPIXIEHACK, WFREDRAWIFHUNG, WFSENDERASEBKGND, WFSENDNCPAINT, WFUPDATEDIRTY, WFWIN31COMPAT, and WFWMPAINTSENT.

Referenced by InternalInvalidate2(), and xxxEndPaint().

    00788 {
    00789     BOOL fNeededPaint;
    00790
    00791     fNeededPaint = NEEDSPAINT(pwnd);
    00792
    00793     if (flags & (RDW_INVALIDATE | RDW_INTERNALPAINT | RDW_ERASE | RDW_FRAME)) {
    00794
    00795         if (flags & RDW_INTERNALPAINT)
    00796             SetWF(pwnd, WFINTERNALPAINT);
    00797
    00798         if (flags & RDW_INVALIDATE) {
    00799
    00800             /*
    00801              * Make sure that the NONCPAINT bit is cleared
    00802              * to ensure that the caption will redraw when we update.
    00803              */
    00804             ClrWF(pwnd, WFNONCPAINT);
    00805
    00806             /*
    00807              * If another app is invalidating this window, then set the
    00808              * UPDATEDIRTY flag.
    00809              *
    00810              * Solves critical section where thread A draws, then validates,
    00811              * but thread B goes and invalidates before A validates.
    00812              * See comments later in RDW_VALIDATE code.
    00813              */
    00814             if (GETPTI(pwnd) != PtiCurrent()) {
    00815
    00816                 SetWF(pwnd, WFUPDATEDIRTY);
    00817
    00818                 /*
    00819                  * Paint order problem, see paint.c
    00820                  */
    00821                 if (TestWF(pwnd, WFWMPAINTSENT)) {
    00822                     SetWF(pwnd, WFDONTVALIDATE);
    00823                 }
    00824             }
    00825
    00826             /*
    00827              * BACKWARD COMPATIBILITY HACK
    00828              *
    00829              * In 3.0, InvalidateRect(pwnd, NULL, FALSE) would always
    00830              * clear the WFSENDERASEBKGND flag, even if it was previously
    00831              * set from an InvalidateRect(pwnd, NULL, TRUE).  This is bogus,
    00832              * because it can cause you to "lose" WM_ERASEBKGND messages, but
    00833              * AttachMate Extra (and maybe other apps) depend on this behavior.
    00834              */
    00835             if ((hrgn == HRGN_FULL) && !TestWF(pwnd, WFWIN31COMPAT))
    00836                 ClrWF(pwnd, WFSENDERASEBKGND);
    00837
    00838             if (flags & RDW_ERASE)
    00839                 SetWF(pwnd, WFSENDERASEBKGND);
    00840
    00841             if ((flags & (RDW_FRAME | RDW_ERASE)) && !TestWF(pwnd, WEFTRANSPARENT))
    00842                 SetHungFlag(pwnd, WFREDRAWIFHUNG);
    00843
    00844             if (flags & RDW_FRAME)
    00845                 SetWF(pwnd, WFSENDNCPAINT);
    00846
    00847             /*
    00848              * If window is already completely invalidated,
    00849              * no need to do any further invalidation.
    00850              */
    00851             if (pwnd->hrgnUpdate != HRGN_FULL) {
    00852
    00853                 if (hrgn == HRGN_FULL) {
    00854 InvalidateAll:
    00855                     DeleteMaybeSpecialRgn(pwnd->hrgnUpdate);
    00856                     pwnd->hrgnUpdate = HRGN_FULL;
    00857
    00858                 } else {
    00859                     if (pwnd->hrgnUpdate == NULL) {
    00860
    00861                         if (!(pwnd->hrgnUpdate = CreateEmptyRgnPublic()))
    00862                             goto InvalidateAll;
    00863
    00864                         if (CopyRgn(pwnd->hrgnUpdate, hrgn) == ERROR)
    00865                             goto InvalidateAll;
    00866
    00867                     } else {   // pwnd->hrgnUpdate is a region
    00868
    00869                         if (UnionRgn(pwnd->hrgnUpdate,
    00870                                      pwnd->hrgnUpdate,
    00871                                      hrgn) == ERROR) {
    00872
    00873                             goto InvalidateAll;
    00874                         }
    00875                     }
    00876                 }
    00877             }
    00878         }
    00879
    00880         if (!fNeededPaint && NEEDSPAINT(pwnd))
    00881             IncPaintCount(pwnd);
    00882
    00883     } else if (flags & (RDW_VALIDATE | RDW_NOINTERNALPAINT | RDW_NOERASE | RDW_NOFRAME)) {
    00884
    00885         /*
    00886          * Validation:
    00887          *
    00888          * Do not allow validation if this window has been invalidated from
    00889          * another process - because this window may be validating just
    00890          * after another process invalidated, thereby validating invalid
    00891          * bits.
    00892          *
    00893          * Sometimes applications draw stuff, then validate what they drew.
    00894          * If another app invalidated some area during the drawing operation,
    00895          * then it will need another paint message.
    00896          *
    00897          * This wouldn't be necessary if people validated BEFORE they drew.
    00898          */
    00899         if (TestWF(pwnd, WFUPDATEDIRTY) && !(flags & RDW_IGNOREUPDATEDIRTY))
    00900             return;
    00901
    00902         if (flags & RDW_NOINTERNALPAINT)
    00903             ClrWF(pwnd, WFINTERNALPAINT);
    00904
    00905         if (flags & RDW_VALIDATE) {
    00906
    00907             if (flags & RDW_NOERASE)
    00908                 ClrWF(pwnd, WFSENDERASEBKGND);
    00909
    00910             if (flags & RDW_NOFRAME) {
    00911                 ClrWF(pwnd, WFSENDNCPAINT);
    00912                 ClrWF(pwnd, WFPIXIEHACK);
    00913             }
    00914
    00915             if (flags & (RDW_NOERASE | RDW_NOFRAME))
    00916                 ClearHungFlag(pwnd, WFREDRAWIFHUNG);
    00917
    00918             if (pwnd->hrgnUpdate != NULL) {
    00919
    00920                 /*
    00921                  * If WFSENDNCPAINT is set, then all or part of the
    00922                  * window border still needs to be drawn.  This means
    00923                  * that we must subtract off the client rectangle only.
    00924                  * Convert HRGN_FULL to the client region.
    00925                  */
    00926                 if (TestWF(pwnd, WFSENDNCPAINT) && (hrgn == HRGN_FULL)) {
    00927                     hrgn = ghrgnInv2;
    00928                     CalcWindowRgn(pwnd, hrgn, TRUE);
    00929                 }
    00930
    00931                 if (hrgn == HRGN_FULL) {
    00932 ValidateAll:
    00933
    00934                     /*
    00935                      * We're validating the entire window.  Just
    00936                      * blow away the update region.
    00937                      */
    00938                     DeleteMaybeSpecialRgn(pwnd->hrgnUpdate);
    00939                     pwnd->hrgnUpdate = (HRGN)NULL;
    00940
    00941                     /*
    00942                      * No need to erase the background...
    00943                      */
    00944                     ClrWF(pwnd, WFSENDERASEBKGND);
    00945                     ClearHungFlag(pwnd, WFREDRAWIFHUNG);
    00946
    00947                 } else {
    00948
    00949                     /*
    00950                      * Subtracting some region from pwnd->hrgnUpdate.
    00951                      * Be sure pwnd->hrgnUpdate is a real region.
    00952                      */
    00953                     if (pwnd->hrgnUpdate == HRGN_FULL) {
    00954
    00955                         /*
    00956                          * If the WFSENDNCPAINT bit is set,
    00957                          * the update region must include the entire window
    00958                          * area.  Otherwise it includes only the client.
    00959                          */
    00960                         pwnd->hrgnUpdate = CreateEmptyRgnPublic();
    00961
    00962                         /*
    00963                          * If the creation failed, punt by
    00964                          * invalidating the entire window.
    00965                          */
    00966                         if (pwnd->hrgnUpdate == NULL)
    00967                             goto InvalidateAll;
    00968
    00969                         if (CalcWindowRgn(pwnd,
    00970                                           pwnd->hrgnUpdate,
    00971                                           !(TestWF(pwnd, WFSENDNCPAINT))) == ERROR) {
    00972
    00973                             goto InvalidateAll;
    00974                         }
    00975                     }
    00976
    00977                     /*
    00978                      * Subtract off the region.  If we get an error,
    00979                      * punt by invalidating everything.  If the
    00980                      * region becomes empty, then validate everything.
    00981                      */
    00982                     switch (SubtractRgn(pwnd->hrgnUpdate,
    00983                                         pwnd->hrgnUpdate,
    00984                                         hrgn)) {
    00985                     case ERROR:
    00986                         goto InvalidateAll;
    00987
    00988                     case NULLREGION:
    00989                         goto ValidateAll;
    00990                     }
    00991                 }
    00992             }
    00993         }
    00994
    00995         if (fNeededPaint && !NEEDSPAINT(pwnd))
    00996             DecPaintCount(pwnd);
    00997     }
    00998 }

BOOL IntersectWithParents | ( | PWND | pwnd,
|  | LPRECT | lprc
| ) |

Definition at line 1772 of file update.c.

References BOOL, FALSE, FLayeredOrRedirected(), IntersectRect(), NULL, tagWND::rcClient, tagWND::spwndParent, TestWF, TRUE, WFMINIMIZED, and WFVISIBLE.

Referenced by SpbTransfer(), ValidateParents(), xxxGetUpdateRect(), xxxGetUpdateRgn(), and xxxInternalInvalidate().

    01775 {
    01776     if (FLayeredOrRedirected(pwnd))
    01777         return TRUE;
    01778
    01779     while ((pwnd = pwnd->spwndParent) != NULL) {
    01780
    01781         if (!TestWF(pwnd, WFVISIBLE) || TestWF(pwnd, WFMINIMIZED))
    01782             return FALSE;
    01783
    01784         if (!IntersectRect(lprc, lprc, &pwnd->rcClient))
    01785             return FALSE;
    01786
    01787         if (FLayeredOrRedirected(pwnd))
    01788             return TRUE;
    01789     }
    01790
    01791     return TRUE;
    01792 }

VOID PixieHack | ( | PWND | pwnd,
|  | LPRECT | prcBounds
| ) |

Definition at line 239 of file update.c.

References _GetDesktopWindow(), IntersectRect(), LOBYTE, tagWND::rcWindow, SetWF, tagWND::spwndChild, tagWND::spwndNext, TestWF, VOID(), WFBORDERMASK, WFCAPTION, WFCLIPCHILDREN, WFMINIMIZED, WFPIXIEHACK, and WFSENDNCPAINT.

Referenced by InternalInvalidate2().

    00242 {
    00243     /*
    00244      * If a child intersects the update region, and it isn't already
    00245      * getting an NCPAINT, then make sure it gets one later.
    00246      *
    00247      * Don't apply this hack to top level windows.
    00248      */
    00249     if ((pwnd != _GetDesktopWindow()) &&
    00250         TestWF(pwnd, WFCLIPCHILDREN)  &&
    00251         !TestWF(pwnd, WFMINIMIZED)) {
    00252
    00253         RECT rc;
    00254
    00255         for (pwnd = pwnd->spwndChild; pwnd; pwnd = pwnd->spwndNext) {
    00256
    00257             /*
    00258              * If the window isn't already getting an NCPAINT message,
    00259              * and it has a caption, and it's inside the bounding rect,
    00260              * make sure it gets a WM_NCPAINT with wParam == HRGN_FULL.
    00261              */
    00262             if (!TestWF(pwnd, WFSENDNCPAINT)                      &&
    00263                 (TestWF(pwnd, WFBORDERMASK) == LOBYTE(WFCAPTION)) &&
    00264                 IntersectRect(&rc, prcBounds, &pwnd->rcWindow)) {
    00265
    00266                 /*
    00267                  * Sync paint count is incremented when
    00268                  * (senderasebkgnd | sendncpaint) goes from 0 to != 0.
    00269                  * (should make a routine out of this!)
    00270                  */
    00271                 SetWF(pwnd, WFSENDNCPAINT);
    00272
    00273                 /*
    00274                  * Force HRGN_FULL clip rgn.
    00275                  */
    00276                 SetWF(pwnd, WFPIXIEHACK);
    00277             }
    00278         }
    00279     }
    00280 }

UINT SmartRectInRegion | ( | HRGN | hrgn,
|  | LPRECT | lprc
| ) |

Definition at line 159 of file update.c.

References EqualRect, ghrgnInv2, IntersectRect(), IntersectRgn, RIR_INSIDE, RIR_INTERSECT, RIR_OUTSIDE, SetRectRgnIndirect(), and UINT.

Referenced by InternalInvalidate2().

    00162 {
    00163     RECT rc;
    00164
    00165     if (!GreRectInRegion(hrgn, lprc))
    00166         return RIR_OUTSIDE;
    00167
    00168     /*
    00169      * Algorithm: if the intersection of hrgn and *lprc is the
    00170      * same as *lprc, then *lprc is completely within hrgn.
    00171      *
    00172      * If the region is a rectangular one, then do it the easy way.
    00173      */
    00174     if (GreGetRgnBox(hrgn, &rc) == SIMPLEREGION) {
    00175
    00176         if (!IntersectRect(&rc, &rc, lprc))
    00177             return RIR_OUTSIDE;
    00178
    00179         if (EqualRect(lprc, &rc))
    00180             return RIR_INSIDE;
    00181
    00182     } else {
    00183
    00184         SetRectRgnIndirect(ghrgnInv2, lprc);
    00185
    00186         switch (IntersectRgn(ghrgnInv2, ghrgnInv2, hrgn)) {
    00187
    00188         case SIMPLEREGION:
    00189             GreGetRgnBox(ghrgnInv2, &rc);
    00190             if (EqualRect(lprc, &rc))
    00191                 return RIR_INSIDE;
    00192             break;
    00193
    00194 #define RECTINREGION_BUG
    00195 #ifdef RECTINREGION_BUG
    00196
    00197         /*
    00198          * NOTE: RectInRegion has a BUG, where it sometimes returns TRUE
    00199          * even if the rectangles of a region touch only on the edges
    00200          * with no overlap.  This will result in an empty region after
    00201          * the combination above.
    00202          */
    00203         case NULLREGION:
    00204             return RIR_OUTSIDE;
    00205             break;
    00206 #endif
    00207
    00208         default:
    00209             break;
    00210         }
    00211     }
    00212
    00213     return RIR_INTERSECT;
    00214 }

BOOL ValidateParents | ( | PWND | pwnd,
|  | BOOL | fRecurse
| ) |

Definition at line 1019 of file update.c.

References BOOL, FALSE, ghrgnInv1, tagWND::hrgnUpdate, InternalInvalidate2(), IntersectRgn, IntersectWithParents(), NULL, tagWND::rcWindow, RDW_IGNOREUPDATEDIRTY, SetRectRgnIndirect(), tagWND::spwndParent, TestWF, TRUE, WFCHILD, WFCLIPCHILDREN, and WFSYNCPAINTPENDING.

Referenced by xxxUpdateWindow2().

    01022 {
    01023     RECT rcParents;
    01024     RECT rc;
    01025     PWND pwndParent = pwnd;
    01026     BOOL fInit = FALSE;
    01027
    01028     /*
    01029      * This is checking whether we are in an in-between state, just before
    01030      * a WM_SYNCPAINT is about to arrive.  If not, then ValidateParents()
    01031      * needs to work like it did in Win 3.1.
    01032      */
    01033     while (TestWF(pwndParent, WFCHILD))
    01034         pwndParent = pwndParent->spwndParent;
    01035
    01036     if (!TestWF(pwndParent, WFSYNCPAINTPENDING))
    01037         fRecurse = FALSE;
    01038
    01039     pwndParent = pwnd;
    01040
    01041     while ((pwndParent = pwndParent->spwndParent) != NULL) {
    01042
    01043         /*
    01044          * Stop when we find a clipchildren parent
    01045          */
    01046         if (TestWF(pwndParent, WFCLIPCHILDREN))
    01047             break;
    01048
    01049         /*
    01050          * Subtract the region from this parent's update region,
    01051          * if it has one.
    01052          */
    01053         if (pwndParent->hrgnUpdate != NULL) {
    01054             if (fRecurse) {
    01055                 return FALSE;
    01056             }
    01057             if (!fInit) {
    01058                 fInit = TRUE;
    01059
    01060                 /*
    01061                  * Do initial setup.  If our window rectangle is
    01062                  * completely obscured, get out.
    01063                  */
    01064                 rc = pwnd->rcWindow;
    01065                 if (!IntersectWithParents(pwnd, &rc))
    01066                     break;
    01067
    01068                 SetRectRgnIndirect(ghrgnInv1, &rc);
    01069
    01070                 /*
    01071                  * If this window has a region, make sure the piece being validated
    01072                  * is within this region.
    01073                  */
    01074                 if (pwnd->hrgnClip != NULL) {
    01075
    01076                     /*
    01077                      * If we get NULLREGION back, there is nothing to validate
    01078                      * against parents, so break out. If ERROR gets returned,
    01079                      * there is not much we can do: the best "wrong" thing
    01080                      * to do is just continue and validate a little more
    01081                      * from the parent.
    01082                      */
    01083                     if (!IntersectRgn(ghrgnInv1, ghrgnInv1, pwnd->hrgnClip))
    01084                         break;
    01085                 }
    01086             }
    01087
    01088             /*
    01089              * Calculate the rcParents parameter to
    01090              * pass up to InternalInvalidate2.
    01091              */
    01092             rcParents = pwndParent->rcWindow;
    01093
    01094             if (!IntersectWithParents(pwndParent, &rcParents))
    01095                 break;
    01096
    01097             InternalInvalidate2(
    01098                     pwndParent,
    01099                     ghrgnInv1,
    01100                     ghrgnInv1,
    01101                     &rcParents,
    01102                     RDW_VALIDATE | RDW_NOCHILDREN | RDW_IGNOREUPDATEDIRTY);
    01103         }
    01104     }
    01105
    01106     return TRUE;
    01107 }

BOOL xxxGetUpdateRect | ( | PWND | pwnd,
|  | LPRECT | lprc,
|  | BOOL | fErase
| ) |

Definition at line 1525 of file update.c.

References BOOL, CFOWNDC, CheckLock, ClrWF, tagDCE::DCX_flags, FALSE, gpDispInfo, tagDCE::hdc, HRGN_FULL, tagWND::hrgnUpdate, IntersectRect(), IntersectWithParents(), NULL, OffsetRect(), tagDISPLAYINFO::pdceFirst, tagDCE::pdceNext, PWNDDESKTOP, tagDCE::pwndOrg, tagWND::rcClient, SetRectEmpty, TestCF, TestWF, TRUE, WFUPDATEDIRTY, WFWIN31COMPAT, and xxxSimpleDoSyncPaint().

Referenced by NtUserGetUpdateRect().

    01529 {
    01530     RECT rc;
    01531
    01532     CheckLock(pwnd);
    01533
    01534     if (fErase)
    01535         xxxSimpleDoSyncPaint(pwnd);
    01536
    01537     /*
    01538      * The app is looking at the update region: okay to allow window
    01539      * validation.
    01540      */
    01541     ClrWF(pwnd, WFUPDATEDIRTY);
    01542
    01543     if (pwnd->hrgnUpdate == NULL) {
    01544
    01545         if (lprc) {
    01546             SetRectEmpty(lprc);
    01547         }
    01548
    01549         return FALSE;
    01550
    01551     } else {
    01552
    01553         /*
    01554          * We must handle the case where a window has an update region,
    01555          * but it is completely obscured by its parents.  In this case, we
    01556          * must validate the window and all its children, and return FALSE.
    01557          *
    01558          * An OffsetChildren() call resulting from SetWindowPos() or
    01559          * ScrollWindowEx() will cause this to happen.  Update regions are
    01560          * just offset without checking their new positions to see if they
    01561          * are obscured by the parent(s).  This is too painful to check in
    01562          * those cases, so we instead handle it here.
    01563          *
    01564          * BeginPaint() handles this case correctly by returning an empty
    01565          * rectangle, so nothing special need be done there.
    01566          */
    01567         if (pwnd->hrgnUpdate == HRGN_FULL) {
    01568
    01569             rc = pwnd->rcClient;
    01570
    01571         } else {
    01572
    01573             switch (GreGetRgnBox(pwnd->hrgnUpdate, &rc)) {
    01574             case ERROR:
    01575             case NULLREGION:
    01576                 SetRectEmpty(&rc);
    01577                 break;
    01578
    01579             case SIMPLEREGION:
    01580             case COMPLEXREGION:
    01581                 break;
    01582             }
    01583
    01584             IntersectRect(&rc, &rc, &pwnd->rcClient);
    01585         }
    01586
    01587         if (IntersectWithParents(pwnd, &rc)) {
    01588
    01589             if (pwnd != PWNDDESKTOP(pwnd)) {
    01590                 OffsetRect(&rc, -pwnd->rcClient.left, -pwnd->rcClient.top);
    01591             }
    01592
    01593             /*
    01594              * If the window is CS_OWNDC, then we must map the returned
    01595              * rectangle with DPtoLP, to ensure that the rectangle is
    01596              * in the same coordinate system as the rectangle returned
    01597              * by BeginPaint().
    01598              *
    01599              * BUT ONLY IF hwnd->hrgnUpdate != HRGN_FULL! For true
    01600              * compatibility with 3.0.
    01601              */
    01602             if (TestCF(pwnd, CFOWNDC) &&
    01603                 (TestWF(pwnd, WFWIN31COMPAT) || pwnd->hrgnUpdate != HRGN_FULL)) {
    01604
    01605                 PDCE pdce;
    01606
    01607                 /*
    01608                  * Look up this window's DC in the cache, and use it to
    01609                  * map the returned rectangle.
    01610                  */
    01611                 for (pdce = gpDispInfo->pdceFirst; pdce; pdce = pdce->pdceNext) {
    01612
    01613                     if (pdce->pwndOrg == pwnd && !(pdce->DCX_flags & DCX_CACHE)) {
    01614                         GreDPtoLP(pdce->hdc, (LPPOINT)&rc, 2);
    01615                         break;
    01616                     }
    01617                 }
    01618             }
    01619
    01620         } else {
    01621            SetRectEmpty(&rc);
    01622         }
    01623     }
    01624
    01625     if (lprc) {
    01626 #ifdef USE_MIRRORING
    01627         if (TestWF(pwnd, WEFLAYOUTRTL)) {
    01628             MirrorRect(pwnd, &rc);
    01629         }
    01630 #endif
    01631         *lprc = rc;
    01632     }
    01633
    01634     /*
    01635      * If we're in the process a dragging a full window, mark the start
    01636      * of the application painting. This is to make sure that if the
    01637      * application calls DefWindowProc on the WM_PAINT after painting, we
    01638      * won't erase the newly painted areas. Visual Slick calls GetUpdateRect
    01639      * and then DefWindowProc.
    01640      * See other comments for xxxBeginPaint and xxxDWP_Paint.
    01641      * 8/3/94 johannec
    01642      *
    01643      * NOTE: This causes other problems in vslick where some controls
    01644      *       won't paint.  Since the app doesn't call BeginPaint/EndPaint
    01645      *       to truly set/clear the STARTPAINT flag, we do not clear this
    01646      *       bit. (6-27-1996 : ChrisWil).
    01647      *
    01648      *
    01649      *  if (TEST_PUDF(PUDF_DRAGGINGFULLWINDOW)) {
    01650      *      SetWF(pwnd, WFSTARTPAINT);
    01651      *  }
    01652      */
    01653
    01654     return TRUE;
    01655 }

int xxxGetUpdateRgn | ( | PWND | pwnd,
|  | HRGN | hrgn,
|  | BOOL | fErase
| ) |

Definition at line 1665 of file update.c.

References BOOL, CheckLock, ClrWF, ghrgnInv2, HRGN_FULL, tagWND::hrgnUpdate, IntersectRgn, IntersectWithParents(), NULL, OffsetRect(), PWNDDESKTOP, tagWND::rcClient, SetEmptyRgn(), SetRectRgnIndirect(), TRUE, WFUPDATEDIRTY, and xxxSimpleDoSyncPaint().

Referenced by NtUserGetUpdateRgn().

    01669 {
    01670     RECT rc;
    01671     int  code;
    01672     BOOL fNotEmpty;
    01673
    01674
    01675     CheckLock(pwnd);
    01676
    01677     if (fErase)
    01678         xxxSimpleDoSyncPaint(pwnd);
    01679
    01680     /*
    01681      * The application is looking at the update region: okay to
    01682      * allow validation
    01683      */
    01684     ClrWF(pwnd, WFUPDATEDIRTY);
    01685
    01686     if (pwnd->hrgnUpdate == NULL)
    01687         goto ReturnEmpty;
    01688
    01689     rc = pwnd->rcClient;
    01690     fNotEmpty = IntersectWithParents(pwnd, &rc);
    01691
    01692     if (pwnd->hrgnUpdate == HRGN_FULL) {
    01693
    01694         /*
    01695          * Since the update region may be larger than the window
    01696          * rectangle, intersect it with the window rectangle.
    01697          */
    01698         if (!fNotEmpty)
    01699             goto ReturnEmpty;
    01700
    01701         code = SIMPLEREGION;
    01702
    01703         /*
    01704          * Normalize the rectangle\region relative to the unclipped window
    01705          */
    01706         if (pwnd != PWNDDESKTOP(pwnd)) {
    01707             OffsetRect(&rc, -pwnd->rcClient.left, -pwnd->rcClient.top);
    01708         }
    01709
    01710         SetRectRgnIndirect(hrgn, &rc);
    01711
    01712     } else {
    01713
    01714         SetRectRgnIndirect(ghrgnInv2, &rc);
    01715         code = IntersectRgn(hrgn, ghrgnInv2, pwnd->hrgnUpdate);
    01716
    01717         switch (code) {
    01718         case NULLREGION:
    01719         case ERROR:
    01720             goto ReturnEmpty;
    01721
    01722         default:
    01723             if (pwnd != PWNDDESKTOP(pwnd)) {
    01724                 GreOffsetRgn(hrgn, -pwnd->rcClient.left, -pwnd->rcClient.top);
    01725             }
    01726             break;
    01727         }
    01728     }
    01729
    01730 #ifdef USE_MIRRORING
    01731     MirrorRegion(pwnd, hrgn, TRUE);
    01732 #endif
    01733     /*
    01734      * If we're in the process a dragging a full window, mark the start
    01735      * of the application painting. This is to make sure that if the
    01736      * application calls DefWindowProc on the WM_PAINT after painting, we
    01737      * won't erase the newly painted areas.
    01738      * See other comments for xxxBeginPaint and xxxDWP_Paint.
    01739      * 8/3/94 johannec
    01740      *
    01741      * NOTE: This causes other problems in vslick where some controls
    01742      *       won't paint.  Since the app doesn't call BeginPaint/EndPaint
    01743      *       to truly set/clear the STARTPAINT flag, we do not clear this
    01744      *       bit. (6-27-1996 : ChrisWil).
    01745      *
    01746      *  if (TEST(PUDF(PUDF_DRAGGINGFULLWINDOW)) {
    01747      *      SetWF(pwnd, WFSTARTPAINT);
    01748      *  }
    01749      */
    01750
    01751     return code;
    01752
    01753 ReturnEmpty:
    01754     SetEmptyRgn(hrgn);
    01755     return NULLREGION;
    01756 }

VOID xxxInternalInvalidate | ( | PWND | pwnd,
|  | HRGN | hrgnUpdate,
|  | DWORD | flags
| ) |

Definition at line 1302 of file update.c.

References AnySpbs, CalcWindowRgn(), CheckLock, DSP_ALLCHILDREN, DSP_ENUMCLIPPEDCHILDREN, FALSE, FLayeredOrRedirected(), ghrgnInv1, HRGN_FULL, InternalInvalidate2(), IntersectRect(), IntersectWithParents(), tagWND::rcClient, tagWND::rcWindow, SetEmptyRgn(), SpbCheckRect(), TRUE, UINT, UW_ENUMCHILDREN, VOID(), xxxDoSyncPaint(), and xxxInternalUpdateWindow().

Referenced by CreateRedirectionBitmap(), LockWindowUpdate2(), SpbTransfer(), UserRedrawDesktop(), xxxRedrawHungWindow(), xxxRedrawWindow(), xxxScrollWindowEx(), xxxSystemParametersInfo(), xxxUserChangeDisplaySettings(), and zzzBltValidBits().

    01306 {
    01307     RECT rcParents;
    01308     HRGN hrgnSubtract;
    01309
    01310 #if DBG
    01311     if (flags & (RDW_ERASENOW | RDW_UPDATENOW)) {
    01312         CheckLock(pwnd);
    01313     }
    01314 #endif
    01315
    01316     /*
    01317      * Allow invalidation of a layered window when someone specifically
    01318      * invalidates it.  This will also prevent invalidation of layered
    01319      * windows during recursive desktop invalidations.
    01320      */
    01321     if (FLayeredOrRedirected(pwnd)) {
    01322         flags |= RDW_INVALIDATELAYERS;
    01323     }
    01324
    01325     /*
    01326      * Ensure that hrgnSubtract is a valid region: if it's NULLREGION,
    01327      * use the client region.
    01328      */
    01329     rcParents = (flags & RDW_FRAME ? pwnd->rcWindow : pwnd->rcClient);
    01330
    01331     if (flags & (RDW_VALIDATE | RDW_INVALIDATE)) {
    01332
    01333         hrgnSubtract = hrgnUpdate;
    01334
    01335         if (hrgnSubtract == HRGN_FULL) {
    01336
    01337             hrgnSubtract = ghrgnInv1;
    01338             CalcWindowRgn(pwnd,
    01339                           hrgnSubtract,
    01340                           (flags & RDW_FRAME) ? FALSE : TRUE);
    01341         }
    01342
    01343         /*
    01344          * Calculate the bounding rectangle of our screen real estate,
    01345          * by intersecting with our parent rectangles.  While we're at
    01346          * it, check the visibility of ourself and our parents.
    01347          *
    01348          * If we're validating we want to skip this, since there
    01349          * are a number of cases where obscured windows may have
    01350          * update regions to be validated -- in particular, after
    01351          * a ScrollWindow() call where a child window was offset
    01352          * by OffsetChildren() to a new, obscured position.  Some of
    01353          * the 3.0 compatibility hacks also can lead to this situation.
    01354          */
    01355         if ((flags & RDW_INVALIDATE) && !IntersectWithParents(pwnd, &rcParents))
    01356             return;
    01357
    01358     } else {
    01359         /*
    01360          * hrgnsubtract needs to be a real region even if
    01361          * we are not invalidating or validating.  It really doesn't
    01362          * matter what the region is, but we set it to null so the code
    01363          * has less degrees of freedom.
    01364          */
    01365         hrgnSubtract = ghrgnInv1;
    01366         SetEmptyRgn(hrgnSubtract);
    01367     }
    01368
    01369     /*
    01370      * If we're invalidating, and we're being called by the app,
    01371      * we need to invalidate any SPBs that might be affected by
    01372      * drawing in the client area of this window.
    01373      * We have to do this because there is no guarantee that the
    01374      * application will draw in an area that is invalidated
    01375      * (e.g., if the window is completely obscured by another).
    01376      */
    01377     if (    (flags & (RDW_INVALIDATE | RDW_REDRAWWINDOW)) == (RDW_INVALIDATE | RDW_REDRAWWINDOW) &&
    01378             AnySpbs()) {
    01379
    01380         RECT rcInvalid;
    01381
    01382         /*
    01383          * Intersect the parent's rect with the region bounds...
    01384          */
    01385         GreGetRgnBox(hrgnSubtract, &rcInvalid);
    01386         IntersectRect(&rcInvalid, &rcInvalid, &rcParents);
    01387         SpbCheckRect(pwnd, &rcInvalid, 0);
    01388     }
    01389
    01390     /*
    01391      * Now go do the recursive update region calculations...
    01392      */
    01393     InternalInvalidate2(pwnd, hrgnUpdate, hrgnSubtract, &rcParents, flags);
    01394
    01395     /*
    01396      * Finally handle any needed drawing.
    01397      *
    01398      * (NOTE: RDW_UPDATENOW implies RDW_ERASENOW)
    01399      */
    01400     if (flags & RDW_UPDATENOW) {
    01401
    01402         xxxInternalUpdateWindow(pwnd,
    01403                                 flags & RDW_NOCHILDREN ? 0 : UW_ENUMCHILDREN);
    01404
    01405     } else if (flags & RDW_ERASENOW) {
    01406
    01407         UINT flagsDSP;
    01408
    01409         if (flags & RDW_NOCHILDREN) {
    01410             flagsDSP = 0;
    01411         } else if (flags & RDW_ALLCHILDREN) {
    01412             flagsDSP = DSP_ALLCHILDREN;
    01413         } else {
    01414             flagsDSP = DSP_ENUMCLIPPEDCHILDREN;
    01415         }
    01416
    01417         xxxDoSyncPaint(pwnd, flagsDSP);
    01418     }
    01419 }

void xxxInternalUpdateWindow | ( | PWND | pwnd,
|  | DWORD | flags
| ) |

Definition at line 1259 of file update.c.

References CheckLock, GETPTI, NEEDSPAINT, NULL, tagWND::spwndNext, TestWF, WEFTRANSPARENT, and xxxUpdateWindow2().

Referenced by xxxInternalInvalidate(), and xxxUpdateWindow().

    01262 {
    01263     CheckLock(pwnd);
    01264
    01265     /*
    01266      * If the passed-in window is transparent and a sibling below
    01267      * needs repainting, don't do anything.
    01268      */
    01269     if (TestWF(pwnd, WEFTRANSPARENT)) {
    01270
    01271         PWND         pwndT = pwnd;
    01272         PTHREADINFO ptiCurrent = GETPTI(pwnd);
    01273
    01274         while ((pwndT = pwndT->spwndNext) != NULL) {
    01275
    01276             /*
    01277              * Make sure sibling window belongs to same app.
    01278              */
    01279             if (GETPTI(pwndT) != ptiCurrent)
    01280                 continue;
    01281
    01282             if (NEEDSPAINT(pwndT))
    01283                 return;
    01284         }
    01285     }
    01286
    01287     /*
    01288      * Enumerate pwnd and all its children, sending WM_PAINTs as needed.
    01289      */
    01290     xxxUpdateWindow2(pwnd, flags);
    01291 }

BOOL xxxInvalidateRect | ( | PWND | pwnd,
|  | LPRECT | lprcInvalid,
|  | BOOL | fErase
| ) |

Definition at line 39 of file update.c.

References BOOL, CheckLock, NULL, and xxxRedrawWindow().

Referenced by NtUserInvalidateRect(), xxxEnableSBCtlArrows(), xxxMNSetGapState(), xxxMNSetTop(), and xxxMNUpdateShownMenu().

    00043 {
    00044     CheckLock(pwnd);
    00045
    00046     /*
    00047      * BACKWARD COMPATIBILITY HACK
    00048      *
    00049      * In Windows 3.0 and less, ValidateRect/InvalidateRect() call with
    00050      * hwnd == NULL always INVALIDATED and ERASED the entire desktop, and
    00051      * synchronously sent WM_ERASEBKGND and WM_NCPAINT messages before
    00052      * returning.  The Rgn() calls did not have this behavior.
    00053      */
    00054     if (pwnd == NULL) {
    00055         return xxxRedrawWindow(
    00056                 pwnd,
    00057                 NULL,
    00058                 NULL,
    00059                 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW);
    00060     } else {
    00061         return xxxRedrawWindow(
    00062                 pwnd,
    00063                 lprcInvalid,
    00064                 NULL,
    00065                 fErase ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE);
    00066     }
    00067 }

BOOL xxxInvalidateRgn | ( | PWND | pwnd,
|  | HRGN | hrgnInvalid,
|  | BOOL | fErase
| ) |

Definition at line 110 of file update.c.

References BOOL, CheckLock, NULL, and xxxRedrawWindow().

Referenced by NtUserInvalidateRgn().

    00114 {
    00115     CheckLock(pwnd);
    00116
    00117     return xxxRedrawWindow(
    00118             pwnd,
    00119             NULL,
    00120             hrgnInvalid,
    00121             fErase ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE);
    00122 }

BOOL xxxRedrawWindow | ( | PWND | pwnd,
|  | LPRECT | lprcUpdate,
|  | HRGN | hrgnUpdate,
|  | DWORD | flags
| ) |

Definition at line 299 of file update.c.

References BOOL, CheckLock, CopyRgn, ghrgnInv0, HRGN_FULL, IsVisible(), NULL, PtiCurrent, PWNDDESKTOP, tagWND::rcClient, SetRectRgnIndirect(), TestWF, ThreadLock, ThreadUnlock, TRUE, and xxxInternalInvalidate().

Referenced by NtUserRedrawWindow(), RemoteRedrawRectangle(), xxxDesktopWndProc(), xxxDestroyWindow(), xxxInvalidateDesktopOnPaletteChange(), xxxInvalidateRect(), xxxInvalidateRgn(), xxxMakeWindowForegroundWithState(), xxxMinimizeHungWindow(), xxxScrollWindowEx(), xxxSetLayeredWindow(), xxxSetWindowPos(), xxxUserResetDisplayDevice(), xxxValidateRect(), and xxxValidateRgn().

    00304 {
    00305     CheckLock(pwnd);
    00306
    00307     /*
    00308      * Always map NULL to the desktop.
    00309      */
    00310     if (pwnd == NULL) {
    00311         pwnd = PtiCurrent()->rpdesk->pDeskInfo->spwnd;
    00312     }
    00313
    00314     UserAssert(pwnd != NULL);
    00315
    00316     if (IsVisible(pwnd)) {
    00317
    00318         TL   tlpwnd;
    00319         HRGN hrgn = hrgnUpdate;
    00320
    00321         if (flags & (RDW_VALIDATE | RDW_INVALIDATE)) {
    00322
    00323             /*
    00324              * Create a (in)validate region in client window coordinates.
    00325              */
    00326             if (hrgn == NULL) {
    00327                 if (!lprcUpdate) {
    00328                     hrgn = HRGN_FULL;
    00329                 } else {
    00330                     hrgn = ghrgnInv0;
    00331
    00332 #ifdef USE_MIRRORING
    00333                     if (TestWF(pwnd, WEFLAYOUTRTL)) {
    00334                         MirrorRect(pwnd, lprcUpdate);
    00335                     }
    00336 #endif
    00337
    00338                     if (pwnd == PWNDDESKTOP(pwnd)) {
    00339                         SetRectRgnIndirect(hrgn, lprcUpdate);
    00340                     } else {
    00341                         GreSetRectRgn(
    00342                                 hrgn,
    00343                                 lprcUpdate->left + pwnd->rcClient.left,
    00344                                 lprcUpdate->top + pwnd->rcClient.top,
    00345                                 lprcUpdate->right + pwnd->rcClient.left,
    00346                                 lprcUpdate->bottom + pwnd->rcClient.top);
    00347                     }
    00348                 }
    00349             } else {
    00350                 /*
    00351                  * If necessary, make a copy of the passed-in region, because
    00352                  * we'll be trashing it...
    00353                  */
    00354                 if (hrgn != HRGN_FULL) {
    00355                     CopyRgn(ghrgnInv0, hrgn);
    00356
    00357 #ifdef USE_MIRRORING
    00358                     MirrorRegion(pwnd, ghrgnInv0, TRUE);
    00359 #endif
    00360
    00361                     hrgn = ghrgnInv0;
    00362                 }
    00363
    00364                 if (pwnd != PWNDDESKTOP(pwnd)) {
    00365                     GreOffsetRgn(hrgn, pwnd->rcClient.left, pwnd->rcClient.top);
    00366                 }
    00367             }
    00368         }
    00369
    00370         ThreadLock(pwnd, &tlpwnd);
    00371         xxxInternalInvalidate(pwnd, hrgn, flags | RDW_REDRAWWINDOW);
    00372         ThreadUnlock(&tlpwnd);
    00373     }
    00374
    00375     return TRUE;
    00376 }

BOOL xxxUpdateWindow | ( | PWND | pwnd | ) |

Definition at line 1430 of file update.c.

References BOOL, CheckLock, TRUE, UW_ENUMCHILDREN, and xxxInternalUpdateWindow().

Referenced by xxxbFullscreenSwitch(), xxxDragObject(), xxxMNInvertItem(), xxxMNOpenHierarchy(), xxxShowSwitchWindow(), and xxxUpdateThreadsWindows().

    01432 {
    01433     CheckLock(pwnd);
    01434
    01435     xxxInternalUpdateWindow(pwnd, UW_ENUMCHILDREN);
    01436
    01437     /*
    01438      * This function needs to return a value, since it is
    01439      * called through NtUserCallHwndLock.
    01440      */
    01441     return TRUE;
    01442 }

void xxxUpdateWindow2 | ( | PWND | pwnd,
|  | DWORD | flags
| ) |

Definition at line 1121 of file update.c.

References CheckLock, ClrWF, DecPaintCount(), FALSE, tagWND::hrgnUpdate, L, NEEDSPAINT, NULL, tagWND::pcls, PWNDDESKTOP, SetWF, tagWND::spwndChild, tagWND::spwndNext, TestWF, ThreadLockExchangeAlways(), ThreadLockNever, ThreadUnlock, TRUE, UW_ENUMCHILDREN, UW_RECURSED, ValidateParents(), WEFTRANSPARENT, WFINTERNALPAINT, WFMINIMIZED, WFPAINTNOTPROCESSED, WFUPDATEDIRTY, WFWIN40COMPAT, xxxSendMessage(), and xxxSimpleDoSyncPaint().

Referenced by xxxInternalUpdateWindow().

    01124 {
    01125     TL tlpwnd;
    01126
    01127     CheckLock(pwnd);
    01128
    01129     if (NEEDSPAINT(pwnd)) {
    01130
    01131         /*
    01132          * Punch a hole in our parent's update region, if we have one.
    01133          */
    01134         if (pwnd->hrgnUpdate) {
    01135             if (ValidateParents(pwnd, flags & UW_RECURSED) == FALSE) {
    01136                 return;
    01137             }
    01138         }
    01139
    01140         /*
    01141          * Now that we're sending the message, clear the
    01142          * internal paint bit if it was previously set.
    01143          */
    01144         if (TestWF(pwnd, WFINTERNALPAINT)) {
    01145
    01146             ClrWF(pwnd, WFINTERNALPAINT);
    01147
    01148             /*
    01149              * If there is no update region, then no further paint messages
    01150              * are pending, so we must dec the paint count.
    01151              */
    01152             if (pwnd->hrgnUpdate == NULL)
    01153                 DecPaintCount(pwnd);
    01154         }
    01155
    01156         /*
    01157          * Set a flag indicating that a paint message was not processed
    01158          * (but should be).
    01159          */
    01160         SetWF(pwnd, WFPAINTNOTPROCESSED);
    01161
    01162         /*
    01163          * Clear this bit, for apps (like MicroLink) that don't call
    01164          * BeginPaint or GetUpdateRect/Rgn (but DO call ValidateRect)
    01165          * when handling their WM_PAINT message.
    01166          */
    01167         ClrWF(pwnd, WFUPDATEDIRTY);
    01168
    01169         /*
    01170          * BACKWARD COMPATIBILITY HACK
    01171          *
    01172          * Win 3.0 always sent WM_PAINTICON with wParam == TRUE for no good
    01173          * reason, and Lotus Notes has come to depend on this.
    01174          */
    01175         if (!TestWF(pwnd, WFWIN40COMPAT) &&
    01176             TestWF(pwnd, WFMINIMIZED)    &&
    01177             (pwnd->pcls->spicn != NULL)) {
    01178
    01179             xxxSendMessage(pwnd, WM_PAINTICON, TRUE, 0L);
    01180
    01181         } else {
    01182
    01183             xxxSendMessage(pwnd, WM_PAINT, 0, 0L);
    01184         }
    01185
    01186         /*
    01187          * If the guy didn't call BeginPaint/EndPaint(), or GetUpdateRect/Rgn
    01188          * with fErase == TRUE, then we have to clean up for him here.
    01189          */
    01190         if (TestWF(pwnd, WFPAINTNOTPROCESSED)) {
    01191
    01192             RIPMSG0(RIP_VERBOSE,
    01193                 "App didn't call BeginPaint() or GetUpdateRect/Rgn(fErase == TRUE) in WM_PAINT");
    01194
    01195             xxxSimpleDoSyncPaint(pwnd);
    01196         }
    01197     }
    01198
    01199     /*
    01200      * For desktop window, do not force the top level window repaint at this
    01201      * this point.  We are calling UpdateWindow() for the desktop before
    01202      * size/move is sent for the top level windows.
    01203      *
    01204      * BUG: The comment above seems a bit random.  Is there really a problem?
    01205      *      If nothing else this has to remain this way because it is
    01206      *      how Win 3.0 worked (neilk)
    01207      */
    01208     if ((flags & UW_ENUMCHILDREN) && (pwnd != PWNDDESKTOP(pwnd))) {
    01209
    01210         /*
    01211          * Update any children...
    01212          */
    01213         ThreadLockNever(&tlpwnd);
    01214         pwnd = pwnd->spwndChild;
    01215         while (pwnd != NULL) {
    01216
    01217             /*
    01218              * If there is a transparent window that needs painting,
    01219              * skip it if another window below it needs to paint.
    01220              */
    01221             if (TestWF(pwnd, WEFTRANSPARENT) && NEEDSPAINT(pwnd)) {
    01222
    01223                 PWND pwndT = pwnd;
    01224
    01225                 while ((pwndT = pwndT->spwndNext) != NULL) {
    01226                     if (NEEDSPAINT(pwndT))
    01227                         break;
    01228                 }
    01229
    01230                 if (pwndT != NULL) {
    01231                     pwnd = pwnd->spwndNext;
    01232                     continue;
    01233                 }
    01234             }
    01235
    01236             ThreadLockExchangeAlways(pwnd, &tlpwnd);
    01237             xxxUpdateWindow2(pwnd, flags | UW_RECURSED);
    01238             pwnd = pwnd->spwndNext;
    01239         }
    01240
    01241         ThreadUnlock(&tlpwnd);
    01242     }
    01243
    01244     return;
    01245 }

BOOL xxxValidateRect | ( | PWND | pwnd,
|  | LPRECT | lprcValid
| ) |

Definition at line 77 of file update.c.

References BOOL, CheckLock, NULL, and xxxRedrawWindow().

Referenced by NtUserValidateRect(), xxxMenuWindowProc(), and xxxMoveWindow().

    00080 {
    00081     CheckLock(pwnd);
    00082
    00083     /*
    00084      * BACKWARD COMPATIBILITY HACK
    00085      *
    00086      * In Windows 3.0 and less, ValidateRect/InvalidateRect() call with
    00087      * hwnd == NULL always INVALIDATED and ERASED the entire desktop, and
    00088      * synchronously sent WM_ERASEBKGND and WM_NCPAINT messages before
    00089      * returning.  The Rgn() calls did not have this behavior.
    00090      */
    00091     if (pwnd == NULL) {
    00092         return xxxRedrawWindow(
    00093                 pwnd,
    00094                 NULL,
    00095                 NULL,
    00096                 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW);
    00097     } else {
    00098         return xxxRedrawWindow(pwnd, lprcValid, NULL, RDW_VALIDATE);
    00099     }
    00100 }

BOOL xxxValidateRgn | ( | PWND | pwnd,
|  | HRGN | hrgnValid
| ) |

Definition at line 132 of file update.c.

References BOOL, CheckLock, NULL, and xxxRedrawWindow().

    00135 {
    00136     CheckLock(pwnd);
    00137
    00138     return xxxRedrawWindow(pwnd, NULL, hrgnValid, RDW_VALIDATE);
    00139 }