Bug 124685. Change damage propagation algorithm to traverse the widget tree instead of the view tree; speeds up certain testcases. r=kmcclusk,rs=waterson

This commit is contained in:
roc+%cs.cmu.edu 2002-06-12 03:22:35 +00:00
Родитель 03697f6e80
Коммит 5fdacceb4e
7 изменённых файлов: 89 добавлений и 72 удалений

Просмотреть файл

@ -5232,8 +5232,11 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget,
if (NS_FAILED(rv))
return rv;
// pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
// otherwise the view will find its own parent widget and "do the right thing" to
// establish a parent/child widget relationship
rv = view->CreateWidget(kWidgetCID, nsnull,
aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
containerView != nsnull ? nsnull : aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
PR_TRUE, PR_FALSE);
if (rv != NS_OK)
return rv;

Просмотреть файл

@ -5232,8 +5232,11 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget,
if (NS_FAILED(rv))
return rv;
// pass in a native widget to be the parent widget ONLY if the view hierarchy will stand alone.
// otherwise the view will find its own parent widget and "do the right thing" to
// establish a parent/child widget relationship
rv = view->CreateWidget(kWidgetCID, nsnull,
aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
containerView != nsnull ? nsnull : aParentWidget->GetNativeData(NS_NATIVE_WIDGET),
PR_TRUE, PR_FALSE);
if (rv != NS_OK)
return rv;

Просмотреть файл

