зеркало из https://github.com/mozilla/pjs.git
bug #10261: fix for dropping calls to UpdateView, also now correctly handles calls to UpdateView(nsIView*, nsIRegion*, ...) with non-null nsIRegion*.
This commit is contained in:
Родитель
e5c321d37d
Коммит
2e6af96bc5
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче