From 2e6af96bc527ce440243035bd8f7e2b0853952c0 Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Fri, 3 Sep 1999 02:27:40 +0000 Subject: [PATCH] bug #10261: fix for dropping calls to UpdateView, also now correctly handles calls to UpdateView(nsIView*, nsIRegion*, ...) with non-null nsIRegion*. --- view/src/nsScrollingView.cpp | 41 +++++++------------ view/src/nsViewManager.cpp | 78 ++++++++++++++++++++++++++++-------- view/src/nsViewManager.h | 2 + 3 files changed, 77 insertions(+), 44 deletions(-) diff --git a/view/src/nsScrollingView.cpp b/view/src/nsScrollingView.cpp index 28e9676d95f..775750a9a33 100644 --- a/view/src/nsScrollingView.cpp +++ b/view/src/nsScrollingView.cpp @@ -893,6 +893,7 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) nsIView *scrolledView; GetScrolledView(scrolledView); nsIScrollbar *scrollv = nsnull, *scrollh = nsnull; + PRBool hasVertical = PR_TRUE, hasHorizontal = PR_FALSE; nsIWidget *win; if (nsnull != scrolledView) @@ -902,7 +903,6 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) nscoord hwidth, hheight; nscoord vwidth, vheight; PRUint32 oldsizey = mSizeY, oldsizex = mSizeX; - // nsRect area(0, 0, 0, 0); nscoord offx, offy; float scale; nsRect controlRect(0, 0, mBounds.width, mBounds.height); @@ -914,36 +914,31 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) scrolledView->GetDimensions(&mSizeX, &mSizeY); - if (nsnull != mHScrollBarView) - { + if (nsnull != mHScrollBarView) { mHScrollBarView->GetDimensions(&hwidth, &hheight); mHScrollBarView->GetWidget(win); - + if (NS_OK == win->QueryInterface(kIScrollbarIID, (void **)&scrollh)) { if (((mSizeX > controlRect.width) && (mScrollPref != nsScrollPreference_kNeverScroll)) || (mScrollPref == nsScrollPreference_kAlwaysScroll)) { - scrollh->Release(); //DO NOT USE NS_RELEASE()! MMP - } - else - { - NS_RELEASE(scrollh); //MUST USE NS_RELEASE()! MMP + hasHorizontal = PR_TRUE; } + NS_RELEASE(scrollh); } NS_RELEASE(win); } - if (nsnull != mVScrollBarView) - { + if (nsnull != mVScrollBarView) { mVScrollBarView->GetDimensions(&vwidth, &vheight); offy = mOffsetY; mVScrollBarView->GetWidget(win); if (NS_OK == win->QueryInterface(kIScrollbarIID, (void **)&scrollv)) { - if ((mSizeY > (controlRect.height - ((nsnull != scrollh) ? hheight : 0)))) { + if ((mSizeY > (controlRect.height - (hasHorizontal ? hheight : 0)))) { // if we are scrollable if (mScrollPref != nsScrollPreference_kNeverScroll) { //we need to be able to scroll @@ -960,7 +955,7 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) scrollv->GetPosition(oldpos); px->GetDevUnitsToAppUnits(p2t); - availheight = controlRect.height - ((nsnull != scrollh) ? hheight : 0); + availheight = controlRect.height - (hasHorizontal ? hheight : 0); // XXX Check for 0 initial size. This is really indicative // of a problem. @@ -984,8 +979,7 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) scrollv->SetParameters(mSizeY, availheight, mOffsetY, mLineHeight); } - } else - { + } else { // The scrolled view is entirely visible vertically. Either hide the // vertical scrollbar or disable it mOffsetY = 0; @@ -1002,13 +996,11 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) { ((ScrollBarView *)mVScrollBarView)->SetEnabled(PR_FALSE); win->Enable(PR_TRUE); - NS_RELEASE(scrollv); + hasVertical = PR_FALSE; } } - //don't release the vertical scroller here because if we need to - //create a horizontal one, it will need to know that there is a vertical one -// //create a horizontal one, it will need to tweak the vertical one + NS_RELEASE(scrollv); } NS_RELEASE(win); @@ -1016,11 +1008,10 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) if (nsnull != mHScrollBarView) { offx = mOffsetX; - mHScrollBarView->GetWidget(win); - + if (NS_OK == win->QueryInterface(kIScrollbarIID, (void **)&scrollh)) { - if ((mSizeX > (controlRect.width - ((nsnull != scrollv) ? vwidth : 0)))) { + if ((mSizeX > (controlRect.width - (hasVertical ? vwidth : 0)))) { if (mScrollPref != nsScrollPreference_kNeverScroll) { //we need to be able to scroll @@ -1036,7 +1027,7 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) scrollh->GetPosition(oldpos); px->GetDevUnitsToAppUnits(p2t); - availwidth = controlRect.width - ((nsnull != scrollv) ? vwidth : 0); + availwidth = controlRect.width - (hasVertical ? vwidth : 0); // XXX Check for 0 initial size. This is really indicative // of a problem. @@ -1112,10 +1103,6 @@ NS_IMETHODIMP nsScrollingView::ComputeScrollOffsets(PRBool aAdjustWidgets) ((CornerView *)mCornerView)->Show(PR_FALSE, PR_FALSE); } - // now we can release the vertical scroller if there was one... - - NS_IF_RELEASE(scrollv); - if ((dx != 0) || (dy != 0) && aAdjustWidgets) AdjustChildWidgets(this, scrolledView, 0, 0, scale); diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index 40a3a416ff5..b1cda5ceb9e 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -529,6 +529,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con if (localcx != aContext) NS_RELEASE(localcx); +#if 0 // Subtract the area we just painted from the dirty region nsIRegion *dirtyRegion; aView->GetDirtyRegion(dirtyRegion); @@ -544,6 +545,7 @@ void nsViewManager :: Refresh(nsIView *aView, nsIRenderingContext *aContext, con dirtyRegion->Subtract(pixrect.x, pixrect.y, pixrect.width, pixrect.height); NS_RELEASE(dirtyRegion); } +#endif mLastRefresh = PR_IntervalNow(); @@ -1278,6 +1280,25 @@ void nsViewManager :: UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) cons } } +void nsViewManager::ProcessPendingUpdates(nsIView* aView) +{ + nsIRegion* dirtyRegion = nsnull; + aView->GetDirtyRegion(dirtyRegion); + if (dirtyRegion != nsnull && !dirtyRegion->IsEmpty()) { + UpdateView(aView, dirtyRegion, 0); + dirtyRegion->Init(); + NS_RELEASE(dirtyRegion); + } + + // process pending updates in child view. + nsIView* childView = nsnull; + aView->GetChild(0, childView); + while (nsnull != childView) { + ProcessPendingUpdates(childView); + childView->GetNextSibling(childView); + } +} + NS_IMETHODIMP nsViewManager :: Composite() { if (mUpdateCnt > 0) @@ -1292,8 +1313,19 @@ NS_IMETHODIMP nsViewManager :: Composite() return NS_OK; } -NS_IMETHODIMP nsViewManager :: UpdateView(nsIView *aView, nsIRegion *aRegion, PRUint32 aUpdateFlags) +NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, nsIRegion *aRegion, PRUint32 aUpdateFlags) { + // TODO: should ads nsIWidget::Invalidate(nsIRegion*). + nsRect dirtyRect; + if (aRegion != nsnull) { + aRegion->GetBoundingBox(&dirtyRect.x, &dirtyRect.y, &dirtyRect.width, &dirtyRect.height); + } else { + aView->GetBounds(dirtyRect); + dirtyRect.x = dirtyRect.y = 0; + } + UpdateView(aView, dirtyRect, aUpdateFlags); + +#if 0 // XXX Huh. What about the case where aRegion isn't nsull? // XXX yeah? what about it? if (aRegion == nsnull) @@ -1305,14 +1337,18 @@ NS_IMETHODIMP nsViewManager :: UpdateView(nsIView *aView, nsIRegion *aRegion, PR trect.x = trect.y = 0; UpdateView(aView, trect, aUpdateFlags); } +#endif - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsViewManager :: UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags) { NS_PRECONDITION(nsnull != aView, "null view"); if (!mRefreshEnabled && 0 == mUpdateBatchCnt) { + // accumulate this rectangle in the view's dirty region, so we can process it later. + AddRectToDirtyRegion(aView, aRect); + ++mUpdateCnt; return NS_OK; } @@ -2136,26 +2172,30 @@ nsIRenderingContext * nsViewManager :: CreateRenderingContext(nsIView &aView) return cx; } -void nsViewManager :: AddRectToDirtyRegion(nsIView* aView, const nsRect &aRect) const +void nsViewManager::AddRectToDirtyRegion(nsIView* aView, const nsRect &aRect) const { - // Get the dirty region associated with the view - nsIRegion *dirtyRegion; + // Get the dirty region associated with the view + nsIRegion *dirtyRegion; - aView->GetDirtyRegion(dirtyRegion); + aView->GetDirtyRegion(dirtyRegion); - if (nsnull == dirtyRegion) - { - // The view doesn't have a dirty region so create one - nsresult rv = nsComponentManager::CreateInstance(kRegionCID, - nsnull, - kIRegionIID, - (void **)&dirtyRegion); + if (nsnull == dirtyRegion) { + // The view doesn't have a dirty region so create one + nsresult rv = nsComponentManager::CreateInstance(kRegionCID, + nsnull, + kIRegionIID, + (void **)&dirtyRegion); - if (NS_FAILED(rv)) return; - dirtyRegion->Init(); - aView->SetDirtyRegion(dirtyRegion); - } + if (NS_FAILED(rv)) return; + dirtyRegion->Init(); + aView->SetDirtyRegion(dirtyRegion); + } + // since this is only used to buffer update requests, keep them in app units. + dirtyRegion->Union(aRect.x, aRect.y, aRect.width, aRect.height); + NS_RELEASE(dirtyRegion); + +#if 0 // Dirty regions are in device units, and aRect is in app units so // we need to convert to device units nsRect trect = aRect; @@ -2166,6 +2206,7 @@ void nsViewManager :: AddRectToDirtyRegion(nsIView* aView, const nsRect &aRect) trect.ScaleRoundOut(t2p); dirtyRegion->Union(trect.x, trect.y, trect.width, trect.height); NS_IF_RELEASE(dirtyRegion); +#endif } void nsViewManager :: UpdateTransCnt(nsIView *oldview, nsIView *newview) @@ -2205,6 +2246,9 @@ NS_IMETHODIMP nsViewManager :: EnableRefresh(void) { mRefreshEnabled = PR_TRUE; + if (mUpdateCnt > 0) + ProcessPendingUpdates(mRootView); + if (mTrueFrameRate > 0) { PRInt32 deltams = PR_IntervalToMilliseconds(PR_IntervalNow() - mLastRefresh); diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index c902c1b580b..a270dc6cecc 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -128,6 +128,8 @@ private: void UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) const; void UpdateTransCnt(nsIView *oldview, nsIView *newview); + void ProcessPendingUpdates(nsIView *aView); + void Refresh(nsIView *aView, nsIRenderingContext *aContext, nsIRegion *region, PRUint32 aUpdateFlags); void Refresh(nsIView* aView, nsIRenderingContext *aContext,