@ -788,8 +788,17 @@ NS_IMETHODIMP nsView::CreateWidget(const nsIID &aWindowIID,
mWindow->Create(aNative, trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
else
{
nsWidgetInitData initData;
if (nsnull == aWidgetInitData && nsnull != GetParent()) {
if (GetParent()->GetViewManager() != mViewManager) {
initData.mListenForResizes = PR_TRUE;
aWidgetInitData = &initData;
}
}
nsIWidget *parent;
GetOffsetFromWidget(nsnull, nsnull, parent);
mWindow->Create(parent, trect, ::HandleEvent, dx, nsnull, nsnull, aWidgetInitData);
NS_IF_RELEASE(parent);
}

Просмотреть файл

@ -1443,7 +1443,7 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, PRUint32 aUpdateFlags)
// Invalidate all widgets which overlap the view, other than the view's own widgets.
NS_IMETHODIMP
void
nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY)
{
nsView* view = NS_STATIC_CAST(nsView*, aView);
@ -1458,7 +1458,7 @@ nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY)
PRBool isEmpty;
view->GetClippedRect(damageRect, isClipped, isEmpty);
if (isEmpty) {
return NS_OK;
return;
}
view->ConvertFromParentCoords(&damageRect.x, &damageRect.y);
damageRect.x += origin.x;
@ -1469,7 +1469,7 @@ nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY)
PRBool viewIsFloating = PR_FALSE;
view->GetFloating(viewIsFloating);
if (viewIsFloating) {
return NS_OK;
return;
}
nsView* realRoot = mRootView;
@ -1477,87 +1477,86 @@ nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY)
realRoot = realRoot->GetParent();
}
UpdateAllCoveringWidgets(realRoot, view, damageRect, PR_FALSE);
UpdateWidgetArea(realRoot, damageRect, view);
Composite();
return NS_OK;
}
// Returns true if this view's widget(s) completely cover the rectangle
// The specified rectangle, relative to aView, is invalidated in every widget child of aView.
// If non-null, aTarget and its children are ignored and only widgets above aTarget's widget
// in Z-order are invalidated (if possible).
PRBool nsViewManager::UpdateAllCoveringWidgets(nsView *aView, nsView *aTarget,
nsRect &aDamagedRect, PRBool aRepaintOnlyUnblittableViews)
// The specified rectangle, relative to aWidgetView, is invalidated in every widget child of aWidgetView,
// plus aWidgetView's own widget
// If non-null, the aIgnoreWidgetView's widget and its children are not updated.
PRBool nsViewManager::UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamagedRect, nsView* aIgnoreWidgetView)
{
if (aView == aTarget) {
aRepaintOnlyUnblittableViews = PR_TRUE;
}
nsRect bounds;
aView->GetBounds(bounds);
aView->ConvertFromParentCoords(&bounds.x, &bounds.y);
aWidgetView->GetDimensions(bounds);
PRBool overlap = bounds.IntersectRect(bounds, aDamagedRect);
if (!overlap) {
return PR_FALSE;
}
PRBool noCropping = bounds == aDamagedRect;
PRBool hasWidget = PR_FALSE;
if (mRootView == aView) {
hasWidget = PR_TRUE;
} else {
aView->HasWidget(&hasWidget);
nsViewVisibility visible;
aWidgetView->GetVisibility(visible);
if (aWidgetView == aIgnoreWidgetView) {
// the widget for aIgnoreWidgetView (and its children) should be treated as already updated.
// We still need to report whether this widget covers the rectangle.
return noCropping && nsViewVisibility_kShow == visible;
}
nsCOMPtr<nsIWidget> widget;
GetWidgetForView(aWidgetView, getter_AddRefs(widget));
NS_ASSERTION(nsnull != widget, "aWidgetView must have a widget");
if (!widget) {
return PR_FALSE;
}
PRUint32 flags = aView->GetViewFlags();
PRBool isBlittable = (flags & NS_VIEW_FLAG_DONT_BITBLT) == 0;
nsView* childView = aView->GetFirstChild();
PRBool childCovers = PR_FALSE;
while (nsnull != childView) {
nsRect childRect = bounds;
childView->ConvertFromParentCoords(&childRect.x, &childRect.y);
if (UpdateAllCoveringWidgets(childView, aTarget, childRect, aRepaintOnlyUnblittableViews)) {
childCovers = PR_TRUE;
// we can't stop here. We're not making any assumptions about how the child
// widgets are z-ordered, and we can't risk failing to invalidate the top-most
// one.
}
childView = childView->GetNextSibling();
nsCOMPtr<nsIEnumerator> children(dont_AddRef(widget->GetChildren()));
if (children) {
children->First();
do {
nsCOMPtr<nsISupports> child;
if (NS_SUCCEEDED(children->CurrentItem(getter_AddRefs(child)))) {
nsCOMPtr<nsIWidget> childWidget = do_QueryInterface(child);
if (childWidget) {
nsView* view = nsView::GetViewFor(childWidget);
if (nsnull != view) {
nsRect damage = bounds;
nsView* vp = view;
while (vp != aWidgetView && nsnull != vp) {
vp->ConvertFromParentCoords(&damage.x, &damage.y);
vp = vp->GetParent();
}
if (nsnull != vp) { // vp == nsnull means it's in a different hierarchy so we ignore it
if (UpdateWidgetArea(view, damage, aIgnoreWidgetView)) {
childCovers = PR_TRUE;
}
}
}
}
}
} while (NS_SUCCEEDED(children->Next()));
}
if (!childCovers && (!isBlittable || (hasWidget && !aRepaintOnlyUnblittableViews))) {
nsViewManager* vm = aView->GetViewManager();
if (!childCovers) {
nsViewManager* vm = aWidgetView->GetViewManager();
++vm->mUpdateCnt;
if (!vm->mRefreshEnabled) {
// accumulate this rectangle in the view's dirty region, so we can process it later.
vm->AddRectToDirtyRegion(aView, bounds);
vm->AddRectToDirtyRegion(aWidgetView, bounds);
vm->mHasPendingInvalidates = PR_TRUE;
} else {
nsView* widgetView = GetWidgetView(aView);
if (widgetView != nsnull) {
ViewToWidget(aView, widgetView, bounds);
nsCOMPtr<nsIWidget> widget;
vm->GetWidgetForView(widgetView, getter_AddRefs(widget));
widget->Invalidate(bounds, PR_FALSE);
}
ViewToWidget(aWidgetView, aWidgetView, bounds);
widget->Invalidate(bounds, PR_FALSE);
}
}
PRBool hasVisibleWidget = PR_FALSE;
if (hasWidget) {
nsViewVisibility visible;
aView->GetVisibility(visible);
if (visible == nsViewVisibility_kShow) {
hasVisibleWidget = PR_TRUE;
}
}
return noCropping && (hasVisibleWidget || childCovers);
return noCropping && (nsViewVisibility_kShow == visible || childCovers);
}
NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags)
@ -1612,7 +1611,7 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
widgetParent->HasWidget(&hasWidget);
}
UpdateAllCoveringWidgets(widgetParent, nsnull, damagedRect, PR_FALSE);
UpdateWidgetArea(widgetParent, damagedRect, nsnull);
} else {
nsPoint origin(damagedRect.x, damagedRect.y);
ComputeViewOffset(view, &origin);
@ -1624,7 +1623,7 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU
realRoot = realRoot->GetParent();
}
UpdateAllCoveringWidgets(realRoot, nsnull, damagedRect, PR_FALSE);
UpdateWidgetArea(realRoot, damagedRect, nsnull);
}
++mUpdateCnt;

