From 9e4e0e3b459007d19a11da67ce0df7bb7ee1956a Mon Sep 17 00:00:00 2001 From: "roc+%cs.cmu.edu" Date: Thu, 8 Aug 2002 01:03:57 +0000 Subject: [PATCH] Bug 159587. Force view manager to invalidate necessary areas when clipping is changed. r=kmcclusk,sr=bz --- view/src/nsView.cpp | 39 ++----------------------- view/src/nsView.h | 29 ++++++------------- view/src/nsViewManager.cpp | 59 +++++++++++++++++++++++++++++--------- 3 files changed, 58 insertions(+), 69 deletions(-) diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 537b02db7c46..9cf2fe6359e4 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -229,11 +229,6 @@ NS_IMETHODIMP nsView::Init(nsIViewManager* aManager, // we don't hold a reference to the view manager mViewManager = NS_STATIC_CAST(nsViewManager*, aManager); - mChildClip.mLeft = 0; - mChildClip.mRight = 0; - mChildClip.mTop = 0; - mChildClip.mBottom = 0; - SetPosition(aBounds.x, aBounds.y); nsRect dim(0, 0, aBounds.width, aBounds.height); @@ -550,28 +545,6 @@ NS_IMETHODIMP nsView::GetBounds(nsRect &aBounds) const return NS_OK; } -NS_IMETHODIMP nsView::SetChildClip(nscoord aLeft, nscoord aTop, nscoord aRight, nscoord aBottom) -{ - NS_PRECONDITION(aLeft <= aRight && aTop <= aBottom, "bad clip values"); - mChildClip.mLeft = aLeft; - mChildClip.mTop = aTop; - mChildClip.mRight = aRight; - mChildClip.mBottom = aBottom; - - - - return NS_OK; -} - -NS_IMETHODIMP nsView::GetChildClip(nscoord *aLeft, nscoord *aTop, nscoord *aRight, nscoord *aBottom) const -{ - *aLeft = mChildClip.mLeft; - *aTop = mChildClip.mTop; - *aRight = mChildClip.mRight; - *aBottom = mChildClip.mBottom; - return NS_OK; -} - NS_IMETHODIMP nsView::SetVisibility(nsViewVisibility aVisibility) { @@ -1047,17 +1020,11 @@ NS_IMETHODIMP nsView::GetClippedRect(nsRect& aClippedRect, PRBool& aIsClipped, P if (parentView->GetClipChildren()) { aIsClipped = PR_TRUE; // Adjust for clip specified by ancestor - nscoord clipLeft; - nscoord clipTop; - nscoord clipRight; - nscoord clipBottom; - parentView->GetChildClip(&clipLeft, &clipTop, &clipRight, &clipBottom); nsRect clipRect; + parentView->GetChildClip(clipRect); //Offset the cliprect by the amount the child offsets from the parent - clipRect.x = clipLeft + ancestorX; - clipRect.y = clipTop + ancestorY; - clipRect.width = clipRight - clipLeft; - clipRect.height = clipBottom - clipTop; + clipRect.x += ancestorX; + clipRect.y += ancestorY; PRBool overlap = aClippedRect.IntersectRect(clipRect, aClippedRect); if (!overlap) { aEmpty = PR_TRUE; // Does not intersect so the rect is empty. diff --git a/view/src/nsView.h b/view/src/nsView.h index 72eebcbe92cc..9b667c93a645 100644 --- a/view/src/nsView.h +++ b/view/src/nsView.h @@ -49,13 +49,6 @@ //mmptemp -struct nsViewClip { - nscoord mLeft; - nscoord mRight; - nscoord mTop; - nscoord mBottom; -}; - class nsIRegion; class nsIRenderingContext; class nsIViewManager; @@ -192,20 +185,17 @@ public: * The clip is relative to the origin of the view. * All of the children of this view will be clipped using * the specified rectangle - * @param aLeft new left position - * @param aTop new top position - * @param aRight new right position - * @param aBottom new bottom position */ - NS_IMETHOD SetChildClip(nscoord aX, nscoord aY, nscoord aWidth, nscoord aHeight); + void SetClipChildren(PRBool aDoClip) { + mVFlags = (mVFlags & ~NS_VIEW_FLAG_CLIPCHILDREN) | (aDoClip ? NS_VIEW_FLAG_CLIPCHILDREN : 0); + } + void SetChildClip(const nsRect &aRect) { mChildClip = aRect; } /** - * Called to get the dimensions and position of the clip for the view. - * @param aLeft left position - * @param aTop top position - * @param aRight right position - * @param aBottom bottom position + * Called to get the dimensions and position of the clip for the children of this view. */ - NS_IMETHOD GetChildClip(nscoord *aLeft, nscoord *aTop, nscoord *aRight, nscoord *aBottom) const; + PRBool GetClipChildren() const { return (mVFlags & NS_VIEW_FLAG_CLIPCHILDREN) != 0; } + void GetChildClip(nsRect &aRect) const { aRect = mChildClip; } + /** * Called to indicate that the visibility of a view has been * changed. @@ -304,7 +294,6 @@ public: // NOT in nsIView, so only available in view module nsViewVisibility GetVisibility() const { return mVis; } void* GetClientData() const { return mClientData; } PRBool GetFloating() const { return (mVFlags & NS_VIEW_FLAG_FLOATING) != 0; } - PRBool GetClipChildren() const { return (mVFlags & NS_VIEW_FLAG_CLIPCHILDREN) != 0; } PRInt32 GetChildCount() const { return mNumKids; } nsView* GetChild(PRInt32 aIndex) const; @@ -345,7 +334,7 @@ protected: PRInt32 mNumKids; nscoord mPosX, mPosY; nsRect mDimBounds; // relative to parent - nsViewClip mChildClip; + nsRect mChildClip; float mOpacity; PRUint32 mVFlags; nsIRegion* mDirtyRegion; diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 6883455ae75c..62d9327a44ea 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -2444,9 +2444,13 @@ NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, const nsRect &aRect, PRB // nsIClipViews clip everything, including their child views. So we note that explicitly. // This means nsView::GetClippedRect will now take account of the clipping effects of // nsIClipViews. + // This will be overridden by SetViewChildClipRegion below, if necessary if (IsClipView(view)) { - view->SetViewFlags(view->GetViewFlags() | NS_VIEW_FLAG_CLIPCHILDREN); - view->SetChildClip(0, 0, aRect.width, aRect.height); + nsRect childClipRect = aRect; + childClipRect.x = 0; + childClipRect.y = 0; + view->SetClipChildren(PR_TRUE); + view->SetChildClip(childClipRect); } } @@ -2459,31 +2463,60 @@ NS_IMETHODIMP nsViewManager::SetViewChildClipRegion(nsIView *aView, nsIRegion *a NS_ASSERTION(!(nsnull == view), "no view"); - // XXX Shouldn't we repaint the view here? + PRBool oldClipFlag = view->GetClipChildren(); + nsRect oldClipRect; + if (oldClipFlag) { + view->GetChildClip(oldClipRect); + } else { + // clipping may not have been enabled, but get the area to invalidate anyway + view->GetDimensions(oldClipRect); + } + PRBool newClipFlag; + nsRect newClipRect; // If the view implements nsIClipView then we ensure a clip rect is set, // and it is set to no more than the bounds of the view. if (aRegion != nsnull) { - nsRect newClip; - aRegion->GetBoundingBox(&newClip.x, &newClip.y, &newClip.width, &newClip.height); + newClipFlag = PR_TRUE; + aRegion->GetBoundingBox(&newClipRect.x, &newClipRect.y, &newClipRect.width, &newClipRect.height); if (IsClipView(view)) { nsRect dims; view->GetDimensions(dims); - newClip.IntersectRect(newClip, dims); + newClipRect.IntersectRect(newClipRect, dims); } - view->SetViewFlags(view->GetViewFlags() | NS_VIEW_FLAG_CLIPCHILDREN); - view->SetChildClip(newClip.x, newClip.y, newClip.XMost(), newClip.YMost()); } else { if (IsClipView(view)) { - nsRect dims; - view->GetDimensions(dims); - view->SetViewFlags(view->GetViewFlags() | NS_VIEW_FLAG_CLIPCHILDREN); - view->SetChildClip(0, 0, dims.width, dims.height); + newClipFlag = PR_TRUE; + view->GetDimensions(newClipRect); + newClipRect.x = 0; + newClipRect.y = 0; } else { - view->SetViewFlags(view->GetViewFlags() & ~NS_VIEW_FLAG_CLIPCHILDREN); + newClipFlag = PR_FALSE; + // clipping is not enabled, but get the new unclipped area for invalidation purposes + view->GetDimensions(newClipRect); } } + + if (newClipFlag == oldClipFlag + && (!newClipFlag || newClipRect == oldClipRect)) { + return NS_OK; + } + + // Update the view properties + view->SetClipChildren(newClipFlag); + view->SetChildClip(newClipRect); + // Invalidate changed areas + // Paint (new - old) in the current view + InvalidateRectDifference(view, newClipRect, oldClipRect, NS_VMREFRESH_NO_SYNC); + // Paint (old - new) in the parent view, since it'll be clipped out of the current view + nsView* parent = view->GetParent(); + if (parent != nsnull) { + view->ConvertToParentCoords(&oldClipRect.x, &oldClipRect.y); + view->ConvertToParentCoords(&newClipRect.x, &newClipRect.y); + InvalidateRectDifference(parent, oldClipRect, newClipRect, NS_VMREFRESH_NO_SYNC); + } + return NS_OK; }