diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index 43ff46eb27b..f3c60299131 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -88,10 +88,9 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame*& aFrameSubTree); NS_IMETHOD ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, @@ -716,13 +715,12 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } -NS_IMETHODIMP StyleSetImpl::ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree) +NS_IMETHODIMP StyleSetImpl::ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aFrameSubTree) { - return mFrameConstructor->ConstructFrame(aPresContext, aContent, - aParentFrame, aFrameSubTree); + return mFrameConstructor->ConstructRootFrame(aPresContext, aDocElement, + aFrameSubTree); } NS_IMETHODIMP diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.cpp b/mozilla/content/html/content/src/nsHTMLAtoms.cpp index 60d75d84ef7..ed5dea36bd7 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.cpp +++ b/mozilla/content/html/content/src/nsHTMLAtoms.cpp @@ -175,6 +175,7 @@ nsIAtom* nsHTMLAtoms::p; nsIAtom* nsHTMLAtoms::pagex; nsIAtom* nsHTMLAtoms::pagey; nsIAtom* nsHTMLAtoms::param; +nsIAtom* nsHTMLAtoms::placeholderPseudo; nsIAtom* nsHTMLAtoms::pointSize; nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::profile; @@ -406,6 +407,7 @@ void nsHTMLAtoms::AddrefAtoms() pagex = NS_NewAtom("PAGEX"); pagey = NS_NewAtom("PAGEY"); param = NS_NewAtom("PARAM"); + placeholderPseudo = NS_NewAtom(":PLACEHOLDER-FRAME"); pointSize = NS_NewAtom("POINT-SIZE"); pre = NS_NewAtom("PRE"); profile = NS_NewAtom("PROFILE"); @@ -632,6 +634,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(pagex); NS_RELEASE(pagey); NS_RELEASE(param); + NS_RELEASE(placeholderPseudo); NS_RELEASE(pointSize); NS_RELEASE(pre); NS_RELEASE(profile); diff --git a/mozilla/content/html/content/src/nsHTMLAtoms.h b/mozilla/content/html/content/src/nsHTMLAtoms.h index eda5f44142f..69b497fde5a 100644 --- a/mozilla/content/html/content/src/nsHTMLAtoms.h +++ b/mozilla/content/html/content/src/nsHTMLAtoms.h @@ -207,6 +207,7 @@ public: static nsIAtom* pagex; static nsIAtom* pagey; static nsIAtom* param; + static nsIAtom* placeholderPseudo; static nsIAtom* pointSize; static nsIAtom* pre; static nsIAtom* profile; diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp index 401448b90cb..959f0239f36 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp @@ -44,6 +44,7 @@ #include "nsIWebShell.h" #include "nsHTMLContainerFrame.h" #include "nsINameSpaceManager.h" +#include "nsLayoutAtoms.h" static NS_DEFINE_IID(kIHTMLStyleSheetIID, NS_IHTML_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -207,6 +208,49 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- +// Structure used when constructing formatting object trees. Contains +// state information needed for absolutely positioned elements +struct nsAbsoluteItems { + nsIFrame* const containingBlock; // containing block for absolutely positioned elements + nsIFrame* childList; // list of absolutely positioned child frames + + nsAbsoluteItems(nsIFrame* aContainingBlock); + + // Adds a child frame to the list of absolutely positioned child frames + void AddAbsolutelyPositionedChild(nsIFrame* aChildFrame); +}; + +nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock) + : containingBlock(aContainingBlock) +{ + childList = nsnull; +} + +void +nsAbsoluteItems::AddAbsolutelyPositionedChild(nsIFrame* aChildFrame) +{ +#ifdef NS_DEBUG + nsIFrame* parent; + aChildFrame->GetGeometricParent(parent); + NS_PRECONDITION(parent == containingBlock, "bad geometric parent"); +#endif + + if (nsnull == childList) { + childList = aChildFrame; + } else { + // Get the last frane in the list + nsIFrame* lastChild = nsnull; + + for (nsIFrame* f = childList; nsnull != f; f->GetNextSibling(f)) { + lastChild = f; + } + + lastChild->SetNextSibling(aChildFrame); + } +} + +// ----------------------------------------------------------- + class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, public nsIStyleFrameConstruction { public: @@ -264,10 +308,9 @@ public: NS_IMETHOD UnsetAttributeFor(nsIAtom* aAttribute, nsIHTMLContent* aContent, nsIHTMLAttributes*& aAttributes); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aNewFrame); NS_IMETHODIMP ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, @@ -333,9 +376,11 @@ protected: PRInt32 aAttrCount, nsIHTMLAttributes*& aAttributes); - nsresult ConstructRootFrame(nsIPresContext* aPresContext, - nsIContent* aDocElement, - nsIFrame*& aNewFrame); + nsresult ConstructFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aFrameSubTree); nsresult ConstructDocElementFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, @@ -347,37 +392,49 @@ protected: nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAboluteItems, nsIFrame*& aNewFrame); nsresult ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); + nsresult CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame); + nsresult ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); - nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, - const nsStyleDisplay* aDisplay, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIStyleContext* aStyleContext, - nsIFrame*& aNewFrame); + nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, + const nsStyleDisplay* aDisplay, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aNewFrame); nsresult GetAdjustedParentFrame(nsIFrame* aCurrentParentFrame, PRUint8 aChildDisplayType, nsIFrame*& aNewParentFrame); - nsresult ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList); + nsresult ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList); nsresult CreateInputFrame(nsIContent* aContent, nsIFrame*& aFrame); @@ -386,6 +443,9 @@ protected: nsIFrame* GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresContext, nsIContent* aContent); + nsIFrame* GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame); + protected: PRUint32 mInHeap : 1; PRUint32 mRefCnt : 31; @@ -397,6 +457,7 @@ protected: HTMLAnchorRule* mActiveRule; nsHashtable mAttrTable; nsIHTMLAttributes* mRecycledAttrs; + nsIFrame* mInitialContainingBlock; }; @@ -443,7 +504,8 @@ HTMLStyleSheetImpl::HTMLStyleSheetImpl(void) mLinkRule(nsnull), mVisitedRule(nsnull), mActiveRule(nsnull), - mRecycledAttrs(nsnull) + mRecycledAttrs(nsnull), + mInitialContainingBlock(nsnull) { NS_INIT_REFCNT(); } @@ -931,11 +993,23 @@ NS_IMETHODIMP HTMLStyleSheetImpl::UnsetAttributeFor(nsIAtom* aAttribute, } +/** + * Request to process the child content elements and create frames. + * + * @param aContent the content object whose child elements to process + * @param aFrame the the associated with aContent. This will be the + * parent frame (both content and geometric) for the flowed + * child frames + * @param aState the state information associated with the current process + * @param aChildList an OUT parameter. This is the list of flowed child + * frames that should go in the principal child list + */ nsresult -HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList) +HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList) { // Initialize OUT parameter aChildList = nsnull; @@ -943,6 +1017,7 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, // Iterate the child content objects and construct a frame nsIFrame* lastChildFrame = nsnull; PRInt32 count; + aContent->ChildCount(count); for (PRInt32 i = 0; i < count; i++) { nsIContent* childContent; @@ -952,19 +1027,18 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, nsIFrame* childFrame; // Construct a child frame - ConstructFrame(aPresContext, childContent, aFrame, childFrame); + ConstructFrame(aPresContext, childContent, aFrame, aAbsoluteItems, childFrame); + NS_RELEASE(childContent); if (nsnull != childFrame) { - // Link the frame into the child list - if (nsnull == lastChildFrame) { + // Append the child frame to the list of child frames + if (nsnull == aChildList) { aChildList = childFrame; } else { lastChildFrame->SetNextSibling(childFrame); } lastChildFrame = childFrame; } - - NS_RELEASE(childContent); } } @@ -1024,6 +1098,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsIFrame* childList; @@ -1037,7 +1112,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Init the table outer frame and see if we need to create a view, e.g. // the frame is absolutely positioned - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); @@ -1052,7 +1127,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsHTMLAtoms::tablePseudo, aStyleContext); */ - innerFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + innerFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, aStyleContext); // this should be "innerTableStyleContext" but I haven't tested that thoroughly yet // Iterate the child content @@ -1080,10 +1155,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Have we already created a caption? If so, ignore this caption if (nsnull == captionFrame) { NS_NewAreaFrame(captionFrame, NS_BODY_NO_AUTO_MARGINS); - captionFrame->Init(*aPresContext, childContent, aNewFrame, childStyleContext); + captionFrame->Init(*aPresContext, childContent, aNewFrame, + aNewFrame, childStyleContext); // Process the caption's child content and set the initial child list nsIFrame* captionChildList; - ProcessChildren(aPresContext, captionFrame, childContent, captionChildList); + ProcessChildren(aPresContext, childContent, captionFrame, + aAbsoluteItems, captionChildList); captionFrame->SetInitialChildList(*aPresContext, nsnull, captionChildList); // Prepend the caption frame to the outer frame's child list @@ -1095,7 +1172,8 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: NS_NewTableRowGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, + childStyleContext); break; case NS_STYLE_DISPLAY_TABLE_ROW: @@ -1112,12 +1190,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableRowGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = rowGroupStyleContext; // the row group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, + innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context rowStyleContext = aPresContext->ResolveStyleContextFor(childContent, rowGroupStyleContext); nsIFrame *rowFrame; NS_NewTableRowFrame(rowFrame); - rowFrame->Init(*aPresContext, childContent, frame, rowStyleContext); + rowFrame->Init(*aPresContext, childContent, frame, frame, rowStyleContext); rowFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = rowFrame; break; @@ -1163,12 +1242,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableColGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = colGroupStyleContext; // the col group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context colStyleContext = aPresContext->ResolveStyleContextFor(childContent, colGroupStyleContext); nsIFrame *colFrame; NS_NewTableColFrame(colFrame); - colFrame->Init(*aPresContext, childContent, frame, colStyleContext); + colFrame->Init(*aPresContext, childContent, frame, frame, colStyleContext); colFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = colFrame; break; @@ -1176,7 +1255,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: NS_NewTableColGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); break; default: @@ -1190,14 +1269,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, if (nsnull != frame) { // Process the children, and set the frame's initial child list nsIFrame* childChildList; - if (nsnull==grandChildList) - { - ProcessChildren(aPresContext, frame, childContent, childChildList); + if (nsnull==grandChildList) { + ProcessChildren(aPresContext, childContent, frame, aAbsoluteItems, + childChildList); grandChildList = childChildList; - } - else - { - ProcessChildren(aPresContext, grandChildList, childContent, childChildList); + } else { + ProcessChildren(aPresContext, childContent, grandChildList, + aAbsoluteItems, childChildList); grandChildList->SetInitialChildList(*aPresContext, nsnull, childChildList); } frame->SetInitialChildList(*aPresContext, nsnull, grandChildList); @@ -1229,6 +1307,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsresult rv; @@ -1237,7 +1316,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, rv = NS_NewTableCellFrame(aNewFrame); if (NS_SUCCEEDED(rv)) { // Initialize the table cell frame - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); // Create an area frame that will format the cell's content nsIFrame* cellBodyFrame; @@ -1252,12 +1331,13 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, // Resolve pseudo style and initialize the body cell frame nsIStyleContext* bodyPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::cellContentPseudo, aStyleContext); - cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, bodyPseudoStyle); + cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, bodyPseudoStyle); NS_RELEASE(bodyPseudoStyle); // Process children and set the body cell frame's initial child list nsIFrame* childList; - rv = ProcessChildren(aPresContext, cellBodyFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, cellBodyFrame, aAbsoluteItems, + childList); if (NS_SUCCEEDED(rv)) { cellBodyFrame->SetInitialChildList(*aPresContext, nsnull, childList); } @@ -1286,11 +1366,13 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // the root frame. // XXX We only need the scroll frame if it's print preview... NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootStyleContext); + scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootFrame, + aRootStyleContext); // The page sequence frame needs a view, because it's a scrolled frame NS_NewSimplePageSequenceFrame(pageSequenceFrame); - pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, aRootStyleContext); + pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, scrollFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageSequenceFrame, aRootStyleContext, PR_TRUE); @@ -1301,7 +1383,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // Initialize the page and force it to have a view. This makes printing of // the pages easier and faster. // XXX Use a PAGE style context... - pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, aRootStyleContext); + pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, pageSequenceFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageFrame, aRootStyleContext, PR_TRUE); @@ -1309,20 +1392,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, nsIStyleContext* styleContext; styleContext = aPresContext->ResolveStyleContextFor(aDocElement, aRootStyleContext); - // Create an area frame for the document element. This serves as the - // "initial containing block" + // Create an area frame for the document element nsIFrame* areaFrame; NS_NewAreaFrame(areaFrame, 0); - areaFrame->Init(*aPresContext, aDocElement, pageFrame, styleContext); + areaFrame->Init(*aPresContext, aDocElement, pageFrame, pageFrame, styleContext); NS_RELEASE(styleContext); + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; + // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } pageFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); pageSequenceFrame->SetInitialChildList(*aPresContext, nsnull, pageFrame); scrollFrame->SetInitialChildList(*aPresContext, nsnull, pageSequenceFrame); @@ -1363,7 +1454,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, if (NS_STYLE_OVERFLOW_HIDDEN != scrolling) { NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, styleContext); + scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, aRootFrame, + styleContext); // The scrolled frame gets a pseudo element style context nsIStyleContext* scrolledPseudoStyle = @@ -1381,18 +1473,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // XXX Until we clean up how painting damage is handled, we need to use the // flag that says that this is the body... NS_NewAreaFrame(areaFrame, NS_BODY_THE_BODY); - areaFrame->Init(*aPresContext, aDocElement, scrollFrame ? scrollFrame : - aRootFrame, styleContext); + nsIFrame* parentFrame = scrollFrame ? scrollFrame : aRootFrame; + areaFrame->Init(*aPresContext, aDocElement, parentFrame, parentFrame, + styleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, areaFrame, styleContext, PR_FALSE); NS_RELEASE(styleContext); + + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } if (nsnull != scrollFrame) { scrollFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); } @@ -1403,7 +1505,7 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, return NS_OK; } -nsresult +NS_IMETHODIMP HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, nsIFrame*& aNewFrame) @@ -1431,7 +1533,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsHTMLAtoms::rootPseudo, nsnull); // Initialize the root frame. It has a NULL content object - rootFrame->Init(*aPresContext, nsnull, nsnull, rootPseudoStyle); + rootFrame->Init(*aPresContext, nsnull, nsnull, nsnull, rootPseudoStyle); // Bind the root frame to the root view nsIPresShell* presShell = aPresContext->GetShell(); @@ -1443,7 +1545,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, rootFrame->SetView(rootView); NS_RELEASE(viewManager); - // Create frames for the document element and its child content + // Create frames for the document element and its child elements nsIFrame* docElementFrame; ConstructDocElementFrame(aPresContext, aDocElement, rootFrame, rootPseudoStyle, docElementFrame); @@ -1456,16 +1558,51 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, return NS_OK; } +nsresult +HTMLStyleSheetImpl::CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame) +{ + nsIFrame* placeholderFrame; + nsresult rv; + + rv = NS_NewEmptyFrame(&placeholderFrame); + + if (NS_SUCCEEDED(rv)) { + // The placeholder frame gets a pseudo style context + nsIStyleContext* placeholderPseudoStyle = + aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::placeholderPseudo, aStyleContext); + placeholderFrame->Init(*aPresContext, aContent, aParentFrame, + aParentFrame, placeholderPseudoStyle); + NS_RELEASE(placeholderPseudoStyle); + + // Add mapping from absolutely positioned frame to its placeholder frame + nsIPresShell* presShell = aPresContext->GetShell(); + presShell->SetPlaceholderFrameFor(aFrame, placeholderFrame); + NS_RELEASE(presShell); + + aPlaceholderFrame = placeholderFrame; + } + + return rv; +} + nsresult HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { PRBool processChildren = PR_FALSE; // whether we should process child content nsresult rv = NS_OK; + PRBool isAbsolutelyPositioned = PR_FALSE; // Initialize OUT parameter aNewFrame = nsnull; @@ -1475,8 +1612,18 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else { nsIHTMLContent *htmlContent; + + // Ignore the tag if it's not HTML content rv = aContent->QueryInterface(kIHTMLContentIID, (void **)&htmlContent); if (NS_SUCCEEDED(rv)) { + // See if the element is absolutely positioned + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { + isAbsolutelyPositioned = PR_TRUE; + } + + // Create a frame based on the tag if (nsHTMLAtoms::img == aTag) { rv = NS_NewImageFrame(aNewFrame); } @@ -1511,13 +1658,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::legend == aTag) { rv = NS_NewLegendFrame(aNewFrame); processChildren = PR_TRUE; + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::object == aTag) { rv = NS_NewObjectFrame(aNewFrame); //rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); nsIFrame *blockFrame; NS_NewBlockFrame(blockFrame, 0); - blockFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + blockFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, + aStyleContext); aNewFrame = blockFrame; processChildren = PR_TRUE; } @@ -1526,12 +1675,14 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::iframe == aTag) { rv = NS_NewHTMLFrameOuterFrame(aNewFrame); } else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::button == aTag) { rv = NS_NewHTMLButtonControlFrame(aNewFrame); @@ -1543,16 +1694,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } NS_RELEASE(htmlContent); } - else { - aNewFrame = nsnull; - rv = NS_OK; - } } // If we succeeded in creating a frame then initialize it, process its // children (if requested), and set the initial child list if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + aNewFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); // See if we need to create a view, e.g. the frame is absolutely positioned nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, @@ -1561,11 +1711,27 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, // Process the child content if requested nsIFrame* childList = nsnull; if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); } // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; + } } return rv; @@ -1577,143 +1743,264 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresConte nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { - PRBool processChildren = PR_FALSE; // whether we should process child content - nsIFrame* wrapperFrame = nsnull; - nsresult rv = NS_OK; + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + PRBool isAbsolutelyPositioned = PR_FALSE; + PRBool isBlock = aDisplay->IsBlockLevel(); + nsresult rv = NS_OK; // Initialize OUT parameter aNewFrame = nsnull; - // If the element is floated and it's a block or inline, then we need to - // wrap it in a area frame - if (((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || - (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay)) && - (NS_STYLE_FLOAT_NONE != aDisplay->mFloats)) { - - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - aStyleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, aStyleContext); - aParentFrame = wrapperFrame; - aStyleContext = wrappedPseudoStyle; + // The frame is also a block if it's an inline frame that's floated or + // absolutely positioned + if ((NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) && + ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) || + (NS_STYLE_POSITION_ABSOLUTE == position->mPosition))) { + isBlock = PR_TRUE; } - switch (aDisplay->mDisplay) { - case NS_STYLE_DISPLAY_BLOCK: - case NS_STYLE_DISPLAY_LIST_ITEM: - case NS_STYLE_DISPLAY_RUN_IN: - case NS_STYLE_DISPLAY_COMPACT: - rv = NS_NewBlockFrame(aNewFrame, 0); - processChildren = PR_TRUE; - break; + // If the frame is a block-level frame and is scrollable then wrap it + // in a scroll frame. + // XXX Applies to replaced elements, too, but how to tell if the element + // is replaced? + // XXX Ignore tables for the time being + if ((isBlock && (aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE)) && + IsScrollable(aPresContext, aDisplay)) { - case NS_STYLE_DISPLAY_INLINE: - rv = NS_NewInlineFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if it's absolutely positioned + isAbsolutelyPositioned = NS_STYLE_POSITION_ABSOLUTE == position->mPosition; - case NS_STYLE_DISPLAY_TABLE: - rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; + // Create a scroll frame + nsIFrame* scrollFrame; + NS_NewScrollFrame(scrollFrame); - case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: - case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: - case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: - // XXX We should check for being inside of a table. If there's a missing - // table then create an anonynmous table frame - // XXX: see ConstructTableFrame for a prototype of how this should be done, - // and propagate similar logic to other table elements - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableRowGroupFrame(aNewFrame); - processChildren = PR_TRUE; + // Initialize it + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + scrollFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); + + // The scroll frame gets the original style context, and the scrolled + // frame gets a SCROLLED-CONTENT pseudo element style context that + // inherits the background properties + nsIStyleContext* scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::scrolledContentPseudo, aStyleContext); + + // Create an area container for the frame + nsIFrame* scrolledFrame; + NS_NewAreaFrame(scrolledFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame and force it to have a view + scrolledFrame->Init(*aPresContext, aContent, scrollFrame, scrollFrame, + scrolledPseudoStyle); + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, scrolledFrame, + scrolledPseudoStyle, PR_TRUE); + NS_RELEASE(scrolledPseudoStyle); + + // Process children + if (isAbsolutelyPositioned) { + nsAbsoluteItems absoluteItems(scrolledFrame); + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, absoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + scrolledFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); } + + } else { + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, aAbsoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); } - break; + scrollFrame->SetInitialChildList(*aPresContext, nsnull, scrolledFrame); + aNewFrame = scrollFrame; - case NS_STYLE_DISPLAY_TABLE_COLUMN: - // XXX We should check for being inside of a table column group... - rv = NS_NewTableColFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if the frame is absolutely positioned + } else if ((NS_STYLE_POSITION_ABSOLUTE == position->mPosition) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { - case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: - // XXX We should check for being inside of a table... - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableColGroupFrame(aNewFrame); - processChildren = PR_TRUE; - } - } - break; + isAbsolutelyPositioned = PR_TRUE; - case NS_STYLE_DISPLAY_TABLE_ROW: - // XXX We should check for being inside of a table row group... - rv = NS_NewTableRowFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + aNewFrame->Init(*aPresContext, aContent, aAbsoluteItems.containingBlock, + aParentFrame, aStyleContext); - case NS_STYLE_DISPLAY_TABLE_CELL: - // XXX We should check for being inside of a table row frame... - rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; - - case NS_STYLE_DISPLAY_TABLE_CAPTION: - // XXX We should check for being inside of a table row frame... - rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); - processChildren = PR_TRUE; - break; - - default: - // Don't create any frame for content that's not displayed... - break; - } - - // If we succeeded in creating a frame then initialize the frame, - // process children (if requested), and initialize the frame - if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - - // See if we need to create a view, e.g. the frame is absolutely positioned + // Create a view nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); - // Process the child content if requested - nsIFrame* childList = nsnull; - if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); - } + // Process the child content + nsAbsoluteItems absoluteItems(aNewFrame); + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, absoluteItems, childList); // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + aNewFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } + + // See if the frame is floated, and it's a block or inline frame + } else if ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { + + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, childList); + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + } else { + PRBool processChildren = PR_FALSE; // whether we should process child content + + // Use the 'display' property to chose a frame type + switch (aDisplay->mDisplay) { + case NS_STYLE_DISPLAY_BLOCK: + case NS_STYLE_DISPLAY_LIST_ITEM: + case NS_STYLE_DISPLAY_RUN_IN: + case NS_STYLE_DISPLAY_COMPACT: + rv = NS_NewBlockFrame(aNewFrame, 0); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_INLINE: + rv = NS_NewInlineFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE: + rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, aStyleContext, + aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: + case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: + case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: + // XXX We should check for being inside of a table. If there's a missing + // table then create an anonynmous table frame + // XXX: see ConstructTableFrame for a prototype of how this should be done, + // and propagate similar logic to other table elements + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableRowGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN: + // XXX We should check for being inside of a table column group... + rv = NS_NewTableColFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: + // XXX We should check for being inside of a table... + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableColGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_ROW: + // XXX We should check for being inside of a table row group... + rv = NS_NewTableRowFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_CELL: + // XXX We should check for being inside of a table row frame... + rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, + aStyleContext, aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_CAPTION: + // XXX We should check for being inside of a table row frame... + rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); + processChildren = PR_TRUE; + break; + + default: + // Don't create any frame for content that's not displayed... + break; + } + + // If we succeeded in creating a frame then initialize the frame and + // process children if requested + if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view, e.g. the frame is absolutely positioned + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content if requested + nsIFrame* childList = nsnull; + if (processChildren) { + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); + } + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + } } - // If there's a wrapper frame then set its initial child list, and return the - // wrapper frame as the new frame - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aNewFrame); - aNewFrame = wrapperFrame; + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; } return rv; @@ -1787,177 +2074,69 @@ HTMLStyleSheetImpl::IsScrollable(nsIPresContext* aPresContext, return PR_FALSE; } -NS_IMETHODIMP +nsresult HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aFrameSubTree) { + NS_PRECONDITION(nsnull != aParentFrame, "no parent frame"); + nsresult rv; // Initialize OUT paremeter aFrameSubTree = nsnull; - // See if we're constructing a frame for the document element - if (nsnull == aParentFrame) { - // The root frame has only a single child frame, which is the frame for - // the document element - rv = ConstructRootFrame(aPresContext, aContent, aFrameSubTree); + // Get the element's tag + nsIAtom* tag; + aContent->GetTag(tag); + // Resolve the style context based on the content object and the parent + // style context + nsIStyleContext* styleContext; + nsIStyleContext* parentStyleContext; + + aParentFrame->GetStyleContext(parentStyleContext); + if (nsnull == tag) { + // Use a special pseudo element style context for text + nsIContent* parentContent = nsnull; + if (nsnull != aParentFrame) { + aParentFrame->GetContent(parentContent); + } + styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, + nsHTMLAtoms::textPseudo, + parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + NS_IF_RELEASE(parentContent); } else { - // Get the element's tag - nsIAtom* tag; - aContent->GetTag(tag); - - // Resolve the style context based on the content object and the parent - // style context - nsIStyleContext* styleContext; - nsIStyleContext* parentStyleContext; + styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + NS_IF_RELEASE(parentStyleContext); - aParentFrame->GetStyleContext(parentStyleContext); - if (nsnull == tag) { - // Use a special pseudo element style context for text - nsIContent* parentContent = nsnull; - if (nsnull != aParentFrame) { - aParentFrame->GetContent(parentContent); + if (NS_SUCCEEDED(rv)) { + // Pre-check for display "none" - if we find that, don't create + // any frame at all + const nsStyleDisplay* display = (const nsStyleDisplay*) + styleContext->GetStyleData(eStyleStruct_Display); + + if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { + // Handle specific frame types + rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, tag, + styleContext, aAbsoluteItems, aFrameSubTree); + + if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { + // When there is no explicit frame to create, assume it's a + // container and let display style dictate the rest + rv = ConstructFrameByDisplayType(aPresContext, display, aContent, aParentFrame, + styleContext, aAbsoluteItems, aFrameSubTree); } - styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, - nsHTMLAtoms::textPseudo, - parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; - NS_IF_RELEASE(parentContent); - } else { - styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } - NS_IF_RELEASE(parentStyleContext); - - if (NS_SUCCEEDED(rv)) { - // Pre-check for display "none" - if we find that, don't create - // any frame at all - const nsStyleDisplay* display = (const nsStyleDisplay*) - styleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // If the frame is a block-level frame and is scrollable then wrap it - // in a scroll frame. - // XXX Applies to replaced elements, too, but how to tell if the element - // is replaced? - nsIFrame* scrollFrame = nsnull; - nsIFrame* wrapperFrame = nsnull; - - if ((display->mDisplay!=NS_STYLE_DISPLAY_TABLE) && display->IsBlockLevel() && - IsScrollable(aPresContext, display)) { - - // Create a scroll frame which will wrap the frame that needs to - // be scrolled - if (NS_SUCCEEDED(NS_NewScrollFrame(scrollFrame))) { - nsIStyleContext* scrolledPseudoStyle; - - // The scroll frame gets the original style context, and the scrolled - // frame gets a SCROLLED-CONTENT pseudo element style context that - // inherits the background properties - scrollFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::scrolledContentPseudo, - styleContext); - NS_RELEASE(styleContext); - - // If the content element can contain children then wrap it in a - // area frame - PRBool isContainer; - aContent->CanContainChildren(isContainer); - if (isContainer) { - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - - // Initialize the frame and force it to have a view - wrapperFrame->Init(*aPresContext, aContent, scrollFrame, scrolledPseudoStyle); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - scrolledPseudoStyle, PR_TRUE); - - // The wrapped frame also gets a pseudo style context, but it doesn't - // inherit any background properties. It does inherit the 'display' - // property (it's very important that it does) - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::wrappedFramePseudo, - scrolledPseudoStyle); - NS_RELEASE(scrolledPseudoStyle); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - - } else { - aParentFrame = scrollFrame; - styleContext = scrolledPseudoStyle; - } - } - } - - // See if the element is absolutely positioned - const nsStylePosition* position = (const nsStylePosition*) - styleContext->GetStyleData(eStyleStruct_Position); - - if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { - // If it can contain children then wrap it in an area frame. - // XxX Don't wrap tables, because that causes all sort of problems. - // We need to figure out how to wrap tables... - PRBool isContainer; - aContent->CanContainChildren(isContainer); - - if ((NS_STYLE_DISPLAY_TABLE != display->mDisplay) && isContainer) { - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - styleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, styleContext); - NS_RELEASE(styleContext); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - } - } - - // Handle specific frame types - rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, - tag, styleContext, aFrameSubTree); - - if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { - // When there is no explicit frame to create, assume it's a - // container and let display style dictate the rest - rv = ConstructFrameByDisplayType(aPresContext, display, - aContent, aParentFrame, - styleContext, aFrameSubTree); - } - - // If there's a scroll frame or a wrapper frame then set their initial - // child lists, and return that frame as the frame sub-tree. - // Because SetInitialChildList() is called bottom-up we need to wait - // until after we've created the frame sub-tree - if (nsnull != scrollFrame) { - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - scrollFrame->SetInitialChildList(*aPresContext, nsnull, wrapperFrame); - } else { - scrollFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - } - aFrameSubTree = scrollFrame; - - } else if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - aFrameSubTree = wrapperFrame; - } - } - NS_RELEASE(styleContext); - } - - NS_IF_RELEASE(tag); + NS_RELEASE(styleContext); } + NS_IF_RELEASE(tag); return rv; } @@ -2044,6 +2223,47 @@ HTMLStyleSheetImpl::GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresC return frame; } +nsIFrame* +HTMLStyleSheetImpl::GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + // For the time being just return the initial containing block + NS_PRECONDITION(nsnull != mInitialContainingBlock, "no initial containing block"); + return mInitialContainingBlock; + + // XXX TROY +#if 0 + // Look for a containing frame that is absolutely positioned. If we don't + // find one then use the initial containg block which is the BODY + nsIFrame* lastFrame = (nsIFrame*)this; + nsIFrame* result; + + GetContentParent(result); + while (nsnull != result) { + const nsStylePosition* position; + + // Get the style data + result->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if (position->mPosition == NS_STYLE_POSITION_ABSOLUTE) { + // XXX This needs cleaning up... + // Make sure the frame supports the nsIAbsoluteItems interface. If not, + // walk the geometric parent hierarchy and find the nearest one that does... + nsIAbsoluteItems* interface; + while ((nsnull != result) && + NS_FAILED(result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface))) { + result->GetGeometricParent(result); + } + break; + } + + // Get the next contentual parent + lastFrame = result; + result->GetContentParent(result); + } +#endif +} + NS_IMETHODIMP HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -2067,10 +2287,15 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, } } + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + // Create some new frames - PRInt32 count; - nsIFrame* lastChildFrame = nsnull; - nsIFrame* firstAppendedFrame = nsnull; + PRInt32 count; + nsIFrame* lastChildFrame = nsnull; + nsIFrame* firstAppendedFrame = nsnull; + nsAbsoluteItems absoluteItems(absoluteContainingBlock); aContainer->ChildCount(count); @@ -2079,7 +2304,7 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIFrame* frame; aContainer->ChildAt(i, child); - ConstructFrame(aPresContext, child, parentFrame, frame); + ConstructFrame(aPresContext, child, parentFrame, absoluteItems, frame); if (nsnull != frame) { // Link the frame into the child frame list @@ -2116,6 +2341,21 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + result = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(result)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } @@ -2230,8 +2470,13 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Construct a new frame nsresult rv = NS_OK; if (nsnull != parentFrame) { - nsIFrame* newFrame; - rv = ConstructFrame(aPresContext, aChild, parentFrame, newFrame); + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + + nsAbsoluteItems absoluteItems(absoluteContainingBlock); + nsIFrame* newFrame; + rv = ConstructFrame(aPresContext, aChild, parentFrame, absoluteItems, newFrame); if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { nsIReflowCommand* reflowCmd = nsnull; @@ -2245,11 +2490,25 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Generate a FrameInserted reflow command rv = NS_NewHTMLReflowCommand(&reflowCmd, parentFrame, newFrame, prevSibling); } - if (NS_SUCCEEDED(rv)) { shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + rv = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } diff --git a/mozilla/content/shared/public/nsHTMLAtoms.h b/mozilla/content/shared/public/nsHTMLAtoms.h index eda5f44142f..69b497fde5a 100644 --- a/mozilla/content/shared/public/nsHTMLAtoms.h +++ b/mozilla/content/shared/public/nsHTMLAtoms.h @@ -207,6 +207,7 @@ public: static nsIAtom* pagex; static nsIAtom* pagey; static nsIAtom* param; + static nsIAtom* placeholderPseudo; static nsIAtom* pointSize; static nsIAtom* pre; static nsIAtom* profile; diff --git a/mozilla/content/shared/src/nsHTMLAtoms.cpp b/mozilla/content/shared/src/nsHTMLAtoms.cpp index 60d75d84ef7..ed5dea36bd7 100644 --- a/mozilla/content/shared/src/nsHTMLAtoms.cpp +++ b/mozilla/content/shared/src/nsHTMLAtoms.cpp @@ -175,6 +175,7 @@ nsIAtom* nsHTMLAtoms::p; nsIAtom* nsHTMLAtoms::pagex; nsIAtom* nsHTMLAtoms::pagey; nsIAtom* nsHTMLAtoms::param; +nsIAtom* nsHTMLAtoms::placeholderPseudo; nsIAtom* nsHTMLAtoms::pointSize; nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::profile; @@ -406,6 +407,7 @@ void nsHTMLAtoms::AddrefAtoms() pagex = NS_NewAtom("PAGEX"); pagey = NS_NewAtom("PAGEY"); param = NS_NewAtom("PARAM"); + placeholderPseudo = NS_NewAtom(":PLACEHOLDER-FRAME"); pointSize = NS_NewAtom("POINT-SIZE"); pre = NS_NewAtom("PRE"); profile = NS_NewAtom("PROFILE"); @@ -632,6 +634,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(pagex); NS_RELEASE(pagey); NS_RELEASE(param); + NS_RELEASE(placeholderPseudo); NS_RELEASE(pointSize); NS_RELEASE(pre); NS_RELEASE(profile); diff --git a/mozilla/layout/base/nsIPresShell.h b/mozilla/layout/base/nsIPresShell.h index 007b30c15df..7460c44dcbe 100644 --- a/mozilla/layout/base/nsIPresShell.h +++ b/mozilla/layout/base/nsIPresShell.h @@ -109,6 +109,18 @@ public: virtual nsIFrame* FindFrameWithContent(nsIContent* aContent) = 0; + /** + * Get/Set the placeholder frame associated with the specified frame. + * + * Out of flow frames (e.g., absolutely positioned frames and floated frames) + * can have placeholder frames that are inserted into the flow and indicate + * where the frame would be if it were part of the flow + */ + NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const = 0; + NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame) = 0; + virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand) = 0; virtual void ProcessReflowCommands() = 0; diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index ae086de9a10..f8fca69d63a 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -51,7 +51,6 @@ static PRBool gsNoisyRefs = PR_FALSE; #undef NOISY -#if 0 static PLHashNumber HashKey(nsIFrame* key) { @@ -87,7 +86,6 @@ FrameHashTable::FrameHashTable() FrameHashTable::~FrameHashTable() { - // XXX if debugging then we should assert that the table is empty PL_HashTableDestroy(mTable); } @@ -143,7 +141,6 @@ FrameHashTable::Remove(nsIFrame* aKey) } return oldValue; } -#endif //---------------------------------------------------------------------- @@ -244,6 +241,10 @@ public: virtual nsIFrame* GetRootFrame(); NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame); virtual nsIFrame* FindFrameWithContent(nsIContent* aContent); + NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const; + NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame); virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand); virtual void ProcessReflowCommands(); virtual void ClearFrameRefs(nsIFrame*); @@ -288,6 +289,7 @@ protected: nsIFrame* mFocusEventFrame; //keeps track of which frame has focus. nsIFrame* mAnchorEventFrame; //keeps track of which frame has focus. nsISelection *mSelection; + FrameHashTable* mPlaceholderMap; }; #ifdef NS_DEBUG @@ -429,6 +431,7 @@ PresShell::~PresShell() } NS_IF_RELEASE(mSelection); mRefCnt = 0; + delete mPlaceholderMap; } /** @@ -598,7 +601,7 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) if (nsnull != root) { // Have style sheet processor construct a frame for the // root content object - mStyleSet->ConstructFrame(mPresContext, root, nsnull, mRootFrame); + mStyleSet->ConstructRootFrame(mPresContext, root, mRootFrame); NS_RELEASE(root); } } @@ -1189,6 +1192,38 @@ PresShell::FindFrameWithContent(nsIContent* aContent) return ::FindFrameWithContent(mRootFrame, aContent); } +NS_IMETHODIMP +PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const +{ + NS_PRECONDITION(nsnull != aFrame, "no frame"); + + if (nsnull == mPlaceholderMap) { + aPlaceholderFrame = nsnull; + } else { + aPlaceholderFrame = (nsIFrame*)mPlaceholderMap->Get(aFrame); + } + + return NS_OK; +} + +NS_IMETHODIMP +PresShell::SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame) +{ + NS_PRECONDITION(nsnull != aFrame, "no frame"); + + if (nsnull == mPlaceholderMap) { + mPlaceholderMap = new FrameHashTable; + if (nsnull == mPlaceholderMap) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + mPlaceholderMap->Put(aFrame, (void*)aPlaceholderFrame); + return NS_OK; +} + //nsIViewObserver NS_IMETHODIMP diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index 9e47eb9b908..027bbd3090e 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -145,12 +145,14 @@ public: * now. * * @param aContent the content object associated with the frame - * @param aParent the parent frame + * @param aGeometricParent the geometric parent frame + * @param aContentParent the content parent frame * @param aContext the style context associated with the frame */ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) = 0; /** diff --git a/mozilla/layout/base/public/nsIPresShell.h b/mozilla/layout/base/public/nsIPresShell.h index 007b30c15df..7460c44dcbe 100644 --- a/mozilla/layout/base/public/nsIPresShell.h +++ b/mozilla/layout/base/public/nsIPresShell.h @@ -109,6 +109,18 @@ public: virtual nsIFrame* FindFrameWithContent(nsIContent* aContent) = 0; + /** + * Get/Set the placeholder frame associated with the specified frame. + * + * Out of flow frames (e.g., absolutely positioned frames and floated frames) + * can have placeholder frames that are inserted into the flow and indicate + * where the frame would be if it were part of the flow + */ + NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const = 0; + NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame) = 0; + virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand) = 0; virtual void ProcessReflowCommands() = 0; diff --git a/mozilla/layout/base/public/nsIReflowCommand.h b/mozilla/layout/base/public/nsIReflowCommand.h index 0e603f913fd..730b5e163fc 100644 --- a/mozilla/layout/base/public/nsIReflowCommand.h +++ b/mozilla/layout/base/public/nsIReflowCommand.h @@ -196,6 +196,13 @@ public: */ NS_IMETHOD GetChildListName(nsIAtom*& aListName) const = 0; + /** + * Sets the name of the child list to which the child frame belongs. + * Only used for reflow command types FrameAppended, FrameInserted, and + * FrameRemoved + */ + NS_IMETHOD SetChildListName(nsIAtom* aListName) = 0; + /** * Get the previous sibling frame associated with the reflow command. * This is used for FrameInserted reflow commands. diff --git a/mozilla/layout/base/public/nsIStyleFrameConstruction.h b/mozilla/layout/base/public/nsIStyleFrameConstruction.h index c4255567bf1..1bc0574979f 100644 --- a/mozilla/layout/base/public/nsIStyleFrameConstruction.h +++ b/mozilla/layout/base/public/nsIStyleFrameConstruction.h @@ -29,15 +29,13 @@ class nsIFrame; class nsIStyleFrameConstruction : public nsISupports { public: /** - * Handles association of elements in the content model to frames. Finds the - * applicable construction rule, applies the action, and produces a sub-tree - * of frame objects. Can return nsnull. + * Create frames for the root content element and its child content. */ - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree) = 0; + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aFrameSubTree) = 0; + // XXX TROY Is this what we want? // Causes reconstruction of a frame hierarchy rooted by the // frame aFrameSubTree. This is often called when radical style // change precludes incremental reflow. diff --git a/mozilla/layout/base/public/nsIStyleSet.h b/mozilla/layout/base/public/nsIStyleSet.h index a728f3e1dbb..7dcdbad4e99 100644 --- a/mozilla/layout/base/public/nsIStyleSet.h +++ b/mozilla/layout/base/public/nsIStyleSet.h @@ -90,13 +90,10 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE) = 0; - // Handles association of elements in the content model to frames. Finds the - // applicable construction rule, applies the action, and produces a sub-tree - // of frame objects. Can return nsnull. - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree) = 0; + // Create frames for the root content element and its child content + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aFrameSubTree) = 0; // Causes reconstruction of a frame hierarchy rooted by the // frame aFrameSubTree. This is often called when radical style diff --git a/mozilla/layout/base/src/nsStyleSet.cpp b/mozilla/layout/base/src/nsStyleSet.cpp index 43ff46eb27b..f3c60299131 100644 --- a/mozilla/layout/base/src/nsStyleSet.cpp +++ b/mozilla/layout/base/src/nsStyleSet.cpp @@ -88,10 +88,9 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame*& aFrameSubTree); NS_IMETHOD ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, @@ -716,13 +715,12 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } -NS_IMETHODIMP StyleSetImpl::ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree) +NS_IMETHODIMP StyleSetImpl::ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aFrameSubTree) { - return mFrameConstructor->ConstructFrame(aPresContext, aContent, - aParentFrame, aFrameSubTree); + return mFrameConstructor->ConstructRootFrame(aPresContext, aDocElement, + aFrameSubTree); } NS_IMETHODIMP diff --git a/mozilla/layout/forms/nsFieldSetFrame.cpp b/mozilla/layout/forms/nsFieldSetFrame.cpp index 7d1569b5000..46d9334d9bc 100644 --- a/mozilla/layout/forms/nsFieldSetFrame.cpp +++ b/mozilla/layout/forms/nsFieldSetFrame.cpp @@ -131,7 +131,7 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::fieldsetContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); nsIFrame* newChildList = aChildList; diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 60a8b5befe1..79c38a71d06 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -196,7 +196,7 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, text->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::disabled, nsAutoString("1"), PR_FALSE); // XXX this should use an "empty" bool value } NS_NewTextControlFrame(childFrame); - childFrame->Init(aPresContext, text, this, mStyleContext); + childFrame->Init(aPresContext, text, this, this, mStyleContext); mTextFrame = (nsTextControlFrame*)childFrame; mFirstChild = childFrame; @@ -210,7 +210,7 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, NS_NewButtonControlFrame(childFrame); ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); mBrowseFrame = (nsButtonControlFrame*)childFrame; - childFrame->Init(aPresContext, browse, this, mStyleContext); + childFrame->Init(aPresContext, browse, this, this, mStyleContext); mFirstChild->SetNextSibling(childFrame); diff --git a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp index a6823241d70..64157787f08 100644 --- a/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsHTMLButtonControlFrame.cpp @@ -511,7 +511,7 @@ nsHTMLButtonControlFrame::SetInitialChildList(nsIPresContext& aPresContext, // Resolve style and initialize the frame nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::buttonContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); // Set the geometric and content parent for each of the child frames diff --git a/mozilla/layout/forms/nsLegendFrame.cpp b/mozilla/layout/forms/nsLegendFrame.cpp index 1e15ce38c7c..5ba65b3730d 100644 --- a/mozilla/layout/forms/nsLegendFrame.cpp +++ b/mozilla/layout/forms/nsLegendFrame.cpp @@ -95,7 +95,7 @@ nsLegendFrame::SetInitialChildList(nsIPresContext& aPresContext, // Resolve style and initialize the frame nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::legendContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); // Set the geometric and content parent for each of the child frames diff --git a/mozilla/layout/generic/nsAreaFrame.cpp b/mozilla/layout/generic/nsAreaFrame.cpp index fd4756772ce..e005d2ea268 100644 --- a/mozilla/layout/generic/nsAreaFrame.cpp +++ b/mozilla/layout/generic/nsAreaFrame.cpp @@ -29,7 +29,6 @@ #include "nsHTMLAtoms.h" #include "nsIView.h" #include "nsViewsCID.h" -#include "nsAbsoluteFrame.h" #include "nsHTMLIIDs.h" #include "nsIWebShell.h" #include "nsHTMLValue.h" @@ -61,24 +60,6 @@ nsAreaFrame::~nsAreaFrame() NS_RELEASE(mSpaceManager); } -///////////////////////////////////////////////////////////////////////////// -// nsISupports - -nsresult -nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - NS_PRECONDITION(0 != aInstancePtr, "null ptr"); - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kIAbsoluteItemsIID)) { - nsIAbsoluteItems* tmp = this; - *aInstancePtr = (void*) tmp; - return NS_OK; - } - return nsBlockFrame::QueryInterface(aIID, aInstancePtr); -} - ///////////////////////////////////////////////////////////////////////////// // nsIFrame @@ -89,6 +70,23 @@ nsAreaFrame::DeleteFrame(nsIPresContext& aPresContext) return nsBlockFrame::DeleteFrame(aPresContext); } +NS_IMETHODIMP +nsAreaFrame::SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv; + + if (nsLayoutAtoms::absoluteList == aListName) { + mAbsoluteFrames = aChildList; + rv = NS_OK; + } else { + rv = nsBlockFrame::SetInitialChildList(aPresContext, aListName, aChildList); + } + + return rv; +} + NS_IMETHODIMP nsAreaFrame::GetAdditionalChildListName(PRInt32 aIndex, nsIAtom*& aListName) const @@ -247,6 +245,8 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, aReflowState.maxSize.height, aReflowState.reason)); + nsresult rv = NS_OK; + // Make a copy of the reflow state so we can set the space manager nsHTMLReflowState reflowState(aReflowState); reflowState.spaceManager = mSpaceManager; @@ -254,9 +254,40 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // Clear the spacemanager's regions. mSpaceManager->ClearRegions(); - // XXX We need to peek at incremental reflow commands and see if the next - // frame is one of the absolutely positioned frames... - nsresult rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + // See if the reflow command is for an absolutely positioned frame + PRBool wasHandled = PR_FALSE; + if (eReflowReason_Incremental == aReflowState.reason) { + nsIFrame* targetFrame; + + aReflowState.reflowCommand->GetTarget(targetFrame); + if (this == targetFrame) { + nsIAtom* listName; + + aReflowState.reflowCommand->GetChildListName(listName); + if (nsLayoutAtoms::absoluteList == listName) { + nsIReflowCommand::ReflowType type; + + aReflowState.reflowCommand->GetType(type); + NS_ASSERTION(nsIReflowCommand::FrameAppended == type, "unexpected reflow type"); + + // Add the frames to our list of absolutely position frames + nsIFrame* childFrames; + aReflowState.reflowCommand->GetChildFrame(childFrames); + NS_ASSERTION(nsnull != childFrames, "null child list"); + AddAbsoluteFrame(childFrames); + + // Indicate we handled the reflow command + wasHandled = PR_TRUE; + } + NS_IF_RELEASE(listName); + } + } + + if (!wasHandled) { + // XXX We need to peek at incremental reflow commands and see if the next + // frame is one of the absolutely positioned frames... + rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + } // Reflow any absolutely positioned frames that need reflowing // XXX We shouldn't really be doing this for all incremental reflow commands @@ -286,13 +317,10 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, mStyleContext->GetStyleData(eStyleStruct_Display); if (NS_STYLE_OVERFLOW_HIDDEN != display->mOverflow) { - for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) { - // Get the anchor frame - nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i]; - nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame(); - nsRect rect; + for (nsIFrame* f = mAbsoluteFrames; nsnull != f; f->GetNextSibling(f)) { + nsRect rect; - absoluteFrame->GetRect(rect); + f->GetRect(rect); nscoord xmost = rect.XMost(); nscoord ymost = rect.YMost(); if (xmost > aDesiredSize.width) { @@ -369,7 +397,7 @@ nsAreaFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; @@ -392,49 +420,21 @@ void nsAreaFrame::AddAbsoluteFrame(nsIFrame* aFrame) } } -///////////////////////////////////////////////////////////////////////////// - -// nsIAbsoluteItems - -NS_METHOD nsAreaFrame::AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) -{ - // Add the absolute anchor frame to our list of absolutely positioned - // items. - mAbsoluteItems.AppendElement(aAnchorFrame); - return NS_OK; -} - -PRBool -nsAreaFrame::IsAbsoluteFrame(nsIFrame* aFrame) -{ - // Check whether the frame is in our list of absolutely positioned frames - for (nsIFrame* f = mAbsoluteFrames; nsnull != f; f->GetNextSibling(f)) { - if (f == aFrame) { - return PR_TRUE; - } - } - - return PR_FALSE; -} - -NS_METHOD nsAreaFrame::RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) -{ - NS_NOTYETIMPLEMENTED("removing an absolutely positioned frame"); - return NS_ERROR_NOT_IMPLEMENTED; -} - // Called at the end of the Reflow() member function so we can process // any abolutely positioned items that need to be reflowed void nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState) { - for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) { - // Get the anchor frame and its absolutely positioned frame - nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i]; - nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame(); + for (nsIFrame* absoluteFrame = mAbsoluteFrames; + nsnull != absoluteFrame; absoluteFrame->GetNextSibling(absoluteFrame)) { + PRBool placeFrame = PR_FALSE; +#if 0 PRBool reflowFrame = PR_FALSE; +#else + PRBool reflowFrame = PR_TRUE; +#endif nsReflowReason reflowReason = eReflowReason_Resize; // Get its style information @@ -444,6 +444,7 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, absoluteFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); absoluteFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); +#if 0 // See whether the frame is a newly added frame if (!IsAbsoluteFrame(absoluteFrame)) { // The absolutely position item hasn't yet been added to our child list @@ -463,6 +464,7 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, placeFrame = reflowFrame = PR_TRUE; } else { +#endif // We need to place the frame if the left-offset or the top-offset are // auto or a percentage if ((eStyleUnit_Coord != position->mLeftOffset.GetUnit()) || @@ -476,12 +478,15 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, (eStyleUnit_Coord != position->mHeight.GetUnit())) { reflowFrame = PR_TRUE; } +#if 0 } +#endif if (placeFrame || reflowFrame) { // Get the rect for the absolutely positioned element nsRect rect; - ComputeAbsoluteFrameBounds(anchorFrame, aReflowState, position, rect); + ComputeAbsoluteFrameBounds(aPresContext, absoluteFrame, aReflowState, + position, rect); nsIHTMLReflow* htmlReflow; if (NS_OK == absoluteFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { @@ -541,7 +546,8 @@ void nsAreaFrame::TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const } } -void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame, +void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIPresContext& aPresContext, + nsIFrame* aFrame, const nsHTMLReflowState& aReflowState, const nsStylePosition* aPosition, nsRect& aRect) const @@ -552,11 +558,20 @@ void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFra // // If either the left or top are 'auto' then get the offset of the anchor // frame from this frame - nsPoint offset; + nsPoint offset(0, 0); if ((eStyleUnit_Auto == aPosition->mLeftOffset.GetUnit()) || (eStyleUnit_Auto == aPosition->mTopOffset.GetUnit())) { - aAnchorFrame->GetOrigin(offset); - TranslatePoint(aAnchorFrame, offset); + // Get the placeholder frame + nsIFrame* placeholderFrame; + nsIPresShell* presShell = aPresContext.GetShell(); + + presShell->GetPlaceholderFrameFor(aFrame, placeholderFrame); + NS_RELEASE(presShell); + NS_ASSERTION(nsnull != placeholderFrame, "no placeholder frame"); + if (nsnull != placeholderFrame) { + placeholderFrame->GetOrigin(offset); + TranslatePoint(placeholderFrame, offset); + } } // left-offset diff --git a/mozilla/layout/generic/nsAreaFrame.h b/mozilla/layout/generic/nsAreaFrame.h index 1df200711f7..8d144ac1b05 100644 --- a/mozilla/layout/generic/nsAreaFrame.h +++ b/mozilla/layout/generic/nsAreaFrame.h @@ -19,7 +19,6 @@ #define nsAreaFrame_h___ #include "nsBlockFrame.h" -#include "nsIAbsoluteItems.h" #include "nsISpaceManager.h" #include "nsVoidArray.h" @@ -40,18 +39,18 @@ struct nsStylePosition; * * @see nsLayoutAtoms::absoluteList */ -class nsAreaFrame : public nsBlockFrame, - public nsIAbsoluteItems +class nsAreaFrame : public nsBlockFrame { public: friend nsresult NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags); - // nsISupports - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - // nsIFrame NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext); + NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, nsIAtom*& aListName) const; @@ -77,10 +76,6 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent, nsIListFilter* aFilter) const; NS_IMETHOD GetFrameName(nsString& aResult) const; - // nsIAbsoluteItems - NS_IMETHOD AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame); - NS_IMETHOD RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame); - protected: nsAreaFrame(); virtual ~nsAreaFrame(); @@ -90,17 +85,16 @@ protected: void TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const; - void ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame, + void ComputeAbsoluteFrameBounds(nsIPresContext& aPresContext, + nsIFrame* aFrame, const nsHTMLReflowState& aState, const nsStylePosition* aPosition, nsRect& aRect) const; void AddAbsoluteFrame(nsIFrame* aFrame); - PRBool IsAbsoluteFrame(nsIFrame* aFrame); private: nsSpaceManager* mSpaceManager; - nsVoidArray mAbsoluteItems; nsIFrame* mAbsoluteFrames; // additional named child list #ifdef NS_DEBUG diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index 7ebeb82d0a8..cfddc0c1448 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -272,12 +272,14 @@ nsrefcnt nsFrame::Release(void) NS_IMETHODIMP nsFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) { mContent = aContent; NS_IF_ADDREF(mContent); - mGeometricParent = mContentParent = aParent; + mGeometricParent = aGeometricParent; + mContentParent = aContentParent; return SetStyleContext(&aPresContext, aContext); } diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index bb91c453e3c..3705640c65a 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -113,7 +113,8 @@ public: // nsIFrame NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext); NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, diff --git a/mozilla/layout/generic/nsFrameFrame.cpp b/mozilla/layout/generic/nsFrameFrame.cpp index 05329047d17..78e66424804 100644 --- a/mozilla/layout/generic/nsFrameFrame.cpp +++ b/mozilla/layout/generic/nsFrameFrame.cpp @@ -321,7 +321,7 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext& aPresContext, if (nsnull == mFirstChild) { mFirstChild = new nsHTMLFrameInnerFrame; // XXX temporary! use style system to get correct style! - mFirstChild->Init(aPresContext, mContent, this, mStyleContext); + mFirstChild->Init(aPresContext, mContent, this, this, mStyleContext); } // nsContainerFrame::PaintBorder has some problems, kludge it here diff --git a/mozilla/layout/generic/nsFrameSetFrame.cpp b/mozilla/layout/generic/nsFrameSetFrame.cpp index cdb339719f8..4e600534a23 100644 --- a/mozilla/layout/generic/nsFrameSetFrame.cpp +++ b/mozilla/layout/generic/nsFrameSetFrame.cpp @@ -936,7 +936,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, if (nsHTMLAtoms::frameset == tag) { result = NS_NewHTMLFramesetFrame(frame); - frame->Init(aPresContext, child, this, kidSC); + frame->Init(aPresContext, child, this, this, kidSC); childTypes[mChildCount] = FRAMESET; nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame; @@ -946,7 +946,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, childBorderColors[mChildCount].Set(childFrame->GetBorderColor()); } else { // frame result = NS_NewHTMLFrameOuterFrame(frame); - frame->Init(aPresContext, child, this, kidSC); + frame->Init(aPresContext, child, this, this, kidSC); childTypes[mChildCount] = FRAME; // @@ -979,7 +979,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, nsHTMLFramesetBlankFrame* blankFrame = new nsHTMLFramesetBlankFrame; nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::framesetBlankPseudo, mStyleContext); - blankFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + blankFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); if (nsnull == lastChild) { @@ -1017,7 +1017,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, borderFrame = new nsHTMLFramesetBorderFrame(borderWidth, PR_FALSE, PR_FALSE); nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::horizontalFramesetBorderPseudo, mStyleContext); - borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + borderFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); mChildCount++; @@ -1042,7 +1042,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, borderFrame = new nsHTMLFramesetBorderFrame(borderWidth, PR_TRUE, PR_FALSE); nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::verticalFramesetBorderPseudo, mStyleContext); - borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + borderFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); mChildCount++; diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.cpp b/mozilla/layout/generic/nsHTMLContainerFrame.cpp index d0024f878e5..bc0a0a6b783 100644 --- a/mozilla/layout/generic/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/generic/nsHTMLContainerFrame.cpp @@ -31,7 +31,6 @@ #include "nsIDocument.h" #include "nsIURL.h" #include "nsIPtr.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsIHTMLContent.h" #include "nsHTMLParts.h" @@ -90,7 +89,7 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, nsPlaceholderFrame* placeholder; NS_NewPlaceholderFrame((nsIFrame**)&placeholder); - placeholder->Init(aPresContext, content, this, kidSC); + placeholder->Init(aPresContext, content, this, this, kidSC); placeholder->SetAnchoredItem(aFloatedFrame); NS_IF_RELEASE(content); NS_RELEASE(kidSC); @@ -98,27 +97,6 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, return placeholder; } -nsAbsoluteFrame* -nsHTMLContainerFrame::CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, - nsIFrame* aAbsoluteFrame) -{ - nsIContent* content; - aAbsoluteFrame->GetContent(content); - - // Let the placeholder share the same style context as the floated element - nsIStyleContext* kidSC; - aAbsoluteFrame->GetStyleContext(kidSC); - - nsAbsoluteFrame* placeholder; - NS_NewAbsoluteFrame((nsIFrame**)&placeholder); - placeholder->Init(aPresContext, content, this, kidSC); - placeholder->SetAbsoluteFrame(aAbsoluteFrame); - NS_IF_RELEASE(content); - NS_RELEASE(kidSC); - - return placeholder; -} - // XXX pass in aFrame's style context instead PRBool nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, @@ -134,9 +112,8 @@ nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, PRBool isFloated = (NS_STYLE_FLOAT_LEFT == aDisplay->mFloats) || (NS_STYLE_FLOAT_RIGHT == aDisplay->mFloats); - PRBool isAbsolute = NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition; - if (isFloated || isAbsolute) { + if (isFloated) { nsIFrame* nextSibling; // Set aFrame's next sibling to nsnull, and remember the current next @@ -144,21 +121,9 @@ nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, aFrame->GetNextSibling(nextSibling); aFrame->SetNextSibling(nsnull); - nsIFrame* frameToWrapWithAView = aFrame; - if (isFloated) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, aFrame); - - aPlaceholderFrame = placeholder; - - } else { - // Create a placeholder frame that will serve as the anchor point. - nsAbsoluteFrame* placeholder = - CreateAbsolutePlaceholderFrame(aPresContext, aFrame); - - aPlaceholderFrame = placeholder; - } + // Create a placeholder frame that will serve as the anchor point. + nsPlaceholderFrame* placeholder = CreatePlaceholderFrame(aPresContext, aFrame); + aPlaceholderFrame = placeholder; // Set the placeholder's next sibling to what aFrame's next sibling was aPlaceholderFrame->SetNextSibling(nextSibling); diff --git a/mozilla/layout/generic/nsHTMLContainerFrame.h b/mozilla/layout/generic/nsHTMLContainerFrame.h index 46953c32372..009a155893b 100644 --- a/mozilla/layout/generic/nsHTMLContainerFrame.h +++ b/mozilla/layout/generic/nsHTMLContainerFrame.h @@ -35,8 +35,6 @@ public: nsFramePaintLayer aWhichLayer); nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext& aPresContext, nsIFrame* aFloatedFrame); - nsAbsoluteFrame* CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, - nsIFrame* aAbsoluteFrame); // If the frame should be floated or absolutely positioned creates a placeholder // frame and returns PR_TRUE. The sibling list is modified so aFrame's next diff --git a/mozilla/layout/generic/nsHTMLReflowCommand.cpp b/mozilla/layout/generic/nsHTMLReflowCommand.cpp index 427cf8991fd..9e8d3d2997b 100644 --- a/mozilla/layout/generic/nsHTMLReflowCommand.cpp +++ b/mozilla/layout/generic/nsHTMLReflowCommand.cpp @@ -73,7 +73,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsIFrame* aChildFrame, nsIAtom* aAttribute) : mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame), - mAttribute(aAttribute), mPrevSiblingFrame(nsnull) + mAttribute(aAttribute), mPrevSiblingFrame(nsnull), mListName(nsnull) { NS_PRECONDITION(mTargetFrame != nsnull, "null target frame"); if (nsnull!=mAttribute) @@ -85,7 +85,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsIFrame* aChildFrame, nsIFrame* aPrevSiblingFrame) : mType(FrameInserted), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame), - mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull) + mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull), mListName(nsnull) { NS_PRECONDITION(mTargetFrame != nsnull, "null target frame"); NS_INIT_REFCNT(); @@ -94,6 +94,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsHTMLReflowCommand::~nsHTMLReflowCommand() { NS_IF_RELEASE(mAttribute); + NS_IF_RELEASE(mListName); } NS_IMPL_ISUPPORTS(nsHTMLReflowCommand, kIReflowCommandIID); @@ -210,7 +211,15 @@ NS_IMETHODIMP nsHTMLReflowCommand::GetChildFrame(nsIFrame*& aChildFrame) const NS_IMETHODIMP nsHTMLReflowCommand::GetChildListName(nsIAtom*& aListName) const { - aListName = nsnull; + aListName = mListName; + NS_IF_ADDREF(aListName); + return NS_OK; +} + +NS_IMETHODIMP nsHTMLReflowCommand::SetChildListName(nsIAtom* aListName) +{ + mListName = aListName; + NS_IF_ADDREF(mListName); return NS_OK; } diff --git a/mozilla/layout/generic/nsHTMLReflowCommand.h b/mozilla/layout/generic/nsHTMLReflowCommand.h index b497a20d811..29b070b821b 100644 --- a/mozilla/layout/generic/nsHTMLReflowCommand.h +++ b/mozilla/layout/generic/nsHTMLReflowCommand.h @@ -67,6 +67,7 @@ public: NS_IMETHOD GetChildFrame(nsIFrame*& aChildFrame) const; NS_IMETHOD GetChildListName(nsIAtom*& aListName) const; + NS_IMETHOD SetChildListName(nsIAtom* aListName); NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const; protected: @@ -79,6 +80,7 @@ private: nsIFrame* mChildFrame; nsIFrame* mPrevSiblingFrame; nsIAtom* mAttribute; + nsIAtom* mListName; nsVoidArray mPath; }; diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 9e47eb9b908..027bbd3090e 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -145,12 +145,14 @@ public: * now. * * @param aContent the content object associated with the frame - * @param aParent the parent frame + * @param aGeometricParent the geometric parent frame + * @param aContentParent the content parent frame * @param aContext the style context associated with the frame */ NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) = 0; /** diff --git a/mozilla/layout/generic/nsImageFrame.cpp b/mozilla/layout/generic/nsImageFrame.cpp index 3ffedc3c2b9..3bb33e1501b 100644 --- a/mozilla/layout/generic/nsImageFrame.cpp +++ b/mozilla/layout/generic/nsImageFrame.cpp @@ -340,6 +340,30 @@ nsImageFrame::DeleteFrame(nsIPresContext& aPresContext) return nsLeafFrame::DeleteFrame(aPresContext); } +NS_IMETHODIMP +nsImageFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, + nsIStyleContext* aContext) +{ + nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aGeometricParent, + aContentParent, aContext); + + // Set the image loader's source URL and base URL + nsAutoString src, base; + if ((NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, src)) && + (src.Length() > 0)) { + mImageLoader.SetURL(src); + if (NS_CONTENT_ATTR_HAS_VALUE == + mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::_baseHref, base)) { + mImageLoader.SetBaseHREF(base); + } + } + + return rv; +} + NS_IMETHODIMP nsImageFrame::SizeOf(nsISizeOfHandler* aHandler) const { @@ -420,20 +444,6 @@ nsImageFrame::Reflow(nsIPresContext& aPresContext, NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); - // If this is the initial reflow then set the image loader's - // source URL and base URL - if (eReflowReason_Initial == aReflowState.reason) { - nsAutoString src, base; - if ((NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, src)) && - (src.Length() > 0)) { - mImageLoader.SetURL(src); - if (NS_CONTENT_ATTR_HAS_VALUE == - mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::_baseHref, base)) { - mImageLoader.SetBaseHREF(base); - } - } - } - GetDesiredSize(&aPresContext, aReflowState, aMetrics); AddBordersAndPadding(&aPresContext, aReflowState, aMetrics, mBorderPadding); if (nsnull != aMetrics.maxElementSize) { diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 4a363be284d..f1a6d484845 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -276,7 +276,7 @@ nsInlineFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/generic/nsPageFrame.cpp b/mozilla/layout/generic/nsPageFrame.cpp index 20cdd2aa652..e0ed34dc43d 100644 --- a/mozilla/layout/generic/nsPageFrame.cpp +++ b/mozilla/layout/generic/nsPageFrame.cpp @@ -132,7 +132,7 @@ nsPageFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); aContinuingFrame = cf; return NS_OK; diff --git a/mozilla/layout/generic/nsTextFrame.cpp b/mozilla/layout/generic/nsTextFrame.cpp index 1381ee2349a..af2dbe2d329 100644 --- a/mozilla/layout/generic/nsTextFrame.cpp +++ b/mozilla/layout/generic/nsTextFrame.cpp @@ -481,7 +481,7 @@ TextFrame::CreateContinuingFrame(nsIPresContext& aCX, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aCX, mContent, aParent, aStyleContext); + cf->Init(aCX, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); aContinuingFrame = cf; return NS_OK; diff --git a/mozilla/layout/html/base/src/Makefile.in b/mozilla/layout/html/base/src/Makefile.in index d41ba95ac79..e4e48ac8c1f 100644 --- a/mozilla/layout/html/base/src/Makefile.in +++ b/mozilla/layout/html/base/src/Makefile.in @@ -27,7 +27,6 @@ LIBRARY_NAME = raptorhtmlbase_s # Note the sophisticated alphabetical ordering :-| CPPSRCS= \ nsAreaFrame.cpp \ - nsAbsoluteFrame.cpp \ nsBRFrame.cpp \ nsBlockBandData.cpp \ nsBlockFrame.cpp \ diff --git a/mozilla/layout/html/base/src/makefile.win b/mozilla/layout/html/base/src/makefile.win index 552dab43ca1..44fec5353e2 100644 --- a/mozilla/layout/html/base/src/makefile.win +++ b/mozilla/layout/html/base/src/makefile.win @@ -26,7 +26,6 @@ DEFINES = $(DEFINES) -DXP_NEW_SELECTION !endif CPPSRCS= \ - nsAbsoluteFrame.cpp \ nsAreaFrame.cpp \ nsBRFrame.cpp \ nsBlockBandData.cpp \ @@ -64,7 +63,6 @@ CPPSRCS= \ $(NULL) CPP_OBJS= \ - .\$(OBJDIR)\nsAbsoluteFrame.obj \ .\$(OBJDIR)\nsAreaFrame.obj \ .\$(OBJDIR)\nsBRFrame.obj \ .\$(OBJDIR)\nsBlockBandData.obj \ diff --git a/mozilla/layout/html/base/src/nsAbsoluteFrame.cpp b/mozilla/layout/html/base/src/nsAbsoluteFrame.cpp deleted file mode 100644 index b9057157a75..00000000000 --- a/mozilla/layout/html/base/src/nsAbsoluteFrame.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * The contents of this file are subject to the Netscape Public License - * Version 1.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights - * Reserved. - */ -#include "nsAbsoluteFrame.h" -#include "nsBodyFrame.h" -#include "nsIAbsoluteItems.h" -#include "nsIStyleContext.h" -#include "nsStyleConsts.h" -#include "nsHTMLIIDs.h" - -nsresult -NS_NewAbsoluteFrame(nsIFrame** aInstancePtrResult) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - nsIFrame* it = new nsAbsoluteFrame; - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - *aInstancePtrResult = it; - return NS_OK; -} - -nsAbsoluteFrame::~nsAbsoluteFrame() -{ -} - -NS_IMETHODIMP nsAbsoluteFrame::Reflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - if (eReflowReason_Initial == aReflowState.reason) { - // By this point we expect to have been told which absolute frame we're - // associated with - NS_ASSERTION(nsnull != mFrame, "no absolute frame"); - - // Get the containing block - nsIFrame* containingBlock = GetContainingBlock(); - NS_ASSERTION(nsnull != containingBlock, "no initial containing block"); - - // Query for its nsIAbsoluteItems interface - nsIAbsoluteItems* absoluteItemContainer; - nsresult rv; - - rv = containingBlock->QueryInterface(kIAbsoluteItemsIID, (void**)&absoluteItemContainer); - NS_ASSERTION(NS_SUCCEEDED(rv), "no nsIAbsoluteItems support"); - - // Notify it that there's a new absolutely positioned frame, passing it the - // anchor frame - absoluteItemContainer->AddAbsoluteItem(this); - } - - // Return our desired size as (0, 0) - return nsFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); -} - -NS_IMETHODIMP nsAbsoluteFrame::ContentChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsISupports* aSubContent) -{ - NS_ASSERTION(mContent == aChild, "bad content-changed target"); - - // Forward the notification to the absolutely positioned frame - if (nsnull != mFrame) { - return mFrame->ContentChanged(aPresContext, aChild, aSubContent); - } - - return NS_OK; -} - -NS_IMETHODIMP nsAbsoluteFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint) -{ - NS_ASSERTION(mContent == aChild, "bad content-changed target"); - - // Forward the notification to the absolutely positioned frame - if (nsnull != mFrame) { - return mFrame->AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - return NS_OK; -} - - -nsIFrame* nsAbsoluteFrame::GetContainingBlock() const -{ - // Look for a containing frame that is absolutely positioned. If we don't - // find one then use the initial containg block which is the BODY - nsIFrame* lastFrame = (nsIFrame*)this; - nsIFrame* result; - - GetContentParent(result); - while (nsnull != result) { - const nsStylePosition* position; - - // Get the style data - result->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); - - if (position->mPosition == NS_STYLE_POSITION_ABSOLUTE) { - // XXX This needs cleaning up... - // Make sure the frame supports the nsIAbsoluteItems interface. If not, - // walk the geometric parent hierarchy and find the nearest one that does... - nsIAbsoluteItems* interface; - while ((nsnull != result) && - NS_FAILED(result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface))) { - result->GetGeometricParent(result); - } - break; - } - - // Get the next contentual parent - lastFrame = result; - result->GetContentParent(result); - } - - if (nsnull == result) { - // Walk back down the tree until we find a frame that supports - // nsIAbsoluteItems - // XXX This is pretty yucky, but there isn't currently a better way to do - // this... - lastFrame->FirstChild(nsnull, result); - - while (nsnull != result) { - nsIAbsoluteItems* interface; - if (NS_SUCCEEDED(result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface))) { - break; - } - - result->FirstChild(nsnull, result); - } - } - - return result; -} - -NS_IMETHODIMP -nsAbsoluteFrame::GetFrameName(nsString& aResult) const -{ - return MakeFrameName("Absolute", aResult); -} diff --git a/mozilla/layout/html/base/src/nsAbsoluteFrame.h b/mozilla/layout/html/base/src/nsAbsoluteFrame.h deleted file mode 100644 index ebc2f3b36e7..00000000000 --- a/mozilla/layout/html/base/src/nsAbsoluteFrame.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * The contents of this file are subject to the Netscape Public License - * Version 1.0 (the "NPL"); you may not use this file except in - * compliance with the NPL. You may obtain a copy of the NPL at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the NPL is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL - * for the specific language governing rights and limitations under the - * NPL. - * - * The Initial Developer of this code under the NPL is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998 Netscape Communications Corporation. All Rights - * Reserved. - */ -#ifndef nsAbsoluteFrame_h___ -#define nsAbsoluteFrame_h___ - -#include "nsFrame.h" - -// Implementation of a frame that's used as a placeholder for an absolutely -// positioned frame -class nsAbsoluteFrame : public nsFrame { -public: - /** - * Create a placeholder for an absolutely positioned frame. - * - * @see #GetAbsoluteFrame() - */ - friend nsresult NS_NewAbsoluteFrame(nsIFrame** aInstancePtrResult); - - // Returns the associated anchored item - nsIFrame* GetAbsoluteFrame() const {return mFrame;} - void SetAbsoluteFrame(nsIFrame* aAbsoluteFrame) {mFrame = aAbsoluteFrame;} - - // nsIHTMLReflow overrides - NS_IMETHOD Reflow(nsIPresContext& aPresContext, - nsHTMLReflowMetrics& aDesiredSize, - const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); - - // nsIFrame overrides - NS_IMETHOD ContentChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsISupports* aSubContent); - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint); - - NS_IMETHOD GetFrameName(nsString& aResult) const; - -protected: - nsIFrame* mFrame; // the absolutely positioned frame - - virtual ~nsAbsoluteFrame(); - - nsIFrame* GetContainingBlock() const; -}; - -#endif /* nsAbsoluteFrame_h___ */ diff --git a/mozilla/layout/html/base/src/nsAreaFrame.cpp b/mozilla/layout/html/base/src/nsAreaFrame.cpp index fd4756772ce..e005d2ea268 100644 --- a/mozilla/layout/html/base/src/nsAreaFrame.cpp +++ b/mozilla/layout/html/base/src/nsAreaFrame.cpp @@ -29,7 +29,6 @@ #include "nsHTMLAtoms.h" #include "nsIView.h" #include "nsViewsCID.h" -#include "nsAbsoluteFrame.h" #include "nsHTMLIIDs.h" #include "nsIWebShell.h" #include "nsHTMLValue.h" @@ -61,24 +60,6 @@ nsAreaFrame::~nsAreaFrame() NS_RELEASE(mSpaceManager); } -///////////////////////////////////////////////////////////////////////////// -// nsISupports - -nsresult -nsAreaFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - NS_PRECONDITION(0 != aInstancePtr, "null ptr"); - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - } - if (aIID.Equals(kIAbsoluteItemsIID)) { - nsIAbsoluteItems* tmp = this; - *aInstancePtr = (void*) tmp; - return NS_OK; - } - return nsBlockFrame::QueryInterface(aIID, aInstancePtr); -} - ///////////////////////////////////////////////////////////////////////////// // nsIFrame @@ -89,6 +70,23 @@ nsAreaFrame::DeleteFrame(nsIPresContext& aPresContext) return nsBlockFrame::DeleteFrame(aPresContext); } +NS_IMETHODIMP +nsAreaFrame::SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList) +{ + nsresult rv; + + if (nsLayoutAtoms::absoluteList == aListName) { + mAbsoluteFrames = aChildList; + rv = NS_OK; + } else { + rv = nsBlockFrame::SetInitialChildList(aPresContext, aListName, aChildList); + } + + return rv; +} + NS_IMETHODIMP nsAreaFrame::GetAdditionalChildListName(PRInt32 aIndex, nsIAtom*& aListName) const @@ -247,6 +245,8 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, aReflowState.maxSize.height, aReflowState.reason)); + nsresult rv = NS_OK; + // Make a copy of the reflow state so we can set the space manager nsHTMLReflowState reflowState(aReflowState); reflowState.spaceManager = mSpaceManager; @@ -254,9 +254,40 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, // Clear the spacemanager's regions. mSpaceManager->ClearRegions(); - // XXX We need to peek at incremental reflow commands and see if the next - // frame is one of the absolutely positioned frames... - nsresult rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + // See if the reflow command is for an absolutely positioned frame + PRBool wasHandled = PR_FALSE; + if (eReflowReason_Incremental == aReflowState.reason) { + nsIFrame* targetFrame; + + aReflowState.reflowCommand->GetTarget(targetFrame); + if (this == targetFrame) { + nsIAtom* listName; + + aReflowState.reflowCommand->GetChildListName(listName); + if (nsLayoutAtoms::absoluteList == listName) { + nsIReflowCommand::ReflowType type; + + aReflowState.reflowCommand->GetType(type); + NS_ASSERTION(nsIReflowCommand::FrameAppended == type, "unexpected reflow type"); + + // Add the frames to our list of absolutely position frames + nsIFrame* childFrames; + aReflowState.reflowCommand->GetChildFrame(childFrames); + NS_ASSERTION(nsnull != childFrames, "null child list"); + AddAbsoluteFrame(childFrames); + + // Indicate we handled the reflow command + wasHandled = PR_TRUE; + } + NS_IF_RELEASE(listName); + } + } + + if (!wasHandled) { + // XXX We need to peek at incremental reflow commands and see if the next + // frame is one of the absolutely positioned frames... + rv = nsBlockFrame::Reflow(aPresContext, aDesiredSize, reflowState, aStatus); + } // Reflow any absolutely positioned frames that need reflowing // XXX We shouldn't really be doing this for all incremental reflow commands @@ -286,13 +317,10 @@ nsAreaFrame::Reflow(nsIPresContext& aPresContext, mStyleContext->GetStyleData(eStyleStruct_Display); if (NS_STYLE_OVERFLOW_HIDDEN != display->mOverflow) { - for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) { - // Get the anchor frame - nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i]; - nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame(); - nsRect rect; + for (nsIFrame* f = mAbsoluteFrames; nsnull != f; f->GetNextSibling(f)) { + nsRect rect; - absoluteFrame->GetRect(rect); + f->GetRect(rect); nscoord xmost = rect.XMost(); nscoord ymost = rect.YMost(); if (xmost > aDesiredSize.width) { @@ -369,7 +397,7 @@ nsAreaFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; @@ -392,49 +420,21 @@ void nsAreaFrame::AddAbsoluteFrame(nsIFrame* aFrame) } } -///////////////////////////////////////////////////////////////////////////// - -// nsIAbsoluteItems - -NS_METHOD nsAreaFrame::AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) -{ - // Add the absolute anchor frame to our list of absolutely positioned - // items. - mAbsoluteItems.AppendElement(aAnchorFrame); - return NS_OK; -} - -PRBool -nsAreaFrame::IsAbsoluteFrame(nsIFrame* aFrame) -{ - // Check whether the frame is in our list of absolutely positioned frames - for (nsIFrame* f = mAbsoluteFrames; nsnull != f; f->GetNextSibling(f)) { - if (f == aFrame) { - return PR_TRUE; - } - } - - return PR_FALSE; -} - -NS_METHOD nsAreaFrame::RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) -{ - NS_NOTYETIMPLEMENTED("removing an absolutely positioned frame"); - return NS_ERROR_NOT_IMPLEMENTED; -} - // Called at the end of the Reflow() member function so we can process // any abolutely positioned items that need to be reflowed void nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, const nsHTMLReflowState& aReflowState) { - for (PRInt32 i = 0; i < mAbsoluteItems.Count(); i++) { - // Get the anchor frame and its absolutely positioned frame - nsAbsoluteFrame* anchorFrame = (nsAbsoluteFrame*)mAbsoluteItems[i]; - nsIFrame* absoluteFrame = anchorFrame->GetAbsoluteFrame(); + for (nsIFrame* absoluteFrame = mAbsoluteFrames; + nsnull != absoluteFrame; absoluteFrame->GetNextSibling(absoluteFrame)) { + PRBool placeFrame = PR_FALSE; +#if 0 PRBool reflowFrame = PR_FALSE; +#else + PRBool reflowFrame = PR_TRUE; +#endif nsReflowReason reflowReason = eReflowReason_Resize; // Get its style information @@ -444,6 +444,7 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, absoluteFrame->GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display); absoluteFrame->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); +#if 0 // See whether the frame is a newly added frame if (!IsAbsoluteFrame(absoluteFrame)) { // The absolutely position item hasn't yet been added to our child list @@ -463,6 +464,7 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, placeFrame = reflowFrame = PR_TRUE; } else { +#endif // We need to place the frame if the left-offset or the top-offset are // auto or a percentage if ((eStyleUnit_Coord != position->mLeftOffset.GetUnit()) || @@ -476,12 +478,15 @@ nsAreaFrame::ReflowAbsoluteItems(nsIPresContext& aPresContext, (eStyleUnit_Coord != position->mHeight.GetUnit())) { reflowFrame = PR_TRUE; } +#if 0 } +#endif if (placeFrame || reflowFrame) { // Get the rect for the absolutely positioned element nsRect rect; - ComputeAbsoluteFrameBounds(anchorFrame, aReflowState, position, rect); + ComputeAbsoluteFrameBounds(aPresContext, absoluteFrame, aReflowState, + position, rect); nsIHTMLReflow* htmlReflow; if (NS_OK == absoluteFrame->QueryInterface(kIHTMLReflowIID, (void**)&htmlReflow)) { @@ -541,7 +546,8 @@ void nsAreaFrame::TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const } } -void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame, +void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIPresContext& aPresContext, + nsIFrame* aFrame, const nsHTMLReflowState& aReflowState, const nsStylePosition* aPosition, nsRect& aRect) const @@ -552,11 +558,20 @@ void nsAreaFrame::ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFra // // If either the left or top are 'auto' then get the offset of the anchor // frame from this frame - nsPoint offset; + nsPoint offset(0, 0); if ((eStyleUnit_Auto == aPosition->mLeftOffset.GetUnit()) || (eStyleUnit_Auto == aPosition->mTopOffset.GetUnit())) { - aAnchorFrame->GetOrigin(offset); - TranslatePoint(aAnchorFrame, offset); + // Get the placeholder frame + nsIFrame* placeholderFrame; + nsIPresShell* presShell = aPresContext.GetShell(); + + presShell->GetPlaceholderFrameFor(aFrame, placeholderFrame); + NS_RELEASE(presShell); + NS_ASSERTION(nsnull != placeholderFrame, "no placeholder frame"); + if (nsnull != placeholderFrame) { + placeholderFrame->GetOrigin(offset); + TranslatePoint(placeholderFrame, offset); + } } // left-offset diff --git a/mozilla/layout/html/base/src/nsAreaFrame.h b/mozilla/layout/html/base/src/nsAreaFrame.h index 1df200711f7..8d144ac1b05 100644 --- a/mozilla/layout/html/base/src/nsAreaFrame.h +++ b/mozilla/layout/html/base/src/nsAreaFrame.h @@ -19,7 +19,6 @@ #define nsAreaFrame_h___ #include "nsBlockFrame.h" -#include "nsIAbsoluteItems.h" #include "nsISpaceManager.h" #include "nsVoidArray.h" @@ -40,18 +39,18 @@ struct nsStylePosition; * * @see nsLayoutAtoms::absoluteList */ -class nsAreaFrame : public nsBlockFrame, - public nsIAbsoluteItems +class nsAreaFrame : public nsBlockFrame { public: friend nsresult NS_NewAreaFrame(nsIFrame*& aResult, PRUint32 aFlags); - // nsISupports - NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); - // nsIFrame NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext); + NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, + nsIAtom* aListName, + nsIFrame* aChildList); + NS_IMETHOD GetAdditionalChildListName(PRInt32 aIndex, nsIAtom*& aListName) const; @@ -77,10 +76,6 @@ public: NS_IMETHOD List(FILE* out, PRInt32 aIndent, nsIListFilter* aFilter) const; NS_IMETHOD GetFrameName(nsString& aResult) const; - // nsIAbsoluteItems - NS_IMETHOD AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame); - NS_IMETHOD RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame); - protected: nsAreaFrame(); virtual ~nsAreaFrame(); @@ -90,17 +85,16 @@ protected: void TranslatePoint(nsIFrame* aFrameFrom, nsPoint& aPoint) const; - void ComputeAbsoluteFrameBounds(nsIFrame* aAnchorFrame, + void ComputeAbsoluteFrameBounds(nsIPresContext& aPresContext, + nsIFrame* aFrame, const nsHTMLReflowState& aState, const nsStylePosition* aPosition, nsRect& aRect) const; void AddAbsoluteFrame(nsIFrame* aFrame); - PRBool IsAbsoluteFrame(nsIFrame* aFrame); private: nsSpaceManager* mSpaceManager; - nsVoidArray mAbsoluteItems; nsIFrame* mAbsoluteFrames; // additional named child list #ifdef NS_DEBUG diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index f9b043fc26a..2c6382f658b 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -25,7 +25,6 @@ #include "nsFrameReflowState.h" #include "nsLineLayout.h" #include "nsInlineReflow.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsStyleConsts.h" #include "nsHTMLIIDs.h" @@ -4166,7 +4165,7 @@ nsBlockFrame::SetInitialChildList(nsIPresContext& aPresContext, NS_RELEASE(kidSC); return NS_ERROR_OUT_OF_MEMORY; } - mBullet->Init(aPresContext, mContent, this, kidSC); + mBullet->Init(aPresContext, mContent, this, this, kidSC); NS_RELEASE(kidSC); // If the list bullet frame should be positioned inside then add @@ -4329,7 +4328,7 @@ nsBlockFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/html/base/src/nsBodyFrame.h b/mozilla/layout/html/base/src/nsBodyFrame.h index 422917afac3..68d46f70952 100644 --- a/mozilla/layout/html/base/src/nsBodyFrame.h +++ b/mozilla/layout/html/base/src/nsBodyFrame.h @@ -19,7 +19,6 @@ #define nsBodyFrame_h___ #include "nsBlockFrame.h" -#include "nsIAbsoluteItems.h" #include "nsISpaceManager.h" #include "nsVoidArray.h" diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index 7ebeb82d0a8..cfddc0c1448 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -272,12 +272,14 @@ nsrefcnt nsFrame::Release(void) NS_IMETHODIMP nsFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) { mContent = aContent; NS_IF_ADDREF(mContent); - mGeometricParent = mContentParent = aParent; + mGeometricParent = aGeometricParent; + mContentParent = aContentParent; return SetStyleContext(&aPresContext, aContext); } diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h index bb91c453e3c..3705640c65a 100644 --- a/mozilla/layout/html/base/src/nsFrame.h +++ b/mozilla/layout/html/base/src/nsFrame.h @@ -113,7 +113,8 @@ public: // nsIFrame NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext); NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, nsIAtom* aListName, diff --git a/mozilla/layout/html/base/src/nsHTMLAtoms.cpp b/mozilla/layout/html/base/src/nsHTMLAtoms.cpp index 60d75d84ef7..ed5dea36bd7 100644 --- a/mozilla/layout/html/base/src/nsHTMLAtoms.cpp +++ b/mozilla/layout/html/base/src/nsHTMLAtoms.cpp @@ -175,6 +175,7 @@ nsIAtom* nsHTMLAtoms::p; nsIAtom* nsHTMLAtoms::pagex; nsIAtom* nsHTMLAtoms::pagey; nsIAtom* nsHTMLAtoms::param; +nsIAtom* nsHTMLAtoms::placeholderPseudo; nsIAtom* nsHTMLAtoms::pointSize; nsIAtom* nsHTMLAtoms::pre; nsIAtom* nsHTMLAtoms::profile; @@ -406,6 +407,7 @@ void nsHTMLAtoms::AddrefAtoms() pagex = NS_NewAtom("PAGEX"); pagey = NS_NewAtom("PAGEY"); param = NS_NewAtom("PARAM"); + placeholderPseudo = NS_NewAtom(":PLACEHOLDER-FRAME"); pointSize = NS_NewAtom("POINT-SIZE"); pre = NS_NewAtom("PRE"); profile = NS_NewAtom("PROFILE"); @@ -632,6 +634,7 @@ void nsHTMLAtoms::ReleaseAtoms() NS_RELEASE(pagex); NS_RELEASE(pagey); NS_RELEASE(param); + NS_RELEASE(placeholderPseudo); NS_RELEASE(pointSize); NS_RELEASE(pre); NS_RELEASE(profile); diff --git a/mozilla/layout/html/base/src/nsHTMLAtoms.h b/mozilla/layout/html/base/src/nsHTMLAtoms.h index eda5f44142f..69b497fde5a 100644 --- a/mozilla/layout/html/base/src/nsHTMLAtoms.h +++ b/mozilla/layout/html/base/src/nsHTMLAtoms.h @@ -207,6 +207,7 @@ public: static nsIAtom* pagex; static nsIAtom* pagey; static nsIAtom* param; + static nsIAtom* placeholderPseudo; static nsIAtom* pointSize; static nsIAtom* pre; static nsIAtom* profile; diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp index d0024f878e5..bc0a0a6b783 100644 --- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.cpp @@ -31,7 +31,6 @@ #include "nsIDocument.h" #include "nsIURL.h" #include "nsIPtr.h" -#include "nsAbsoluteFrame.h" #include "nsPlaceholderFrame.h" #include "nsIHTMLContent.h" #include "nsHTMLParts.h" @@ -90,7 +89,7 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, nsPlaceholderFrame* placeholder; NS_NewPlaceholderFrame((nsIFrame**)&placeholder); - placeholder->Init(aPresContext, content, this, kidSC); + placeholder->Init(aPresContext, content, this, this, kidSC); placeholder->SetAnchoredItem(aFloatedFrame); NS_IF_RELEASE(content); NS_RELEASE(kidSC); @@ -98,27 +97,6 @@ nsHTMLContainerFrame::CreatePlaceholderFrame(nsIPresContext& aPresContext, return placeholder; } -nsAbsoluteFrame* -nsHTMLContainerFrame::CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, - nsIFrame* aAbsoluteFrame) -{ - nsIContent* content; - aAbsoluteFrame->GetContent(content); - - // Let the placeholder share the same style context as the floated element - nsIStyleContext* kidSC; - aAbsoluteFrame->GetStyleContext(kidSC); - - nsAbsoluteFrame* placeholder; - NS_NewAbsoluteFrame((nsIFrame**)&placeholder); - placeholder->Init(aPresContext, content, this, kidSC); - placeholder->SetAbsoluteFrame(aAbsoluteFrame); - NS_IF_RELEASE(content); - NS_RELEASE(kidSC); - - return placeholder; -} - // XXX pass in aFrame's style context instead PRBool nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, @@ -134,9 +112,8 @@ nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, PRBool isFloated = (NS_STYLE_FLOAT_LEFT == aDisplay->mFloats) || (NS_STYLE_FLOAT_RIGHT == aDisplay->mFloats); - PRBool isAbsolute = NS_STYLE_POSITION_ABSOLUTE == aPosition->mPosition; - if (isFloated || isAbsolute) { + if (isFloated) { nsIFrame* nextSibling; // Set aFrame's next sibling to nsnull, and remember the current next @@ -144,21 +121,9 @@ nsHTMLContainerFrame::MoveFrameOutOfFlow(nsIPresContext& aPresContext, aFrame->GetNextSibling(nextSibling); aFrame->SetNextSibling(nsnull); - nsIFrame* frameToWrapWithAView = aFrame; - if (isFloated) { - // Create a placeholder frame that will serve as the anchor point. - nsPlaceholderFrame* placeholder = - CreatePlaceholderFrame(aPresContext, aFrame); - - aPlaceholderFrame = placeholder; - - } else { - // Create a placeholder frame that will serve as the anchor point. - nsAbsoluteFrame* placeholder = - CreateAbsolutePlaceholderFrame(aPresContext, aFrame); - - aPlaceholderFrame = placeholder; - } + // Create a placeholder frame that will serve as the anchor point. + nsPlaceholderFrame* placeholder = CreatePlaceholderFrame(aPresContext, aFrame); + aPlaceholderFrame = placeholder; // Set the placeholder's next sibling to what aFrame's next sibling was aPlaceholderFrame->SetNextSibling(nextSibling); diff --git a/mozilla/layout/html/base/src/nsHTMLContainerFrame.h b/mozilla/layout/html/base/src/nsHTMLContainerFrame.h index 46953c32372..009a155893b 100644 --- a/mozilla/layout/html/base/src/nsHTMLContainerFrame.h +++ b/mozilla/layout/html/base/src/nsHTMLContainerFrame.h @@ -35,8 +35,6 @@ public: nsFramePaintLayer aWhichLayer); nsPlaceholderFrame* CreatePlaceholderFrame(nsIPresContext& aPresContext, nsIFrame* aFloatedFrame); - nsAbsoluteFrame* CreateAbsolutePlaceholderFrame(nsIPresContext& aPresContext, - nsIFrame* aAbsoluteFrame); // If the frame should be floated or absolutely positioned creates a placeholder // frame and returns PR_TRUE. The sibling list is modified so aFrame's next diff --git a/mozilla/layout/html/base/src/nsHTMLIIDs.cpp b/mozilla/layout/html/base/src/nsHTMLIIDs.cpp index 6e156587188..e80a3af7b58 100644 --- a/mozilla/layout/html/base/src/nsHTMLIIDs.cpp +++ b/mozilla/layout/html/base/src/nsHTMLIIDs.cpp @@ -17,12 +17,10 @@ */ #include "nsHTMLIIDs.h" #include "nsIHTMLContent.h" -#include "nsIAbsoluteItems.h" #include "nsIAnchoredItems.h" #include "nsIHTMLReflow.h" #include "nsIPageSequenceFrame.h" -const nsIID kIAbsoluteItemsIID = NS_IABSOLUTE_ITEMS_IID; const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID; const nsIID kIHTMLReflowIID = NS_IHTMLREFLOW_IID; const nsIID kIPageSequenceFrameIID = NS_IPAGESEQUENCEFRAME_IID; diff --git a/mozilla/layout/html/base/src/nsHTMLImage.h b/mozilla/layout/html/base/src/nsHTMLImage.h index 0023ce9a07e..dc7d04ab5f2 100644 --- a/mozilla/layout/html/base/src/nsHTMLImage.h +++ b/mozilla/layout/html/base/src/nsHTMLImage.h @@ -100,6 +100,11 @@ protected: class nsImageFrame : public ImageFrameSuper { public: NS_IMETHOD DeleteFrame(nsIPresContext& aPresContext); + NS_IMETHOD Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, + nsIStyleContext* aContext); NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const; NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, diff --git a/mozilla/layout/html/base/src/nsHTMLReflowCommand.cpp b/mozilla/layout/html/base/src/nsHTMLReflowCommand.cpp index 427cf8991fd..9e8d3d2997b 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowCommand.cpp +++ b/mozilla/layout/html/base/src/nsHTMLReflowCommand.cpp @@ -73,7 +73,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsIFrame* aChildFrame, nsIAtom* aAttribute) : mType(aReflowType), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame), - mAttribute(aAttribute), mPrevSiblingFrame(nsnull) + mAttribute(aAttribute), mPrevSiblingFrame(nsnull), mListName(nsnull) { NS_PRECONDITION(mTargetFrame != nsnull, "null target frame"); if (nsnull!=mAttribute) @@ -85,7 +85,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsIFrame* aChildFrame, nsIFrame* aPrevSiblingFrame) : mType(FrameInserted), mTargetFrame(aTargetFrame), mChildFrame(aChildFrame), - mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull) + mPrevSiblingFrame(aPrevSiblingFrame), mAttribute(nsnull), mListName(nsnull) { NS_PRECONDITION(mTargetFrame != nsnull, "null target frame"); NS_INIT_REFCNT(); @@ -94,6 +94,7 @@ nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame, nsHTMLReflowCommand::~nsHTMLReflowCommand() { NS_IF_RELEASE(mAttribute); + NS_IF_RELEASE(mListName); } NS_IMPL_ISUPPORTS(nsHTMLReflowCommand, kIReflowCommandIID); @@ -210,7 +211,15 @@ NS_IMETHODIMP nsHTMLReflowCommand::GetChildFrame(nsIFrame*& aChildFrame) const NS_IMETHODIMP nsHTMLReflowCommand::GetChildListName(nsIAtom*& aListName) const { - aListName = nsnull; + aListName = mListName; + NS_IF_ADDREF(aListName); + return NS_OK; +} + +NS_IMETHODIMP nsHTMLReflowCommand::SetChildListName(nsIAtom* aListName) +{ + mListName = aListName; + NS_IF_ADDREF(mListName); return NS_OK; } diff --git a/mozilla/layout/html/base/src/nsHTMLReflowCommand.h b/mozilla/layout/html/base/src/nsHTMLReflowCommand.h index b497a20d811..29b070b821b 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowCommand.h +++ b/mozilla/layout/html/base/src/nsHTMLReflowCommand.h @@ -67,6 +67,7 @@ public: NS_IMETHOD GetChildFrame(nsIFrame*& aChildFrame) const; NS_IMETHOD GetChildListName(nsIAtom*& aListName) const; + NS_IMETHOD SetChildListName(nsIAtom* aListName); NS_IMETHOD GetPrevSiblingFrame(nsIFrame*& aSiblingFrame) const; protected: @@ -79,6 +80,7 @@ private: nsIFrame* mChildFrame; nsIFrame* mPrevSiblingFrame; nsIAtom* mAttribute; + nsIAtom* mListName; nsVoidArray mPath; }; diff --git a/mozilla/layout/html/base/src/nsIAbsoluteItems.h b/mozilla/layout/html/base/src/nsIAbsoluteItems.h deleted file mode 100644 index 7db30558e4d..00000000000 --- a/mozilla/layout/html/base/src/nsIAbsoluteItems.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * The contents of this file are subject to the Netscape Public License - * Version 1.0 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/NPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and limitations - * under the License. - * - * The Original Code is Mozilla Communicator client code. - * - * The Initial Developer of the Original Code is Netscape Communications - * Corporation. Portions created by Netscape are Copyright (C) 1998 - * Netscape Communications Corporation. All Rights Reserved. - */ -#ifndef nsIAbsoluteItems_h___ -#define nsIAbsoluteItems_h___ - -class nsAbsoluteFrame; - -// IID for the nsIAbsoluteItems interface {28E68A10-0BD4-11d2-85DD-00A02468FAB6} -#define NS_IABSOLUTE_ITEMS_IID \ -{ 0x28e68a10, 0xbd4, 0x11d2, \ - {0x85, 0xdd, 0x0, 0xa0, 0x24, 0x68, 0xfa, 0xb6}} - -/** - * An interface for managing absolutely positioned items. Note that this interface - * is not an nsISupports interface, and therefore you cannot QueryInterface() back - */ -class nsIAbsoluteItems -{ -public: - /** - * Request to add an absolutely positioned item. The anchor for the - * absolutely positioned item is passed as an argument - * - * @see nsAbsoluteFrame::GetAbsoluteFrame() - */ - NS_IMETHOD AddAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) = 0; - - /** - * Called to remove an absolutely positioned item, most likely because the - * associated piece of content has been removed. - **/ - NS_IMETHOD RemoveAbsoluteItem(nsAbsoluteFrame* aAnchorFrame) = 0; -}; - -#endif /* nsIAbsoluteItems_h___ */ diff --git a/mozilla/layout/html/base/src/nsImageFrame.cpp b/mozilla/layout/html/base/src/nsImageFrame.cpp index 3ffedc3c2b9..3bb33e1501b 100644 --- a/mozilla/layout/html/base/src/nsImageFrame.cpp +++ b/mozilla/layout/html/base/src/nsImageFrame.cpp @@ -340,6 +340,30 @@ nsImageFrame::DeleteFrame(nsIPresContext& aPresContext) return nsLeafFrame::DeleteFrame(aPresContext); } +NS_IMETHODIMP +nsImageFrame::Init(nsIPresContext& aPresContext, + nsIContent* aContent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, + nsIStyleContext* aContext) +{ + nsresult rv = nsLeafFrame::Init(aPresContext, aContent, aGeometricParent, + aContentParent, aContext); + + // Set the image loader's source URL and base URL + nsAutoString src, base; + if ((NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, src)) && + (src.Length() > 0)) { + mImageLoader.SetURL(src); + if (NS_CONTENT_ATTR_HAS_VALUE == + mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::_baseHref, base)) { + mImageLoader.SetBaseHREF(base); + } + } + + return rv; +} + NS_IMETHODIMP nsImageFrame::SizeOf(nsISizeOfHandler* aHandler) const { @@ -420,20 +444,6 @@ nsImageFrame::Reflow(nsIPresContext& aPresContext, NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); - // If this is the initial reflow then set the image loader's - // source URL and base URL - if (eReflowReason_Initial == aReflowState.reason) { - nsAutoString src, base; - if ((NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::src, src)) && - (src.Length() > 0)) { - mImageLoader.SetURL(src); - if (NS_CONTENT_ATTR_HAS_VALUE == - mContent->GetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::_baseHref, base)) { - mImageLoader.SetBaseHREF(base); - } - } - } - GetDesiredSize(&aPresContext, aReflowState, aMetrics); AddBordersAndPadding(&aPresContext, aReflowState, aMetrics, mBorderPadding); if (nsnull != aMetrics.maxElementSize) { diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index 4a363be284d..f1a6d484845 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -276,7 +276,7 @@ nsInlineFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->SetFlags(mFlags); cf->AppendToFlow(this); aContinuingFrame = cf; diff --git a/mozilla/layout/html/base/src/nsPageFrame.cpp b/mozilla/layout/html/base/src/nsPageFrame.cpp index 20cdd2aa652..e0ed34dc43d 100644 --- a/mozilla/layout/html/base/src/nsPageFrame.cpp +++ b/mozilla/layout/html/base/src/nsPageFrame.cpp @@ -132,7 +132,7 @@ nsPageFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); aContinuingFrame = cf; return NS_OK; diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index ae086de9a10..f8fca69d63a 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -51,7 +51,6 @@ static PRBool gsNoisyRefs = PR_FALSE; #undef NOISY -#if 0 static PLHashNumber HashKey(nsIFrame* key) { @@ -87,7 +86,6 @@ FrameHashTable::FrameHashTable() FrameHashTable::~FrameHashTable() { - // XXX if debugging then we should assert that the table is empty PL_HashTableDestroy(mTable); } @@ -143,7 +141,6 @@ FrameHashTable::Remove(nsIFrame* aKey) } return oldValue; } -#endif //---------------------------------------------------------------------- @@ -244,6 +241,10 @@ public: virtual nsIFrame* GetRootFrame(); NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame); virtual nsIFrame* FindFrameWithContent(nsIContent* aContent); + NS_IMETHOD GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const; + NS_IMETHOD SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame); virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand); virtual void ProcessReflowCommands(); virtual void ClearFrameRefs(nsIFrame*); @@ -288,6 +289,7 @@ protected: nsIFrame* mFocusEventFrame; //keeps track of which frame has focus. nsIFrame* mAnchorEventFrame; //keeps track of which frame has focus. nsISelection *mSelection; + FrameHashTable* mPlaceholderMap; }; #ifdef NS_DEBUG @@ -429,6 +431,7 @@ PresShell::~PresShell() } NS_IF_RELEASE(mSelection); mRefCnt = 0; + delete mPlaceholderMap; } /** @@ -598,7 +601,7 @@ PresShell::InitialReflow(nscoord aWidth, nscoord aHeight) if (nsnull != root) { // Have style sheet processor construct a frame for the // root content object - mStyleSet->ConstructFrame(mPresContext, root, nsnull, mRootFrame); + mStyleSet->ConstructRootFrame(mPresContext, root, mRootFrame); NS_RELEASE(root); } } @@ -1189,6 +1192,38 @@ PresShell::FindFrameWithContent(nsIContent* aContent) return ::FindFrameWithContent(mRootFrame, aContent); } +NS_IMETHODIMP +PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame*& aPlaceholderFrame) const +{ + NS_PRECONDITION(nsnull != aFrame, "no frame"); + + if (nsnull == mPlaceholderMap) { + aPlaceholderFrame = nsnull; + } else { + aPlaceholderFrame = (nsIFrame*)mPlaceholderMap->Get(aFrame); + } + + return NS_OK; +} + +NS_IMETHODIMP +PresShell::SetPlaceholderFrameFor(nsIFrame* aFrame, + nsIFrame* aPlaceholderFrame) +{ + NS_PRECONDITION(nsnull != aFrame, "no frame"); + + if (nsnull == mPlaceholderMap) { + mPlaceholderMap = new FrameHashTable; + if (nsnull == mPlaceholderMap) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + mPlaceholderMap->Put(aFrame, (void*)aPlaceholderFrame); + return NS_OK; +} + //nsIViewObserver NS_IMETHODIMP diff --git a/mozilla/layout/html/base/src/nsScrollFrame.cpp b/mozilla/layout/html/base/src/nsScrollFrame.cpp index 9390799d053..56b897b3817 100644 --- a/mozilla/layout/html/base/src/nsScrollFrame.cpp +++ b/mozilla/layout/html/base/src/nsScrollFrame.cpp @@ -24,7 +24,6 @@ #include "nsViewsCID.h" #include "nsIView.h" #include "nsIViewManager.h" -#include "nsBodyFrame.h" #include "nsHTMLContainerFrame.h" #include "nsHTMLIIDs.h" #include "nsCSSRendering.h" @@ -49,7 +48,8 @@ class nsScrollFrame : public nsHTMLContainerFrame { public: NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext); NS_IMETHOD SetInitialChildList(nsIPresContext& aPresContext, @@ -81,11 +81,13 @@ private: NS_IMETHODIMP nsScrollFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aStyleContext) { nsresult rv = nsHTMLContainerFrame::Init(aPresContext, aContent, - aParent, aStyleContext); + aGeometricParent, aContentParent, + aStyleContext); // Create the scrolling view CreateScrollingView(); diff --git a/mozilla/layout/html/base/src/nsTextFrame.cpp b/mozilla/layout/html/base/src/nsTextFrame.cpp index 1381ee2349a..af2dbe2d329 100644 --- a/mozilla/layout/html/base/src/nsTextFrame.cpp +++ b/mozilla/layout/html/base/src/nsTextFrame.cpp @@ -481,7 +481,7 @@ TextFrame::CreateContinuingFrame(nsIPresContext& aCX, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aCX, mContent, aParent, aStyleContext); + cf->Init(aCX, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); aContinuingFrame = cf; return NS_OK; diff --git a/mozilla/layout/html/document/src/nsFrameFrame.cpp b/mozilla/layout/html/document/src/nsFrameFrame.cpp index 05329047d17..78e66424804 100644 --- a/mozilla/layout/html/document/src/nsFrameFrame.cpp +++ b/mozilla/layout/html/document/src/nsFrameFrame.cpp @@ -321,7 +321,7 @@ nsHTMLFrameOuterFrame::Reflow(nsIPresContext& aPresContext, if (nsnull == mFirstChild) { mFirstChild = new nsHTMLFrameInnerFrame; // XXX temporary! use style system to get correct style! - mFirstChild->Init(aPresContext, mContent, this, mStyleContext); + mFirstChild->Init(aPresContext, mContent, this, this, mStyleContext); } // nsContainerFrame::PaintBorder has some problems, kludge it here diff --git a/mozilla/layout/html/document/src/nsFrameSetFrame.cpp b/mozilla/layout/html/document/src/nsFrameSetFrame.cpp index cdb339719f8..4e600534a23 100644 --- a/mozilla/layout/html/document/src/nsFrameSetFrame.cpp +++ b/mozilla/layout/html/document/src/nsFrameSetFrame.cpp @@ -936,7 +936,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, if (nsHTMLAtoms::frameset == tag) { result = NS_NewHTMLFramesetFrame(frame); - frame->Init(aPresContext, child, this, kidSC); + frame->Init(aPresContext, child, this, this, kidSC); childTypes[mChildCount] = FRAMESET; nsHTMLFramesetFrame* childFrame = (nsHTMLFramesetFrame*)frame; @@ -946,7 +946,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, childBorderColors[mChildCount].Set(childFrame->GetBorderColor()); } else { // frame result = NS_NewHTMLFrameOuterFrame(frame); - frame->Init(aPresContext, child, this, kidSC); + frame->Init(aPresContext, child, this, this, kidSC); childTypes[mChildCount] = FRAME; // @@ -979,7 +979,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, nsHTMLFramesetBlankFrame* blankFrame = new nsHTMLFramesetBlankFrame; nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::framesetBlankPseudo, mStyleContext); - blankFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + blankFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); if (nsnull == lastChild) { @@ -1017,7 +1017,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, borderFrame = new nsHTMLFramesetBorderFrame(borderWidth, PR_FALSE, PR_FALSE); nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::horizontalFramesetBorderPseudo, mStyleContext); - borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + borderFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); mChildCount++; @@ -1042,7 +1042,7 @@ nsHTMLFramesetFrame::Reflow(nsIPresContext& aPresContext, borderFrame = new nsHTMLFramesetBorderFrame(borderWidth, PR_TRUE, PR_FALSE); nsIStyleContext* pseudoStyleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::verticalFramesetBorderPseudo, mStyleContext); - borderFrame->Init(aPresContext, mContent, this, pseudoStyleContext); + borderFrame->Init(aPresContext, mContent, this, this, pseudoStyleContext); NS_RELEASE(pseudoStyleContext); mChildCount++; diff --git a/mozilla/layout/html/document/src/ua.css b/mozilla/layout/html/document/src/ua.css index 05ad1c5f6ca..1b3a8fac742 100644 --- a/mozilla/layout/html/document/src/ua.css +++ b/mozilla/layout/html/document/src/ua.css @@ -500,8 +500,8 @@ NOFRAMES { :SCROLLBAR-LOOK { background-color: #c0c0c0; - //border-color: inherit; - //border: 2px outset #c0c0c0; + /* border-color: inherit; */ + /* border: 2px outset #c0c0c0; */ } :SCROLLBAR-ARROW-LOOK { @@ -526,6 +526,12 @@ NOFRAMES { display: inherit; } +:PLACEHOLDER-FRAME { + display: inline; + width: 0; + height: 0; +} + :ROOT { background-color: inherit; } diff --git a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp index 7d1569b5000..46d9334d9bc 100644 --- a/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFieldSetFrame.cpp @@ -131,7 +131,7 @@ nsFieldSetFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::fieldsetContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); nsIFrame* newChildList = aChildList; diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index 60a8b5befe1..79c38a71d06 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -196,7 +196,7 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, text->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::disabled, nsAutoString("1"), PR_FALSE); // XXX this should use an "empty" bool value } NS_NewTextControlFrame(childFrame); - childFrame->Init(aPresContext, text, this, mStyleContext); + childFrame->Init(aPresContext, text, this, this, mStyleContext); mTextFrame = (nsTextControlFrame*)childFrame; mFirstChild = childFrame; @@ -210,7 +210,7 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, NS_NewButtonControlFrame(childFrame); ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); mBrowseFrame = (nsButtonControlFrame*)childFrame; - childFrame->Init(aPresContext, browse, this, mStyleContext); + childFrame->Init(aPresContext, browse, this, this, mStyleContext); mFirstChild->SetNextSibling(childFrame); diff --git a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp index a6823241d70..64157787f08 100644 --- a/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsHTMLButtonControlFrame.cpp @@ -511,7 +511,7 @@ nsHTMLButtonControlFrame::SetInitialChildList(nsIPresContext& aPresContext, // Resolve style and initialize the frame nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::buttonContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); // Set the geometric and content parent for each of the child frames diff --git a/mozilla/layout/html/forms/src/nsLabelFrame.cpp b/mozilla/layout/html/forms/src/nsLabelFrame.cpp index 27cac158bef..8c8eecd1dcd 100644 --- a/mozilla/layout/html/forms/src/nsLabelFrame.cpp +++ b/mozilla/layout/html/forms/src/nsLabelFrame.cpp @@ -359,7 +359,7 @@ nsLabelFrame::SetInitialChildList(nsIPresContext& aPresContext, // Resolve style and initialize the frame nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::labelContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); // Set the geometric and content parent for each of the child frames diff --git a/mozilla/layout/html/forms/src/nsLegendFrame.cpp b/mozilla/layout/html/forms/src/nsLegendFrame.cpp index 1e15ce38c7c..5ba65b3730d 100644 --- a/mozilla/layout/html/forms/src/nsLegendFrame.cpp +++ b/mozilla/layout/html/forms/src/nsLegendFrame.cpp @@ -95,7 +95,7 @@ nsLegendFrame::SetInitialChildList(nsIPresContext& aPresContext, // Resolve style and initialize the frame nsIStyleContext* styleContext = aPresContext.ResolvePseudoStyleContextFor(mContent, nsHTMLAtoms::legendContentPseudo, mStyleContext); - mFirstChild->Init(aPresContext, mContent, this, styleContext); + mFirstChild->Init(aPresContext, mContent, this, this, styleContext); NS_RELEASE(styleContext); // Set the geometric and content parent for each of the child frames diff --git a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp index 401448b90cb..959f0239f36 100644 --- a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp @@ -44,6 +44,7 @@ #include "nsIWebShell.h" #include "nsHTMLContainerFrame.h" #include "nsINameSpaceManager.h" +#include "nsLayoutAtoms.h" static NS_DEFINE_IID(kIHTMLStyleSheetIID, NS_IHTML_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -207,6 +208,49 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- +// Structure used when constructing formatting object trees. Contains +// state information needed for absolutely positioned elements +struct nsAbsoluteItems { + nsIFrame* const containingBlock; // containing block for absolutely positioned elements + nsIFrame* childList; // list of absolutely positioned child frames + + nsAbsoluteItems(nsIFrame* aContainingBlock); + + // Adds a child frame to the list of absolutely positioned child frames + void AddAbsolutelyPositionedChild(nsIFrame* aChildFrame); +}; + +nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock) + : containingBlock(aContainingBlock) +{ + childList = nsnull; +} + +void +nsAbsoluteItems::AddAbsolutelyPositionedChild(nsIFrame* aChildFrame) +{ +#ifdef NS_DEBUG + nsIFrame* parent; + aChildFrame->GetGeometricParent(parent); + NS_PRECONDITION(parent == containingBlock, "bad geometric parent"); +#endif + + if (nsnull == childList) { + childList = aChildFrame; + } else { + // Get the last frane in the list + nsIFrame* lastChild = nsnull; + + for (nsIFrame* f = childList; nsnull != f; f->GetNextSibling(f)) { + lastChild = f; + } + + lastChild->SetNextSibling(aChildFrame); + } +} + +// ----------------------------------------------------------- + class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, public nsIStyleFrameConstruction { public: @@ -264,10 +308,9 @@ public: NS_IMETHOD UnsetAttributeFor(nsIAtom* aAttribute, nsIHTMLContent* aContent, nsIHTMLAttributes*& aAttributes); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aNewFrame); NS_IMETHODIMP ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, @@ -333,9 +376,11 @@ protected: PRInt32 aAttrCount, nsIHTMLAttributes*& aAttributes); - nsresult ConstructRootFrame(nsIPresContext* aPresContext, - nsIContent* aDocElement, - nsIFrame*& aNewFrame); + nsresult ConstructFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aFrameSubTree); nsresult ConstructDocElementFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, @@ -347,37 +392,49 @@ protected: nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAboluteItems, nsIFrame*& aNewFrame); nsresult ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); + nsresult CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame); + nsresult ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); - nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, - const nsStyleDisplay* aDisplay, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIStyleContext* aStyleContext, - nsIFrame*& aNewFrame); + nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, + const nsStyleDisplay* aDisplay, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aNewFrame); nsresult GetAdjustedParentFrame(nsIFrame* aCurrentParentFrame, PRUint8 aChildDisplayType, nsIFrame*& aNewParentFrame); - nsresult ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList); + nsresult ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList); nsresult CreateInputFrame(nsIContent* aContent, nsIFrame*& aFrame); @@ -386,6 +443,9 @@ protected: nsIFrame* GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresContext, nsIContent* aContent); + nsIFrame* GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame); + protected: PRUint32 mInHeap : 1; PRUint32 mRefCnt : 31; @@ -397,6 +457,7 @@ protected: HTMLAnchorRule* mActiveRule; nsHashtable mAttrTable; nsIHTMLAttributes* mRecycledAttrs; + nsIFrame* mInitialContainingBlock; }; @@ -443,7 +504,8 @@ HTMLStyleSheetImpl::HTMLStyleSheetImpl(void) mLinkRule(nsnull), mVisitedRule(nsnull), mActiveRule(nsnull), - mRecycledAttrs(nsnull) + mRecycledAttrs(nsnull), + mInitialContainingBlock(nsnull) { NS_INIT_REFCNT(); } @@ -931,11 +993,23 @@ NS_IMETHODIMP HTMLStyleSheetImpl::UnsetAttributeFor(nsIAtom* aAttribute, } +/** + * Request to process the child content elements and create frames. + * + * @param aContent the content object whose child elements to process + * @param aFrame the the associated with aContent. This will be the + * parent frame (both content and geometric) for the flowed + * child frames + * @param aState the state information associated with the current process + * @param aChildList an OUT parameter. This is the list of flowed child + * frames that should go in the principal child list + */ nsresult -HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList) +HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList) { // Initialize OUT parameter aChildList = nsnull; @@ -943,6 +1017,7 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, // Iterate the child content objects and construct a frame nsIFrame* lastChildFrame = nsnull; PRInt32 count; + aContent->ChildCount(count); for (PRInt32 i = 0; i < count; i++) { nsIContent* childContent; @@ -952,19 +1027,18 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, nsIFrame* childFrame; // Construct a child frame - ConstructFrame(aPresContext, childContent, aFrame, childFrame); + ConstructFrame(aPresContext, childContent, aFrame, aAbsoluteItems, childFrame); + NS_RELEASE(childContent); if (nsnull != childFrame) { - // Link the frame into the child list - if (nsnull == lastChildFrame) { + // Append the child frame to the list of child frames + if (nsnull == aChildList) { aChildList = childFrame; } else { lastChildFrame->SetNextSibling(childFrame); } lastChildFrame = childFrame; } - - NS_RELEASE(childContent); } } @@ -1024,6 +1098,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsIFrame* childList; @@ -1037,7 +1112,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Init the table outer frame and see if we need to create a view, e.g. // the frame is absolutely positioned - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); @@ -1052,7 +1127,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsHTMLAtoms::tablePseudo, aStyleContext); */ - innerFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + innerFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, aStyleContext); // this should be "innerTableStyleContext" but I haven't tested that thoroughly yet // Iterate the child content @@ -1080,10 +1155,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Have we already created a caption? If so, ignore this caption if (nsnull == captionFrame) { NS_NewAreaFrame(captionFrame, NS_BODY_NO_AUTO_MARGINS); - captionFrame->Init(*aPresContext, childContent, aNewFrame, childStyleContext); + captionFrame->Init(*aPresContext, childContent, aNewFrame, + aNewFrame, childStyleContext); // Process the caption's child content and set the initial child list nsIFrame* captionChildList; - ProcessChildren(aPresContext, captionFrame, childContent, captionChildList); + ProcessChildren(aPresContext, childContent, captionFrame, + aAbsoluteItems, captionChildList); captionFrame->SetInitialChildList(*aPresContext, nsnull, captionChildList); // Prepend the caption frame to the outer frame's child list @@ -1095,7 +1172,8 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: NS_NewTableRowGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, + childStyleContext); break; case NS_STYLE_DISPLAY_TABLE_ROW: @@ -1112,12 +1190,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableRowGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = rowGroupStyleContext; // the row group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, + innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context rowStyleContext = aPresContext->ResolveStyleContextFor(childContent, rowGroupStyleContext); nsIFrame *rowFrame; NS_NewTableRowFrame(rowFrame); - rowFrame->Init(*aPresContext, childContent, frame, rowStyleContext); + rowFrame->Init(*aPresContext, childContent, frame, frame, rowStyleContext); rowFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = rowFrame; break; @@ -1163,12 +1242,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableColGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = colGroupStyleContext; // the col group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context colStyleContext = aPresContext->ResolveStyleContextFor(childContent, colGroupStyleContext); nsIFrame *colFrame; NS_NewTableColFrame(colFrame); - colFrame->Init(*aPresContext, childContent, frame, colStyleContext); + colFrame->Init(*aPresContext, childContent, frame, frame, colStyleContext); colFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = colFrame; break; @@ -1176,7 +1255,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: NS_NewTableColGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); break; default: @@ -1190,14 +1269,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, if (nsnull != frame) { // Process the children, and set the frame's initial child list nsIFrame* childChildList; - if (nsnull==grandChildList) - { - ProcessChildren(aPresContext, frame, childContent, childChildList); + if (nsnull==grandChildList) { + ProcessChildren(aPresContext, childContent, frame, aAbsoluteItems, + childChildList); grandChildList = childChildList; - } - else - { - ProcessChildren(aPresContext, grandChildList, childContent, childChildList); + } else { + ProcessChildren(aPresContext, childContent, grandChildList, + aAbsoluteItems, childChildList); grandChildList->SetInitialChildList(*aPresContext, nsnull, childChildList); } frame->SetInitialChildList(*aPresContext, nsnull, grandChildList); @@ -1229,6 +1307,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsresult rv; @@ -1237,7 +1316,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, rv = NS_NewTableCellFrame(aNewFrame); if (NS_SUCCEEDED(rv)) { // Initialize the table cell frame - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); // Create an area frame that will format the cell's content nsIFrame* cellBodyFrame; @@ -1252,12 +1331,13 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, // Resolve pseudo style and initialize the body cell frame nsIStyleContext* bodyPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::cellContentPseudo, aStyleContext); - cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, bodyPseudoStyle); + cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, bodyPseudoStyle); NS_RELEASE(bodyPseudoStyle); // Process children and set the body cell frame's initial child list nsIFrame* childList; - rv = ProcessChildren(aPresContext, cellBodyFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, cellBodyFrame, aAbsoluteItems, + childList); if (NS_SUCCEEDED(rv)) { cellBodyFrame->SetInitialChildList(*aPresContext, nsnull, childList); } @@ -1286,11 +1366,13 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // the root frame. // XXX We only need the scroll frame if it's print preview... NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootStyleContext); + scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootFrame, + aRootStyleContext); // The page sequence frame needs a view, because it's a scrolled frame NS_NewSimplePageSequenceFrame(pageSequenceFrame); - pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, aRootStyleContext); + pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, scrollFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageSequenceFrame, aRootStyleContext, PR_TRUE); @@ -1301,7 +1383,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // Initialize the page and force it to have a view. This makes printing of // the pages easier and faster. // XXX Use a PAGE style context... - pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, aRootStyleContext); + pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, pageSequenceFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageFrame, aRootStyleContext, PR_TRUE); @@ -1309,20 +1392,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, nsIStyleContext* styleContext; styleContext = aPresContext->ResolveStyleContextFor(aDocElement, aRootStyleContext); - // Create an area frame for the document element. This serves as the - // "initial containing block" + // Create an area frame for the document element nsIFrame* areaFrame; NS_NewAreaFrame(areaFrame, 0); - areaFrame->Init(*aPresContext, aDocElement, pageFrame, styleContext); + areaFrame->Init(*aPresContext, aDocElement, pageFrame, pageFrame, styleContext); NS_RELEASE(styleContext); + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; + // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } pageFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); pageSequenceFrame->SetInitialChildList(*aPresContext, nsnull, pageFrame); scrollFrame->SetInitialChildList(*aPresContext, nsnull, pageSequenceFrame); @@ -1363,7 +1454,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, if (NS_STYLE_OVERFLOW_HIDDEN != scrolling) { NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, styleContext); + scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, aRootFrame, + styleContext); // The scrolled frame gets a pseudo element style context nsIStyleContext* scrolledPseudoStyle = @@ -1381,18 +1473,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // XXX Until we clean up how painting damage is handled, we need to use the // flag that says that this is the body... NS_NewAreaFrame(areaFrame, NS_BODY_THE_BODY); - areaFrame->Init(*aPresContext, aDocElement, scrollFrame ? scrollFrame : - aRootFrame, styleContext); + nsIFrame* parentFrame = scrollFrame ? scrollFrame : aRootFrame; + areaFrame->Init(*aPresContext, aDocElement, parentFrame, parentFrame, + styleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, areaFrame, styleContext, PR_FALSE); NS_RELEASE(styleContext); + + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } if (nsnull != scrollFrame) { scrollFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); } @@ -1403,7 +1505,7 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, return NS_OK; } -nsresult +NS_IMETHODIMP HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, nsIFrame*& aNewFrame) @@ -1431,7 +1533,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsHTMLAtoms::rootPseudo, nsnull); // Initialize the root frame. It has a NULL content object - rootFrame->Init(*aPresContext, nsnull, nsnull, rootPseudoStyle); + rootFrame->Init(*aPresContext, nsnull, nsnull, nsnull, rootPseudoStyle); // Bind the root frame to the root view nsIPresShell* presShell = aPresContext->GetShell(); @@ -1443,7 +1545,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, rootFrame->SetView(rootView); NS_RELEASE(viewManager); - // Create frames for the document element and its child content + // Create frames for the document element and its child elements nsIFrame* docElementFrame; ConstructDocElementFrame(aPresContext, aDocElement, rootFrame, rootPseudoStyle, docElementFrame); @@ -1456,16 +1558,51 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, return NS_OK; } +nsresult +HTMLStyleSheetImpl::CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame) +{ + nsIFrame* placeholderFrame; + nsresult rv; + + rv = NS_NewEmptyFrame(&placeholderFrame); + + if (NS_SUCCEEDED(rv)) { + // The placeholder frame gets a pseudo style context + nsIStyleContext* placeholderPseudoStyle = + aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::placeholderPseudo, aStyleContext); + placeholderFrame->Init(*aPresContext, aContent, aParentFrame, + aParentFrame, placeholderPseudoStyle); + NS_RELEASE(placeholderPseudoStyle); + + // Add mapping from absolutely positioned frame to its placeholder frame + nsIPresShell* presShell = aPresContext->GetShell(); + presShell->SetPlaceholderFrameFor(aFrame, placeholderFrame); + NS_RELEASE(presShell); + + aPlaceholderFrame = placeholderFrame; + } + + return rv; +} + nsresult HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { PRBool processChildren = PR_FALSE; // whether we should process child content nsresult rv = NS_OK; + PRBool isAbsolutelyPositioned = PR_FALSE; // Initialize OUT parameter aNewFrame = nsnull; @@ -1475,8 +1612,18 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else { nsIHTMLContent *htmlContent; + + // Ignore the tag if it's not HTML content rv = aContent->QueryInterface(kIHTMLContentIID, (void **)&htmlContent); if (NS_SUCCEEDED(rv)) { + // See if the element is absolutely positioned + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { + isAbsolutelyPositioned = PR_TRUE; + } + + // Create a frame based on the tag if (nsHTMLAtoms::img == aTag) { rv = NS_NewImageFrame(aNewFrame); } @@ -1511,13 +1658,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::legend == aTag) { rv = NS_NewLegendFrame(aNewFrame); processChildren = PR_TRUE; + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::object == aTag) { rv = NS_NewObjectFrame(aNewFrame); //rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); nsIFrame *blockFrame; NS_NewBlockFrame(blockFrame, 0); - blockFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + blockFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, + aStyleContext); aNewFrame = blockFrame; processChildren = PR_TRUE; } @@ -1526,12 +1675,14 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::iframe == aTag) { rv = NS_NewHTMLFrameOuterFrame(aNewFrame); } else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::button == aTag) { rv = NS_NewHTMLButtonControlFrame(aNewFrame); @@ -1543,16 +1694,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } NS_RELEASE(htmlContent); } - else { - aNewFrame = nsnull; - rv = NS_OK; - } } // If we succeeded in creating a frame then initialize it, process its // children (if requested), and set the initial child list if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + aNewFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); // See if we need to create a view, e.g. the frame is absolutely positioned nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, @@ -1561,11 +1711,27 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, // Process the child content if requested nsIFrame* childList = nsnull; if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); } // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; + } } return rv; @@ -1577,143 +1743,264 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresConte nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { - PRBool processChildren = PR_FALSE; // whether we should process child content - nsIFrame* wrapperFrame = nsnull; - nsresult rv = NS_OK; + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + PRBool isAbsolutelyPositioned = PR_FALSE; + PRBool isBlock = aDisplay->IsBlockLevel(); + nsresult rv = NS_OK; // Initialize OUT parameter aNewFrame = nsnull; - // If the element is floated and it's a block or inline, then we need to - // wrap it in a area frame - if (((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || - (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay)) && - (NS_STYLE_FLOAT_NONE != aDisplay->mFloats)) { - - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - aStyleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, aStyleContext); - aParentFrame = wrapperFrame; - aStyleContext = wrappedPseudoStyle; + // The frame is also a block if it's an inline frame that's floated or + // absolutely positioned + if ((NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) && + ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) || + (NS_STYLE_POSITION_ABSOLUTE == position->mPosition))) { + isBlock = PR_TRUE; } - switch (aDisplay->mDisplay) { - case NS_STYLE_DISPLAY_BLOCK: - case NS_STYLE_DISPLAY_LIST_ITEM: - case NS_STYLE_DISPLAY_RUN_IN: - case NS_STYLE_DISPLAY_COMPACT: - rv = NS_NewBlockFrame(aNewFrame, 0); - processChildren = PR_TRUE; - break; + // If the frame is a block-level frame and is scrollable then wrap it + // in a scroll frame. + // XXX Applies to replaced elements, too, but how to tell if the element + // is replaced? + // XXX Ignore tables for the time being + if ((isBlock && (aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE)) && + IsScrollable(aPresContext, aDisplay)) { - case NS_STYLE_DISPLAY_INLINE: - rv = NS_NewInlineFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if it's absolutely positioned + isAbsolutelyPositioned = NS_STYLE_POSITION_ABSOLUTE == position->mPosition; - case NS_STYLE_DISPLAY_TABLE: - rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; + // Create a scroll frame + nsIFrame* scrollFrame; + NS_NewScrollFrame(scrollFrame); - case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: - case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: - case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: - // XXX We should check for being inside of a table. If there's a missing - // table then create an anonynmous table frame - // XXX: see ConstructTableFrame for a prototype of how this should be done, - // and propagate similar logic to other table elements - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableRowGroupFrame(aNewFrame); - processChildren = PR_TRUE; + // Initialize it + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + scrollFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); + + // The scroll frame gets the original style context, and the scrolled + // frame gets a SCROLLED-CONTENT pseudo element style context that + // inherits the background properties + nsIStyleContext* scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::scrolledContentPseudo, aStyleContext); + + // Create an area container for the frame + nsIFrame* scrolledFrame; + NS_NewAreaFrame(scrolledFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame and force it to have a view + scrolledFrame->Init(*aPresContext, aContent, scrollFrame, scrollFrame, + scrolledPseudoStyle); + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, scrolledFrame, + scrolledPseudoStyle, PR_TRUE); + NS_RELEASE(scrolledPseudoStyle); + + // Process children + if (isAbsolutelyPositioned) { + nsAbsoluteItems absoluteItems(scrolledFrame); + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, absoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + scrolledFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); } + + } else { + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, aAbsoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); } - break; + scrollFrame->SetInitialChildList(*aPresContext, nsnull, scrolledFrame); + aNewFrame = scrollFrame; - case NS_STYLE_DISPLAY_TABLE_COLUMN: - // XXX We should check for being inside of a table column group... - rv = NS_NewTableColFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if the frame is absolutely positioned + } else if ((NS_STYLE_POSITION_ABSOLUTE == position->mPosition) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { - case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: - // XXX We should check for being inside of a table... - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableColGroupFrame(aNewFrame); - processChildren = PR_TRUE; - } - } - break; + isAbsolutelyPositioned = PR_TRUE; - case NS_STYLE_DISPLAY_TABLE_ROW: - // XXX We should check for being inside of a table row group... - rv = NS_NewTableRowFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + aNewFrame->Init(*aPresContext, aContent, aAbsoluteItems.containingBlock, + aParentFrame, aStyleContext); - case NS_STYLE_DISPLAY_TABLE_CELL: - // XXX We should check for being inside of a table row frame... - rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; - - case NS_STYLE_DISPLAY_TABLE_CAPTION: - // XXX We should check for being inside of a table row frame... - rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); - processChildren = PR_TRUE; - break; - - default: - // Don't create any frame for content that's not displayed... - break; - } - - // If we succeeded in creating a frame then initialize the frame, - // process children (if requested), and initialize the frame - if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - - // See if we need to create a view, e.g. the frame is absolutely positioned + // Create a view nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); - // Process the child content if requested - nsIFrame* childList = nsnull; - if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); - } + // Process the child content + nsAbsoluteItems absoluteItems(aNewFrame); + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, absoluteItems, childList); // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + aNewFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } + + // See if the frame is floated, and it's a block or inline frame + } else if ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { + + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, childList); + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + } else { + PRBool processChildren = PR_FALSE; // whether we should process child content + + // Use the 'display' property to chose a frame type + switch (aDisplay->mDisplay) { + case NS_STYLE_DISPLAY_BLOCK: + case NS_STYLE_DISPLAY_LIST_ITEM: + case NS_STYLE_DISPLAY_RUN_IN: + case NS_STYLE_DISPLAY_COMPACT: + rv = NS_NewBlockFrame(aNewFrame, 0); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_INLINE: + rv = NS_NewInlineFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE: + rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, aStyleContext, + aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: + case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: + case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: + // XXX We should check for being inside of a table. If there's a missing + // table then create an anonynmous table frame + // XXX: see ConstructTableFrame for a prototype of how this should be done, + // and propagate similar logic to other table elements + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableRowGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN: + // XXX We should check for being inside of a table column group... + rv = NS_NewTableColFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: + // XXX We should check for being inside of a table... + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableColGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_ROW: + // XXX We should check for being inside of a table row group... + rv = NS_NewTableRowFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_CELL: + // XXX We should check for being inside of a table row frame... + rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, + aStyleContext, aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_CAPTION: + // XXX We should check for being inside of a table row frame... + rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); + processChildren = PR_TRUE; + break; + + default: + // Don't create any frame for content that's not displayed... + break; + } + + // If we succeeded in creating a frame then initialize the frame and + // process children if requested + if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view, e.g. the frame is absolutely positioned + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content if requested + nsIFrame* childList = nsnull; + if (processChildren) { + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); + } + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + } } - // If there's a wrapper frame then set its initial child list, and return the - // wrapper frame as the new frame - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aNewFrame); - aNewFrame = wrapperFrame; + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; } return rv; @@ -1787,177 +2074,69 @@ HTMLStyleSheetImpl::IsScrollable(nsIPresContext* aPresContext, return PR_FALSE; } -NS_IMETHODIMP +nsresult HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aFrameSubTree) { + NS_PRECONDITION(nsnull != aParentFrame, "no parent frame"); + nsresult rv; // Initialize OUT paremeter aFrameSubTree = nsnull; - // See if we're constructing a frame for the document element - if (nsnull == aParentFrame) { - // The root frame has only a single child frame, which is the frame for - // the document element - rv = ConstructRootFrame(aPresContext, aContent, aFrameSubTree); + // Get the element's tag + nsIAtom* tag; + aContent->GetTag(tag); + // Resolve the style context based on the content object and the parent + // style context + nsIStyleContext* styleContext; + nsIStyleContext* parentStyleContext; + + aParentFrame->GetStyleContext(parentStyleContext); + if (nsnull == tag) { + // Use a special pseudo element style context for text + nsIContent* parentContent = nsnull; + if (nsnull != aParentFrame) { + aParentFrame->GetContent(parentContent); + } + styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, + nsHTMLAtoms::textPseudo, + parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + NS_IF_RELEASE(parentContent); } else { - // Get the element's tag - nsIAtom* tag; - aContent->GetTag(tag); - - // Resolve the style context based on the content object and the parent - // style context - nsIStyleContext* styleContext; - nsIStyleContext* parentStyleContext; + styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + NS_IF_RELEASE(parentStyleContext); - aParentFrame->GetStyleContext(parentStyleContext); - if (nsnull == tag) { - // Use a special pseudo element style context for text - nsIContent* parentContent = nsnull; - if (nsnull != aParentFrame) { - aParentFrame->GetContent(parentContent); + if (NS_SUCCEEDED(rv)) { + // Pre-check for display "none" - if we find that, don't create + // any frame at all + const nsStyleDisplay* display = (const nsStyleDisplay*) + styleContext->GetStyleData(eStyleStruct_Display); + + if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { + // Handle specific frame types + rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, tag, + styleContext, aAbsoluteItems, aFrameSubTree); + + if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { + // When there is no explicit frame to create, assume it's a + // container and let display style dictate the rest + rv = ConstructFrameByDisplayType(aPresContext, display, aContent, aParentFrame, + styleContext, aAbsoluteItems, aFrameSubTree); } - styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, - nsHTMLAtoms::textPseudo, - parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; - NS_IF_RELEASE(parentContent); - } else { - styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } - NS_IF_RELEASE(parentStyleContext); - - if (NS_SUCCEEDED(rv)) { - // Pre-check for display "none" - if we find that, don't create - // any frame at all - const nsStyleDisplay* display = (const nsStyleDisplay*) - styleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // If the frame is a block-level frame and is scrollable then wrap it - // in a scroll frame. - // XXX Applies to replaced elements, too, but how to tell if the element - // is replaced? - nsIFrame* scrollFrame = nsnull; - nsIFrame* wrapperFrame = nsnull; - - if ((display->mDisplay!=NS_STYLE_DISPLAY_TABLE) && display->IsBlockLevel() && - IsScrollable(aPresContext, display)) { - - // Create a scroll frame which will wrap the frame that needs to - // be scrolled - if (NS_SUCCEEDED(NS_NewScrollFrame(scrollFrame))) { - nsIStyleContext* scrolledPseudoStyle; - - // The scroll frame gets the original style context, and the scrolled - // frame gets a SCROLLED-CONTENT pseudo element style context that - // inherits the background properties - scrollFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::scrolledContentPseudo, - styleContext); - NS_RELEASE(styleContext); - - // If the content element can contain children then wrap it in a - // area frame - PRBool isContainer; - aContent->CanContainChildren(isContainer); - if (isContainer) { - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - - // Initialize the frame and force it to have a view - wrapperFrame->Init(*aPresContext, aContent, scrollFrame, scrolledPseudoStyle); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - scrolledPseudoStyle, PR_TRUE); - - // The wrapped frame also gets a pseudo style context, but it doesn't - // inherit any background properties. It does inherit the 'display' - // property (it's very important that it does) - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::wrappedFramePseudo, - scrolledPseudoStyle); - NS_RELEASE(scrolledPseudoStyle); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - - } else { - aParentFrame = scrollFrame; - styleContext = scrolledPseudoStyle; - } - } - } - - // See if the element is absolutely positioned - const nsStylePosition* position = (const nsStylePosition*) - styleContext->GetStyleData(eStyleStruct_Position); - - if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { - // If it can contain children then wrap it in an area frame. - // XxX Don't wrap tables, because that causes all sort of problems. - // We need to figure out how to wrap tables... - PRBool isContainer; - aContent->CanContainChildren(isContainer); - - if ((NS_STYLE_DISPLAY_TABLE != display->mDisplay) && isContainer) { - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - styleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, styleContext); - NS_RELEASE(styleContext); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - } - } - - // Handle specific frame types - rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, - tag, styleContext, aFrameSubTree); - - if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { - // When there is no explicit frame to create, assume it's a - // container and let display style dictate the rest - rv = ConstructFrameByDisplayType(aPresContext, display, - aContent, aParentFrame, - styleContext, aFrameSubTree); - } - - // If there's a scroll frame or a wrapper frame then set their initial - // child lists, and return that frame as the frame sub-tree. - // Because SetInitialChildList() is called bottom-up we need to wait - // until after we've created the frame sub-tree - if (nsnull != scrollFrame) { - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - scrollFrame->SetInitialChildList(*aPresContext, nsnull, wrapperFrame); - } else { - scrollFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - } - aFrameSubTree = scrollFrame; - - } else if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - aFrameSubTree = wrapperFrame; - } - } - NS_RELEASE(styleContext); - } - - NS_IF_RELEASE(tag); + NS_RELEASE(styleContext); } + NS_IF_RELEASE(tag); return rv; } @@ -2044,6 +2223,47 @@ HTMLStyleSheetImpl::GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresC return frame; } +nsIFrame* +HTMLStyleSheetImpl::GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + // For the time being just return the initial containing block + NS_PRECONDITION(nsnull != mInitialContainingBlock, "no initial containing block"); + return mInitialContainingBlock; + + // XXX TROY +#if 0 + // Look for a containing frame that is absolutely positioned. If we don't + // find one then use the initial containg block which is the BODY + nsIFrame* lastFrame = (nsIFrame*)this; + nsIFrame* result; + + GetContentParent(result); + while (nsnull != result) { + const nsStylePosition* position; + + // Get the style data + result->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if (position->mPosition == NS_STYLE_POSITION_ABSOLUTE) { + // XXX This needs cleaning up... + // Make sure the frame supports the nsIAbsoluteItems interface. If not, + // walk the geometric parent hierarchy and find the nearest one that does... + nsIAbsoluteItems* interface; + while ((nsnull != result) && + NS_FAILED(result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface))) { + result->GetGeometricParent(result); + } + break; + } + + // Get the next contentual parent + lastFrame = result; + result->GetContentParent(result); + } +#endif +} + NS_IMETHODIMP HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -2067,10 +2287,15 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, } } + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + // Create some new frames - PRInt32 count; - nsIFrame* lastChildFrame = nsnull; - nsIFrame* firstAppendedFrame = nsnull; + PRInt32 count; + nsIFrame* lastChildFrame = nsnull; + nsIFrame* firstAppendedFrame = nsnull; + nsAbsoluteItems absoluteItems(absoluteContainingBlock); aContainer->ChildCount(count); @@ -2079,7 +2304,7 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIFrame* frame; aContainer->ChildAt(i, child); - ConstructFrame(aPresContext, child, parentFrame, frame); + ConstructFrame(aPresContext, child, parentFrame, absoluteItems, frame); if (nsnull != frame) { // Link the frame into the child frame list @@ -2116,6 +2341,21 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + result = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(result)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } @@ -2230,8 +2470,13 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Construct a new frame nsresult rv = NS_OK; if (nsnull != parentFrame) { - nsIFrame* newFrame; - rv = ConstructFrame(aPresContext, aChild, parentFrame, newFrame); + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + + nsAbsoluteItems absoluteItems(absoluteContainingBlock); + nsIFrame* newFrame; + rv = ConstructFrame(aPresContext, aChild, parentFrame, absoluteItems, newFrame); if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { nsIReflowCommand* reflowCmd = nsnull; @@ -2245,11 +2490,25 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Generate a FrameInserted reflow command rv = NS_NewHTMLReflowCommand(&reflowCmd, parentFrame, newFrame, prevSibling); } - if (NS_SUCCEEDED(rv)) { shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + rv = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } diff --git a/mozilla/layout/html/table/src/nsTableCellFrame.cpp b/mozilla/layout/html/table/src/nsTableCellFrame.cpp index 9b09c6ef01e..1e1f15cc96c 100644 --- a/mozilla/layout/html/table/src/nsTableCellFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableCellFrame.cpp @@ -561,7 +561,7 @@ nsTableCellFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); cf->InitCellFrame(GetColIndex()); aContinuingFrame = cf; diff --git a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp index caebe072336..2145f65fe95 100644 --- a/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableColGroupFrame.cpp @@ -90,7 +90,7 @@ nsTableColGroupFrame::InitNewFrames(nsIPresContext& aPresContext, nsIFrame* aChi // Set its style context nsIStyleContextPtr colStyleContext = aPresContext.ResolveStyleContextFor(col, mStyleContext, PR_TRUE); - colFrame->Init(aPresContext, col, this, colStyleContext); + colFrame->Init(aPresContext, col, this, this, colStyleContext); colFrame->SetInitialChildList(aPresContext, nsnull, nsnull); // Set nsColFrame-specific information diff --git a/mozilla/layout/html/table/src/nsTableFrame.cpp b/mozilla/layout/html/table/src/nsTableFrame.cpp index 8a53cab1817..ba930aa1fe5 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableFrame.cpp @@ -290,7 +290,8 @@ nsTableFrame::nsTableFrame() NS_IMETHODIMP nsTableFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) { float p2t = aPresContext.GetPixelsToTwips(); @@ -298,7 +299,8 @@ nsTableFrame::Init(nsIPresContext& aPresContext, mDefaultCellSpacingY = NSIntPixelsToTwips(2, p2t); mDefaultCellPadding = NSIntPixelsToTwips(1, p2t); - return nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext); + return nsHTMLContainerFrame::Init(aPresContext, aContent, aGeometricParent, + aContentParent, aContext); } @@ -726,7 +728,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext) // Create a col group frame nsIFrame* newFrame; NS_NewTableColGroupFrame(newFrame); - newFrame->Init(aPresContext, lastColGroupElement, this, colGroupStyleContext); + newFrame->Init(aPresContext, lastColGroupElement, this, this, colGroupStyleContext); lastColGroupFrame = (nsTableColGroupFrame*)newFrame; NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT-- @@ -758,7 +760,8 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext) lastColGroupStyle, PR_TRUE); // colStyleContext: REFCNT++ NS_NewTableColFrame(colFrame); - colFrame->Init(aPresContext, lastColGroupElement, lastColGroupFrame, colStyleContext); + colFrame->Init(aPresContext, lastColGroupElement, lastColGroupFrame, + lastColGroupFrame, colStyleContext); NS_RELEASE(colStyleContext); colFrame->SetInitialChildList(aPresContext, nsnull, nsnull); @@ -4197,7 +4200,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); // set my width, because all frames in a table flow are the same width @@ -4229,7 +4232,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext& aPresContext, nsIFrame* duplicateFrame; NS_NewTableRowGroupFrame(duplicateFrame); - duplicateFrame->Init(aPresContext, content, cf, kidStyleContext); + duplicateFrame->Init(aPresContext, content, cf, cf, kidStyleContext); NS_RELEASE(kidStyleContext); // kidStyleContenxt: REFCNT-- if (nsnull==lastSib) diff --git a/mozilla/layout/html/table/src/nsTableFrame.h b/mozilla/layout/html/table/src/nsTableFrame.h index 6b1b896d771..dc09f7409af 100644 --- a/mozilla/layout/html/table/src/nsTableFrame.h +++ b/mozilla/layout/html/table/src/nsTableFrame.h @@ -80,7 +80,8 @@ public: NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext); diff --git a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp index 6107eaceea9..de81ab095ce 100644 --- a/mozilla/layout/html/table/src/nsTableOuterFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableOuterFrame.cpp @@ -17,7 +17,6 @@ */ #include "nsTableOuterFrame.h" #include "nsTableFrame.h" -#include "nsBodyFrame.h" #include "nsIReflowCommand.h" #include "nsIStyleContext.h" #include "nsStyleConsts.h" @@ -1142,7 +1141,7 @@ nsTableOuterFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableOuterFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); diff --git a/mozilla/layout/html/table/src/nsTableRowFrame.cpp b/mozilla/layout/html/table/src/nsTableRowFrame.cpp index f9d6d5cc2da..27a40ce48cc 100644 --- a/mozilla/layout/html/table/src/nsTableRowFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowFrame.cpp @@ -1439,7 +1439,7 @@ nsTableRowFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); cf->SetRowIndex(GetRowIndex()); diff --git a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp index 09422224024..6008e5f3c1a 100644 --- a/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/html/table/src/nsTableRowGroupFrame.cpp @@ -1399,7 +1399,7 @@ nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); aContinuingFrame = cf; diff --git a/mozilla/layout/style/nsHTMLStyleSheet.cpp b/mozilla/layout/style/nsHTMLStyleSheet.cpp index 401448b90cb..959f0239f36 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLStyleSheet.cpp @@ -44,6 +44,7 @@ #include "nsIWebShell.h" #include "nsHTMLContainerFrame.h" #include "nsINameSpaceManager.h" +#include "nsLayoutAtoms.h" static NS_DEFINE_IID(kIHTMLStyleSheetIID, NS_IHTML_STYLE_SHEET_IID); static NS_DEFINE_IID(kIStyleSheetIID, NS_ISTYLE_SHEET_IID); @@ -207,6 +208,49 @@ nsHashKey* AttributeKey::Clone(void) const // ----------------------------------------------------------- +// Structure used when constructing formatting object trees. Contains +// state information needed for absolutely positioned elements +struct nsAbsoluteItems { + nsIFrame* const containingBlock; // containing block for absolutely positioned elements + nsIFrame* childList; // list of absolutely positioned child frames + + nsAbsoluteItems(nsIFrame* aContainingBlock); + + // Adds a child frame to the list of absolutely positioned child frames + void AddAbsolutelyPositionedChild(nsIFrame* aChildFrame); +}; + +nsAbsoluteItems::nsAbsoluteItems(nsIFrame* aContainingBlock) + : containingBlock(aContainingBlock) +{ + childList = nsnull; +} + +void +nsAbsoluteItems::AddAbsolutelyPositionedChild(nsIFrame* aChildFrame) +{ +#ifdef NS_DEBUG + nsIFrame* parent; + aChildFrame->GetGeometricParent(parent); + NS_PRECONDITION(parent == containingBlock, "bad geometric parent"); +#endif + + if (nsnull == childList) { + childList = aChildFrame; + } else { + // Get the last frane in the list + nsIFrame* lastChild = nsnull; + + for (nsIFrame* f = childList; nsnull != f; f->GetNextSibling(f)) { + lastChild = f; + } + + lastChild->SetNextSibling(aChildFrame); + } +} + +// ----------------------------------------------------------- + class HTMLStyleSheetImpl : public nsIHTMLStyleSheet, public nsIStyleFrameConstruction { public: @@ -264,10 +308,9 @@ public: NS_IMETHOD UnsetAttributeFor(nsIAtom* aAttribute, nsIHTMLContent* aContent, nsIHTMLAttributes*& aAttributes); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aNewFrame); NS_IMETHODIMP ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, @@ -333,9 +376,11 @@ protected: PRInt32 aAttrCount, nsIHTMLAttributes*& aAttributes); - nsresult ConstructRootFrame(nsIPresContext* aPresContext, - nsIContent* aDocElement, - nsIFrame*& aNewFrame); + nsresult ConstructFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aFrameSubTree); nsresult ConstructDocElementFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, @@ -347,37 +392,49 @@ protected: nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAboluteItems, nsIFrame*& aNewFrame); nsresult ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); + nsresult CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame); + nsresult ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame); - nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, - const nsStyleDisplay* aDisplay, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIStyleContext* aStyleContext, - nsIFrame*& aNewFrame); + nsresult ConstructFrameByDisplayType(nsIPresContext* aPresContext, + const nsStyleDisplay* aDisplay, + nsIContent* aContent, + nsIFrame* aParentFrame, + nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aNewFrame); nsresult GetAdjustedParentFrame(nsIFrame* aCurrentParentFrame, PRUint8 aChildDisplayType, nsIFrame*& aNewParentFrame); - nsresult ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList); + nsresult ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList); nsresult CreateInputFrame(nsIContent* aContent, nsIFrame*& aFrame); @@ -386,6 +443,9 @@ protected: nsIFrame* GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresContext, nsIContent* aContent); + nsIFrame* GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame); + protected: PRUint32 mInHeap : 1; PRUint32 mRefCnt : 31; @@ -397,6 +457,7 @@ protected: HTMLAnchorRule* mActiveRule; nsHashtable mAttrTable; nsIHTMLAttributes* mRecycledAttrs; + nsIFrame* mInitialContainingBlock; }; @@ -443,7 +504,8 @@ HTMLStyleSheetImpl::HTMLStyleSheetImpl(void) mLinkRule(nsnull), mVisitedRule(nsnull), mActiveRule(nsnull), - mRecycledAttrs(nsnull) + mRecycledAttrs(nsnull), + mInitialContainingBlock(nsnull) { NS_INIT_REFCNT(); } @@ -931,11 +993,23 @@ NS_IMETHODIMP HTMLStyleSheetImpl::UnsetAttributeFor(nsIAtom* aAttribute, } +/** + * Request to process the child content elements and create frames. + * + * @param aContent the content object whose child elements to process + * @param aFrame the the associated with aContent. This will be the + * parent frame (both content and geometric) for the flowed + * child frames + * @param aState the state information associated with the current process + * @param aChildList an OUT parameter. This is the list of flowed child + * frames that should go in the principal child list + */ nsresult -HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, - nsIFrame* aFrame, - nsIContent* aContent, - nsIFrame*& aChildList) +HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsAbsoluteItems& aAbsoluteItems, + nsIFrame*& aChildList) { // Initialize OUT parameter aChildList = nsnull; @@ -943,6 +1017,7 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, // Iterate the child content objects and construct a frame nsIFrame* lastChildFrame = nsnull; PRInt32 count; + aContent->ChildCount(count); for (PRInt32 i = 0; i < count; i++) { nsIContent* childContent; @@ -952,19 +1027,18 @@ HTMLStyleSheetImpl::ProcessChildren(nsIPresContext* aPresContext, nsIFrame* childFrame; // Construct a child frame - ConstructFrame(aPresContext, childContent, aFrame, childFrame); + ConstructFrame(aPresContext, childContent, aFrame, aAbsoluteItems, childFrame); + NS_RELEASE(childContent); if (nsnull != childFrame) { - // Link the frame into the child list - if (nsnull == lastChildFrame) { + // Append the child frame to the list of child frames + if (nsnull == aChildList) { aChildList = childFrame; } else { lastChildFrame->SetNextSibling(childFrame); } lastChildFrame = childFrame; } - - NS_RELEASE(childContent); } } @@ -1024,6 +1098,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsIFrame* childList; @@ -1037,7 +1112,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Init the table outer frame and see if we need to create a view, e.g. // the frame is absolutely positioned - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); @@ -1052,7 +1127,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, nsHTMLAtoms::tablePseudo, aStyleContext); */ - innerFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + innerFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, aStyleContext); // this should be "innerTableStyleContext" but I haven't tested that thoroughly yet // Iterate the child content @@ -1080,10 +1155,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, // Have we already created a caption? If so, ignore this caption if (nsnull == captionFrame) { NS_NewAreaFrame(captionFrame, NS_BODY_NO_AUTO_MARGINS); - captionFrame->Init(*aPresContext, childContent, aNewFrame, childStyleContext); + captionFrame->Init(*aPresContext, childContent, aNewFrame, + aNewFrame, childStyleContext); // Process the caption's child content and set the initial child list nsIFrame* captionChildList; - ProcessChildren(aPresContext, captionFrame, childContent, captionChildList); + ProcessChildren(aPresContext, childContent, captionFrame, + aAbsoluteItems, captionChildList); captionFrame->SetInitialChildList(*aPresContext, nsnull, captionChildList); // Prepend the caption frame to the outer frame's child list @@ -1095,7 +1172,8 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: NS_NewTableRowGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, + childStyleContext); break; case NS_STYLE_DISPLAY_TABLE_ROW: @@ -1112,12 +1190,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableRowGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = rowGroupStyleContext; // the row group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, + innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context rowStyleContext = aPresContext->ResolveStyleContextFor(childContent, rowGroupStyleContext); nsIFrame *rowFrame; NS_NewTableRowFrame(rowFrame); - rowFrame->Init(*aPresContext, childContent, frame, rowStyleContext); + rowFrame->Init(*aPresContext, childContent, frame, frame, rowStyleContext); rowFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = rowFrame; break; @@ -1163,12 +1242,12 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, NS_NewTableColGroupFrame(frame); NS_RELEASE(childStyleContext); // we can't use this resolved style, so get rid of it childStyleContext = colGroupStyleContext; // the col group style context will get set to childStyleContext after the switch ends. - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); // need to resolve the style context for the column again to be sure it's a child of the colgroup style context colStyleContext = aPresContext->ResolveStyleContextFor(childContent, colGroupStyleContext); nsIFrame *colFrame; NS_NewTableColFrame(colFrame); - colFrame->Init(*aPresContext, childContent, frame, colStyleContext); + colFrame->Init(*aPresContext, childContent, frame, frame, colStyleContext); colFrame->SetInitialChildList(*aPresContext, nsnull, nsnull); grandChildList = colFrame; break; @@ -1176,7 +1255,7 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: NS_NewTableColGroupFrame(frame); - frame->Init(*aPresContext, childContent, innerFrame, childStyleContext); + frame->Init(*aPresContext, childContent, innerFrame, innerFrame, childStyleContext); break; default: @@ -1190,14 +1269,13 @@ HTMLStyleSheetImpl::ConstructTableFrame(nsIPresContext* aPresContext, if (nsnull != frame) { // Process the children, and set the frame's initial child list nsIFrame* childChildList; - if (nsnull==grandChildList) - { - ProcessChildren(aPresContext, frame, childContent, childChildList); + if (nsnull==grandChildList) { + ProcessChildren(aPresContext, childContent, frame, aAbsoluteItems, + childChildList); grandChildList = childChildList; - } - else - { - ProcessChildren(aPresContext, grandChildList, childContent, childChildList); + } else { + ProcessChildren(aPresContext, childContent, grandChildList, + aAbsoluteItems, childChildList); grandChildList->SetInitialChildList(*aPresContext, nsnull, childChildList); } frame->SetInitialChildList(*aPresContext, nsnull, grandChildList); @@ -1229,6 +1307,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { nsresult rv; @@ -1237,7 +1316,7 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, rv = NS_NewTableCellFrame(aNewFrame); if (NS_SUCCEEDED(rv)) { // Initialize the table cell frame - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, aStyleContext); // Create an area frame that will format the cell's content nsIFrame* cellBodyFrame; @@ -1252,12 +1331,13 @@ HTMLStyleSheetImpl::ConstructTableCellFrame(nsIPresContext* aPresContext, // Resolve pseudo style and initialize the body cell frame nsIStyleContext* bodyPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, nsHTMLAtoms::cellContentPseudo, aStyleContext); - cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, bodyPseudoStyle); + cellBodyFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, bodyPseudoStyle); NS_RELEASE(bodyPseudoStyle); // Process children and set the body cell frame's initial child list nsIFrame* childList; - rv = ProcessChildren(aPresContext, cellBodyFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, cellBodyFrame, aAbsoluteItems, + childList); if (NS_SUCCEEDED(rv)) { cellBodyFrame->SetInitialChildList(*aPresContext, nsnull, childList); } @@ -1286,11 +1366,13 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // the root frame. // XXX We only need the scroll frame if it's print preview... NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootStyleContext); + scrollFrame->Init(*aPresContext, nsnull, aRootFrame, aRootFrame, + aRootStyleContext); // The page sequence frame needs a view, because it's a scrolled frame NS_NewSimplePageSequenceFrame(pageSequenceFrame); - pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, aRootStyleContext); + pageSequenceFrame->Init(*aPresContext, nsnull, scrollFrame, scrollFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageSequenceFrame, aRootStyleContext, PR_TRUE); @@ -1301,7 +1383,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // Initialize the page and force it to have a view. This makes printing of // the pages easier and faster. // XXX Use a PAGE style context... - pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, aRootStyleContext); + pageFrame->Init(*aPresContext, nsnull, pageSequenceFrame, pageSequenceFrame, + aRootStyleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, pageFrame, aRootStyleContext, PR_TRUE); @@ -1309,20 +1392,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, nsIStyleContext* styleContext; styleContext = aPresContext->ResolveStyleContextFor(aDocElement, aRootStyleContext); - // Create an area frame for the document element. This serves as the - // "initial containing block" + // Create an area frame for the document element nsIFrame* areaFrame; NS_NewAreaFrame(areaFrame, 0); - areaFrame->Init(*aPresContext, aDocElement, pageFrame, styleContext); + areaFrame->Init(*aPresContext, aDocElement, pageFrame, pageFrame, styleContext); NS_RELEASE(styleContext); + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; + // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } pageFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); pageSequenceFrame->SetInitialChildList(*aPresContext, nsnull, pageFrame); scrollFrame->SetInitialChildList(*aPresContext, nsnull, pageSequenceFrame); @@ -1363,7 +1454,8 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, if (NS_STYLE_OVERFLOW_HIDDEN != scrolling) { NS_NewScrollFrame(scrollFrame); - scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, styleContext); + scrollFrame->Init(*aPresContext, aDocElement, aRootFrame, aRootFrame, + styleContext); // The scrolled frame gets a pseudo element style context nsIStyleContext* scrolledPseudoStyle = @@ -1381,18 +1473,28 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, // XXX Until we clean up how painting damage is handled, we need to use the // flag that says that this is the body... NS_NewAreaFrame(areaFrame, NS_BODY_THE_BODY); - areaFrame->Init(*aPresContext, aDocElement, scrollFrame ? scrollFrame : - aRootFrame, styleContext); + nsIFrame* parentFrame = scrollFrame ? scrollFrame : aRootFrame; + areaFrame->Init(*aPresContext, aDocElement, parentFrame, parentFrame, + styleContext); nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, areaFrame, styleContext, PR_FALSE); NS_RELEASE(styleContext); + + // The area frame is the "initial containing block" + mInitialContainingBlock = areaFrame; // Process the child content - nsIFrame* childList = nsnull; - ProcessChildren(aPresContext, areaFrame, aDocElement, childList); + nsAbsoluteItems absoluteItems(areaFrame); + nsIFrame* childList; + + ProcessChildren(aPresContext, aDocElement, areaFrame, absoluteItems, childList); // Set the initial child lists areaFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + areaFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } if (nsnull != scrollFrame) { scrollFrame->SetInitialChildList(*aPresContext, nsnull, areaFrame); } @@ -1403,7 +1505,7 @@ HTMLStyleSheetImpl::ConstructDocElementFrame(nsIPresContext* aPresContext, return NS_OK; } -nsresult +NS_IMETHODIMP HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsIContent* aDocElement, nsIFrame*& aNewFrame) @@ -1431,7 +1533,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, nsHTMLAtoms::rootPseudo, nsnull); // Initialize the root frame. It has a NULL content object - rootFrame->Init(*aPresContext, nsnull, nsnull, rootPseudoStyle); + rootFrame->Init(*aPresContext, nsnull, nsnull, nsnull, rootPseudoStyle); // Bind the root frame to the root view nsIPresShell* presShell = aPresContext->GetShell(); @@ -1443,7 +1545,7 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, rootFrame->SetView(rootView); NS_RELEASE(viewManager); - // Create frames for the document element and its child content + // Create frames for the document element and its child elements nsIFrame* docElementFrame; ConstructDocElementFrame(aPresContext, aDocElement, rootFrame, rootPseudoStyle, docElementFrame); @@ -1456,16 +1558,51 @@ HTMLStyleSheetImpl::ConstructRootFrame(nsIPresContext* aPresContext, return NS_OK; } +nsresult +HTMLStyleSheetImpl::CreatePlaceholderFrameFor(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aFrame, + nsIStyleContext* aStyleContext, + nsIFrame* aParentFrame, + nsIFrame*& aPlaceholderFrame) +{ + nsIFrame* placeholderFrame; + nsresult rv; + + rv = NS_NewEmptyFrame(&placeholderFrame); + + if (NS_SUCCEEDED(rv)) { + // The placeholder frame gets a pseudo style context + nsIStyleContext* placeholderPseudoStyle = + aPresContext->ResolvePseudoStyleContextFor(aContent, + nsHTMLAtoms::placeholderPseudo, aStyleContext); + placeholderFrame->Init(*aPresContext, aContent, aParentFrame, + aParentFrame, placeholderPseudoStyle); + NS_RELEASE(placeholderPseudoStyle); + + // Add mapping from absolutely positioned frame to its placeholder frame + nsIPresShell* presShell = aPresContext->GetShell(); + presShell->SetPlaceholderFrameFor(aFrame, placeholderFrame); + NS_RELEASE(presShell); + + aPlaceholderFrame = placeholderFrame; + } + + return rv; +} + nsresult HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, nsIAtom* aTag, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { PRBool processChildren = PR_FALSE; // whether we should process child content nsresult rv = NS_OK; + PRBool isAbsolutelyPositioned = PR_FALSE; // Initialize OUT parameter aNewFrame = nsnull; @@ -1475,8 +1612,18 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else { nsIHTMLContent *htmlContent; + + // Ignore the tag if it's not HTML content rv = aContent->QueryInterface(kIHTMLContentIID, (void **)&htmlContent); if (NS_SUCCEEDED(rv)) { + // See if the element is absolutely positioned + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { + isAbsolutelyPositioned = PR_TRUE; + } + + // Create a frame based on the tag if (nsHTMLAtoms::img == aTag) { rv = NS_NewImageFrame(aNewFrame); } @@ -1511,13 +1658,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, else if (nsHTMLAtoms::legend == aTag) { rv = NS_NewLegendFrame(aNewFrame); processChildren = PR_TRUE; + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::object == aTag) { rv = NS_NewObjectFrame(aNewFrame); //rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); nsIFrame *blockFrame; NS_NewBlockFrame(blockFrame, 0); - blockFrame->Init(*aPresContext, aContent, aNewFrame, aStyleContext); + blockFrame->Init(*aPresContext, aContent, aNewFrame, aNewFrame, + aStyleContext); aNewFrame = blockFrame; processChildren = PR_TRUE; } @@ -1526,12 +1675,14 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::iframe == aTag) { rv = NS_NewHTMLFrameOuterFrame(aNewFrame); } else if (nsHTMLAtoms::spacer == aTag) { rv = NS_NewSpacerFrame(aNewFrame); + isAbsolutelyPositioned = PR_FALSE; // don't absolutely position } else if (nsHTMLAtoms::button == aTag) { rv = NS_NewHTMLButtonControlFrame(aNewFrame); @@ -1543,16 +1694,15 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, } NS_RELEASE(htmlContent); } - else { - aNewFrame = nsnull; - rv = NS_OK; - } } // If we succeeded in creating a frame then initialize it, process its // children (if requested), and set the initial child list if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + aNewFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); // See if we need to create a view, e.g. the frame is absolutely positioned nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, @@ -1561,11 +1711,27 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, // Process the child content if requested nsIFrame* childList = nsnull; if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); } // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; + } } return rv; @@ -1577,143 +1743,264 @@ HTMLStyleSheetImpl::ConstructFrameByDisplayType(nsIPresContext* aPresConte nsIContent* aContent, nsIFrame* aParentFrame, nsIStyleContext* aStyleContext, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aNewFrame) { - PRBool processChildren = PR_FALSE; // whether we should process child content - nsIFrame* wrapperFrame = nsnull; - nsresult rv = NS_OK; + const nsStylePosition* position = (const nsStylePosition*) + aStyleContext->GetStyleData(eStyleStruct_Position); + PRBool isAbsolutelyPositioned = PR_FALSE; + PRBool isBlock = aDisplay->IsBlockLevel(); + nsresult rv = NS_OK; // Initialize OUT parameter aNewFrame = nsnull; - // If the element is floated and it's a block or inline, then we need to - // wrap it in a area frame - if (((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || - (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay)) && - (NS_STYLE_FLOAT_NONE != aDisplay->mFloats)) { - - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - aStyleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, aStyleContext); - aParentFrame = wrapperFrame; - aStyleContext = wrappedPseudoStyle; + // The frame is also a block if it's an inline frame that's floated or + // absolutely positioned + if ((NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) && + ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) || + (NS_STYLE_POSITION_ABSOLUTE == position->mPosition))) { + isBlock = PR_TRUE; } - switch (aDisplay->mDisplay) { - case NS_STYLE_DISPLAY_BLOCK: - case NS_STYLE_DISPLAY_LIST_ITEM: - case NS_STYLE_DISPLAY_RUN_IN: - case NS_STYLE_DISPLAY_COMPACT: - rv = NS_NewBlockFrame(aNewFrame, 0); - processChildren = PR_TRUE; - break; + // If the frame is a block-level frame and is scrollable then wrap it + // in a scroll frame. + // XXX Applies to replaced elements, too, but how to tell if the element + // is replaced? + // XXX Ignore tables for the time being + if ((isBlock && (aDisplay->mDisplay != NS_STYLE_DISPLAY_TABLE)) && + IsScrollable(aPresContext, aDisplay)) { - case NS_STYLE_DISPLAY_INLINE: - rv = NS_NewInlineFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if it's absolutely positioned + isAbsolutelyPositioned = NS_STYLE_POSITION_ABSOLUTE == position->mPosition; - case NS_STYLE_DISPLAY_TABLE: - rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; + // Create a scroll frame + nsIFrame* scrollFrame; + NS_NewScrollFrame(scrollFrame); - case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: - case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: - case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: - // XXX We should check for being inside of a table. If there's a missing - // table then create an anonynmous table frame - // XXX: see ConstructTableFrame for a prototype of how this should be done, - // and propagate similar logic to other table elements - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableRowGroupFrame(aNewFrame); - processChildren = PR_TRUE; + // Initialize it + nsIFrame* geometricParent = isAbsolutelyPositioned ? aAbsoluteItems.containingBlock : + aParentFrame; + scrollFrame->Init(*aPresContext, aContent, geometricParent, aParentFrame, + aStyleContext); + + // The scroll frame gets the original style context, and the scrolled + // frame gets a SCROLLED-CONTENT pseudo element style context that + // inherits the background properties + nsIStyleContext* scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor + (aContent, nsHTMLAtoms::scrolledContentPseudo, aStyleContext); + + // Create an area container for the frame + nsIFrame* scrolledFrame; + NS_NewAreaFrame(scrolledFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame and force it to have a view + scrolledFrame->Init(*aPresContext, aContent, scrollFrame, scrollFrame, + scrolledPseudoStyle); + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, scrolledFrame, + scrolledPseudoStyle, PR_TRUE); + NS_RELEASE(scrolledPseudoStyle); + + // Process children + if (isAbsolutelyPositioned) { + nsAbsoluteItems absoluteItems(scrolledFrame); + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, absoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + scrolledFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); } + + } else { + nsIFrame* childList; + ProcessChildren(aPresContext, aContent, scrolledFrame, aAbsoluteItems, + childList); + + // Set the initial child lists + scrolledFrame->SetInitialChildList(*aPresContext, nsnull, childList); } - break; + scrollFrame->SetInitialChildList(*aPresContext, nsnull, scrolledFrame); + aNewFrame = scrollFrame; - case NS_STYLE_DISPLAY_TABLE_COLUMN: - // XXX We should check for being inside of a table column group... - rv = NS_NewTableColFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // See if the frame is absolutely positioned + } else if ((NS_STYLE_POSITION_ABSOLUTE == position->mPosition) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { - case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: - // XXX We should check for being inside of a table... - { - nsIFrame *parentFrame; - rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); - if (NS_SUCCEEDED(rv)) - { - rv = NS_NewTableColGroupFrame(aNewFrame); - processChildren = PR_TRUE; - } - } - break; + isAbsolutelyPositioned = PR_TRUE; - case NS_STYLE_DISPLAY_TABLE_ROW: - // XXX We should check for being inside of a table row group... - rv = NS_NewTableRowFrame(aNewFrame); - processChildren = PR_TRUE; - break; + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + aNewFrame->Init(*aPresContext, aContent, aAbsoluteItems.containingBlock, + aParentFrame, aStyleContext); - case NS_STYLE_DISPLAY_TABLE_CELL: - // XXX We should check for being inside of a table row frame... - rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, - aStyleContext, aNewFrame); - // Note: table construction function takes care of initializing the frame, - // processing children, and setting the initial child list - return rv; - - case NS_STYLE_DISPLAY_TABLE_CAPTION: - // XXX We should check for being inside of a table row frame... - rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); - processChildren = PR_TRUE; - break; - - default: - // Don't create any frame for content that's not displayed... - break; - } - - // If we succeeded in creating a frame then initialize the frame, - // process children (if requested), and initialize the frame - if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { - aNewFrame->Init(*aPresContext, aContent, aParentFrame, aStyleContext); - - // See if we need to create a view, e.g. the frame is absolutely positioned + // Create a view nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, aStyleContext, PR_FALSE); - // Process the child content if requested - nsIFrame* childList = nsnull; - if (processChildren) { - rv = ProcessChildren(aPresContext, aNewFrame, aContent, childList); - } + // Process the child content + nsAbsoluteItems absoluteItems(aNewFrame); + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, absoluteItems, childList); // Set the frame's initial child list aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + if (nsnull != absoluteItems.childList) { + aNewFrame->SetInitialChildList(*aPresContext, nsLayoutAtoms::absoluteList, + absoluteItems.childList); + } + + // See if the frame is floated, and it's a block or inline frame + } else if ((NS_STYLE_FLOAT_NONE != aDisplay->mFloats) && + ((NS_STYLE_DISPLAY_BLOCK == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_INLINE == aDisplay->mDisplay) || + (NS_STYLE_DISPLAY_LIST_ITEM == aDisplay->mDisplay))) { + + // Create an area frame + NS_NewAreaFrame(aNewFrame, NS_BODY_SHRINK_WRAP); + + // Initialize the frame + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content + nsIFrame* childList = nsnull; + ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, childList); + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + + } else { + PRBool processChildren = PR_FALSE; // whether we should process child content + + // Use the 'display' property to chose a frame type + switch (aDisplay->mDisplay) { + case NS_STYLE_DISPLAY_BLOCK: + case NS_STYLE_DISPLAY_LIST_ITEM: + case NS_STYLE_DISPLAY_RUN_IN: + case NS_STYLE_DISPLAY_COMPACT: + rv = NS_NewBlockFrame(aNewFrame, 0); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_INLINE: + rv = NS_NewInlineFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE: + rv = ConstructTableFrame(aPresContext, aContent, aParentFrame, aStyleContext, + aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_ROW_GROUP: + case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP: + case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP: + // XXX We should check for being inside of a table. If there's a missing + // table then create an anonynmous table frame + // XXX: see ConstructTableFrame for a prototype of how this should be done, + // and propagate similar logic to other table elements + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableRowGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN: + // XXX We should check for being inside of a table column group... + rv = NS_NewTableColFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP: + // XXX We should check for being inside of a table... + { + nsIFrame *parentFrame; + rv = GetAdjustedParentFrame(aParentFrame, aDisplay->mDisplay, parentFrame); + if (NS_SUCCEEDED(rv)) + { + rv = NS_NewTableColGroupFrame(aNewFrame); + processChildren = PR_TRUE; + } + } + break; + + case NS_STYLE_DISPLAY_TABLE_ROW: + // XXX We should check for being inside of a table row group... + rv = NS_NewTableRowFrame(aNewFrame); + processChildren = PR_TRUE; + break; + + case NS_STYLE_DISPLAY_TABLE_CELL: + // XXX We should check for being inside of a table row frame... + rv = ConstructTableCellFrame(aPresContext, aContent, aParentFrame, + aStyleContext, aAbsoluteItems, aNewFrame); + // Note: table construction function takes care of initializing the frame, + // processing children, and setting the initial child list + return rv; + + case NS_STYLE_DISPLAY_TABLE_CAPTION: + // XXX We should check for being inside of a table row frame... + rv = NS_NewAreaFrame(aNewFrame, NS_BODY_NO_AUTO_MARGINS); + processChildren = PR_TRUE; + break; + + default: + // Don't create any frame for content that's not displayed... + break; + } + + // If we succeeded in creating a frame then initialize the frame and + // process children if requested + if (NS_SUCCEEDED(rv) && (nsnull != aNewFrame)) { + aNewFrame->Init(*aPresContext, aContent, aParentFrame, aParentFrame, + aStyleContext); + + // See if we need to create a view, e.g. the frame is absolutely positioned + nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, aNewFrame, + aStyleContext, PR_FALSE); + + // Process the child content if requested + nsIFrame* childList = nsnull; + if (processChildren) { + rv = ProcessChildren(aPresContext, aContent, aNewFrame, aAbsoluteItems, + childList); + } + + // Set the frame's initial child list + aNewFrame->SetInitialChildList(*aPresContext, nsnull, childList); + } } - // If there's a wrapper frame then set its initial child list, and return the - // wrapper frame as the new frame - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aNewFrame); - aNewFrame = wrapperFrame; + // If the frame is absolutely positioned then create a placeholder frame + if (isAbsolutelyPositioned) { + nsIFrame* placeholderFrame; + + CreatePlaceholderFrameFor(aPresContext, aContent, aNewFrame, aStyleContext, + aParentFrame, placeholderFrame); + + // Add the absolutely positioned frame to its containing block's list + // of child frames + aAbsoluteItems.AddAbsolutelyPositionedChild(aNewFrame); + + // Add the placeholder frame to the flow + aNewFrame = placeholderFrame; } return rv; @@ -1787,177 +2074,69 @@ HTMLStyleSheetImpl::IsScrollable(nsIPresContext* aPresContext, return PR_FALSE; } -NS_IMETHODIMP +nsresult HTMLStyleSheetImpl::ConstructFrame(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, + nsAbsoluteItems& aAbsoluteItems, nsIFrame*& aFrameSubTree) { + NS_PRECONDITION(nsnull != aParentFrame, "no parent frame"); + nsresult rv; // Initialize OUT paremeter aFrameSubTree = nsnull; - // See if we're constructing a frame for the document element - if (nsnull == aParentFrame) { - // The root frame has only a single child frame, which is the frame for - // the document element - rv = ConstructRootFrame(aPresContext, aContent, aFrameSubTree); + // Get the element's tag + nsIAtom* tag; + aContent->GetTag(tag); + // Resolve the style context based on the content object and the parent + // style context + nsIStyleContext* styleContext; + nsIStyleContext* parentStyleContext; + + aParentFrame->GetStyleContext(parentStyleContext); + if (nsnull == tag) { + // Use a special pseudo element style context for text + nsIContent* parentContent = nsnull; + if (nsnull != aParentFrame) { + aParentFrame->GetContent(parentContent); + } + styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, + nsHTMLAtoms::textPseudo, + parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + NS_IF_RELEASE(parentContent); } else { - // Get the element's tag - nsIAtom* tag; - aContent->GetTag(tag); - - // Resolve the style context based on the content object and the parent - // style context - nsIStyleContext* styleContext; - nsIStyleContext* parentStyleContext; + styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); + rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + NS_IF_RELEASE(parentStyleContext); - aParentFrame->GetStyleContext(parentStyleContext); - if (nsnull == tag) { - // Use a special pseudo element style context for text - nsIContent* parentContent = nsnull; - if (nsnull != aParentFrame) { - aParentFrame->GetContent(parentContent); + if (NS_SUCCEEDED(rv)) { + // Pre-check for display "none" - if we find that, don't create + // any frame at all + const nsStyleDisplay* display = (const nsStyleDisplay*) + styleContext->GetStyleData(eStyleStruct_Display); + + if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { + // Handle specific frame types + rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, tag, + styleContext, aAbsoluteItems, aFrameSubTree); + + if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { + // When there is no explicit frame to create, assume it's a + // container and let display style dictate the rest + rv = ConstructFrameByDisplayType(aPresContext, display, aContent, aParentFrame, + styleContext, aAbsoluteItems, aFrameSubTree); } - styleContext = aPresContext->ResolvePseudoStyleContextFor(parentContent, - nsHTMLAtoms::textPseudo, - parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; - NS_IF_RELEASE(parentContent); - } else { - styleContext = aPresContext->ResolveStyleContextFor(aContent, parentStyleContext); - rv = (nsnull == styleContext) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } - NS_IF_RELEASE(parentStyleContext); - - if (NS_SUCCEEDED(rv)) { - // Pre-check for display "none" - if we find that, don't create - // any frame at all - const nsStyleDisplay* display = (const nsStyleDisplay*) - styleContext->GetStyleData(eStyleStruct_Display); - - if (NS_STYLE_DISPLAY_NONE != display->mDisplay) { - // If the frame is a block-level frame and is scrollable then wrap it - // in a scroll frame. - // XXX Applies to replaced elements, too, but how to tell if the element - // is replaced? - nsIFrame* scrollFrame = nsnull; - nsIFrame* wrapperFrame = nsnull; - - if ((display->mDisplay!=NS_STYLE_DISPLAY_TABLE) && display->IsBlockLevel() && - IsScrollable(aPresContext, display)) { - - // Create a scroll frame which will wrap the frame that needs to - // be scrolled - if (NS_SUCCEEDED(NS_NewScrollFrame(scrollFrame))) { - nsIStyleContext* scrolledPseudoStyle; - - // The scroll frame gets the original style context, and the scrolled - // frame gets a SCROLLED-CONTENT pseudo element style context that - // inherits the background properties - scrollFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - scrolledPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::scrolledContentPseudo, - styleContext); - NS_RELEASE(styleContext); - - // If the content element can contain children then wrap it in a - // area frame - PRBool isContainer; - aContent->CanContainChildren(isContainer); - if (isContainer) { - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - - // Initialize the frame and force it to have a view - wrapperFrame->Init(*aPresContext, aContent, scrollFrame, scrolledPseudoStyle); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - scrolledPseudoStyle, PR_TRUE); - - // The wrapped frame also gets a pseudo style context, but it doesn't - // inherit any background properties. It does inherit the 'display' - // property (it's very important that it does) - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor - (aContent, nsHTMLAtoms::wrappedFramePseudo, - scrolledPseudoStyle); - NS_RELEASE(scrolledPseudoStyle); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - - } else { - aParentFrame = scrollFrame; - styleContext = scrolledPseudoStyle; - } - } - } - - // See if the element is absolutely positioned - const nsStylePosition* position = (const nsStylePosition*) - styleContext->GetStyleData(eStyleStruct_Position); - - if (NS_STYLE_POSITION_ABSOLUTE == position->mPosition) { - // If it can contain children then wrap it in an area frame. - // XxX Don't wrap tables, because that causes all sort of problems. - // We need to figure out how to wrap tables... - PRBool isContainer; - aContent->CanContainChildren(isContainer); - - if ((NS_STYLE_DISPLAY_TABLE != display->mDisplay) && isContainer) { - // The area wrapper frame gets the original style context - NS_NewAreaFrame(wrapperFrame, NS_BODY_SHRINK_WRAP); - wrapperFrame->Init(*aPresContext, aContent, aParentFrame, styleContext); - nsHTMLContainerFrame::CreateViewForFrame(*aPresContext, wrapperFrame, - styleContext, PR_FALSE); - - // The wrapped frame gets a pseudo style context that inherits the - // display property - nsIStyleContext* wrappedPseudoStyle; - wrappedPseudoStyle = aPresContext->ResolvePseudoStyleContextFor(aContent, - nsHTMLAtoms::wrappedFramePseudo, styleContext); - NS_RELEASE(styleContext); - aParentFrame = wrapperFrame; - styleContext = wrappedPseudoStyle; - } - } - - // Handle specific frame types - rv = ConstructFrameByTag(aPresContext, aContent, aParentFrame, - tag, styleContext, aFrameSubTree); - - if (NS_SUCCEEDED(rv) && (nsnull == aFrameSubTree)) { - // When there is no explicit frame to create, assume it's a - // container and let display style dictate the rest - rv = ConstructFrameByDisplayType(aPresContext, display, - aContent, aParentFrame, - styleContext, aFrameSubTree); - } - - // If there's a scroll frame or a wrapper frame then set their initial - // child lists, and return that frame as the frame sub-tree. - // Because SetInitialChildList() is called bottom-up we need to wait - // until after we've created the frame sub-tree - if (nsnull != scrollFrame) { - if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - scrollFrame->SetInitialChildList(*aPresContext, nsnull, wrapperFrame); - } else { - scrollFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - } - aFrameSubTree = scrollFrame; - - } else if (nsnull != wrapperFrame) { - wrapperFrame->SetInitialChildList(*aPresContext, nsnull, aFrameSubTree); - aFrameSubTree = wrapperFrame; - } - } - NS_RELEASE(styleContext); - } - - NS_IF_RELEASE(tag); + NS_RELEASE(styleContext); } + NS_IF_RELEASE(tag); return rv; } @@ -2044,6 +2223,47 @@ HTMLStyleSheetImpl::GetFrameFor(nsIPresShell* aPresShell, nsIPresContext* aPresC return frame; } +nsIFrame* +HTMLStyleSheetImpl::GetAbsoluteContainingBlock(nsIPresContext* aPresContext, + nsIFrame* aFrame) +{ + // For the time being just return the initial containing block + NS_PRECONDITION(nsnull != mInitialContainingBlock, "no initial containing block"); + return mInitialContainingBlock; + + // XXX TROY +#if 0 + // Look for a containing frame that is absolutely positioned. If we don't + // find one then use the initial containg block which is the BODY + nsIFrame* lastFrame = (nsIFrame*)this; + nsIFrame* result; + + GetContentParent(result); + while (nsnull != result) { + const nsStylePosition* position; + + // Get the style data + result->GetStyleData(eStyleStruct_Position, (const nsStyleStruct*&)position); + + if (position->mPosition == NS_STYLE_POSITION_ABSOLUTE) { + // XXX This needs cleaning up... + // Make sure the frame supports the nsIAbsoluteItems interface. If not, + // walk the geometric parent hierarchy and find the nearest one that does... + nsIAbsoluteItems* interface; + while ((nsnull != result) && + NS_FAILED(result->QueryInterface(kIAbsoluteItemsIID, (void**)&interface))) { + result->GetGeometricParent(result); + } + break; + } + + // Get the next contentual parent + lastFrame = result; + result->GetContentParent(result); + } +#endif +} + NS_IMETHODIMP HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIContent* aContainer, @@ -2067,10 +2287,15 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, } } + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + // Create some new frames - PRInt32 count; - nsIFrame* lastChildFrame = nsnull; - nsIFrame* firstAppendedFrame = nsnull; + PRInt32 count; + nsIFrame* lastChildFrame = nsnull; + nsIFrame* firstAppendedFrame = nsnull; + nsAbsoluteItems absoluteItems(absoluteContainingBlock); aContainer->ChildCount(count); @@ -2079,7 +2304,7 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, nsIFrame* frame; aContainer->ChildAt(i, child); - ConstructFrame(aPresContext, child, parentFrame, frame); + ConstructFrame(aPresContext, child, parentFrame, absoluteItems, frame); if (nsnull != frame) { // Link the frame into the child frame list @@ -2116,6 +2341,21 @@ HTMLStyleSheetImpl::ContentAppended(nsIPresContext* aPresContext, shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + result = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(result)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } @@ -2230,8 +2470,13 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Construct a new frame nsresult rv = NS_OK; if (nsnull != parentFrame) { - nsIFrame* newFrame; - rv = ConstructFrame(aPresContext, aChild, parentFrame, newFrame); + // Get the containing block for absolutely positioned elements + nsIFrame* absoluteContainingBlock = GetAbsoluteContainingBlock(aPresContext, + parentFrame); + + nsAbsoluteItems absoluteItems(absoluteContainingBlock); + nsIFrame* newFrame; + rv = ConstructFrame(aPresContext, aChild, parentFrame, absoluteItems, newFrame); if (NS_SUCCEEDED(rv) && (nsnull != newFrame)) { nsIReflowCommand* reflowCmd = nsnull; @@ -2245,11 +2490,25 @@ HTMLStyleSheetImpl::ContentInserted(nsIPresContext* aPresContext, // Generate a FrameInserted reflow command rv = NS_NewHTMLReflowCommand(&reflowCmd, parentFrame, newFrame, prevSibling); } - if (NS_SUCCEEDED(rv)) { shell->AppendReflowCommand(reflowCmd); NS_RELEASE(reflowCmd); } + + // If there are new absolutely positioned child frames then send a reflow + // command for them, too. + // XXX We can't just assume these frames are being appended, we need to + // determine where in the list they should be inserted... + if (nsnull != absoluteItems.childList) { + rv = NS_NewHTMLReflowCommand(&reflowCmd, absoluteItems.containingBlock, + nsIReflowCommand::FrameAppended, + absoluteItems.childList); + if (NS_SUCCEEDED(rv)) { + reflowCmd->SetChildListName(nsLayoutAtoms::absoluteList); + shell->AppendReflowCommand(reflowCmd); + NS_RELEASE(reflowCmd); + } + } } } diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index 43ff46eb27b..f3c60299131 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -88,10 +88,9 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); - NS_IMETHOD ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree); + NS_IMETHOD ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame*& aFrameSubTree); NS_IMETHOD ReconstructFrames(nsIPresContext* aPresContext, nsIContent* aContent, nsIFrame* aParentFrame, @@ -716,13 +715,12 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } -NS_IMETHODIMP StyleSetImpl::ConstructFrame(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParentFrame, - nsIFrame*& aFrameSubTree) +NS_IMETHODIMP StyleSetImpl::ConstructRootFrame(nsIPresContext* aPresContext, + nsIContent* aDocElement, + nsIFrame*& aFrameSubTree) { - return mFrameConstructor->ConstructFrame(aPresContext, aContent, - aParentFrame, aFrameSubTree); + return mFrameConstructor->ConstructRootFrame(aPresContext, aDocElement, + aFrameSubTree); } NS_IMETHODIMP diff --git a/mozilla/layout/style/ua.css b/mozilla/layout/style/ua.css index 05ad1c5f6ca..1b3a8fac742 100644 --- a/mozilla/layout/style/ua.css +++ b/mozilla/layout/style/ua.css @@ -500,8 +500,8 @@ NOFRAMES { :SCROLLBAR-LOOK { background-color: #c0c0c0; - //border-color: inherit; - //border: 2px outset #c0c0c0; + /* border-color: inherit; */ + /* border: 2px outset #c0c0c0; */ } :SCROLLBAR-ARROW-LOOK { @@ -526,6 +526,12 @@ NOFRAMES { display: inherit; } +:PLACEHOLDER-FRAME { + display: inline; + width: 0; + height: 0; +} + :ROOT { background-color: inherit; } diff --git a/mozilla/layout/tables/nsTableCellFrame.cpp b/mozilla/layout/tables/nsTableCellFrame.cpp index 9b09c6ef01e..1e1f15cc96c 100644 --- a/mozilla/layout/tables/nsTableCellFrame.cpp +++ b/mozilla/layout/tables/nsTableCellFrame.cpp @@ -561,7 +561,7 @@ nsTableCellFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); cf->InitCellFrame(GetColIndex()); aContinuingFrame = cf; diff --git a/mozilla/layout/tables/nsTableColGroupFrame.cpp b/mozilla/layout/tables/nsTableColGroupFrame.cpp index caebe072336..2145f65fe95 100644 --- a/mozilla/layout/tables/nsTableColGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableColGroupFrame.cpp @@ -90,7 +90,7 @@ nsTableColGroupFrame::InitNewFrames(nsIPresContext& aPresContext, nsIFrame* aChi // Set its style context nsIStyleContextPtr colStyleContext = aPresContext.ResolveStyleContextFor(col, mStyleContext, PR_TRUE); - colFrame->Init(aPresContext, col, this, colStyleContext); + colFrame->Init(aPresContext, col, this, this, colStyleContext); colFrame->SetInitialChildList(aPresContext, nsnull, nsnull); // Set nsColFrame-specific information diff --git a/mozilla/layout/tables/nsTableFrame.cpp b/mozilla/layout/tables/nsTableFrame.cpp index 8a53cab1817..ba930aa1fe5 100644 --- a/mozilla/layout/tables/nsTableFrame.cpp +++ b/mozilla/layout/tables/nsTableFrame.cpp @@ -290,7 +290,8 @@ nsTableFrame::nsTableFrame() NS_IMETHODIMP nsTableFrame::Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext) { float p2t = aPresContext.GetPixelsToTwips(); @@ -298,7 +299,8 @@ nsTableFrame::Init(nsIPresContext& aPresContext, mDefaultCellSpacingY = NSIntPixelsToTwips(2, p2t); mDefaultCellPadding = NSIntPixelsToTwips(1, p2t); - return nsHTMLContainerFrame::Init(aPresContext, aContent, aParent, aContext); + return nsHTMLContainerFrame::Init(aPresContext, aContent, aGeometricParent, + aContentParent, aContext); } @@ -726,7 +728,7 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext) // Create a col group frame nsIFrame* newFrame; NS_NewTableColGroupFrame(newFrame); - newFrame->Init(aPresContext, lastColGroupElement, this, colGroupStyleContext); + newFrame->Init(aPresContext, lastColGroupElement, this, this, colGroupStyleContext); lastColGroupFrame = (nsTableColGroupFrame*)newFrame; NS_RELEASE(colGroupStyleContext); // kidStyleContenxt: REFCNT-- @@ -758,7 +760,8 @@ void nsTableFrame::EnsureColumns(nsIPresContext& aPresContext) lastColGroupStyle, PR_TRUE); // colStyleContext: REFCNT++ NS_NewTableColFrame(colFrame); - colFrame->Init(aPresContext, lastColGroupElement, lastColGroupFrame, colStyleContext); + colFrame->Init(aPresContext, lastColGroupElement, lastColGroupFrame, + lastColGroupFrame, colStyleContext); NS_RELEASE(colStyleContext); colFrame->SetInitialChildList(aPresContext, nsnull, nsnull); @@ -4197,7 +4200,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); // set my width, because all frames in a table flow are the same width @@ -4229,7 +4232,7 @@ nsTableFrame::CreateContinuingFrame(nsIPresContext& aPresContext, nsIFrame* duplicateFrame; NS_NewTableRowGroupFrame(duplicateFrame); - duplicateFrame->Init(aPresContext, content, cf, kidStyleContext); + duplicateFrame->Init(aPresContext, content, cf, cf, kidStyleContext); NS_RELEASE(kidStyleContext); // kidStyleContenxt: REFCNT-- if (nsnull==lastSib) diff --git a/mozilla/layout/tables/nsTableFrame.h b/mozilla/layout/tables/nsTableFrame.h index 6b1b896d771..dc09f7409af 100644 --- a/mozilla/layout/tables/nsTableFrame.h +++ b/mozilla/layout/tables/nsTableFrame.h @@ -80,7 +80,8 @@ public: NS_IMETHOD Init(nsIPresContext& aPresContext, nsIContent* aContent, - nsIFrame* aParent, + nsIFrame* aGeometricParent, + nsIFrame* aContentParent, nsIStyleContext* aContext); diff --git a/mozilla/layout/tables/nsTableOuterFrame.cpp b/mozilla/layout/tables/nsTableOuterFrame.cpp index 6107eaceea9..de81ab095ce 100644 --- a/mozilla/layout/tables/nsTableOuterFrame.cpp +++ b/mozilla/layout/tables/nsTableOuterFrame.cpp @@ -17,7 +17,6 @@ */ #include "nsTableOuterFrame.h" #include "nsTableFrame.h" -#include "nsBodyFrame.h" #include "nsIReflowCommand.h" #include "nsIStyleContext.h" #include "nsStyleConsts.h" @@ -1142,7 +1141,7 @@ nsTableOuterFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableOuterFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); diff --git a/mozilla/layout/tables/nsTableRowFrame.cpp b/mozilla/layout/tables/nsTableRowFrame.cpp index f9d6d5cc2da..27a40ce48cc 100644 --- a/mozilla/layout/tables/nsTableRowFrame.cpp +++ b/mozilla/layout/tables/nsTableRowFrame.cpp @@ -1439,7 +1439,7 @@ nsTableRowFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); cf->SetRowIndex(GetRowIndex()); diff --git a/mozilla/layout/tables/nsTableRowGroupFrame.cpp b/mozilla/layout/tables/nsTableRowGroupFrame.cpp index 09422224024..6008e5f3c1a 100644 --- a/mozilla/layout/tables/nsTableRowGroupFrame.cpp +++ b/mozilla/layout/tables/nsTableRowGroupFrame.cpp @@ -1399,7 +1399,7 @@ nsTableRowGroupFrame::CreateContinuingFrame(nsIPresContext& aPresContext, if (nsnull == cf) { return NS_ERROR_OUT_OF_MEMORY; } - cf->Init(aPresContext, mContent, aParent, aStyleContext); + cf->Init(aPresContext, mContent, aParent, mContentParent, aStyleContext); cf->AppendToFlow(this); if (PR_TRUE==gsDebug) printf("nsTableRowGroupFrame::CCF parent = %p, this=%p, cf=%p\n", aParent, this, cf); aContinuingFrame = cf;