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 }


Generated on Sat May 15 19:45:52 2004 for test by doxygen 1.3.7