diff --git a/mozilla/content/base/src/nsDocumentViewer.cpp b/mozilla/content/base/src/nsDocumentViewer.cpp index 7d416f1af29..968ba9902a1 100644 --- a/mozilla/content/base/src/nsDocumentViewer.cpp +++ b/mozilla/content/base/src/nsDocumentViewer.cpp @@ -1083,6 +1083,8 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, nsIDeviceContext* aDeviceContext, const nsRect& aBounds) { + NS_ASSERTION(aParentWidget != nsnull, "Null aParentWidget"); + #ifdef NS_PRINT_PREVIEW mParentWidget = aParentWidget; // not ref counted #endif @@ -3309,7 +3311,11 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink) nsIView* view = nsnull; frame->GetView(aPO->mParent->mPresContext, &view); if (view != nsnull) { - view->GetWidget(*getter_AddRefs(widget)); + nsCOMPtr w2; + view->GetWidget(*getter_AddRefs(w2)); + if (nsnull != w2) { + widget = w2; + } canCreateScrollbars = PR_FALSE; } } @@ -4551,14 +4557,64 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, rv = CallCreateInstance(kViewCID, &mView); if (NS_FAILED(rv)) return rv; - rv = mView->Init(mViewManager, tbounds, nsnull); + + // if aParentWidget has a view, we'll hook our view manager up to its view tree + void* clientData; + nsIView* containerView = nsnull; + if (NS_SUCCEEDED(aParentWidget->GetClientData(clientData))) { + nsISupports* data = (nsISupports*)clientData; + + if (nsnull != data) { + data->QueryInterface(NS_GET_IID(nsIView), (void **)&containerView); + } + } + + if (nsnull != containerView) { + // see if the containerView has already been hooked into a foreign view manager hierarchy + // if it has, then we have to hook into the hierarchy too otherwise bad things will happen. + nsCOMPtr containerVM; + containerView->GetViewManager(*getter_AddRefs(containerVM)); + nsCOMPtr checkVM; + nsIView* pView = containerView; + do { + pView->GetParent(pView); + } while (pView != nsnull + && NS_SUCCEEDED(pView->GetViewManager(*getter_AddRefs(checkVM))) && checkVM == containerVM); + + if (nsnull == pView) { + // OK, so the container is not already hooked up into a foreign view manager hierarchy. + // That means we can choose not to hook ourselves up. + // + // If the parent container is a chrome shell, or a frameset, then we won't hook into its view + // tree. This will improve performance a little bit (especially given scrolling/painting perf bugs) + // but is really just for peace of mind. This check can be removed if we want to support fancy + // chrome effects like transparent controls floating over content, transparent Web browsers, and + // things like that, and the perf bugs are fixed. + nsCOMPtr container(do_QueryInterface(mContainer)); + nsCOMPtr parentContainer; + PRInt32 itemType; + if (nsnull == container + || NS_FAILED(container->GetParent(getter_AddRefs(parentContainer))) + || nsnull == parentContainer + || NS_FAILED(parentContainer->GetItemType(&itemType)) + || itemType != nsIDocShellTreeItem::typeContent) { + containerView = nsnull; + } else { + nsCOMPtr webShell(do_QueryInterface(parentContainer)); + if (nsnull == webShell || IsWebShellAFrameSet(webShell)) { + containerView = nsnull; + } + } + } + } + + rv = mView->Init(mViewManager, tbounds, containerView); if (NS_FAILED(rv)) return rv; rv = mView->CreateWidget(kWidgetCID, nsnull, aParentWidget->GetNativeData(NS_NATIVE_WIDGET), PR_TRUE, PR_FALSE); - if (rv != NS_OK) return rv; diff --git a/mozilla/layout/base/nsCSSRendering.cpp b/mozilla/layout/base/nsCSSRendering.cpp index ea8f7cdea80..ad502891d67 100644 --- a/mozilla/layout/base/nsCSSRendering.cpp +++ b/mozilla/layout/base/nsCSSRendering.cpp @@ -2555,18 +2555,26 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, return; } - // Ensure that we always paint a color for the root (in case there's - // no background at all or a partly transparent image). nsStyleBackground canvasColor(*color); - if (canvasColor.mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) { - canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; - aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor); - } nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); nsCOMPtr vm; shell->GetViewManager(getter_AddRefs(vm)); + + if (canvasColor.mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) { + nsIView* rootView; + vm->GetRootView(rootView); + nsIView* rootParent; + rootView->GetParent(rootParent); + if (nsnull == rootParent) { + // Ensure that we always paint a color for the root (in case there's + // no background at all or a partly transparent image). + canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; + aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor); + } + } + vm->SetDefaultBackgroundColor(canvasColor.mBackgroundColor); // Since nsHTMLContainerFrame::CreateViewForFrame might have created diff --git a/mozilla/layout/base/nsDocumentViewer.cpp b/mozilla/layout/base/nsDocumentViewer.cpp index 7d416f1af29..968ba9902a1 100644 --- a/mozilla/layout/base/nsDocumentViewer.cpp +++ b/mozilla/layout/base/nsDocumentViewer.cpp @@ -1083,6 +1083,8 @@ DocumentViewerImpl::Init(nsIWidget* aParentWidget, nsIDeviceContext* aDeviceContext, const nsRect& aBounds) { + NS_ASSERTION(aParentWidget != nsnull, "Null aParentWidget"); + #ifdef NS_PRINT_PREVIEW mParentWidget = aParentWidget; // not ref counted #endif @@ -3309,7 +3311,11 @@ DocumentViewerImpl::ReflowPrintObject(PrintObject * aPO, PRBool aDoCalcShrink) nsIView* view = nsnull; frame->GetView(aPO->mParent->mPresContext, &view); if (view != nsnull) { - view->GetWidget(*getter_AddRefs(widget)); + nsCOMPtr w2; + view->GetWidget(*getter_AddRefs(w2)); + if (nsnull != w2) { + widget = w2; + } canCreateScrollbars = PR_FALSE; } } @@ -4551,14 +4557,64 @@ DocumentViewerImpl::MakeWindow(nsIWidget* aParentWidget, rv = CallCreateInstance(kViewCID, &mView); if (NS_FAILED(rv)) return rv; - rv = mView->Init(mViewManager, tbounds, nsnull); + + // if aParentWidget has a view, we'll hook our view manager up to its view tree + void* clientData; + nsIView* containerView = nsnull; + if (NS_SUCCEEDED(aParentWidget->GetClientData(clientData))) { + nsISupports* data = (nsISupports*)clientData; + + if (nsnull != data) { + data->QueryInterface(NS_GET_IID(nsIView), (void **)&containerView); + } + } + + if (nsnull != containerView) { + // see if the containerView has already been hooked into a foreign view manager hierarchy + // if it has, then we have to hook into the hierarchy too otherwise bad things will happen. + nsCOMPtr containerVM; + containerView->GetViewManager(*getter_AddRefs(containerVM)); + nsCOMPtr checkVM; + nsIView* pView = containerView; + do { + pView->GetParent(pView); + } while (pView != nsnull + && NS_SUCCEEDED(pView->GetViewManager(*getter_AddRefs(checkVM))) && checkVM == containerVM); + + if (nsnull == pView) { + // OK, so the container is not already hooked up into a foreign view manager hierarchy. + // That means we can choose not to hook ourselves up. + // + // If the parent container is a chrome shell, or a frameset, then we won't hook into its view + // tree. This will improve performance a little bit (especially given scrolling/painting perf bugs) + // but is really just for peace of mind. This check can be removed if we want to support fancy + // chrome effects like transparent controls floating over content, transparent Web browsers, and + // things like that, and the perf bugs are fixed. + nsCOMPtr container(do_QueryInterface(mContainer)); + nsCOMPtr parentContainer; + PRInt32 itemType; + if (nsnull == container + || NS_FAILED(container->GetParent(getter_AddRefs(parentContainer))) + || nsnull == parentContainer + || NS_FAILED(parentContainer->GetItemType(&itemType)) + || itemType != nsIDocShellTreeItem::typeContent) { + containerView = nsnull; + } else { + nsCOMPtr webShell(do_QueryInterface(parentContainer)); + if (nsnull == webShell || IsWebShellAFrameSet(webShell)) { + containerView = nsnull; + } + } + } + } + + rv = mView->Init(mViewManager, tbounds, containerView); if (NS_FAILED(rv)) return rv; rv = mView->CreateWidget(kWidgetCID, nsnull, aParentWidget->GetNativeData(NS_NATIVE_WIDGET), PR_TRUE, PR_FALSE); - if (rv != NS_OK) return rv; diff --git a/mozilla/layout/forms/nsFormControlFrame.cpp b/mozilla/layout/forms/nsFormControlFrame.cpp index 9f182267549..7f81fc68097 100644 --- a/mozilla/layout/forms/nsFormControlFrame.cpp +++ b/mozilla/layout/forms/nsFormControlFrame.cpp @@ -981,23 +981,32 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, float p2t; aPresContext->GetTwipsToPixels(&t2p); aPresContext->GetPixelsToTwips(&p2t); - + // Add in frame's offset from it it's containing view nsIView *containingView = nsnull; nsPoint offset; rv = aFrame->GetOffsetFromView(aPresContext, offset, &containingView); + if (NS_SUCCEEDED(rv) && (nsnull != containingView)) { aAbsoluteTwipsRect.x += offset.x; aAbsoluteTwipsRect.y += offset.y; nsPoint viewOffset; containingView->GetPosition(&viewOffset.x, &viewOffset.y); + nsIView * parent; containingView->GetParent(parent); // if we don't have a parent view then // check to see if we have a widget and adjust our offset for the widget if (parent == nsnull) { + // account for space above and to the left of the containingView origin. + // the widget is aligned with containingView's bounds, not its origin + nsRect bounds; + containingView->GetBounds(bounds); + aAbsoluteTwipsRect.x += viewOffset.x - bounds.x; + aAbsoluteTwipsRect.y += viewOffset.y - bounds.y; + nsIWidget * widget; containingView->GetWidget(widget); if (nsnull != widget) { @@ -1012,7 +1021,6 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, } rv = NS_OK; } else { - while (nsnull != parent) { nsPoint po; parent->GetPosition(&po.x, &po.y); @@ -1029,6 +1037,13 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, nsIWidget * widget; parent->GetWidget(widget); if (nsnull != widget) { + // account for space above and to the left of the containingView origin. + // the widget is aligned with containingView's bounds, not its origin + nsRect bounds; + parent->GetBounds(bounds); + aAbsoluteTwipsRect.x += po.x - bounds.x; + aAbsoluteTwipsRect.y += po.y - bounds.y; + // Add in the absolute offset of the widget. nsRect absBounds; nsRect lc; diff --git a/mozilla/layout/forms/nsListControlFrame.cpp b/mozilla/layout/forms/nsListControlFrame.cpp index a95fbcfc1c9..ea24269a10f 100644 --- a/mozilla/layout/forms/nsListControlFrame.cpp +++ b/mozilla/layout/forms/nsListControlFrame.cpp @@ -2275,6 +2275,12 @@ nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, parent = aView; while (nsnull != parent) { + nsCOMPtr vm; + parent->GetViewManager(*getter_AddRefs(vm)); + if (vm != aManager) { + break; + } + nscoord x, y; parent->GetPosition(&x, &y); aPoint.x += x; diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 1e6726f40c5..1490a0b35d5 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -410,7 +410,11 @@ nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, nsCOMPtr vm; view->GetViewManager(*getter_AddRefs(vm)); - if (containingView != parentView) { + // it's possible for the parentView to be nonnull but containingView to be + // null, when the parent view doesn't belong to this frame tree but to + // the frame tree of some enclosing document. We do nothing in that case, + // but we have to check that containingView is nonnull or we will crash. + if (nsnull != containingView && containingView != parentView) { // it is possible for parent view not to have a frame attached to it // kind of an anonymous view. This happens with native scrollbars and // the clip view. To fix this we need to go up and parentView chain @@ -546,9 +550,17 @@ nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, // See if the view should be hidden or visible PRBool viewIsVisible = PR_TRUE; PRBool viewHasTransparentContent = - !isCanvas && (!hasBG || (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)); + if (isCanvas && viewHasTransparentContent) { + nsIView* rootView; + vm->GetRootView(rootView); + nsIView* rootParent; + rootView->GetParent(rootParent); + if (nsnull == rootParent) { + viewHasTransparentContent = PR_FALSE; + } + } if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) { viewIsVisible = PR_FALSE; diff --git a/mozilla/layout/generic/nsFrameFrame.cpp b/mozilla/layout/generic/nsFrameFrame.cpp index f261feab74f..a26612bc9bc 100644 --- a/mozilla/layout/generic/nsFrameFrame.cpp +++ b/mozilla/layout/generic/nsFrameFrame.cpp @@ -326,17 +326,24 @@ nsHTMLFrameOuterFrame::Init(nsIPresContext* aPresContext, if (NS_FAILED(rv)) return rv; + // nsHTMLFrameInnerFrame is going to create a view for its frame + // right away, in the call to Init(). If we need a view for the + // OuterFrame but we wait for the normal view creation path in + // nsCSSFrameConstructor, then we will lose because the InnerFrame's + // view's parent will already have been set to some outer view + // (e.g., the canvas) when it really needs to have the OuterFrame's + // view as its parent. So, create the OuterFrame's view right away + // if we need it, and the InnerFrame's view will get it as the parent. + nsIView* view = nsnull; + GetView(aPresContext, &view); + if (!view) { + nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,mStyleContext,nsnull,PR_TRUE); + GetView(aPresContext, &view); + } + const nsStyleDisplay* disp; aParent->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)disp)); if (disp->mDisplay == NS_STYLE_DISPLAY_DECK) { - nsIView* view = nsnull; - GetView(aPresContext, &view); - - if (!view) { - nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,mStyleContext,nsnull,PR_TRUE); - GetView(aPresContext, &view); - } - nsCOMPtr widget; view->GetWidget(*getter_AddRefs(widget)); @@ -1239,6 +1246,7 @@ nsHTMLFrameInnerFrame::CreateViewAndWidget(nsIPresContext* aPresContext, nsIView* view; nsresult rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), (void **)&view); + if (NS_OK != rv) { NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); return rv; diff --git a/mozilla/layout/html/base/src/nsContainerFrame.cpp b/mozilla/layout/html/base/src/nsContainerFrame.cpp index 1e6726f40c5..1490a0b35d5 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsContainerFrame.cpp @@ -410,7 +410,11 @@ nsContainerFrame::PositionFrameView(nsIPresContext* aPresContext, nsCOMPtr vm; view->GetViewManager(*getter_AddRefs(vm)); - if (containingView != parentView) { + // it's possible for the parentView to be nonnull but containingView to be + // null, when the parent view doesn't belong to this frame tree but to + // the frame tree of some enclosing document. We do nothing in that case, + // but we have to check that containingView is nonnull or we will crash. + if (nsnull != containingView && containingView != parentView) { // it is possible for parent view not to have a frame attached to it // kind of an anonymous view. This happens with native scrollbars and // the clip view. To fix this we need to go up and parentView chain @@ -546,9 +550,17 @@ nsContainerFrame::SyncFrameViewAfterReflow(nsIPresContext* aPresContext, // See if the view should be hidden or visible PRBool viewIsVisible = PR_TRUE; PRBool viewHasTransparentContent = - !isCanvas && (!hasBG || (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT)); + if (isCanvas && viewHasTransparentContent) { + nsIView* rootView; + vm->GetRootView(rootView); + nsIView* rootParent; + rootView->GetParent(rootParent); + if (nsnull == rootParent) { + viewHasTransparentContent = PR_FALSE; + } + } if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) { viewIsVisible = PR_FALSE; diff --git a/mozilla/layout/html/document/src/nsFrameFrame.cpp b/mozilla/layout/html/document/src/nsFrameFrame.cpp index f261feab74f..a26612bc9bc 100644 --- a/mozilla/layout/html/document/src/nsFrameFrame.cpp +++ b/mozilla/layout/html/document/src/nsFrameFrame.cpp @@ -326,17 +326,24 @@ nsHTMLFrameOuterFrame::Init(nsIPresContext* aPresContext, if (NS_FAILED(rv)) return rv; + // nsHTMLFrameInnerFrame is going to create a view for its frame + // right away, in the call to Init(). If we need a view for the + // OuterFrame but we wait for the normal view creation path in + // nsCSSFrameConstructor, then we will lose because the InnerFrame's + // view's parent will already have been set to some outer view + // (e.g., the canvas) when it really needs to have the OuterFrame's + // view as its parent. So, create the OuterFrame's view right away + // if we need it, and the InnerFrame's view will get it as the parent. + nsIView* view = nsnull; + GetView(aPresContext, &view); + if (!view) { + nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,mStyleContext,nsnull,PR_TRUE); + GetView(aPresContext, &view); + } + const nsStyleDisplay* disp; aParent->GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)disp)); if (disp->mDisplay == NS_STYLE_DISPLAY_DECK) { - nsIView* view = nsnull; - GetView(aPresContext, &view); - - if (!view) { - nsHTMLContainerFrame::CreateViewForFrame(aPresContext,this,mStyleContext,nsnull,PR_TRUE); - GetView(aPresContext, &view); - } - nsCOMPtr widget; view->GetWidget(*getter_AddRefs(widget)); @@ -1239,6 +1246,7 @@ nsHTMLFrameInnerFrame::CreateViewAndWidget(nsIPresContext* aPresContext, nsIView* view; nsresult rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, NS_GET_IID(nsIView), (void **)&view); + if (NS_OK != rv) { NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); return rv; diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp index 9f182267549..7f81fc68097 100644 --- a/mozilla/layout/html/forms/src/nsFormControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.cpp @@ -981,23 +981,32 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, float p2t; aPresContext->GetTwipsToPixels(&t2p); aPresContext->GetPixelsToTwips(&p2t); - + // Add in frame's offset from it it's containing view nsIView *containingView = nsnull; nsPoint offset; rv = aFrame->GetOffsetFromView(aPresContext, offset, &containingView); + if (NS_SUCCEEDED(rv) && (nsnull != containingView)) { aAbsoluteTwipsRect.x += offset.x; aAbsoluteTwipsRect.y += offset.y; nsPoint viewOffset; containingView->GetPosition(&viewOffset.x, &viewOffset.y); + nsIView * parent; containingView->GetParent(parent); // if we don't have a parent view then // check to see if we have a widget and adjust our offset for the widget if (parent == nsnull) { + // account for space above and to the left of the containingView origin. + // the widget is aligned with containingView's bounds, not its origin + nsRect bounds; + containingView->GetBounds(bounds); + aAbsoluteTwipsRect.x += viewOffset.x - bounds.x; + aAbsoluteTwipsRect.y += viewOffset.y - bounds.y; + nsIWidget * widget; containingView->GetWidget(widget); if (nsnull != widget) { @@ -1012,7 +1021,6 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, } rv = NS_OK; } else { - while (nsnull != parent) { nsPoint po; parent->GetPosition(&po.x, &po.y); @@ -1029,6 +1037,13 @@ nsFormControlFrame::GetAbsoluteFramePosition(nsIPresContext* aPresContext, nsIWidget * widget; parent->GetWidget(widget); if (nsnull != widget) { + // account for space above and to the left of the containingView origin. + // the widget is aligned with containingView's bounds, not its origin + nsRect bounds; + parent->GetBounds(bounds); + aAbsoluteTwipsRect.x += po.x - bounds.x; + aAbsoluteTwipsRect.y += po.y - bounds.y; + // Add in the absolute offset of the widget. nsRect absBounds; nsRect lc; diff --git a/mozilla/layout/html/forms/src/nsListControlFrame.cpp b/mozilla/layout/html/forms/src/nsListControlFrame.cpp index a95fbcfc1c9..ea24269a10f 100644 --- a/mozilla/layout/html/forms/src/nsListControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsListControlFrame.cpp @@ -2275,6 +2275,12 @@ nsListControlFrame::GetViewOffset(nsIViewManager* aManager, nsIView* aView, parent = aView; while (nsnull != parent) { + nsCOMPtr vm; + parent->GetViewManager(*getter_AddRefs(vm)); + if (vm != aManager) { + break; + } + nscoord x, y; parent->GetPosition(&x, &y); aPoint.x += x; diff --git a/mozilla/layout/html/style/src/nsCSSRendering.cpp b/mozilla/layout/html/style/src/nsCSSRendering.cpp index ea8f7cdea80..ad502891d67 100644 --- a/mozilla/layout/html/style/src/nsCSSRendering.cpp +++ b/mozilla/layout/html/style/src/nsCSSRendering.cpp @@ -2555,18 +2555,26 @@ nsCSSRendering::PaintBackground(nsIPresContext* aPresContext, return; } - // Ensure that we always paint a color for the root (in case there's - // no background at all or a partly transparent image). nsStyleBackground canvasColor(*color); - if (canvasColor.mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) { - canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; - aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor); - } nsCOMPtr shell; aPresContext->GetShell(getter_AddRefs(shell)); nsCOMPtr vm; shell->GetViewManager(getter_AddRefs(vm)); + + if (canvasColor.mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) { + nsIView* rootView; + vm->GetRootView(rootView); + nsIView* rootParent; + rootView->GetParent(rootParent); + if (nsnull == rootParent) { + // Ensure that we always paint a color for the root (in case there's + // no background at all or a partly transparent image). + canvasColor.mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT; + aPresContext->GetDefaultBackgroundColor(&canvasColor.mBackgroundColor); + } + } + vm->SetDefaultBackgroundColor(canvasColor.mBackgroundColor); // Since nsHTMLContainerFrame::CreateViewForFrame might have created diff --git a/mozilla/view/public/nsIViewManager.h b/mozilla/view/public/nsIViewManager.h index db5eba7ee63..6d56cb6c9b1 100644 --- a/mozilla/view/public/nsIViewManager.h +++ b/mozilla/view/public/nsIViewManager.h @@ -83,7 +83,7 @@ public: /** * Set the root of the view tree. Does not destroy the current root view. - * One of following must be true: + * At least one of following must be true: * a) the aWidget parameter is an nsIWidget instance to render into * that is not owned by any view and aView has no widget, or * b) aView has a nsIWidget instance and aWidget is null, or diff --git a/mozilla/view/src/nsView.cpp b/mozilla/view/src/nsView.cpp index 2f07a1f9523..3e065c13469 100644 --- a/mozilla/view/src/nsView.cpp +++ b/mozilla/view/src/nsView.cpp @@ -103,7 +103,13 @@ nsView::~nsView() while (GetFirstChild() != nsnull) { - GetFirstChild()->Destroy(); + nsView* child = GetFirstChild(); + if (child->GetViewManager() == mViewManager) { + child->Destroy(); + } else { + // just unhook it. Someone else will want to destroy this. + RemoveChild(child); + } } if (nsnull != mViewManager) @@ -112,24 +118,23 @@ nsView::~nsView() if (nsnull != rootView) { + // Root views can have parents! + if (nsnull != mParent) + { + mViewManager->RemoveChild(this); + } + if (rootView == this) { // Inform the view manager that the root view has gone away... mViewManager->SetRootView(nsnull); } - else - { - if (nsnull != mParent) - { - mViewManager->RemoveChild(this); - } - } - } + } else if (nsnull != mParent) { mParent->RemoveChild(this); } - + nsView* grabbingView = mViewManager->GetMouseEventGrabber(); //check to see if we are capturing!!! if (grabbingView == this) { diff --git a/mozilla/view/src/nsViewManager.cpp b/mozilla/view/src/nsViewManager.cpp index 9ef3d80c430..51625b3d8e6 100644 --- a/mozilla/view/src/nsViewManager.cpp +++ b/mozilla/view/src/nsViewManager.cpp @@ -64,17 +64,6 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); XXX TODO XXX DeCOMify newly private methods - Move event handling into nsViewManager - Make event handling use CreateDisplayList - Reverse storage order of views so that LAST view in document order is the LAST child - of its parent view - Audit users of nsIView::GetPosition and nsIView::GetBounds, then - fix nsContainerFrame::SyncFrameViewAfterReflow to size views to contain - left-or-above content - Remove nsIClipView stuff and just use the CLIPCHILDREN flag - Put in support for hierarchy of viewmanagers (handle nsViewManager::SetRootView - case where aWidget == null and aView has a non-null parent with a different view - manager) Fix opacity model to conform to SVG (requires backbuffer stack) Optimize view storage */ @@ -270,7 +259,7 @@ nsViewManager::PostInvalidateEvent() NS_ASSERTION(nsnull != ev,"InvalidateEvent is null"); NS_ASSERTION(nsnull != mEventQueue,"Event queue is null"); mEventQueue->PostEvent(ev); - mPendingInvalidateEvent = PR_TRUE; + mPendingInvalidateEvent = PR_TRUE; } } @@ -530,6 +519,13 @@ NS_IMETHODIMP nsViewManager::SetRootView(nsIView *aView, nsIWidget* aWidget) // case b) The aView has a nsIWidget instance if (nsnull != mRootView) { + nsView* parent = mRootView->GetParent(); + if (nsnull != parent) { + parent->InsertChild(mRootView, nsnull); + } + + mRootView->SetZIndex(PR_FALSE, 0); + mRootView->GetWidget(mRootWindow); if (nsnull != mRootWindow) { return NS_OK; @@ -1045,6 +1041,7 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsIRegion* aRgn, nsIDeviceC void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRect& aRect, PRBool &aResult) { BuildDisplayList(aRootView, aRect, PR_FALSE, PR_FALSE); + nsRect fakeClipRect; PRInt32 index = 0; PRBool anyRendered; @@ -1054,6 +1051,8 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC, con OptimizeDisplayList(aRect, finalTransparentRect); + // ShowDisplayList(mDisplayListCount); + if (!finalTransparentRect.IsEmpty()) { // There are some bits here that aren't going to be completely painted unless we do it now. // XXX Which color should we use for these bits? @@ -1393,7 +1392,9 @@ void nsViewManager::ProcessPendingUpdates(nsView* aView) // process pending updates in child view. nsView* childView = aView->GetFirstChild(); while (nsnull != childView) { - ProcessPendingUpdates(childView); + if (childView->GetViewManager() == this) { + ProcessPendingUpdates(childView); + } childView = childView->GetNextSibling(); } @@ -1446,7 +1447,12 @@ nsViewManager::UpdateViewAfterScroll(nsIView *aView, PRInt32 aDX, PRInt32 aDY) return NS_OK; } - UpdateAllCoveringWidgets(mRootView, view, damageRect, PR_FALSE); + nsView* realRoot = mRootView; + while (realRoot->GetParent() != nsnull) { + realRoot = realRoot->GetParent(); + } + + UpdateAllCoveringWidgets(realRoot, view, damageRect, PR_FALSE); Composite(); return NS_OK; } @@ -1499,19 +1505,20 @@ PRBool nsViewManager::UpdateAllCoveringWidgets(nsView *aView, nsView *aTarget, } if (!childCovers && (!isBlittable || (hasWidget && !aRepaintOnlyUnblittableViews))) { - ++mUpdateCnt; + nsViewManager* vm = aView->GetViewManager(); + ++vm->mUpdateCnt; - if (!mRefreshEnabled) { + if (!vm->mRefreshEnabled) { // accumulate this rectangle in the view's dirty region, so we can process it later. - AddRectToDirtyRegion(aView, bounds); - mHasPendingInvalidates = PR_TRUE; + vm->AddRectToDirtyRegion(aView, bounds); + vm->mHasPendingInvalidates = PR_TRUE; } else { nsView* widgetView = GetWidgetView(aView); if (widgetView != nsnull) { ViewToWidget(aView, widgetView, bounds); nsCOMPtr widget; - GetWidgetForView(widgetView, getter_AddRefs(widget)); + vm->GetWidgetForView(widgetView, getter_AddRefs(widget)); widget->Invalidate(bounds, PR_FALSE); } } @@ -1589,7 +1596,12 @@ NS_IMETHODIMP nsViewManager::UpdateView(nsIView *aView, const nsRect &aRect, PRU damagedRect.x = origin.x; damagedRect.y = origin.y; - UpdateAllCoveringWidgets(mRootView, nsnull, damagedRect, PR_FALSE); + nsView* realRoot = mRootView; + while (realRoot->GetParent() != nsnull) { + realRoot = realRoot->GetParent(); + } + + UpdateAllCoveringWidgets(realRoot, nsnull, damagedRect, PR_FALSE); } ++mUpdateCnt; @@ -1620,7 +1632,9 @@ void nsViewManager::UpdateViews(nsView *aView, PRUint32 aUpdateFlags) // update all children as well. nsView* childView = aView->GetFirstChild(); while (nsnull != childView) { - UpdateViews(childView, aUpdateFlags); + if (childView->GetViewManager() == this) { + UpdateViews(childView, aUpdateFlags); + } childView = childView->GetNextSibling(); } } @@ -1805,14 +1819,14 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, nsEventStatus *aS nsView *parent; parent = baseView; - while (nsnull != parent) { + while (mRootView != parent) { parent->ConvertToParentCoords(&offset.x, &offset.y); parent = parent->GetParent(); } //Subtract back offset from root of view parent = view; - while (nsnull != parent) { + while (mRootView != parent) { parent->ConvertFromParentCoords(&offset.x, &offset.y); parent = parent->GetParent(); } @@ -1947,7 +1961,7 @@ void nsViewManager::BuildEventTargetList(nsAutoVoidArray &aTargets, nsView* aVie BuildDisplayList(aView, eventRect, PR_TRUE, aCaptured); - // ShowDisplayList(mDisplayListCount); + ShowDisplayList(mDisplayListCount); // The display list is in order from back to front. We return the target list in order from // front to back. @@ -1984,17 +1998,33 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBo } nsAutoVoidArray targetViews; + nsAutoVoidArray heldRefCountsToOtherVMs; // In fact, we only need to take this expensive path when the event is a mouse event ... riiiight? BuildEventTargetList(targetViews, aView, aEvent, aCaptured); nsEventStatus status = nsEventStatus_eIgnore; - for (PRInt32 i = 0; i < targetViews.Count(); i++) { + // get a death grip on any view managers' view observers (other than this one) + PRInt32 i; + for (i = 0; i < targetViews.Count(); i++) { + DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, targetViews.ElementAt(i)); + nsView* v = element->mView; + nsViewManager* vVM = v->GetViewManager(); + if (vVM != this) { + nsIViewObserver* vobs = nsnull; + vVM->GetViewObserver(vobs); + if (nsnull != vobs) { + heldRefCountsToOtherVMs.AppendElement(vobs); + } + } + } + + for (i = 0; i < targetViews.Count(); i++) { DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, targetViews.ElementAt(i)); nsView* v = element->mView; - if (nsnull != v->GetClientData() && nsnull != obs) { + if (nsnull != v->GetClientData()) { PRBool handled = PR_FALSE; nsRect r; v->GetDimensions(r); @@ -2005,7 +2035,18 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBo aEvent->point.x -= x; aEvent->point.y -= y; - obs->HandleEvent(v, aEvent, &status, i == targetViews.Count() - 1, handled); + nsViewManager* vVM = v->GetViewManager(); + if (vVM == this) { + if (nsnull != obs) { + obs->HandleEvent(v, aEvent, &status, i == targetViews.Count() - 1, handled); + } + } else { + nsIViewObserver* vobs = nsnull; + vVM->GetViewObserver(vobs); + if (nsnull != vobs) { + vobs->HandleEvent(v, aEvent, &status, i == targetViews.Count() - 1, handled); + } + } aEvent->point.x += x; aEvent->point.y += y; @@ -2025,6 +2066,12 @@ nsEventStatus nsViewManager::HandleEvent(nsView* aView, nsGUIEvent* aEvent, PRBo delete element; } + // release death grips + for (i = 0; i < heldRefCountsToOtherVMs.Count(); i++) { + nsIViewObserver* element = NS_STATIC_CAST(nsIViewObserver*, heldRefCountsToOtherVMs.ElementAt(i)); + NS_RELEASE(element); + } + return status; } @@ -2455,6 +2502,12 @@ NS_IMETHODIMP nsViewManager::SetViewZIndex(nsIView *aView, PRBool aAutoZIndex, P NS_ASSERTION((view != nsnull), "no view"); + // don't allow the root view's z-index to be changed. It should always be zero. + // This could be removed and replaced with a style rule, or just removed altogether, with interesting consequences + if (aView == mRootView) { + return rv; + } + if (aAutoZIndex) { aZIndex = 0; } @@ -2763,7 +2816,9 @@ NS_IMETHODIMP nsViewManager::SetRootScrollableView(nsIScrollableView *aScrollabl mRootScrollable = aScrollable; //XXX this needs to go away when layout start setting this bit on it's own. MMP - if (mRootScrollable) + // We don't set ALWAYS_BLIT if this isn't the root of the view manager tree, + // because non-roots may not, in fact, always be able to blit + if (mRootScrollable && mRootView->GetParent() == nsnull) mRootScrollable->SetScrollProperties(NS_SCROLL_PROPERTY_ALWAYS_BLIT); return NS_OK; @@ -3373,11 +3428,11 @@ void nsViewManager::ShowDisplayList(PRInt32 flatlen) nest[nestcnt << 1] = 0; - printf("%snsIView@%p{%d,%d,%d,%d @ %d,%d; p=%p, z=%d} [x=%d, y=%d, w=%d, h=%d, absX=%d, absY=%d]\n", + printf("%snsIView@%p{%d,%d,%d,%d @ %d,%d; p=%p,m=%p z=%d} [x=%d, y=%d, w=%d, h=%d, absX=%d, absY=%d]\n", nest, (void*)view, dim.x, dim.y, dim.width, dim.height, vx, vy, - (void*)parent, zindex, + (void*)parent, (void*)view->GetViewManager(), zindex, rect.x, rect.y, rect.width, rect.height, element->mAbsX, element->mAbsY); @@ -3438,7 +3493,7 @@ PRBool nsViewManager::IsClipView(nsView* aView) } -nsView* nsViewManager::GetWidgetView(nsView *aView) const +nsView* nsViewManager::GetWidgetView(nsView *aView) { while (aView != nsnull) { PRBool hasWidget; @@ -3479,7 +3534,7 @@ nsresult nsViewManager::GetVisibleRect(nsRect& aVisibleRect) nsIScrollableView* scrollingView; GetRootScrollableView(&scrollingView); - if (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* clipViewI; @@ -3651,9 +3706,11 @@ nsViewManager::ProcessWidgetChanges(nsView* aView) nsView *child = aView->GetFirstChild(); while (nsnull != child) { - rv = ProcessWidgetChanges(child); - if (NS_FAILED(rv)) - return rv; + if (child->GetViewManager() == this) { + rv = ProcessWidgetChanges(child); + if (NS_FAILED(rv)) + return rv; + } child = child->GetNextSibling(); }