From d8e63b5bf99752affc7ed7be5a06af61e39744bb Mon Sep 17 00:00:00 2001 From: "beard%netscape.com" Date: Tue, 30 Nov 1999 22:27:56 +0000 Subject: [PATCH] bug #13131, 18140: now accumulating paint requests into a region for each view that has a widget. r=pavlov git-svn-id: svn://10.0.0.236/trunk@54787 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/view/src/nsViewManager.cpp | 402 ++++++++++------------------- 1 file changed, 136 insertions(+), 266 deletions(-) diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index ed4b79c03d2..76434e525ab 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -1325,35 +1325,26 @@ void nsViewManager :: RenderView(nsIView *aView, nsIRenderingContext &aRC, const aRC.PopState(aResult); } -void nsViewManager :: UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) const +void nsViewManager::UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) const { - nsRect pardamage; - nsRect bounds; - + nsRect bounds; aView->GetBounds(bounds); - //translate parent rect into child coords. + // translate parent rect into child coords. + nsRect parDamage; + if (nsnull != aParentRect) { + parDamage = *aParentRect; + parDamage.IntersectRect(bounds, parDamage); + parDamage.MoveBy(-bounds.x, -bounds.y); + } else + parDamage = bounds; - if (nsnull != aParentRect) - { - pardamage = *aParentRect; - - pardamage.IntersectRect(bounds, pardamage); - pardamage.MoveBy(-bounds.x, -bounds.y); - } - else - pardamage = bounds; - - if (PR_FALSE == pardamage.IsEmpty()) - { + if (PR_FALSE == parDamage.IsEmpty()) { nsIWidget *widget; - aView->GetWidget(widget); - - if (nsnull != widget) - { + if (nsnull != widget) { float scale; - nsRect pixrect = pardamage; + nsRect pixrect = parDamage; mContext->GetAppUnitsToDevUnits(scale); pixrect.ScaleRoundOut(scale); @@ -1370,22 +1361,27 @@ void nsViewManager :: UpdateDirtyViews(nsIView *aView, nsRect *aParentRect) cons aView->GetChild(0, child); - while (nsnull != child) - { - UpdateDirtyViews(child, &pardamage); + while (nsnull != child) { + UpdateDirtyViews(child, &parDamage); child->GetNextSibling(child); } } void nsViewManager::ProcessPendingUpdates(nsIView* aView) { - nsCOMPtr dirtyRegion; - aView->GetDirtyRegion(*getter_AddRefs(dirtyRegion)); - if (dirtyRegion != nsnull && !dirtyRegion->IsEmpty()) { - nsRect dirtyRect; - dirtyRegion->GetBoundingBox(&dirtyRect.x, &dirtyRect.y, &dirtyRect.width, &dirtyRect.height); - UpdateView(aView, dirtyRect, 0); - dirtyRegion->Init(); + PRBool hasWidget; + aView->HasWidget(&hasWidget); + if (hasWidget) { + nsCOMPtr dirtyRegion; + aView->GetDirtyRegion(*getter_AddRefs(dirtyRegion)); + if (dirtyRegion != nsnull && !dirtyRegion->IsEmpty()) { + nsCOMPtr widget; + aView->GetWidget(*getter_AddRefs(widget)); + if (widget) { + widget->InvalidateRegion(dirtyRegion, PR_FALSE); + } + dirtyRegion->Init(); + } } // process pending updates in child view. @@ -1413,120 +1409,81 @@ NS_IMETHODIMP nsViewManager :: Composite() NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags) { - nsRect dirtyRect; - aView->GetBounds(dirtyRect); - dirtyRect.x = dirtyRect.y = 0; - return UpdateView(aView, dirtyRect, aUpdateFlags); + // Mark the entire view as damaged + nsRect bounds; + aView->GetBounds(bounds); + bounds.x = bounds.y = 0; + return UpdateView(aView, bounds, aUpdateFlags); } -NS_IMETHODIMP nsViewManager :: UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags) +NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags) { - NS_PRECONDITION(nsnull != aView, "null view"); - if (!mRefreshEnabled) { - // accumulate this rectangle in the view's dirty region, so we can process it later. - if (aRect.width != 0 && aRect.height != 0) { - AddRectToDirtyRegion(aView, aRect); - ++mUpdateCnt; - } - return NS_OK; - } + NS_PRECONDITION(nsnull != aView, "null view"); + if (!mRefreshEnabled) { + // accumulate this rectangle in the view's dirty region, so we can process it later. + if (aRect.width != 0 && aRect.height != 0) { + AddRectToDirtyRegion(aView, aRect); + ++mUpdateCnt; + } + return NS_OK; + } - // Ignore any silly requests... - if ((aRect.width == 0) || (aRect.height == 0)) - return NS_OK; - - // is this view even visible? - nsViewVisibility visibility; - aView->GetVisibility(visibility); - if (visibility == nsViewVisibility_kHide) - return NS_OK; + // Ignore any silly requests... + if ((aRect.width == 0) || (aRect.height == 0)) + return NS_OK; -#ifdef GS_DEBUG - printf("ViewManager::UpdateView: %p, rect ", aView); - stdout << aRect; - printf("\n"); + // is this view even visible? + nsViewVisibility visibility; + aView->GetVisibility(visibility); + if (visibility == nsViewVisibility_kHide) + return NS_OK; + + // Find the nearest view (including this view) that has a widget + nsIView *widgetView = GetWidgetView(aView); + if (nsnull != widgetView) { + if (0 == mUpdateCnt) + RestartTimer(); + + mUpdateCnt++; + +#if 0 + // Transform damaged rect to widgetView's coordinate system. + nsRect widgetRect = aRect; + nsIView *parentView = aView; + while (parentView != widgetView) { + nscoord x, y; + parentView->GetPosition(&x, &y); + widgetRect.x += x; + widgetRect.y += y; + parentView->GetParent(parentView); + } + + // Add this rect to the widgetView's dirty region. + if (nsnull != widgetView) + UpdateDirtyViews(widgetView, &widgetRect); +#else + // Go ahead and invalidate the entire rectangular area. + // regardless of parentage. + nsRect widgetRect = aRect; + ViewToWidget(aView, widgetView, widgetRect); + nsCOMPtr widget; + widgetView->GetWidget(*getter_AddRefs(widget)); + widget->Invalidate(widgetRect, PR_FALSE); #endif - // Find the nearest view (including this view) that has a widget - nsRect trect = aRect; - nsIView *par = aView; - nscoord x, y; - nsIView *widgetView = aView; + // See if we should do an immediate refresh or wait + if (aUpdateFlags & NS_VMREFRESH_IMMEDIATE) { + Composite(); + } else if ((mTrueFrameRate > 0) && !(aUpdateFlags & NS_VMREFRESH_NO_SYNC)) { + // or if a sync paint is allowed and it's time for the compositor to + // do a refresh + PRInt32 deltams = PR_IntervalToMilliseconds(PR_IntervalNow() - mLastRefresh); + if (deltams > (1000 / (PRInt32)mTrueFrameRate)) + Composite(); + } + } - do - { - nsIWidget *widget; - - // See if this view has a widget - widgetView->GetWidget(widget); - - if (nsnull != widget) - { - NS_RELEASE(widget); - break; - } - - // Get the parent view - widgetView->GetParent(widgetView); - } while (nsnull != widgetView); -// NS_ASSERTION(nsnull != widgetView, "no widget"); this assertion not valid for printing...MMP - - if (nsnull != widgetView) - { - if (0 == mUpdateCnt) - RestartTimer(); - - mUpdateCnt++; - - // Convert damage rect to coordinate space of containing view with - // a widget - // XXX Consolidate this code with the code above... -// if (aView != widgetView) -// { - // first our position - par->GetPosition(&x, &y); - trect.x += x; - trect.y += y; - - // go up parent chain until we hit the widgetView. - // make sure we include the widget view in the calculation - while ((nsnull != par) && (par != widgetView)) - { - par->GetParent(par); - - if (par == nsnull) - break; - - par->GetPosition(&x, &y); - trect.x += x; - trect.y += y; - } -// } - - // Add this rect to the widgetView's dirty region. - - if (nsnull != widgetView) - UpdateDirtyViews(widgetView, &trect); - - // See if we should do an immediate refresh or wait - - if (aUpdateFlags & NS_VMREFRESH_IMMEDIATE) - { - Composite(); - } - else if ((mTrueFrameRate > 0) && !(aUpdateFlags & NS_VMREFRESH_NO_SYNC)) - { - // or if a sync paint is allowed and it's time for the compositor to - // do a refresh - - PRInt32 deltams = PR_IntervalToMilliseconds(PR_IntervalNow() - mLastRefresh); - - if (deltams > (1000 / (PRInt32)mTrueFrameRate)) - Composite(); - } - } - - return NS_OK; + return NS_OK; } NS_IMETHODIMP nsViewManager::UpdateAllViews(PRUint32 aUpdateFlags) @@ -1538,10 +1495,7 @@ NS_IMETHODIMP nsViewManager::UpdateAllViews(PRUint32 aUpdateFlags) void nsViewManager::UpdateViews(nsIView *aView, PRUint32 aUpdateFlags) { // update this view. - nsRect dirtyRect; - aView->GetBounds(dirtyRect); - dirtyRect.x = dirtyRect.y = 0; - UpdateView(aView, dirtyRect, aUpdateFlags); + UpdateView(aView, aUpdateFlags); // update all children as well. nsIView* childView = nsnull; @@ -1552,9 +1506,8 @@ void nsViewManager::UpdateViews(nsIView *aView, PRUint32 aUpdateFlags) } } -NS_IMETHODIMP nsViewManager :: DispatchEvent(nsGUIEvent *aEvent, nsEventStatus* aStatus) +NS_IMETHODIMP nsViewManager :: DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aStatus) { - NS_ENSURE_ARG_POINTER(aStatus); *aStatus = nsEventStatus_eIgnore; switch(aEvent->message) @@ -1894,33 +1847,29 @@ NS_IMETHODIMP nsViewManager :: MoveViewBy(nsIView *aView, nscoord aX, nscoord aY return NS_OK; } -NS_IMETHODIMP nsViewManager :: MoveViewTo(nsIView *aView, nscoord aX, nscoord aY) +NS_IMETHODIMP nsViewManager::MoveViewTo(nsIView *aView, nscoord aX, nscoord aY) { - nscoord oldX; - nscoord oldY; + nscoord oldX, oldY; + aView->GetPosition(&oldX, &oldY); + aView->SetPosition(aX, aY); - aView->GetPosition(&oldX, &oldY); - aView->SetPosition(aX, aY); + // only do damage control if the view is visible - // only do damage control if the view is visible - - if ((aX != oldX) || (aY != oldY)) - { - nsViewVisibility visibility; - aView->GetVisibility(visibility); - if (visibility != nsViewVisibility_kHide) - { - nsRect bounds; - aView->GetBounds(bounds); - nsRect oldArea(oldX, oldY, bounds.width, bounds.height); - nsIView* parent; - aView->GetParent(parent); - UpdateView(parent, oldArea, NS_VMREFRESH_NO_SYNC); - nsRect newArea(aX, aY, bounds.width, bounds.height); - UpdateView(parent, newArea, NS_VMREFRESH_NO_SYNC); - } - } - return NS_OK; + if ((aX != oldX) || (aY != oldY)) { + nsViewVisibility visibility; + aView->GetVisibility(visibility); + if (visibility != nsViewVisibility_kHide) { + nsRect bounds; + aView->GetBounds(bounds); + nsRect oldArea(oldX, oldY, bounds.width, bounds.height); + nsIView* parentView; + aView->GetParent(parentView); + UpdateView(parentView, oldArea, NS_VMREFRESH_NO_SYNC); + nsRect newArea(aX, aY, bounds.width, bounds.height); + UpdateView(parentView, newArea, NS_VMREFRESH_NO_SYNC); + } + } + return NS_OK; } NS_IMETHODIMP nsViewManager::ResizeView(nsIView *aView, nscoord width, nscoord height) @@ -2296,28 +2245,22 @@ nsIRenderingContext * nsViewManager :: CreateRenderingContext(nsIView &aView) void nsViewManager::AddRectToDirtyRegion(nsIView* aView, const nsRect &aRect) const { - // Get the dirty region associated with the view + // Find a view with an associated widget. We'll transform this rect from the + // current view's coordinate system to a "heavyweight" parent view, then convert + // the rect to pixel coordinates, and accumulate the rect into that view's dirty region. + nsRect widgetRect = aRect; + nsIView* widgetView = GetWidgetView(aView); + ViewToWidget(aView, widgetView, widgetRect); + + // Get the dirty region associated with the widget view nsCOMPtr dirtyRegion; - aView->GetDirtyRegion(*getter_AddRefs(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); - -#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; - float t2p; - - mContext->GetAppUnitsToDevUnits(t2p); - - trect.ScaleRoundOut(t2p); - dirtyRegion->Union(trect.x, trect.y, trect.width, trect.height); - NS_IF_RELEASE(dirtyRegion); -#endif + if (NS_SUCCEEDED(widgetView->GetDirtyRegion(*getter_AddRefs(dirtyRegion)))) { + // add this rect to the widget view's dirty region. + dirtyRegion->Union(widgetRect.x, widgetRect.y, widgetRect.width, widgetRect.height); + } } -void nsViewManager :: UpdateTransCnt(nsIView *oldview, nsIView *newview) +void nsViewManager::UpdateTransCnt(nsIView *oldview, nsIView *newview) { if (nsnull != oldview) { @@ -2698,84 +2641,6 @@ void nsViewManager::ShowDisplayList(PRInt32 flatlen) } } -#if 0 - -void nsViewManager :: FlattenViewTreeUp(nsIView *aView, PRInt32 *aIndex, - const nsRect *aDamageRect, nsIView *aParView, - nsVoidArray *aArray) -{ - nsIView *nextview; - nsRect bounds, irect; - PRBool trans; - float opacity; - PRBool haswidget; - nsViewVisibility vis; - nsPoint *point; - - aView->GetNextSibling(nextview); - - if (!nextview) - { - nextview = aParView; - nextview->GetParent(aParView); - } - - if (!aParView) - return; - - aParView->GetScratchPoint(&point); - - if (nextview) - { - nextview->GetBounds(bounds); - - bounds.x += point->x; - bounds.y += point->y; - - haswidget = DoesViewHaveNativeWidget(*nextview); - nextview->GetVisibility(vis); - nextview->HasTransparency(trans); - nextview->GetOpacity(opacity); - - if (!haswidget && irect.IntersectRect(bounds, *aDamageRect) && - (nsViewVisibility_kShow == vis) && (opacity > 0.0f)) - { - aArray->ReplaceElementAt(nextview, (*aIndex)++); - - nsRect *grect = (nsRect *)aArray->ElementAt(*aIndex); - - if (!grect) - { - grect = new nsRect(bounds.x, bounds.y, bounds.width, bounds.height); - - if (!grect) - { - (*aIndex)--; - return; - } - - aArray->ReplaceElementAt(grect, *aIndex); - } - else - *grect = bounds; - - (*aIndex)++; - - aArray->ReplaceElementAt(nsnull, (*aIndex)++); - - //if this view completely covers the damage area and it's opaque - //then we're done. - - if (!trans && (opacity == 1.0f) && (irect == *aDamageRect)) - return; - } - - FlattenViewTreeUp(nextview, aIndex, aDamageRect, aParView, aArray); - } -} - -#endif - void nsViewManager :: ComputeViewOffset(nsIView *aView, nscoord *aX, nscoord *aY, PRInt32 aFlag) { nsIView *parent; @@ -2812,7 +2677,6 @@ PRBool nsViewManager :: DoesViewHaveNativeWidget(nsIView &aView) void *nativewidget; nativewidget = widget->GetNativeData(NS_NATIVE_WIDGET); - NS_RELEASE(widget); if (nsnull != nativewidget) @@ -2855,6 +2719,12 @@ void nsViewManager::ViewToWidget(nsIView *aView, nsIView* aWidgetView, nsRect &a aView->GetParent(aView); } + // intersect aRect with bounds of aWidgetView, to prevent generating any illegal rectangles. + nsRect bounds; + aWidgetView->GetBounds(bounds); + bounds.x = bounds.y = 0; + aRect.IntersectRect(aRect, bounds); + // finally, convert to device coordinates. float t2p; mContext->GetAppUnitsToDevUnits(t2p);