From ab5a30f802c8536cb355edab34c621a0c7df4ef5 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Tue, 19 Apr 2011 12:55:11 +0100 Subject: [PATCH] Bug 649726 - Move nsHTMLContainerFrame static view methods to nsContainerFrame. r=bz. --- layout/base/nsBidiPresUtils.cpp | 2 +- layout/base/nsCSSFrameConstructor.cpp | 40 ++-- layout/generic/nsBlockFrame.cpp | 4 +- layout/generic/nsCanvasFrame.cpp | 4 +- layout/generic/nsColumnSetFrame.cpp | 4 +- layout/generic/nsContainerFrame.cpp | 240 +++++++++++++++++++++++- layout/generic/nsContainerFrame.h | 17 ++ layout/generic/nsFirstLetterFrame.cpp | 4 +- layout/generic/nsHTMLContainerFrame.cpp | 222 ---------------------- layout/generic/nsHTMLContainerFrame.h | 17 -- layout/generic/nsInlineFrame.cpp | 14 +- layout/generic/nsSubDocumentFrame.cpp | 2 +- layout/xul/base/src/nsDeckFrame.cpp | 2 +- 13 files changed, 286 insertions(+), 286 deletions(-) diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index 5a0d7a57f9e..b5d6ee2063d 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -287,7 +287,7 @@ SplitInlineAncestors(nsIFrame* aFrame) nsFrameList tail = container->StealFramesAfter(frame); // Reparent views as necessary - rv = nsHTMLContainerFrame::ReparentFrameViewList(presContext, tail, parent, newParent); + rv = nsContainerFrame::ReparentFrameViewList(presContext, tail, parent, newParent); if (NS_FAILED(rv)) { return rv; } diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 2b1bac72d32..73834f6f8b9 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -1331,8 +1331,8 @@ MoveChildrenTo(nsPresContext* aPresContext, if (aNewParent->HasView() || aOldParent->HasView() || !sameGrandParent) { // Move the frames into the new view - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, aFrameList, - aOldParent, aNewParent); + nsContainerFrame::ReparentFrameViewList(aPresContext, aFrameList, + aOldParent, aNewParent); } for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) { @@ -1907,7 +1907,7 @@ nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState, // Init the table outer frame and see if we need to create a view, e.g. // the frame is absolutely positioned InitAndRestoreFrame(aState, content, geometricParent, nsnull, newFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); // Create the inner table frame nsIFrame* innerFrame; @@ -1987,7 +1987,7 @@ nsCSSFrameConstructor::ConstructTableRow(nsFrameConstructorState& aState, return NS_ERROR_OUT_OF_MEMORY; } InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); nsFrameItems childItems; nsresult rv; @@ -2088,7 +2088,7 @@ nsCSSFrameConstructor::ConstructTableCell(nsFrameConstructorState& aState, // Initialize the table cell frame InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); // Resolve pseudo style and initialize the body cell frame nsRefPtr innerPseudoStyle; @@ -2438,7 +2438,7 @@ nsCSSFrameConstructor::ConstructDocElementFrame(Element* aDocEle processChildren = PR_TRUE; // See if we need to create a view - nsHTMLContainerFrame::CreateViewForFrame(contentFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(contentFrame, PR_FALSE); } else { return NS_ERROR_FAILURE; } @@ -2957,7 +2957,7 @@ nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState, return rv; } // See if we need to create a view - nsHTMLContainerFrame::CreateViewForFrame(buttonFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(buttonFrame, PR_FALSE); nsRefPtr innerBlockContext; innerBlockContext = @@ -3085,7 +3085,7 @@ nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState, aState.GetGeometricParent(aStyleDisplay, aParentFrame), nsnull, comboboxFrame); - nsHTMLContainerFrame::CreateViewForFrame(comboboxFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(comboboxFrame, PR_FALSE); rv = aState.AddChild(comboboxFrame, aFrameItems, content, styleContext, aParentFrame); @@ -3224,7 +3224,7 @@ nsCSSFrameConstructor::InitializeSelectFrame(nsFrameConstructorState& aState, } } - nsHTMLContainerFrame::CreateViewForFrame(scrollFrame, aBuildCombobox); + nsContainerFrame::CreateViewForFrame(scrollFrame, aBuildCombobox); BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame, geometricParent, scrollFrame); @@ -3275,7 +3275,7 @@ nsCSSFrameConstructor::ConstructFieldSetFrame(nsFrameConstructorState& aState, // See if we need to create a view, e.g. the frame is absolutely // positioned - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); // Resolve style and initialize the frame nsRefPtr fieldsetContentStyle; @@ -3756,8 +3756,8 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt newFrame); NS_ASSERTION(NS_SUCCEEDED(rv), "InitAndRestoreFrame failed"); // See whether we need to create a view - nsHTMLContainerFrame::CreateViewForFrame(newFrame, - (bits & FCDATA_FORCE_VIEW) != 0); + nsContainerFrame::CreateViewForFrame(newFrame, + (bits & FCDATA_FORCE_VIEW) != 0); frameToAddToList = newFrame; } @@ -4235,7 +4235,7 @@ nsCSSFrameConstructor::BeginBuildingScrollFrame(nsFrameConstructorState& aState, InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, gfxScrollFrame); // Create a view - nsHTMLContainerFrame::CreateViewForFrame(gfxScrollFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(gfxScrollFrame, PR_FALSE); } // if there are any anonymous children for the scroll frame, create @@ -4917,7 +4917,7 @@ nsCSSFrameConstructor::ConstructSVGForeignObjectFrame(nsFrameConstructorState& a // We don't allow this frame to be out of flow InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); nsresult rv = aState.AddChild(newFrame, aFrameItems, content, styleContext, aParentFrame, PR_FALSE, PR_FALSE); @@ -8383,7 +8383,7 @@ nsCSSFrameConstructor::CreateContinuingOuterTableFrame(nsIPresShell* aPresShe if (newFrame) { newFrame->Init(aContent, aParentFrame, aFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); // Create a continuing inner table frame, and if there's a caption then // replicate the caption @@ -8429,7 +8429,7 @@ nsCSSFrameConstructor::CreateContinuingTableFrame(nsIPresShell* aPresShell, if (newFrame) { newFrame->Init(aContent, aParentFrame, aFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); // Replicate any header/footer frames nsFrameItems childFrames; @@ -8509,7 +8509,7 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext, if (newFrame) { newFrame->Init(content, aParentFrame, aFrame); - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); } } else if (nsGkAtoms::inlineFrame == frameType) { @@ -10648,7 +10648,7 @@ nsCSSFrameConstructor::ConstructBlock(nsFrameConstructorState& aState, InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, columnSetFrame); // See if we need to create a view - nsHTMLContainerFrame::CreateViewForFrame(columnSetFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(columnSetFrame, PR_FALSE); blockStyle = mPresShell->StyleSet()-> ResolveAnonymousBoxStyle(nsCSSAnonBoxes::columnContent, aStyleContext); parent = columnSetFrame; @@ -10788,7 +10788,7 @@ nsCSSFrameConstructor::ConstructInline(nsFrameConstructorState& aState, // this is part of the fix for bug 42372 // Any inline frame might need a view (because of opacity, or fixed background) - nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(newFrame, PR_FALSE); if (positioned) { // Relatively positioned frames becomes a container for child @@ -10877,7 +10877,7 @@ nsCSSFrameConstructor::CreateIBSiblings(nsFrameConstructorState& aState, PR_FALSE); // Any frame could have a view - nsHTMLContainerFrame::CreateViewForFrame(blockFrame, PR_FALSE); + nsContainerFrame::CreateViewForFrame(blockFrame, PR_FALSE); // Find the first non-block child which defines the end of our block kids // and the start of our next inline's kids diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index a10d10197d2..476460559a5 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -674,8 +674,8 @@ static void ReparentFrame(nsIFrame* aFrame, nsIFrame* aOldParent, // When pushing and pulling frames we need to check for whether any // views need to be reparented - nsHTMLContainerFrame::ReparentFrameView(aFrame->PresContext(), aFrame, - aOldParent, aNewParent); + nsContainerFrame::ReparentFrameView(aFrame->PresContext(), aFrame, + aOldParent, aNewParent); } ////////////////////////////////////////////////////////////////////// diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 3a6b32d44b9..7f7d413739c 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -439,8 +439,8 @@ nsCanvasFrame::Reflow(nsPresContext* aPresContext, if (overflow) { NS_ASSERTION(overflow->OnlyChild(), "must have doc root as canvas frame's only child"); - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, *overflow, - prevCanvasFrame, this); + nsContainerFrame::ReparentFrameViewList(aPresContext, *overflow, + prevCanvasFrame, this); // Prepend overflow to the our child list. There may already be // children placeholders for fixed-pos elements, which don't get // reflowed but must not be lost until the canvas frame is destroyed. diff --git a/layout/generic/nsColumnSetFrame.cpp b/layout/generic/nsColumnSetFrame.cpp index f217e79e150..ed274869407 100644 --- a/layout/generic/nsColumnSetFrame.cpp +++ b/layout/generic/nsColumnSetFrame.cpp @@ -869,8 +869,8 @@ nsColumnSetFrame::DrainOverflowColumns() if (prev) { nsAutoPtr overflows(prev->StealOverflowFrames()); if (overflows) { - nsHTMLContainerFrame::ReparentFrameViewList(PresContext(), *overflows, - prev, this); + nsContainerFrame::ReparentFrameViewList(PresContext(), *overflows, + prev, this); mFrames.InsertFrames(this, nsnull, *overflows); } diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 070480c927f..4564a68f928 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -407,6 +407,106 @@ nsContainerFrame::PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset, ///////////////////////////////////////////////////////////////////////////// // Helper member functions +static nsresult +ReparentFrameViewTo(nsIFrame* aFrame, + nsIViewManager* aViewManager, + nsIView* aNewParentView, + nsIView* aOldParentView) +{ + + // XXX What to do about placeholder views for "position: fixed" elements? + // They should be reparented too. + + // Does aFrame have a view? + if (aFrame->HasView()) { +#ifdef MOZ_XUL + if (aFrame->GetType() == nsGkAtoms::menuPopupFrame) { + // This view must be parented by the root view, don't reparent it. + return NS_OK; + } +#endif + nsIView* view = aFrame->GetView(); + // Verify that the current parent view is what we think it is + //nsIView* parentView; + //NS_ASSERTION(parentView == aOldParentView, "unexpected parent view"); + + aViewManager->RemoveChild(view); + + // The view will remember the Z-order and other attributes that have been set on it. + nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(aNewParentView, aFrame); + aViewManager->InsertChild(aNewParentView, view, insertBefore, insertBefore != nsnull); + } else { + PRInt32 listIndex = 0; + nsIAtom* listName = nsnull; + // This loop iterates through every child list name, and also + // executes once with listName == nsnull. + do { + // Iterate the child frames, and check each child frame to see if it has + // a view + nsIFrame* childFrame = aFrame->GetFirstChild(listName); + for (; childFrame; childFrame = childFrame->GetNextSibling()) { + ReparentFrameViewTo(childFrame, aViewManager, + aNewParentView, aOldParentView); + } + listName = aFrame->GetAdditionalChildListName(listIndex++); + } while (listName); + } + + return NS_OK; +} + +nsresult +nsContainerFrame::CreateViewForFrame(nsIFrame* aFrame, + PRBool aForce) +{ + if (aFrame->HasView()) { + return NS_OK; + } + + // If we don't yet have a view, see if we need a view + if (!aForce && !aFrame->NeedsView()) { + // don't need a view + return NS_OK; + } + + nsIView* parentView = aFrame->GetParent()->GetClosestView(); + NS_ASSERTION(parentView, "no parent with view"); + + nsIViewManager* viewManager = parentView->GetViewManager(); + NS_ASSERTION(viewManager, "null view manager"); + + // Create a view + nsIView* view = viewManager->CreateView(aFrame->GetRect(), parentView); + if (!view) + return NS_ERROR_OUT_OF_MEMORY; + + SyncFrameViewProperties(aFrame->PresContext(), aFrame, nsnull, view); + + nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(parentView, aFrame); + // we insert this view 'above' the insertBefore view, unless insertBefore is null, + // in which case we want to call with aAbove == PR_FALSE to insert at the beginning + // in document order + viewManager->InsertChild(parentView, view, insertBefore, insertBefore != nsnull); + + // REVIEW: Don't create a widget for fixed-pos elements anymore. + // ComputeRepaintRegionForCopy will calculate the right area to repaint + // when we scroll. + // Reparent views on any child frames (or their descendants) to this + // view. We can just call ReparentFrameViewTo on this frame because + // we know this frame has no view, so it will crawl the children. Also, + // we know that any descendants with views must have 'parentView' as their + // parent view. + ReparentFrameViewTo(aFrame, viewManager, view, parentView); + + // Remember our view + aFrame->SetView(view); + + NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, + ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p view=%p", + aFrame)); + return NS_OK; +} + /** * Position the view associated with |aKidFrame|, if there is one. A * container frame should call this method after positioning a frame, @@ -436,6 +536,128 @@ nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame) vm->MoveViewTo(view, pt.x, pt.y); } +nsresult +nsContainerFrame::ReparentFrameView(nsPresContext* aPresContext, + nsIFrame* aChildFrame, + nsIFrame* aOldParentFrame, + nsIFrame* aNewParentFrame) +{ + NS_PRECONDITION(aChildFrame, "null child frame pointer"); + NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer"); + NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer"); + NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame"); + + // See if either the old parent frame or the new parent frame have a view + while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) { + // Walk up both the old parent frame and the new parent frame nodes + // stopping when we either find a common parent or views for one + // or both of the frames. + // + // This works well in the common case where we push/pull and the old parent + // frame and the new parent frame are part of the same flow. They will + // typically be the same distance (height wise) from the + aOldParentFrame = aOldParentFrame->GetParent(); + aNewParentFrame = aNewParentFrame->GetParent(); + + // We should never walk all the way to the root frame without finding + // a view + NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view"); + + // See if we reached a common ancestor + if (aOldParentFrame == aNewParentFrame) { + break; + } + } + + // See if we found a common parent frame + if (aOldParentFrame == aNewParentFrame) { + // We found a common parent and there are no views between the old parent + // and the common parent or the new parent frame and the common parent. + // Because neither the old parent frame nor the new parent frame have views, + // then any child views don't need reparenting + return NS_OK; + } + + // We found views for one or both of the ancestor frames before we + // found a common ancestor. + nsIView* oldParentView = aOldParentFrame->GetClosestView(); + nsIView* newParentView = aNewParentFrame->GetClosestView(); + + // See if the old parent frame and the new parent frame are in the + // same view sub-hierarchy. If they are then we don't have to do + // anything + if (oldParentView != newParentView) { + // They're not so we need to reparent any child views + return ReparentFrameViewTo(aChildFrame, oldParentView->GetViewManager(), newParentView, + oldParentView); + } + + return NS_OK; +} + +nsresult +nsContainerFrame::ReparentFrameViewList(nsPresContext* aPresContext, + const nsFrameList& aChildFrameList, + nsIFrame* aOldParentFrame, + nsIFrame* aNewParentFrame) +{ + NS_PRECONDITION(aChildFrameList.NotEmpty(), "empty child frame list"); + NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer"); + NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer"); + NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame"); + + // See if either the old parent frame or the new parent frame have a view + while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) { + // Walk up both the old parent frame and the new parent frame nodes + // stopping when we either find a common parent or views for one + // or both of the frames. + // + // This works well in the common case where we push/pull and the old parent + // frame and the new parent frame are part of the same flow. They will + // typically be the same distance (height wise) from the + aOldParentFrame = aOldParentFrame->GetParent(); + aNewParentFrame = aNewParentFrame->GetParent(); + + // We should never walk all the way to the root frame without finding + // a view + NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view"); + + // See if we reached a common ancestor + if (aOldParentFrame == aNewParentFrame) { + break; + } + } + + + // See if we found a common parent frame + if (aOldParentFrame == aNewParentFrame) { + // We found a common parent and there are no views between the old parent + // and the common parent or the new parent frame and the common parent. + // Because neither the old parent frame nor the new parent frame have views, + // then any child views don't need reparenting + return NS_OK; + } + + // We found views for one or both of the ancestor frames before we + // found a common ancestor. + nsIView* oldParentView = aOldParentFrame->GetClosestView(); + nsIView* newParentView = aNewParentFrame->GetClosestView(); + + // See if the old parent frame and the new parent frame are in the + // same view sub-hierarchy. If they are then we don't have to do + // anything + if (oldParentView != newParentView) { + nsIViewManager* viewManager = oldParentView->GetViewManager(); + + // They're not so we need to reparent any child views + for (nsFrameList::Enumerator e(aChildFrameList); !e.AtEnd(); e.Next()) { + ReparentFrameViewTo(e.get(), viewManager, newParentView, oldParentView); + } + } + + return NS_OK; +} + static nsIWidget* GetPresContextContainerWidget(nsPresContext* aPresContext) { @@ -880,8 +1102,8 @@ nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPres ExcessOverflowContainersProperty()); if (excessFrames) { excessFrames->ApplySetParent(this); - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, *excessFrames, - prev, this); + nsContainerFrame::ReparentFrameViewList(aPresContext, *excessFrames, + prev, this); overflowContainers = excessFrames; rv = SetPropTableFrames(aPresContext, overflowContainers, OverflowContainersProperty()); @@ -1264,7 +1486,7 @@ nsContainerFrame::PushChildren(nsPresContext* aPresContext, // When pushing and pulling frames we need to check for whether any // views need to be reparented. for (nsIFrame* f = aFromChild; f; f = f->GetNextSibling()) { - nsHTMLContainerFrame::ReparentFrameView(aPresContext, f, this, nextInFlow); + nsContainerFrame::ReparentFrameView(aPresContext, f, this, nextInFlow); } nextInFlow->mFrames.InsertFrames(nextInFlow, nsnull, tail); } @@ -1298,9 +1520,9 @@ nsContainerFrame::MoveOverflowToChildList(nsPresContext* aPresContext) "bad overflow list"); // When pushing and pulling frames we need to check for whether any // views need to be reparented. - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, - *prevOverflowFrames, - prevInFlow, this); + nsContainerFrame::ReparentFrameViewList(aPresContext, + *prevOverflowFrames, + prevInFlow, this); mFrames.AppendFrames(this, *prevOverflowFrames); result = PR_TRUE; } @@ -1448,9 +1670,9 @@ nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont, SetUpListWalker(); } if (aOverflowCont->GetParent() != mParent) { - nsHTMLContainerFrame::ReparentFrameView(presContext, aOverflowCont, - aOverflowCont->GetParent(), - mParent); + nsContainerFrame::ReparentFrameView(presContext, aOverflowCont, + aOverflowCont->GetParent(), + mParent); } mOverflowContList->InsertFrame(mParent, mPrevOverflowCont, aOverflowCont); aReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW; diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 2c413a88f99..f1e19c9fa18 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -117,9 +117,26 @@ public: nsIFrame* aNextInFlow, PRBool aDeletingEmptyFrames); + /** + * Helper method to wrap views around frames. Used by containers + * under special circumstances (can be used by leaf frames as well) + */ + static nsresult CreateViewForFrame(nsIFrame* aFrame, + PRBool aForce); + // Positions the frame's view based on the frame's origin static void PositionFrameView(nsIFrame* aKidFrame); + static nsresult ReparentFrameView(nsPresContext* aPresContext, + nsIFrame* aChildFrame, + nsIFrame* aOldParentFrame, + nsIFrame* aNewParentFrame); + + static nsresult ReparentFrameViewList(nsPresContext* aPresContext, + const nsFrameList& aChildFrameList, + nsIFrame* aOldParentFrame, + nsIFrame* aNewParentFrame); + // Set the view's size and position after its frame has been reflowed. // // Flags: diff --git a/layout/generic/nsFirstLetterFrame.cpp b/layout/generic/nsFirstLetterFrame.cpp index 1d498d9a380..d20f5346cbe 100644 --- a/layout/generic/nsFirstLetterFrame.cpp +++ b/layout/generic/nsFirstLetterFrame.cpp @@ -369,8 +369,8 @@ nsFirstLetterFrame::DrainOverflowFrames(nsPresContext* aPresContext) // When pushing and pulling frames we need to check for whether any // views need to be reparented. - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, *overflowFrames, - prevInFlow, this); + nsContainerFrame::ReparentFrameViewList(aPresContext, *overflowFrames, + prevInFlow, this); mFrames.InsertFrames(this, nsnull, *overflowFrames); } } diff --git a/layout/generic/nsHTMLContainerFrame.cpp b/layout/generic/nsHTMLContainerFrame.cpp index 572c1b99732..ca8eb138066 100644 --- a/layout/generic/nsHTMLContainerFrame.cpp +++ b/layout/generic/nsHTMLContainerFrame.cpp @@ -634,226 +634,4 @@ nsHTMLContainerFrame::CreateNextInFlow(nsPresContext* aPresContext, return NS_OK; } -static nsresult -ReparentFrameViewTo(nsIFrame* aFrame, - nsIViewManager* aViewManager, - nsIView* aNewParentView, - nsIView* aOldParentView) -{ - - // XXX What to do about placeholder views for "position: fixed" elements? - // They should be reparented too. - - // Does aFrame have a view? - if (aFrame->HasView()) { -#ifdef MOZ_XUL - if (aFrame->GetType() == nsGkAtoms::menuPopupFrame) { - // This view must be parented by the root view, don't reparent it. - return NS_OK; - } -#endif - nsIView* view = aFrame->GetView(); - // Verify that the current parent view is what we think it is - //nsIView* parentView; - //NS_ASSERTION(parentView == aOldParentView, "unexpected parent view"); - - aViewManager->RemoveChild(view); - - // The view will remember the Z-order and other attributes that have been set on it. - nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(aNewParentView, aFrame); - aViewManager->InsertChild(aNewParentView, view, insertBefore, insertBefore != nsnull); - } else { - PRInt32 listIndex = 0; - nsIAtom* listName = nsnull; - // This loop iterates through every child list name, and also - // executes once with listName == nsnull. - do { - // Iterate the child frames, and check each child frame to see if it has - // a view - nsIFrame* childFrame = aFrame->GetFirstChild(listName); - for (; childFrame; childFrame = childFrame->GetNextSibling()) { - ReparentFrameViewTo(childFrame, aViewManager, - aNewParentView, aOldParentView); - } - listName = aFrame->GetAdditionalChildListName(listIndex++); - } while (listName); - } - - return NS_OK; -} - -nsresult -nsHTMLContainerFrame::ReparentFrameView(nsPresContext* aPresContext, - nsIFrame* aChildFrame, - nsIFrame* aOldParentFrame, - nsIFrame* aNewParentFrame) -{ - NS_PRECONDITION(aChildFrame, "null child frame pointer"); - NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer"); - NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer"); - NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame"); - - // See if either the old parent frame or the new parent frame have a view - while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) { - // Walk up both the old parent frame and the new parent frame nodes - // stopping when we either find a common parent or views for one - // or both of the frames. - // - // This works well in the common case where we push/pull and the old parent - // frame and the new parent frame are part of the same flow. They will - // typically be the same distance (height wise) from the - aOldParentFrame = aOldParentFrame->GetParent(); - aNewParentFrame = aNewParentFrame->GetParent(); - - // We should never walk all the way to the root frame without finding - // a view - NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view"); - - // See if we reached a common ancestor - if (aOldParentFrame == aNewParentFrame) { - break; - } - } - - // See if we found a common parent frame - if (aOldParentFrame == aNewParentFrame) { - // We found a common parent and there are no views between the old parent - // and the common parent or the new parent frame and the common parent. - // Because neither the old parent frame nor the new parent frame have views, - // then any child views don't need reparenting - return NS_OK; - } - - // We found views for one or both of the ancestor frames before we - // found a common ancestor. - nsIView* oldParentView = aOldParentFrame->GetClosestView(); - nsIView* newParentView = aNewParentFrame->GetClosestView(); - - // See if the old parent frame and the new parent frame are in the - // same view sub-hierarchy. If they are then we don't have to do - // anything - if (oldParentView != newParentView) { - // They're not so we need to reparent any child views - return ReparentFrameViewTo(aChildFrame, oldParentView->GetViewManager(), newParentView, - oldParentView); - } - - return NS_OK; -} - -nsresult -nsHTMLContainerFrame::ReparentFrameViewList(nsPresContext* aPresContext, - const nsFrameList& aChildFrameList, - nsIFrame* aOldParentFrame, - nsIFrame* aNewParentFrame) -{ - NS_PRECONDITION(aChildFrameList.NotEmpty(), "empty child frame list"); - NS_PRECONDITION(aOldParentFrame, "null old parent frame pointer"); - NS_PRECONDITION(aNewParentFrame, "null new parent frame pointer"); - NS_PRECONDITION(aOldParentFrame != aNewParentFrame, "same old and new parent frame"); - - // See if either the old parent frame or the new parent frame have a view - while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) { - // Walk up both the old parent frame and the new parent frame nodes - // stopping when we either find a common parent or views for one - // or both of the frames. - // - // This works well in the common case where we push/pull and the old parent - // frame and the new parent frame are part of the same flow. They will - // typically be the same distance (height wise) from the - aOldParentFrame = aOldParentFrame->GetParent(); - aNewParentFrame = aNewParentFrame->GetParent(); - - // We should never walk all the way to the root frame without finding - // a view - NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view"); - - // See if we reached a common ancestor - if (aOldParentFrame == aNewParentFrame) { - break; - } - } - - - // See if we found a common parent frame - if (aOldParentFrame == aNewParentFrame) { - // We found a common parent and there are no views between the old parent - // and the common parent or the new parent frame and the common parent. - // Because neither the old parent frame nor the new parent frame have views, - // then any child views don't need reparenting - return NS_OK; - } - - // We found views for one or both of the ancestor frames before we - // found a common ancestor. - nsIView* oldParentView = aOldParentFrame->GetClosestView(); - nsIView* newParentView = aNewParentFrame->GetClosestView(); - - // See if the old parent frame and the new parent frame are in the - // same view sub-hierarchy. If they are then we don't have to do - // anything - if (oldParentView != newParentView) { - nsIViewManager* viewManager = oldParentView->GetViewManager(); - - // They're not so we need to reparent any child views - for (nsFrameList::Enumerator e(aChildFrameList); !e.AtEnd(); e.Next()) { - ReparentFrameViewTo(e.get(), viewManager, newParentView, oldParentView); - } - } - - return NS_OK; -} - -nsresult -nsHTMLContainerFrame::CreateViewForFrame(nsIFrame* aFrame, - PRBool aForce) -{ - if (aFrame->HasView()) { - return NS_OK; - } - - // If we don't yet have a view, see if we need a view - if (!aForce && !aFrame->NeedsView()) { - // don't need a view - return NS_OK; - } - - nsIView* parentView = aFrame->GetParent()->GetClosestView(); - NS_ASSERTION(parentView, "no parent with view"); - - nsIViewManager* viewManager = parentView->GetViewManager(); - NS_ASSERTION(viewManager, "null view manager"); - - // Create a view - nsIView* view = viewManager->CreateView(aFrame->GetRect(), parentView); - if (!view) - return NS_ERROR_OUT_OF_MEMORY; - - SyncFrameViewProperties(aFrame->PresContext(), aFrame, nsnull, view); - - nsIView* insertBefore = nsLayoutUtils::FindSiblingViewFor(parentView, aFrame); - // we insert this view 'above' the insertBefore view, unless insertBefore is null, - // in which case we want to call with aAbove == PR_FALSE to insert at the beginning - // in document order - viewManager->InsertChild(parentView, view, insertBefore, insertBefore != nsnull); - - // REVIEW: Don't create a widget for fixed-pos elements anymore. - // ComputeRepaintRegionForCopy will calculate the right area to repaint - // when we scroll. - // Reparent views on any child frames (or their descendants) to this - // view. We can just call ReparentFrameViewTo on this frame because - // we know this frame has no view, so it will crawl the children. Also, - // we know that any descendants with views must have 'parentView' as their - // parent view. - ReparentFrameViewTo(aFrame, viewManager, view, parentView); - - // Remember our view - aFrame->SetView(view); - - NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, - ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p view=%p", - aFrame)); - return NS_OK; -} - NS_IMPL_FRAMEARENA_HELPERS(nsHTMLContainerFrame) diff --git a/layout/generic/nsHTMLContainerFrame.h b/layout/generic/nsHTMLContainerFrame.h index a3b7f453f28..d8456527df3 100644 --- a/layout/generic/nsHTMLContainerFrame.h +++ b/layout/generic/nsHTMLContainerFrame.h @@ -71,23 +71,6 @@ class nsHTMLContainerFrame : public nsContainerFrame { public: NS_DECL_FRAMEARENA_HELPERS - /** - * Helper method to wrap views around frames. Used by containers - * under special circumstances (can be used by leaf frames as well) - */ - static nsresult CreateViewForFrame(nsIFrame* aFrame, - PRBool aForce); - - static nsresult ReparentFrameView(nsPresContext* aPresContext, - nsIFrame* aChildFrame, - nsIFrame* aOldParentFrame, - nsIFrame* aNewParentFrame); - - static nsresult ReparentFrameViewList(nsPresContext* aPresContext, - const nsFrameList& aChildFrameList, - nsIFrame* aOldParentFrame, - nsIFrame* aNewParentFrame); - /** * Helper method to create next-in-flows if necessary. If aFrame * already has a next-in-flow then this method does diff --git a/layout/generic/nsInlineFrame.cpp b/layout/generic/nsInlineFrame.cpp index 071805f74fa..5bc94805fbd 100644 --- a/layout/generic/nsInlineFrame.cpp +++ b/layout/generic/nsInlineFrame.cpp @@ -328,9 +328,9 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext, if (prevOverflowFrames) { // When pushing and pulling frames we need to check for whether any // views need to be reparented. - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, - *prevOverflowFrames, - prevInFlow, this); + nsContainerFrame::ReparentFrameViewList(aPresContext, + *prevOverflowFrames, + prevInFlow, this); // Check if we should do the lazilySetParentPointer optimization. // Only do it in simple cases where we're being reflowed for the @@ -436,9 +436,9 @@ nsInlineFrame::PullOverflowsFromPrevInFlow() nsAutoPtr prevOverflowFrames(prevInFlow->StealOverflowFrames()); if (prevOverflowFrames) { // Assume that our prev-in-flow has the same line container that we do. - nsHTMLContainerFrame::ReparentFrameViewList(PresContext(), - *prevOverflowFrames, - prevInFlow, this); + nsContainerFrame::ReparentFrameViewList(PresContext(), + *prevOverflowFrames, + prevInFlow, this); mFrames.InsertFrames(this, nsnull, *prevOverflowFrames); } } @@ -816,7 +816,7 @@ nsInlineFrame::PullOneFrame(nsPresContext* aPresContext, if (irs.mLineLayout) { irs.mLineLayout->SetDirtyNextLine(); } - nsHTMLContainerFrame::ReparentFrameView(aPresContext, frame, nextInFlow, this); + nsContainerFrame::ReparentFrameView(aPresContext, frame, nextInFlow, this); break; } nextInFlow = (nsInlineFrame*) nextInFlow->GetNextInFlow(); diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index b4f7c328228..c53ec6f1ac9 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -178,7 +178,7 @@ nsSubDocumentFrame::Init(nsIContent* aContent, // really need it or not, and the inner view will get it as the // parent. if (!HasView()) { - rv = nsHTMLContainerFrame::CreateViewForFrame(this, PR_TRUE); + rv = nsContainerFrame::CreateViewForFrame(this, PR_TRUE); NS_ENSURE_SUCCESS(rv, rv); } diff --git a/layout/xul/base/src/nsDeckFrame.cpp b/layout/xul/base/src/nsDeckFrame.cpp index 1342da84fe1..e23b41940c3 100644 --- a/layout/xul/base/src/nsDeckFrame.cpp +++ b/layout/xul/base/src/nsDeckFrame.cpp @@ -114,7 +114,7 @@ static void CreateViewsForFrames(const nsFrameList& aFrames) { for (nsFrameList::Enumerator f(aFrames); !f.AtEnd(); f.Next()) { - nsHTMLContainerFrame::CreateViewForFrame(f.get(), PR_TRUE); + nsContainerFrame::CreateViewForFrame(f.get(), PR_TRUE); } }