Bug 765621 - Drain the parent frame's overflow list before attempting to insert/append new child frames. r=bz

This commit is contained in:
Mats Palmgren 2012-09-18 01:05:05 +02:00
parent 28e0754ba4
commit 7d2088c451
6 changed files with 69 additions and 46 deletions

View File

@ -5692,6 +5692,9 @@ AdjustAppendParentForAfterContent(nsPresContext* aPresContext,
if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle,
nsCSSPseudoElements::ePseudo_after,
aPresContext)) {
// Ensure that the :after frame is on the principal child list.
aParentFrame->DrainSelfOverflowList();
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame);
if (afterFrame) {
*aAfterFrame = afterFrame;
@ -5734,9 +5737,14 @@ FindAppendPrevSibling(nsIFrame* aParentFrame, nsIFrame* aAfterFrame)
{
if (aAfterFrame) {
NS_ASSERTION(aAfterFrame->GetParent() == aParentFrame, "Wrong parent");
NS_ASSERTION(aAfterFrame->GetPrevSibling() ||
aParentFrame->GetFirstPrincipalChild() == aAfterFrame,
":after frame must be on the principal child list here");
return aAfterFrame->GetPrevSibling();
}
aParentFrame->DrainSelfOverflowList();
return aParentFrame->GetLastChild(kPrincipalList);
}

View File

@ -4471,17 +4471,14 @@ nsBlockFrame::DrainOverflowLines()
#ifdef DEBUG
VerifyOverflowSituation();
#endif
FrameLines* overflowLines = nullptr;
FrameLines* ourOverflowLines = nullptr;
// First grab the prev-in-flows overflow lines
nsBlockFrame* prevBlock = (nsBlockFrame*) GetPrevInFlow();
// Steal the prev-in-flow's overflow lines and prepend them.
bool didFindOverflow = false;
nsBlockFrame* prevBlock = static_cast<nsBlockFrame*>(GetPrevInFlow());
if (prevBlock) {
prevBlock->ClearLineCursor();
overflowLines = prevBlock->RemoveOverflowLines();
FrameLines* overflowLines = prevBlock->RemoveOverflowLines();
if (overflowLines) {
NS_ASSERTION(!overflowLines->mLines.empty(),
"overflow lines should never be set and empty");
// Make all the frames on the overflow line list mine.
ReparentFrames(overflowLines->mFrames, prevBlock, this);
@ -4491,55 +4488,49 @@ nsBlockFrame::DrainOverflowLines()
ReparentFrames(oofs.mList, prevBlock, this);
mFloats.InsertFrames(nullptr, nullptr, oofs.mList);
}
if (!mLines.empty()) {
// Remember to recompute the margins on the first line. This will
// also recompute the correct deltaY if necessary.
mLines.front()->MarkPreviousMarginDirty();
}
// The overflow lines have already been marked dirty and their previous
// margins marked dirty also.
// Prepend the overflow frames/lines to our principal list.
mFrames.InsertFrames(nullptr, nullptr, overflowLines->mFrames);
mLines.splice(mLines.begin(), overflowLines->mLines);
NS_ASSERTION(overflowLines->mLines.empty(), "splice should empty list");
delete overflowLines;
didFindOverflow = true;
}
// The lines on the overflow list have already been marked dirty and their
// previous margins marked dirty also.
}
// Don't need to reparent frames in our own overflow lines/oofs, because they're
// Now append our own overflow lines.
return DrainSelfOverflowList() || didFindOverflow;
}
bool
nsBlockFrame::DrainSelfOverflowList()
{
// No need to reparent frames in our own overflow lines/oofs, because they're
// already ours. But we should put overflow floats back in mFloats.
ourOverflowLines = RemoveOverflowLines();
FrameLines* ourOverflowLines = RemoveOverflowLines();
if (ourOverflowLines) {
nsAutoOOFFrameList oofs(this);
if (oofs.mList.NotEmpty()) {
// The overflow floats go after our regular floats
// The overflow floats go after our regular floats.
mFloats.AppendFrames(nullptr, oofs.mList);
}
}
if (!overflowLines && !ourOverflowLines) {
// nothing to do; always the case for non-constrained-height reflows
} else {
return false;
}
// Now join the line lists into mLines
if (overflowLines) {
if (!overflowLines->mLines.empty()) {
// Join the line lists
if (!mLines.empty()) {
// Remember to recompute the margins on the first line. This will
// also recompute the correct deltaY if necessary.
mLines.front()->MarkPreviousMarginDirty();
}
// Join the sibling lists together
mFrames.InsertFrames(nullptr, nullptr, overflowLines->mFrames);
// Place overflow lines at the front of our line list
mLines.splice(mLines.begin(), overflowLines->mLines);
NS_ASSERTION(overflowLines->mLines.empty(), "splice should empty list");
}
delete overflowLines;
if (!ourOverflowLines->mLines.empty()) {
mFrames.AppendFrames(nullptr, ourOverflowLines->mFrames);
mLines.splice(mLines.end(), ourOverflowLines->mLines);
}
if (ourOverflowLines) {
if (!ourOverflowLines->mLines.empty()) {
mFrames.AppendFrames(nullptr, ourOverflowLines->mFrames);
mLines.splice(mLines.end(), ourOverflowLines->mLines);
}
delete ourOverflowLines;
}
delete ourOverflowLines;
return true;
}

View File

@ -268,6 +268,12 @@ public:
nsIAtom* aAttribute,
int32_t aModType);
/**
* Move any frames on our overflow list to the end of our principal list.
* @return true if there were any overflow frames
*/
virtual bool DrainSelfOverflowList();
virtual nsresult StealFrame(nsPresContext* aPresContext,
nsIFrame* aChild,
bool aForceNormal = false);

View File

@ -1539,14 +1539,20 @@ nsContainerFrame::MoveOverflowToChildList(nsPresContext* aPresContext)
}
}
// It's also possible that we have an overflow list for ourselves
// It's also possible that we have an overflow list for ourselves.
return DrainSelfOverflowList() || result;
}
bool
nsContainerFrame::DrainSelfOverflowList()
{
nsAutoPtr<nsFrameList> overflowFrames(StealOverflowFrames());
if (overflowFrames) {
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
mFrames.AppendFrames(nullptr, *overflowFrames);
result = true;
return true;
}
return result;
return false;
}
nsOverflowContinuationTracker::nsOverflowContinuationTracker(nsPresContext* aPresContext,

View File

@ -303,6 +303,12 @@ public:
uint32_t aFlags,
nsReflowStatus& aStatus);
/**
* Move any frames on our overflow list to the end of our principal list.
* @return true if there were any overflow frames
*/
virtual bool DrainSelfOverflowList();
/**
* Removes aChild without destroying it and without requesting reflow.
* Continuations are not affected. Checks the primary and overflow

View File

@ -701,6 +701,12 @@ public:
*/
virtual nsIFrame* GetContentInsertionFrame() { return this; }
/**
* Move any frames on our overflow list to the end of our principal list.
* @return true if there were any overflow frames
*/
virtual bool DrainSelfOverflowList() { return false; }
/**
* Get the frame that should be scrolled if the content associated
* with this frame is targeted for scrolling. For frames implementing