Bug 1041512 - Mark intrinsic widths dirty on a style change even if the frame hasn't had its first reflow yet. r=dbaron

This commit is contained in:
Cameron McCormack
2014-09-17 10:40:11 +10:00
parent 21b8c0bd79
commit 72c8556198
3 changed files with 26 additions and 16 deletions

View File

@@ -501,11 +501,6 @@ RestyleManager::RecomputePosition(nsIFrame* aFrame)
void void
RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint) RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint)
{ {
// If the frame hasn't even received an initial reflow, then don't
// send it a style-change reflow!
if (aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)
return;
nsIPresShell::IntrinsicDirty dirtyType; nsIPresShell::IntrinsicDirty dirtyType;
if (aHint & nsChangeHint_ClearDescendantIntrinsics) { if (aHint & nsChangeHint_ClearDescendantIntrinsics) {
NS_ASSERTION(aHint & nsChangeHint_ClearAncestorIntrinsics, NS_ASSERTION(aHint & nsChangeHint_ClearAncestorIntrinsics,
@@ -518,18 +513,23 @@ RestyleManager::StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint)
} }
nsFrameState dirtyBits; nsFrameState dirtyBits;
if (aHint & nsChangeHint_NeedDirtyReflow) { if (aFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
dirtyBits = nsFrameState(0);
} else if (aHint & nsChangeHint_NeedDirtyReflow) {
dirtyBits = NS_FRAME_IS_DIRTY; dirtyBits = NS_FRAME_IS_DIRTY;
} else { } else {
dirtyBits = NS_FRAME_HAS_DIRTY_CHILDREN; dirtyBits = NS_FRAME_HAS_DIRTY_CHILDREN;
} }
// If we're not going to clear any intrinsic sizes on the frames, and
// there are no dirty bits to set, then there's nothing to do.
if (dirtyType == nsIPresShell::eResize && !dirtyBits)
return;
do { do {
mPresContext->PresShell()->FrameNeedsReflow(aFrame, dirtyType, dirtyBits); mPresContext->PresShell()->FrameNeedsReflow(aFrame, dirtyType, dirtyBits);
aFrame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame); aFrame = nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame);
} while (aFrame); } while (aFrame);
return;
} }
void void

View File

@@ -495,9 +495,13 @@ public:
/** /**
* Tell the pres shell that a frame needs to be marked dirty and needs * Tell the pres shell that a frame needs to be marked dirty and needs
* Reflow. It's OK if this is an ancestor of the frame needing reflow as * Reflow. It's OK if this is an ancestor of the frame needing reflow as
* long as the ancestor chain between them doesn't cross a reflow root. The * long as the ancestor chain between them doesn't cross a reflow root.
* bit to add should be either NS_FRAME_IS_DIRTY or *
* NS_FRAME_HAS_DIRTY_CHILDREN (but not both!). * The bit to add should be NS_FRAME_IS_DIRTY, NS_FRAME_HAS_DIRTY_CHILDREN
* or nsFrameState(0); passing 0 means that dirty bits won't be set on the
* frame or its ancestors/descendants, but that intrinsic widths will still
* be marked dirty. Passing aIntrinsicDirty = eResize and aBitToAdd = 0
* would result in no work being done, so don't do that.
*/ */
enum IntrinsicDirty { enum IntrinsicDirty {
// XXXldb eResize should be renamed // XXXldb eResize should be renamed
@@ -506,8 +510,8 @@ public:
eStyleChange // Do eTreeChange, plus all of aFrame's descendants eStyleChange // Do eTreeChange, plus all of aFrame's descendants
}; };
virtual void FrameNeedsReflow(nsIFrame *aFrame, virtual void FrameNeedsReflow(nsIFrame *aFrame,
IntrinsicDirty aIntrinsicDirty, IntrinsicDirty aIntrinsicDirty,
nsFrameState aBitToAdd) = 0; nsFrameState aBitToAdd) = 0;
/** /**
* Calls FrameNeedsReflow on all fixed position children of the root frame. * Calls FrameNeedsReflow on all fixed position children of the root frame.

View File

@@ -2775,10 +2775,11 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
nsFrameState aBitToAdd) nsFrameState aBitToAdd)
{ {
NS_PRECONDITION(aBitToAdd == NS_FRAME_IS_DIRTY || NS_PRECONDITION(aBitToAdd == NS_FRAME_IS_DIRTY ||
aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN, aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN ||
!aBitToAdd,
"Unexpected bits being added"); "Unexpected bits being added");
NS_PRECONDITION(aIntrinsicDirty != eStyleChange || NS_PRECONDITION(!(aIntrinsicDirty == eStyleChange &&
aBitToAdd == NS_FRAME_IS_DIRTY, aBitToAdd == NS_FRAME_HAS_DIRTY_CHILDREN),
"bits don't correspond to style change reason"); "bits don't correspond to style change reason");
NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow"); NS_ASSERTION(!mIsReflowing, "can't mark frame dirty during reflow");
@@ -2876,6 +2877,11 @@ PresShell::FrameNeedsReflow(nsIFrame *aFrame, IntrinsicDirty aIntrinsicDirty,
} while (stack.Length() != 0); } while (stack.Length() != 0);
} }
// Skip setting dirty bits up the tree if we weren't given a bit to add.
if (!aBitToAdd) {
continue;
}
// Set NS_FRAME_HAS_DIRTY_CHILDREN bits (via nsIFrame::ChildIsDirty) // Set NS_FRAME_HAS_DIRTY_CHILDREN bits (via nsIFrame::ChildIsDirty)
// up the tree until we reach either a frame that's already dirty or // up the tree until we reach either a frame that's already dirty or
// a reflow root. // a reflow root.