diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index a9476d940d6..9950eb94ffb 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -80,6 +80,11 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); + NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext); + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent); @@ -726,6 +731,64 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } + +NS_IMETHODIMP +StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext) +{ + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + + nsresult result = NS_ERROR_NULL_POINTER; + + if (aPresContext && aStyleContext && aNewStyleContext) { + nsIStyleContext* oldParent = aStyleContext->GetParent(); + + if (oldParent == aNewParentContext) { + result = NS_OK; + NS_ADDREF(aStyleContext); // for return + *aNewStyleContext = aStyleContext; + } + else { // really a new parent + nsIStyleContext* newChild = nsnull; + nsIAtom* pseudoTag = nsnull; + aStyleContext->GetPseudoType(pseudoTag); + nsISupportsArray* rules = aStyleContext->GetStyleRules(); + if (aNewParentContext) { + result = aNewParentContext->FindChildWithRules(pseudoTag, rules, newChild); + } + if (newChild) { // new parent already has one + *aNewStyleContext = newChild; + } + else { // need to make one in the new parent + nsISupportsArray* newRules = nsnull; + if (rules) { + newRules = mRecycler; + mRecycler = nsnull; + if (! newRules) { + result = NS_NewISupportsArray(&newRules); + } + if (newRules) { + newRules->AppendElements(rules); + } + } + result = NS_NewStyleContext(aNewStyleContext, aNewParentContext, pseudoTag, + newRules, aPresContext); + NS_IF_RELEASE(newRules); + } + + NS_IF_RELEASE(rules); + NS_IF_RELEASE(pseudoTag); + } + + NS_IF_RELEASE(oldParent); + } + return result; +} + struct StatefulData { StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) : mPresContext(aPresContext), diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index ceb450fb62a..8cb5f466ff7 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -20,6 +20,7 @@ #include "nsIPresContext.h" #include "nsIPresShell.h" #include "nsIStyleSet.h" +#include "nsIStyleContext.h" #include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsCOMPtr.h" @@ -137,10 +138,13 @@ public: NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame); + NS_IMETHOD ReParentStyleContext(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIStyleContext* aNewParentContext); + NS_IMETHOD CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState); NS_IMETHOD RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState); - private: nsIPresShell* mPresShell; // weak link, because the pres shell owns us nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference @@ -564,6 +568,71 @@ FrameManager::CantRenderReplacedElement(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +FrameManager::ReParentStyleContext(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) +{ + nsresult result = NS_ERROR_NULL_POINTER; + if (aFrame) { + nsIStyleContext* oldContext = nsnull; + aFrame->GetStyleContext(&oldContext); + + if (oldContext) { + nsIStyleContext* newContext = nsnull; + result = mStyleSet->ReParentStyleContext(&aPresContext, + oldContext, aNewParentContext, + &newContext); + if (NS_SUCCEEDED(result) && newContext) { + if (newContext != oldContext) { + PRInt32 listIndex = 0; + nsIAtom* childList = nsnull; + nsIFrame* child; + + do { + child = nsnull; + result = aFrame->FirstChild(childList, &child); + while ((NS_SUCCEEDED(result)) && child) { + result = ReParentStyleContext(aPresContext, child, newContext); + child->GetNextSibling(&child); + } + + NS_IF_RELEASE(childList); + aFrame->GetAdditionalChildListName(listIndex++, &childList); + } while (childList); + + aFrame->SetStyleContext(&aPresContext, newContext); + + // do additional contexts + PRInt32 contextIndex = -1; + while (1 == 1) { + nsIStyleContext* oldExtraContext = nsnull; + aFrame->GetAdditionalStyleContext(++contextIndex, &oldExtraContext); + if (oldExtraContext) { + nsIStyleContext* newExtraContext = nsnull; + result = mStyleSet->ReParentStyleContext(&aPresContext, + oldExtraContext, newContext, + &newExtraContext); + if (NS_SUCCEEDED(result) && newExtraContext) { + aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext); + NS_RELEASE(newExtraContext); + } + NS_RELEASE(oldExtraContext); + } + else { + break; + } + } + } + NS_RELEASE(newContext); + } + NS_RELEASE(oldContext); + } + } + return result; +} + + NS_IMETHODIMP FrameManager::CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) { @@ -598,6 +667,7 @@ FrameManager::CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) // XXX We are only going through the principal child list right now. // Need to talk to Troy to find out about other kinds of // child lists and whether they will contain stateful frames. + // (psl) YES, you need to iterate ALL child lists // Capture frame state for the first child nsIFrame* child = nsnull; @@ -649,6 +719,7 @@ FrameManager::RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) // XXX We are only going through the principal child list right now. // Need to talk to Troy to find out about other kinds of // child lists and whether they will contain stateful frames. + // (psl) YES, you need to iterate ALL child lists // Capture frame state for the first child nsIFrame* child = nsnull; diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp index a995c6ec2bd..1ce687f96e5 100644 --- a/mozilla/layout/base/nsPresContext.cpp +++ b/mozilla/layout/base/nsPresContext.cpp @@ -22,6 +22,7 @@ #include "nsILinkHandler.h" #include "nsIStyleSet.h" #include "nsFrameImageLoader.h" +#include "nsIFrameManager.h" #include "nsIImageGroup.h" #include "nsIFrame.h" #include "nsIRenderingContext.h" @@ -454,6 +455,24 @@ nsPresContext::ProbePseudoStyleContextFor(nsIContent* aParentContent, return rv; } +NS_IMETHODIMP +nsPresContext::ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) +{ + NS_PRECONDITION(aFrame, "null ptr"); + if (! aFrame) { + return NS_ERROR_NULL_POINTER; + } + + nsCOMPtr manager; + nsresult rv = mShell->GetFrameManager(getter_AddRefs(manager)); + if (NS_SUCCEEDED(rv) && manager) { + rv = manager->ReParentStyleContext(*this, aFrame, aNewParentContext); + } + return rv; +} + + NS_IMETHODIMP nsPresContext::GetMetricsFor(const nsFont& aFont, nsIFontMetrics** aResult) { diff --git a/mozilla/layout/base/nsPresContext.h b/mozilla/layout/base/nsPresContext.h index e58513560f5..eaff77e77eb 100644 --- a/mozilla/layout/base/nsPresContext.h +++ b/mozilla/layout/base/nsPresContext.h @@ -150,6 +150,14 @@ public: PRBool aForceUnique, nsIStyleContext** aResult) = 0; + /** + * For a given frame tree, get a new style context that is the equivalent + * but within a new parent + */ + NS_IMETHOD ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) = 0; + + /** * Get the font metrics for a given font. */ diff --git a/mozilla/layout/base/public/nsIFrameManager.h b/mozilla/layout/base/public/nsIFrameManager.h index 2bfe1296fca..ecd05083f63 100644 --- a/mozilla/layout/base/public/nsIFrameManager.h +++ b/mozilla/layout/base/public/nsIFrameManager.h @@ -27,6 +27,7 @@ class nsIFrame; class nsIPresContext; class nsIPresShell; class nsIStyleSet; +class nsIStyleContext; class nsILayoutHistoryState; #define NS_IFRAMEMANAGER_IID \ @@ -93,6 +94,12 @@ public: // references to the frame to be cleaned up NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame) = 0; + // reparent the style contexts of this frame sub tree to live under the + // new given parent style context + NS_IMETHOD ReParentStyleContext(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) = 0; + /** * Capture/restore frame state for the frame subtree rooted at aFrame. * aState is the document state storage object onto which each frame diff --git a/mozilla/layout/base/public/nsIPresContext.h b/mozilla/layout/base/public/nsIPresContext.h index e58513560f5..eaff77e77eb 100644 --- a/mozilla/layout/base/public/nsIPresContext.h +++ b/mozilla/layout/base/public/nsIPresContext.h @@ -150,6 +150,14 @@ public: PRBool aForceUnique, nsIStyleContext** aResult) = 0; + /** + * For a given frame tree, get a new style context that is the equivalent + * but within a new parent + */ + NS_IMETHOD ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) = 0; + + /** * Get the font metrics for a given font. */ diff --git a/mozilla/layout/base/public/nsIStyleSet.h b/mozilla/layout/base/public/nsIStyleSet.h index f2bd390ecf2..5f121ebd256 100644 --- a/mozilla/layout/base/public/nsIStyleSet.h +++ b/mozilla/layout/base/public/nsIStyleSet.h @@ -89,6 +89,13 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE) = 0; + // Get a new style context that lives in a different parent + // The new context will be the same as the old if the new parent == the old parent + NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext) = 0; + // Test if style is dependent on content state NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent) = 0; diff --git a/mozilla/layout/base/public/nsPresContext.h b/mozilla/layout/base/public/nsPresContext.h index e58513560f5..eaff77e77eb 100644 --- a/mozilla/layout/base/public/nsPresContext.h +++ b/mozilla/layout/base/public/nsPresContext.h @@ -150,6 +150,14 @@ public: PRBool aForceUnique, nsIStyleContext** aResult) = 0; + /** + * For a given frame tree, get a new style context that is the equivalent + * but within a new parent + */ + NS_IMETHOD ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) = 0; + + /** * Get the font metrics for a given font. */ diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp index a995c6ec2bd..1ce687f96e5 100644 --- a/mozilla/layout/base/src/nsPresContext.cpp +++ b/mozilla/layout/base/src/nsPresContext.cpp @@ -22,6 +22,7 @@ #include "nsILinkHandler.h" #include "nsIStyleSet.h" #include "nsFrameImageLoader.h" +#include "nsIFrameManager.h" #include "nsIImageGroup.h" #include "nsIFrame.h" #include "nsIRenderingContext.h" @@ -454,6 +455,24 @@ nsPresContext::ProbePseudoStyleContextFor(nsIContent* aParentContent, return rv; } +NS_IMETHODIMP +nsPresContext::ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) +{ + NS_PRECONDITION(aFrame, "null ptr"); + if (! aFrame) { + return NS_ERROR_NULL_POINTER; + } + + nsCOMPtr manager; + nsresult rv = mShell->GetFrameManager(getter_AddRefs(manager)); + if (NS_SUCCEEDED(rv) && manager) { + rv = manager->ReParentStyleContext(*this, aFrame, aNewParentContext); + } + return rv; +} + + NS_IMETHODIMP nsPresContext::GetMetricsFor(const nsFont& aFont, nsIFontMetrics** aResult) { diff --git a/mozilla/layout/base/src/nsPresContext.h b/mozilla/layout/base/src/nsPresContext.h index 1da6f8bc1f2..7474f8c24d1 100644 --- a/mozilla/layout/base/src/nsPresContext.h +++ b/mozilla/layout/base/src/nsPresContext.h @@ -64,6 +64,8 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique, nsIStyleContext** aResult); + NS_IMETHOD ReParentStyleContext(nsIFrame* aFrame, + nsIStyleContext* aNewParentContext); NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIFontMetrics** aResult); NS_IMETHOD GetDefaultFont(nsFont& aResult); NS_IMETHOD SetDefaultFont(nsFont& aFont); diff --git a/mozilla/layout/base/src/nsStyleSet.cpp b/mozilla/layout/base/src/nsStyleSet.cpp index a9476d940d6..9950eb94ffb 100644 --- a/mozilla/layout/base/src/nsStyleSet.cpp +++ b/mozilla/layout/base/src/nsStyleSet.cpp @@ -80,6 +80,11 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); + NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext); + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent); @@ -726,6 +731,64 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } + +NS_IMETHODIMP +StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext) +{ + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + + nsresult result = NS_ERROR_NULL_POINTER; + + if (aPresContext && aStyleContext && aNewStyleContext) { + nsIStyleContext* oldParent = aStyleContext->GetParent(); + + if (oldParent == aNewParentContext) { + result = NS_OK; + NS_ADDREF(aStyleContext); // for return + *aNewStyleContext = aStyleContext; + } + else { // really a new parent + nsIStyleContext* newChild = nsnull; + nsIAtom* pseudoTag = nsnull; + aStyleContext->GetPseudoType(pseudoTag); + nsISupportsArray* rules = aStyleContext->GetStyleRules(); + if (aNewParentContext) { + result = aNewParentContext->FindChildWithRules(pseudoTag, rules, newChild); + } + if (newChild) { // new parent already has one + *aNewStyleContext = newChild; + } + else { // need to make one in the new parent + nsISupportsArray* newRules = nsnull; + if (rules) { + newRules = mRecycler; + mRecycler = nsnull; + if (! newRules) { + result = NS_NewISupportsArray(&newRules); + } + if (newRules) { + newRules->AppendElements(rules); + } + } + result = NS_NewStyleContext(aNewStyleContext, aNewParentContext, pseudoTag, + newRules, aPresContext); + NS_IF_RELEASE(newRules); + } + + NS_IF_RELEASE(rules); + NS_IF_RELEASE(pseudoTag); + } + + NS_IF_RELEASE(oldParent); + } + return result; +} + struct StatefulData { StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) : mPresContext(aPresContext), diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/generic/nsFirstLetterFrame.cpp b/mozilla/layout/generic/nsFirstLetterFrame.cpp index 603d9b1a016..dd24b144921 100644 --- a/mozilla/layout/generic/nsFirstLetterFrame.cpp +++ b/mozilla/layout/generic/nsFirstLetterFrame.cpp @@ -139,9 +139,7 @@ nsFirstLetterFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIFrame* aChildList) { mFrames.SetFrames(aChildList); - aChildList->ReResolveStyleContext(&aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext.ReParentStyleContext(aChildList, mStyleContext); // XXX only first frame? return NS_OK; } @@ -290,11 +288,9 @@ nsFirstLetterFrame::DrainOverflowFrames(nsIPresContext* aPresContext) mFrames.AppendFrames(nsnull, mOverflowFrames); } - // Now repair our first frames style context + // Now repair our first frames style context XXX only first frame? nsIFrame* kid = mFrames.FirstChild(); if (kid) { - kid->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext->ReParentStyleContext(kid, mStyleContext); } } diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 157f5888c83..f312c870157 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -1896,15 +1896,13 @@ nsInlineFrame::GetSkipSides() const // nsLineFrame implementation static void -ReResolveChildList(nsIPresContext* aPresContext, - nsIStyleContext* aParentStyleContext, - nsFrameList& aFrameList) +ReParentChildListStyle(nsIPresContext* aPresContext, + nsIStyleContext* aParentStyleContext, + nsFrameList& aFrameList) { nsIFrame* kid = aFrameList.FirstChild(); while (nsnull != kid) { - kid->ReResolveStyleContext(aPresContext, aParentStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext->ReParentStyleContext(kid, aParentStyleContext); kid->GetNextSibling(&kid); } } @@ -2002,7 +2000,7 @@ nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) { nsFrameList frames(aFrameList); - ReResolveChildList(aPresContext, mStyleContext, frames); + ReParentChildListStyle(aPresContext, mStyleContext, frames); // XXX ReparentFrameView mFrames.AppendFrames(this, aFrameList); return NS_OK; @@ -2014,7 +2012,7 @@ nsFirstLineFrame::InsertFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) { nsFrameList frames(aFrameList); - ReResolveChildList(aPresContext, mStyleContext, frames); + ReParentChildListStyle(aPresContext, mStyleContext, frames); // XXX ReparentFrameView mFrames.InsertFrames(this, aPrevFrame, aFrameList); return NS_OK; @@ -2056,8 +2054,7 @@ nsFirstLineFrame::PullInlineFrame(nsIPresContext* aPresContext, if (frame && !mPrevInFlow) { // We are a first-line frame. Fixup the child frames // style-context that we just pulled. - frame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, nsnull, nsnull); + aPresContext->ReParentStyleContext(frame, mStyleContext); } return frame; } @@ -2069,8 +2066,8 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { if (prevInFlow->mOverflowFrames.NotEmpty()) { - ReResolveChildList(aPresContext, mStyleContext, - prevInFlow->mOverflowFrames); + ReParentChildListStyle(aPresContext, mStyleContext, + prevInFlow->mOverflowFrames); mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); } } @@ -2078,7 +2075,7 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) // It's also possible that we have an overflow list for ourselves if (mOverflowFrames.NotEmpty()) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - ReResolveChildList(aPresContext, mStyleContext, mOverflowFrames); + ReParentChildListStyle(aPresContext, mStyleContext, mOverflowFrames); mFrames.AppendFrames(nsnull, mOverflowFrames); } } @@ -2149,9 +2146,7 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, // Fixup style of frame just pulled up nsIFrame* firstFrame = mFrames.FirstChild(); if (firstFrame) { - firstFrame->ReResolveStyleContext(&aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, nsnull, - nsnull); + aPresContext.ReParentStyleContext(firstFrame, mStyleContext); } } if (nsnull == mPrevInFlow) { @@ -2201,7 +2196,7 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, SetStyleContext(&aPresContext, newSC); // Re-resolve all children - ReResolveChildList(&aPresContext, mStyleContext, mFrames); + ReParentChildListStyle(&aPresContext, mStyleContext, mFrames); NS_RELEASE(newSC); } diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index 9bb99995539..eb10a742232 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -4308,10 +4308,8 @@ nsBlockFrame::FixParentAndView(nsIPresContext* aPresContext, nsIFrame* aFrame) aFrame->SetParent(this); if (this != oldParent) { nsHTMLContainerFrame::ReparentFrameView(aFrame, oldParent, this); + aPresContext->ReParentStyleContext(aFrame, mStyleContext); } - aFrame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); aFrame->GetNextSibling(&aFrame); } } diff --git a/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp b/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp index 603d9b1a016..dd24b144921 100644 --- a/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp +++ b/mozilla/layout/html/base/src/nsFirstLetterFrame.cpp @@ -139,9 +139,7 @@ nsFirstLetterFrame::SetInitialChildList(nsIPresContext& aPresContext, nsIFrame* aChildList) { mFrames.SetFrames(aChildList); - aChildList->ReResolveStyleContext(&aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext.ReParentStyleContext(aChildList, mStyleContext); // XXX only first frame? return NS_OK; } @@ -290,11 +288,9 @@ nsFirstLetterFrame::DrainOverflowFrames(nsIPresContext* aPresContext) mFrames.AppendFrames(nsnull, mOverflowFrames); } - // Now repair our first frames style context + // Now repair our first frames style context XXX only first frame? nsIFrame* kid = mFrames.FirstChild(); if (kid) { - kid->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext->ReParentStyleContext(kid, mStyleContext); } } diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index ceb450fb62a..8cb5f466ff7 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -20,6 +20,7 @@ #include "nsIPresContext.h" #include "nsIPresShell.h" #include "nsIStyleSet.h" +#include "nsIStyleContext.h" #include "nsIEventQueueService.h" #include "nsIServiceManager.h" #include "nsCOMPtr.h" @@ -137,10 +138,13 @@ public: NS_IMETHOD NotifyDestroyingFrame(nsIFrame* aFrame); + NS_IMETHOD ReParentStyleContext(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIStyleContext* aNewParentContext); + NS_IMETHOD CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState); NS_IMETHOD RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState); - private: nsIPresShell* mPresShell; // weak link, because the pres shell owns us nsIStyleSet* mStyleSet; // weak link. pres shell holds a reference @@ -564,6 +568,71 @@ FrameManager::CantRenderReplacedElement(nsIPresContext* aPresContext, return rv; } +NS_IMETHODIMP +FrameManager::ReParentStyleContext(nsIPresContext& aPresContext, + nsIFrame* aFrame, + nsIStyleContext* aNewParentContext) +{ + nsresult result = NS_ERROR_NULL_POINTER; + if (aFrame) { + nsIStyleContext* oldContext = nsnull; + aFrame->GetStyleContext(&oldContext); + + if (oldContext) { + nsIStyleContext* newContext = nsnull; + result = mStyleSet->ReParentStyleContext(&aPresContext, + oldContext, aNewParentContext, + &newContext); + if (NS_SUCCEEDED(result) && newContext) { + if (newContext != oldContext) { + PRInt32 listIndex = 0; + nsIAtom* childList = nsnull; + nsIFrame* child; + + do { + child = nsnull; + result = aFrame->FirstChild(childList, &child); + while ((NS_SUCCEEDED(result)) && child) { + result = ReParentStyleContext(aPresContext, child, newContext); + child->GetNextSibling(&child); + } + + NS_IF_RELEASE(childList); + aFrame->GetAdditionalChildListName(listIndex++, &childList); + } while (childList); + + aFrame->SetStyleContext(&aPresContext, newContext); + + // do additional contexts + PRInt32 contextIndex = -1; + while (1 == 1) { + nsIStyleContext* oldExtraContext = nsnull; + aFrame->GetAdditionalStyleContext(++contextIndex, &oldExtraContext); + if (oldExtraContext) { + nsIStyleContext* newExtraContext = nsnull; + result = mStyleSet->ReParentStyleContext(&aPresContext, + oldExtraContext, newContext, + &newExtraContext); + if (NS_SUCCEEDED(result) && newExtraContext) { + aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext); + NS_RELEASE(newExtraContext); + } + NS_RELEASE(oldExtraContext); + } + else { + break; + } + } + } + NS_RELEASE(newContext); + } + NS_RELEASE(oldContext); + } + } + return result; +} + + NS_IMETHODIMP FrameManager::CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) { @@ -598,6 +667,7 @@ FrameManager::CaptureFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) // XXX We are only going through the principal child list right now. // Need to talk to Troy to find out about other kinds of // child lists and whether they will contain stateful frames. + // (psl) YES, you need to iterate ALL child lists // Capture frame state for the first child nsIFrame* child = nsnull; @@ -649,6 +719,7 @@ FrameManager::RestoreFrameState(nsIFrame* aFrame, nsILayoutHistoryState* aState) // XXX We are only going through the principal child list right now. // Need to talk to Troy to find out about other kinds of // child lists and whether they will contain stateful frames. + // (psl) YES, you need to iterate ALL child lists // Capture frame state for the first child nsIFrame* child = nsnull; diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index 157f5888c83..f312c870157 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -1896,15 +1896,13 @@ nsInlineFrame::GetSkipSides() const // nsLineFrame implementation static void -ReResolveChildList(nsIPresContext* aPresContext, - nsIStyleContext* aParentStyleContext, - nsFrameList& aFrameList) +ReParentChildListStyle(nsIPresContext* aPresContext, + nsIStyleContext* aParentStyleContext, + nsFrameList& aFrameList) { nsIFrame* kid = aFrameList.FirstChild(); while (nsnull != kid) { - kid->ReResolveStyleContext(aPresContext, aParentStyleContext, - NS_STYLE_HINT_REFLOW, - nsnull, nsnull); + aPresContext->ReParentStyleContext(kid, aParentStyleContext); kid->GetNextSibling(&kid); } } @@ -2002,7 +2000,7 @@ nsFirstLineFrame::AppendFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) { nsFrameList frames(aFrameList); - ReResolveChildList(aPresContext, mStyleContext, frames); + ReParentChildListStyle(aPresContext, mStyleContext, frames); // XXX ReparentFrameView mFrames.AppendFrames(this, aFrameList); return NS_OK; @@ -2014,7 +2012,7 @@ nsFirstLineFrame::InsertFrames2(nsIPresContext* aPresContext, nsIFrame* aFrameList) { nsFrameList frames(aFrameList); - ReResolveChildList(aPresContext, mStyleContext, frames); + ReParentChildListStyle(aPresContext, mStyleContext, frames); // XXX ReparentFrameView mFrames.InsertFrames(this, aPrevFrame, aFrameList); return NS_OK; @@ -2056,8 +2054,7 @@ nsFirstLineFrame::PullInlineFrame(nsIPresContext* aPresContext, if (frame && !mPrevInFlow) { // We are a first-line frame. Fixup the child frames // style-context that we just pulled. - frame->ReResolveStyleContext(aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, nsnull, nsnull); + aPresContext->ReParentStyleContext(frame, mStyleContext); } return frame; } @@ -2069,8 +2066,8 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) nsFirstLineFrame* prevInFlow = (nsFirstLineFrame*)mPrevInFlow; if (nsnull != prevInFlow) { if (prevInFlow->mOverflowFrames.NotEmpty()) { - ReResolveChildList(aPresContext, mStyleContext, - prevInFlow->mOverflowFrames); + ReParentChildListStyle(aPresContext, mStyleContext, + prevInFlow->mOverflowFrames); mFrames.InsertFrames(this, nsnull, prevInFlow->mOverflowFrames); } } @@ -2078,7 +2075,7 @@ nsFirstLineFrame::DrainOverflow(nsIPresContext* aPresContext) // It's also possible that we have an overflow list for ourselves if (mOverflowFrames.NotEmpty()) { NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames"); - ReResolveChildList(aPresContext, mStyleContext, mOverflowFrames); + ReParentChildListStyle(aPresContext, mStyleContext, mOverflowFrames); mFrames.AppendFrames(nsnull, mOverflowFrames); } } @@ -2149,9 +2146,7 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, // Fixup style of frame just pulled up nsIFrame* firstFrame = mFrames.FirstChild(); if (firstFrame) { - firstFrame->ReResolveStyleContext(&aPresContext, mStyleContext, - NS_STYLE_HINT_REFLOW, nsnull, - nsnull); + aPresContext.ReParentStyleContext(firstFrame, mStyleContext); } } if (nsnull == mPrevInFlow) { @@ -2201,7 +2196,7 @@ nsFirstLineFrame::Reflow(nsIPresContext& aPresContext, SetStyleContext(&aPresContext, newSC); // Re-resolve all children - ReResolveChildList(&aPresContext, mStyleContext, mFrames); + ReParentChildListStyle(&aPresContext, mStyleContext, mFrames); NS_RELEASE(newSC); } diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index a9476d940d6..9950eb94ffb 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -80,6 +80,11 @@ public: nsIStyleContext* aParentContext, PRBool aForceUnique = PR_FALSE); + NS_IMETHOD ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext); + NS_IMETHOD HasStateDependentStyle(nsIPresContext* aPresContext, nsIContent* aContent); @@ -726,6 +731,64 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext, return result; } + +NS_IMETHODIMP +StyleSetImpl::ReParentStyleContext(nsIPresContext* aPresContext, + nsIStyleContext* aStyleContext, + nsIStyleContext* aNewParentContext, + nsIStyleContext** aNewStyleContext) +{ + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + NS_ASSERTION(aPresContext, "must have pres context"); + + nsresult result = NS_ERROR_NULL_POINTER; + + if (aPresContext && aStyleContext && aNewStyleContext) { + nsIStyleContext* oldParent = aStyleContext->GetParent(); + + if (oldParent == aNewParentContext) { + result = NS_OK; + NS_ADDREF(aStyleContext); // for return + *aNewStyleContext = aStyleContext; + } + else { // really a new parent + nsIStyleContext* newChild = nsnull; + nsIAtom* pseudoTag = nsnull; + aStyleContext->GetPseudoType(pseudoTag); + nsISupportsArray* rules = aStyleContext->GetStyleRules(); + if (aNewParentContext) { + result = aNewParentContext->FindChildWithRules(pseudoTag, rules, newChild); + } + if (newChild) { // new parent already has one + *aNewStyleContext = newChild; + } + else { // need to make one in the new parent + nsISupportsArray* newRules = nsnull; + if (rules) { + newRules = mRecycler; + mRecycler = nsnull; + if (! newRules) { + result = NS_NewISupportsArray(&newRules); + } + if (newRules) { + newRules->AppendElements(rules); + } + } + result = NS_NewStyleContext(aNewStyleContext, aNewParentContext, pseudoTag, + newRules, aPresContext); + NS_IF_RELEASE(newRules); + } + + NS_IF_RELEASE(rules); + NS_IF_RELEASE(pseudoTag); + } + + NS_IF_RELEASE(oldParent); + } + return result; +} + struct StatefulData { StatefulData(nsIPresContext* aPresContext, nsIContent* aContent) : mPresContext(aPresContext),