From 66cb01800e0cb4433ddea1f5cd7d39af06740a0c Mon Sep 17 00:00:00 2001 From: "fantasai.cvs%inkedblade.net" Date: Tue, 7 Aug 2007 16:06:57 +0000 Subject: [PATCH] =?UTF-8?q?Bug=20389767=20=EF=BF=BD=EF=BF=BD=EF=BF=BD=20Re?= =?UTF-8?q?gression:=20Fixed-position=20items=20are=20missing=20on=202nd?= =?UTF-8?q?=20page=20of=20print-preview,=20fixed=20on=20behalf=20of=20HP,?= =?UTF-8?q?=20r+sr=3Dbzbarsky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- layout/base/nsCSSFrameConstructor.cpp | 75 ++++++++++----------------- layout/base/nsCSSFrameConstructor.h | 4 ++ layout/generic/nsPageContentFrame.cpp | 15 ++++-- 3 files changed, 44 insertions(+), 50 deletions(-) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index e2dcd7dd4e1..c9942135738 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -4649,8 +4649,6 @@ nsCSSFrameConstructor::ConstructPageFrame(nsIPresShell* aPresShell, aPageFrame->SetInitialChildList(nsnull, aPageContentFrame); - // Fixed pos kids are taken care of directly in CreateContinuingFrame() - return NS_OK; } @@ -10605,75 +10603,58 @@ nsCSSFrameConstructor::CreateContinuingFrame(nsPresContext* aPresContext, if (aFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) { newFrame->AddStateBits(NS_FRAME_GENERATED_CONTENT); } - + + if (nextInFlow) { + nextInFlow->SetPrevInFlow(newFrame); + newFrame->SetNextInFlow(nextInFlow); + } else if (nextContinuation) { + nextContinuation->SetPrevContinuation(newFrame); + newFrame->SetNextContinuation(nextContinuation); + } + return NS_OK; +} + +nsresult +nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame) +{ // Now deal with fixed-pos things.... They should appear on all pages, and // the placeholders must be kids of a block, so we want to move over the // placeholders when processing the child of the pageContentFrame. - if (!aParentFrame) { - return NS_OK; - } - - if (aParentFrame->GetType() != nsGkAtoms::pageContentFrame) { - if (nextInFlow) { - nextInFlow->SetPrevInFlow(newFrame); - newFrame->SetNextInFlow(nextInFlow); - } else if (nextContinuation) { - nextContinuation->SetPrevContinuation(newFrame); - newFrame->SetNextContinuation(nextContinuation); - } - return NS_OK; - } - - // Our parent is a page content frame. Look up its page frame and - // see whether it has a prev-in-flow. - nsIFrame* pageFrame = aParentFrame->GetParent(); - if (!pageFrame) { - NS_ERROR("pageContentFrame does not have parent!"); - newFrame->Destroy(); - *aContinuingFrame = nsnull; - return NS_ERROR_UNEXPECTED; - } - - nsIFrame* prevPage = pageFrame->GetPrevInFlow(); - if (!prevPage) { - return NS_OK; - } - - // OK. now we need to do this fixed-pos game. - // Get prevPage's page content frame - nsIFrame* prevPageContentFrame = prevPage->GetFirstChild(nsnull); + nsIFrame* prevPageContentFrame = aParentFrame->GetPrevInFlow(); if (!prevPageContentFrame) { - newFrame->Destroy(); - *aContinuingFrame = nsnull; + return NS_OK; + } + nsIFrame* docRootFrame = aParentFrame->GetFirstChild(nsnull); + if (!docRootFrame) { + // document's root element's frame: don't need a page if there's no content return NS_ERROR_UNEXPECTED; } - + nsFrameItems fixedPlaceholders; nsIFrame* firstFixed = prevPageContentFrame->GetFirstChild(nsGkAtoms::fixedList); if (!firstFixed) { return NS_OK; } + //XXXbz Should mInitialContainingBlock be docRootFrame? It probably doesn't matter. nsFrameConstructorState state(mPresShell, aParentFrame, mInitialContainingBlock, mInitialContainingBlock); // Iterate the fixed frames and replicate each for (nsIFrame* fixed = firstFixed; fixed; fixed = fixed->GetNextSibling()) { - rv = ConstructFrame(state, fixed->GetContent(), - newFrame, fixedPlaceholders); - if (NS_FAILED(rv)) { - newFrame->Destroy(); - *aContinuingFrame = nsnull; - return rv; - } + nsresult rv = ConstructFrame(state, fixed->GetContent(), + docRootFrame, fixedPlaceholders); + NS_ENSURE_SUCCESS(rv, rv); } // Add the placeholders to our primary child list. // XXXbz this is a little screwed up, since the fixed frames will have the // wrong parent block and hence auto-positioning will be broken. Oh, well. - newFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList); + NS_ASSERTION(!docRootFrame->GetFirstChild(nsnull), + "leaking frames; doc root continuation must be empty"); + docRootFrame->SetInitialChildList(nsnull, fixedPlaceholders.childList); return NS_OK; } diff --git a/layout/base/nsCSSFrameConstructor.h b/layout/base/nsCSSFrameConstructor.h index 62d602f05b6..3a58b325a31 100644 --- a/layout/base/nsCSSFrameConstructor.h +++ b/layout/base/nsCSSFrameConstructor.h @@ -51,6 +51,7 @@ #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsThreadUtils.h" +#include "nsPageContentFrame.h" class nsIDocument; struct nsFrameItems; @@ -185,6 +186,9 @@ public: nsIFrame** aContinuingFrame, PRBool aIsFluid = PR_TRUE); + // Copy over fixed frames from aParentFrame's prev-in-flow + nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame); + // Request to find the primary frame associated with a given content object. // This is typically called by the pres shell when there is no mapping in // the pres shell hash table diff --git a/layout/generic/nsPageContentFrame.cpp b/layout/generic/nsPageContentFrame.cpp index abc88063fa1..75a3803c2c7 100644 --- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -65,15 +65,24 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); aStatus = NS_FRAME_COMPLETE; // initialize out parameter + // 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; + // Also we need to avoid repeating the call to ReplicateFixedFrames. nsPageContentFrame* prevPageContentFrame = static_cast - (GetPrevInFlow()); - if (prevPageContentFrame) { + (GetPrevInFlow()); + if (mFrames.IsEmpty() && prevPageContentFrame) { + // Pull the doc root frame's continuation and copy fixed frames. nsIFrame* overflow = prevPageContentFrame->GetOverflowFrames(aPresContext, PR_TRUE); - nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, overflow, prevPageContentFrame, this); + NS_ASSERTION(overflow && !overflow->GetNextSibling(), + "must have doc root as pageContentFrame's only child"); + nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevPageContentFrame, this); // Prepend overflow to the page content frame. There may already be // children placeholders which don't get reflowed but must not be // lost until the page content frame is destroyed. mFrames.InsertFrames(this, nsnull, overflow); + nsresult rv = aPresContext->PresShell()->FrameConstructor() + ->ReplicateFixedFrames(this); + NS_ENSURE_SUCCESS(rv, rv); } // Resize our frame allowing it only to be as big as we are