diff --git a/view/src/nsScrollPortView.cpp b/view/src/nsScrollPortView.cpp index c99e4ccaf730..cbe2672f3ed0 100644 --- a/view/src/nsScrollPortView.cpp +++ b/view/src/nsScrollPortView.cpp @@ -59,6 +59,13 @@ nsScrollPortView::~nsScrollPortView() NS_RELEASE(mListeners); } + if (nsnull != mViewManager) { + nsIScrollableView* scrollingView; + mViewManager->GetRootScrollableView(&scrollingView); + if ((nsnull != scrollingView) && (this == scrollingView)) { + mViewManager->SetRootScrollableView(nsnull); + } + } } nsresult nsScrollPortView::QueryInterface(const nsIID& aIID, void** aInstancePtr) diff --git a/view/src/nsScrollingView.cpp b/view/src/nsScrollingView.cpp index d1d49ae41d3e..f6a6877908c1 100644 --- a/view/src/nsScrollingView.cpp +++ b/view/src/nsScrollingView.cpp @@ -404,6 +404,14 @@ nsScrollingView::~nsScrollingView() mListeners->Clear(); NS_RELEASE(mListeners); } + + if (nsnull != mViewManager) { + nsIScrollableView* scrollingView; + mViewManager->GetRootScrollableView(&scrollingView); + if ((nsnull != scrollingView) && (this == scrollingView)) { + mViewManager->SetRootScrollableView(nsnull); + } + } } nsresult nsScrollingView::QueryInterface(const nsIID& aIID, void** aInstancePtr) diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 35eabb9681ac..bc14e0f7ccc8 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -1445,6 +1445,15 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags) NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags) { NS_PRECONDITION(nsnull != aView, "null view"); + + // If the rectangle is not visible then abort + // without invalidating. This is a performance + // enhancement since invalidating a native widget + // can be expensive. + if (! IsRectVisible(aView, aRect)) { + return NS_OK; + } + if (!mRefreshEnabled) { // accumulate this rectangle in the view's dirty region, so we can process it later. if (aRect.width != 0 && aRect.height != 0) { @@ -2827,3 +2836,96 @@ void nsViewManager::ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &a aRect.ScaleRoundOut(t2p); } + +nsresult nsViewManager::GetVisibleRect(nsRect& aVisibleRect) +{ + nsresult rv = NS_OK; + + // Get the viewport scroller + nsIScrollableView* scrollingView; + GetRootScrollableView(&scrollingView); + + if (scrollingView) { + // Determine the visible rect in the scrolled view's coordinate space. + // The size of the visible area is the clip view size + const nsIView* clipView; + nsRect visibleRect; + + scrollingView->GetScrollPosition(aVisibleRect.x, aVisibleRect.y); + scrollingView->GetClipView(&clipView); + clipView->GetDimensions(&aVisibleRect.width, &aVisibleRect.height); + } else { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + +nsresult nsViewManager::GetAbsoluteRect(nsIView *aView, const nsRect &aRect, + nsRect& aAbsRect) +{ + nsIScrollableView* scrollingView = nsnull; + nsIView* scrolledView = nsnull; + GetRootScrollableView(&scrollingView); + if (nsnull == scrollingView) { + return NS_ERROR_FAILURE; + } + + scrollingView->GetScrolledView(scrolledView); + + // Calculate the absolute coordinates of the aRect passed in. + // aRects values are relative to aView + aAbsRect = aRect; + nsIView *parentView = aView; + while ((parentView != nsnull) && (parentView != scrolledView)) { + nscoord x, y; + parentView->GetPosition(&x, &y); + aAbsRect.MoveBy(x, y); + parentView->GetParent(parentView); + } + + if (parentView != scrolledView) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +PRBool nsViewManager::IsRectVisible(nsIView *aView, const nsRect &aRect) +{ + // Calculate the absolute coordinates for the visible rectangle + nsRect visibleRect; + if (GetVisibleRect(visibleRect) == NS_ERROR_FAILURE) { + return PR_TRUE; + } + + // Calculate the absolute coordinates of the aRect passed in. + // aRects values are relative to aView + nsRect absRect; + if ((GetAbsoluteRect(aView, aRect, absRect)) == NS_ERROR_FAILURE) { + return PR_TRUE; + } + + // Compare the visible rect against the rect passed in. + PRBool overlaps = absRect.IntersectRect(absRect, visibleRect); + +#if 0 + // Debugging code + static int toggle = 0; + for (int i = 0; i < toggle; i++) { + printf(" "); + } + if (toggle == 10) { + toggle = 0; + } else { + toggle++; + } + printf("***overlaps %d\n", overlaps); +#endif + + return overlaps; +} + + + diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index 66064514a3b0..115a20c24c74 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -180,6 +180,35 @@ private: void ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &aRect) const; // void WidgetToView(nsIView* aView, nsRect &aWidgetRect); + /** + * Transforms a rectangle from specified view's coordinate system to + * an absolute coordinate rectangle which can be compared against the + * rectangle returned by GetVisibleRect to determine visibility. + * @param aView view that aRect coordinates are specified relative to + * @param aRect rectangle in twips to convert to absolute coordinates + * @param aAbsRect rectangle in absolute coorindates. + * @returns NS_OK if successful otherwise, NS_ERROR_FAILURE + */ + + nsresult GetAbsoluteRect(nsIView *aView, const nsRect &aRect, + nsRect& aAbsRect); + /** + * Determine the visible rect + * @param aVisibleRect visible rectangle in twips + * @returns NS_OK if successful, otherwise NS_ERROR_FAILURE. + */ + + nsresult GetVisibleRect(nsRect& aVisibleRect); + + /** + * Determine if a rectangle specified in the view's coordinate system + * is completely, or partially visible. + * @param aView view that aRect coordinates are specified relative to + * @param aRect rectangle in twips to test for visibility + * @returns PR_TRUE if the rect is visible, PR_FALSE otherwise. + */ + PRBool IsRectVisible(nsIView *aView, const nsRect &aRect); + private: nsIDeviceContext *mContext; nsIViewObserver *mObserver; diff --git a/view/src/nsViewManager2.cpp b/view/src/nsViewManager2.cpp index 41562c7c4477..4fab65ecf63e 100755 --- a/view/src/nsViewManager2.cpp +++ b/view/src/nsViewManager2.cpp @@ -853,8 +853,8 @@ nsresult nsViewManager2::CreateBlendingBuffers(nsIRenderingContext &aRC) mBlender->Init(mContext); } - gBlendWidth = mTranslucentBounds.width * mPixelsToTwips; - gBlendHeight = mTranslucentBounds.height * mPixelsToTwips; + gBlendWidth = (PRInt32)(mTranslucentBounds.width * mPixelsToTwips); + gBlendHeight = (PRInt32)(mTranslucentBounds.height * mPixelsToTwips); return NS_OK; } @@ -946,6 +946,15 @@ NS_IMETHODIMP nsViewManager2::UpdateView(nsIView *aView, PRUint32 aUpdateFlags) NS_IMETHODIMP nsViewManager2::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags) { NS_PRECONDITION(nsnull != aView, "null view"); + + // If the rectangle is not visible then abort + // without invalidating. This is a performance + // enhancement since invalidating a native widget + // can be expensive. + if (! IsRectVisible(aView, aRect)) { + return NS_OK; + } + if (!mRefreshEnabled) { // accumulate this rectangle in the view's dirty region, so we can process it later. if (aRect.width != 0 && aRect.height != 0) { @@ -2368,3 +2377,95 @@ void nsViewManager2::ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect & mContext->GetAppUnitsToDevUnits(t2p); aRect.ScaleRoundOut(t2p); } + +nsresult nsViewManager2::GetVisibleRect(nsRect& aVisibleRect) +{ + nsresult rv = NS_OK; + + // Get the viewport scroller + nsIScrollableView* scrollingView; + GetRootScrollableView(&scrollingView); + + if (scrollingView) { + // Determine the visible rect in the scrolled view's coordinate space. + // The size of the visible area is the clip view size + const nsIView* clipView; + nsRect visibleRect; + + scrollingView->GetScrollPosition(aVisibleRect.x, aVisibleRect.y); + scrollingView->GetClipView(&clipView); + clipView->GetDimensions(&aVisibleRect.width, &aVisibleRect.height); + } else { + rv = NS_ERROR_FAILURE; + } + + return rv; +} + +nsresult nsViewManager2::GetAbsoluteRect(nsIView *aView, const nsRect &aRect, + nsRect& aAbsRect) +{ + nsIScrollableView* scrollingView = nsnull; + nsIView* scrolledView = nsnull; + GetRootScrollableView(&scrollingView); + if (nsnull == scrollingView) { + return NS_ERROR_FAILURE; + } + + scrollingView->GetScrolledView(scrolledView); + + // Calculate the absolute coordinates of the aRect passed in. + // aRects values are relative to aView + aAbsRect = aRect; + nsIView *parentView = aView; + while ((parentView != nsnull) && (parentView != scrolledView)) { + nscoord x, y; + parentView->GetPosition(&x, &y); + aAbsRect.MoveBy(x, y); + parentView->GetParent(parentView); + } + + if (parentView != scrolledView) { + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +PRBool nsViewManager2::IsRectVisible(nsIView *aView, const nsRect &aRect) +{ + // Calculate the absolute coordinates for the visible rectangle + nsRect visibleRect; + if (GetVisibleRect(visibleRect) == NS_ERROR_FAILURE) { + return PR_TRUE; + } + + // Calculate the absolute coordinates of the aRect passed in. + // aRects values are relative to aView + nsRect absRect; + if ((GetAbsoluteRect(aView, aRect, absRect)) == NS_ERROR_FAILURE) { + return PR_TRUE; + } + + // Compare the visible rect against the rect passed in. + PRBool overlaps = absRect.IntersectRect(absRect, visibleRect); + +#if 0 + // Debugging code + static int toggle = 0; + for (int i = 0; i < toggle; i++) { + printf(" "); + } + if (toggle == 10) { + toggle = 0; + } else { + toggle++; + } + printf("***overlaps %d\n", overlaps); +#endif + + return overlaps; +} + + diff --git a/view/src/nsViewManager2.h b/view/src/nsViewManager2.h index 0d3f2e925a66..6d92aa7465aa 100755 --- a/view/src/nsViewManager2.h +++ b/view/src/nsViewManager2.h @@ -193,6 +193,35 @@ private: void ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &aRect) const; // void WidgetToView(nsIView* aView, nsRect &aWidgetRect); + /** + * Transforms a rectangle from specified view's coordinate system to + * an absolute coordinate rectangle which can be compared against the + * rectangle returned by GetVisibleRect to determine visibility. + * @param aView view that aRect coordinates are specified relative to + * @param aRect rectangle in twips to convert to absolute coordinates + * @param aAbsRect rectangle in absolute coorindates. + * @returns NS_OK if successful otherwise, NS_ERROR_FAILURE + */ + + nsresult GetAbsoluteRect(nsIView *aView, const nsRect &aRect, + nsRect& aAbsRect); + /** + * Determine the visible rect + * @param aVisibleRect visible rectangle in twips + * @returns NS_OK if successful, otherwise NS_ERROR_FAILURE. + */ + + nsresult GetVisibleRect(nsRect& aVisibleRect); + + /** + * Determine if a rectangle specified in the view's coordinate system + * is completely, or partially visible. + * @param aView view that aRect coordinates are specified relative to + * @param aRect rectangle in twips to test for visibility + * @returns PR_TRUE if the rect is visible, PR_FALSE otherwise. + */ + PRBool IsRectVisible(nsIView *aView, const nsRect &aRect); + private: nsIDeviceContext *mContext; float mTwipsToPixels;