diff --git a/mozilla/layout/generic/nsBlockFrame.h b/mozilla/layout/generic/nsBlockFrame.h index 1eb55559f10..fb1860645a7 100644 --- a/mozilla/layout/generic/nsBlockFrame.h +++ b/mozilla/layout/generic/nsBlockFrame.h @@ -387,8 +387,8 @@ protected: * contains aPrevSibling and add aFrameList after aPrevSibling on that line. * new lines are created as necessary to handle block data in aFrameList. */ - nsresult AddFrames(nsIFrame* aFrameList, - nsIFrame* aPrevSibling); + virtual nsresult AddFrames(nsIFrame* aFrameList, + nsIFrame* aPrevSibling); #ifdef IBMBIDI /** diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index 91db6b46c92..f3570400267 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -1028,6 +1028,14 @@ nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder* aBuilder, } } +nsresult +nsContainerFrame::AddFrames(nsIFrame* aFrameList, + nsIFrame* aPrevSibling) +{ + mFrames.InsertFrames(nsnull, aPrevSibling, aFrameList); + return NS_OK; +} + nsresult nsContainerFrame::StealFrame(nsPresContext* aPresContext, nsIFrame* aChild, diff --git a/mozilla/layout/generic/nsContainerFrame.h b/mozilla/layout/generic/nsContainerFrame.h index a259cea3f32..8f21ca79685 100644 --- a/mozilla/layout/generic/nsContainerFrame.h +++ b/mozilla/layout/generic/nsContainerFrame.h @@ -272,6 +272,13 @@ public: PRUint32 aFlags, nsReflowStatus& aStatus); + /** + * Inserts aFrameList's frames into our main child list--without reparenting + * or requesting reflow. + */ + virtual nsresult AddFrames(nsIFrame* aFrameList, + nsIFrame* aPrevSibling); + /** * Removes aChild without destroying it and without requesting reflow. * Continuations are not affected. Checks the primary and overflow diff --git a/mozilla/layout/generic/nsPageContentFrame.cpp b/mozilla/layout/generic/nsPageContentFrame.cpp index d90c7a38d80..657ad4c60f3 100644 --- a/mozilla/layout/generic/nsPageContentFrame.cpp +++ b/mozilla/layout/generic/nsPageContentFrame.cpp @@ -36,6 +36,7 @@ * ***** END LICENSE BLOCK ***** */ #include "nsPageContentFrame.h" #include "nsPageFrame.h" +#include "nsPlaceholderFrame.h" #include "nsCSSFrameConstructor.h" #include "nsHTMLContainerFrame.h" #include "nsHTMLParts.h" @@ -68,6 +69,55 @@ nsPageContentFrame::ComputeSize(nsIRenderingContext *aRenderingContext, return nsSize(aAvailableWidth, height); } +/** + * Returns true if aFrame is a placeholder for one of our fixed frames. + */ +inline PRBool +nsPageContentFrame::IsFixedPlaceholder(nsIFrame* aFrame) +{ + if (!aFrame || nsGkAtoms::placeholderFrame != aFrame->GetType()) + return PR_FALSE; + + return static_cast(aFrame)->GetOutOfFlowFrame() + ->GetParent() == this; +} + +/** + * Steals replicated fixed placeholder frames from aDocRoot so they don't + * get in the way of reflow. + */ +inline nsFrameList +nsPageContentFrame::StealFixedPlaceholders(nsIFrame* aDocRoot) +{ + nsPresContext* presContext = PresContext(); + nsFrameList list; + if (GetPrevInFlow()) { + for (nsIFrame* f = aDocRoot->GetFirstChild(nsnull); + IsFixedPlaceholder(f); f = aDocRoot->GetFirstChild(nsnull)) { + nsresult rv = static_cast(aDocRoot) + ->StealFrame(presContext, f); + NS_ENSURE_SUCCESS(rv, list); + list.AppendFrame(nsnull, f); + } + } + return list; +} + +/** + * Restores stolen replicated fixed placeholder frames to aDocRoot. + */ +static inline nsresult +ReplaceFixedPlaceholders(nsIFrame* aDocRoot, + nsFrameList& aPlaceholderList) +{ + nsresult rv = NS_OK; + if (aPlaceholderList.NotEmpty()) { + rv = static_cast(aDocRoot) + ->AddFrames(aPlaceholderList.FirstChild(), nsnull); + } + return rv; +} + NS_IMETHODIMP nsPageContentFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -77,6 +127,7 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aStatus = NS_FRAME_COMPLETE; // initialize out parameter + nsresult rv = NS_OK; // A PageContentFrame must always have one child: the doc root element's frame. // We only need to get overflow frames if we don't already have that child; @@ -107,8 +158,16 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, mPD->mPageContentSize = aReflowState.availableWidth; - // Reflow the page content area to get the child's desired size - ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); + // Get replicated fixed frames' placeholders out of the way + nsFrameList stolenPlaceholders = StealFixedPlaceholders(frame); + + // Reflow the page content area + rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); + NS_ENSURE_SUCCESS(rv, rv); + + // Put removed fixed placeholders back + rv = ReplaceFixedPlaceholders(frame, stolenPlaceholders); + NS_ENSURE_SUCCESS(rv, rv); if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) { nsIFrame* nextFrame = frame->GetNextInFlow(); diff --git a/mozilla/layout/generic/nsPageContentFrame.h b/mozilla/layout/generic/nsPageContentFrame.h index 7306dfef31d..994c32d5949 100644 --- a/mozilla/layout/generic/nsPageContentFrame.h +++ b/mozilla/layout/generic/nsPageContentFrame.h @@ -87,6 +87,10 @@ protected: nsPageContentFrame(nsStyleContext* aContext) : ViewportFrame(aContext) {} nsSharedPageData* mPD; + +private: + PRBool IsFixedPlaceholder(nsIFrame* aFrame); + nsFrameList StealFixedPlaceholders(nsIFrame* aDocRoot); }; #endif /* nsPageContentFrame_h___ */ diff --git a/mozilla/layout/reftests/bugs/417676-ref.html b/mozilla/layout/reftests/bugs/417676-ref.html new file mode 100644 index 00000000000..44b2643aaec --- /dev/null +++ b/mozilla/layout/reftests/bugs/417676-ref.html @@ -0,0 +1,18 @@ + + +Fixed Positioning Test + + +
+This box must be repeated at this same position on the first, second, and third pages. +
+ +
+This box must be repeated at this same position on the first, second, and third pages. +
+ +
+This box must be repeated at this same position on the first, second, and third pages. +
diff --git a/mozilla/layout/reftests/bugs/417676.html b/mozilla/layout/reftests/bugs/417676.html new file mode 100644 index 00000000000..75a85cd80f5 --- /dev/null +++ b/mozilla/layout/reftests/bugs/417676.html @@ -0,0 +1,9 @@ + + +Fixed Positioning Test + +
+This box must be repeated at this same position on the first, second, and third pages. +
+ +

\ No newline at end of file diff --git a/mozilla/layout/reftests/bugs/reftest.list b/mozilla/layout/reftests/bugs/reftest.list index ae8ed3d3dcf..2485551eaa4 100644 --- a/mozilla/layout/reftests/bugs/reftest.list +++ b/mozilla/layout/reftests/bugs/reftest.list @@ -732,3 +732,4 @@ random == 403134-1.html 403134-1-ref.html # bug 405377 == 414123.xhtml 414123-ref.xhtml == 414851-1.html 414851-1-ref.html == 416106-1.xhtml 416106-1-ref.xhtml +== 417676.html 417676-ref.html