Просмотреть файл

@ -144,14 +144,6 @@ public:
NS_IMETHOD UpdateView(nsIView *aView, PRUint32 aUpdateFlags);
NS_IMETHOD UpdateView(nsIView *aView, const nsRect &aRect, PRUint32 aUpdateFlags);
NS_IMETHOD UpdateAllViews(PRUint32 aUpdateFlags);
/**
* Called to inform the view manager that a view has scrolled.
* The view manager will invalidate any widgets which may need
* to be rerendered.
* @param aView view to paint. should be root view
* @param aUpdateFlags see bottom of nsIViewManager.h for description
*/
NS_IMETHOD UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY);
NS_IMETHOD DispatchEvent(nsGUIEvent *aEvent, nsEventStatus* aStatus);
@ -252,7 +244,7 @@ private:
void AddRectToDirtyRegion(nsView* aView, const nsRect &aRect) const;
void UpdateTransCnt(nsView *oldview, nsView *newview);
PRBool UpdateAllCoveringWidgets(nsView *aView, nsView *aTarget, nsRect &aDamagedRect, PRBool aOnlyRepaintIfUnblittable);
PRBool UpdateWidgetArea(nsView *aWidgetView, const nsRect &aDamagedRect, nsView* aIgnoreWidgetView);
void UpdateViews(nsView *aView, PRUint32 aUpdateFlags);
@ -357,6 +349,15 @@ public: // NOT in nsIViewManager, so private to the view module
nsEventStatus HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBool aCaptured);
/**
* Called to inform the view manager that a view has scrolled.
* The view manager will invalidate any widgets which may need
* to be rerendered.
* @param aView view to paint. should be root view
* @param aUpdateFlags see bottom of nsIViewManager.h for description
*/
void UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY);
PRBool CanScrollWithBitBlt(nsView* aView);
private:

Просмотреть файл

@ -212,6 +212,7 @@ struct nsWidgetInitData {
: clipChildren(PR_FALSE),
clipSiblings(PR_FALSE),
mDropShadow(PR_FALSE),
mListenForResizes(PR_FALSE),
mWindowType(eWindowType_child),
mBorderStyle(eBorderStyle_default)
{
@ -219,6 +220,7 @@ struct nsWidgetInitData {
// when painting exclude area occupied by child windows and sibling windows
PRPackedBool clipChildren, clipSiblings, mDropShadow;
PRPackedBool mListenForResizes;
nsWindowType mWindowType;
nsBorderStyle mBorderStyle;
};

Просмотреть файл

@ -1166,11 +1166,11 @@ nsresult nsWidget::CreateWidget(nsIWidget *aParent,
if (aNativeParent) {
parentWidget = GTK_OBJECT(aNativeParent);
// we've got a native parent so listen for resizes
mListenForResizes = PR_TRUE;
} else if (aParent) {
// this ups the refcount of the gtk widget, we must unref later.
parentWidget = GTK_OBJECT(aParent->GetNativeData(NS_NATIVE_WIDGET));
mListenForResizes = aInitData ? aInitData->mListenForResizes : PR_FALSE;
}
mBounds = aRect;