diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index fe55750d358c..481bd2c23458 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -785,9 +785,11 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) // frame does not maintain overflow rects, so avoid calling // FinishAndStoreOverflow on it: hint = NS_SubtractHint(hint, - NS_CombineHint(nsChangeHint_UpdateOverflow, - NS_CombineHint(nsChangeHint_ChildrenOnlyTransform, - nsChangeHint_UpdatePostTransformOverflow))); + NS_CombineHint( + NS_CombineHint(nsChangeHint_UpdateOverflow, + nsChangeHint_ChildrenOnlyTransform), + NS_CombineHint(nsChangeHint_UpdatePostTransformOverflow, + nsChangeHint_UpdateParentOverflow))); } if (!(frame->GetStateBits() & NS_FRAME_MAY_BE_TRANSFORMED)) { @@ -829,11 +831,12 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) if (!didReflowThisFrame && (hint & (nsChangeHint_UpdateOverflow | nsChangeHint_UpdatePostTransformOverflow | + nsChangeHint_UpdateParentOverflow | nsChangeHint_UpdateSubtreeOverflow))) { if (hint & nsChangeHint_UpdateSubtreeOverflow) { + // FIXME (bug 1133392): Continuations? AddSubtreeToOverflowTracker(frame); } - OverflowChangedTracker::ChangeKind changeKind; if (hint & nsChangeHint_ChildrenOnlyTransform) { // The overflow areas of the child frames need to be updated: nsIFrame* hintFrame = GetFrameForChildrenOnlyTransformHint(frame); @@ -865,18 +868,37 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList) // overflows since that will happen when it's reflowed. if (!(frame->GetStateBits() & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) { - // If we have both nsChangeHint_UpdateOverflow and - // nsChangeHint_UpdatePostTransformOverflow, CHILDREN_AND_PARENT_CHANGED - // is selected as it is stronger. - if (hint & (nsChangeHint_UpdateOverflow | - nsChangeHint_UpdateSubtreeOverflow)) { - changeKind = OverflowChangedTracker::CHILDREN_AND_PARENT_CHANGED; - } else { - changeKind = OverflowChangedTracker::TRANSFORM_CHANGED; + if (hint & (nsChangeHint_UpdateOverflow | + nsChangeHint_UpdateSubtreeOverflow | + nsChangeHint_UpdatePostTransformOverflow)) { + OverflowChangedTracker::ChangeKind changeKind; + // If we have both nsChangeHint_UpdateOverflow and + // nsChangeHint_UpdatePostTransformOverflow, + // CHILDREN_AND_PARENT_CHANGED is selected as it is + // strictly stronger. + if (hint & (nsChangeHint_UpdateOverflow | + nsChangeHint_UpdateSubtreeOverflow)) { + changeKind = OverflowChangedTracker::CHILDREN_AND_PARENT_CHANGED; + } else { + changeKind = OverflowChangedTracker::TRANSFORM_CHANGED; + } + for (nsIFrame *cont = frame; cont; cont = + nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) { + mOverflowChangedTracker.AddFrame(cont, changeKind); + } } - for (nsIFrame *cont = frame; cont; cont = - nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) { - mOverflowChangedTracker.AddFrame(cont, changeKind); + // UpdateParentOverflow hints need to be processed in addition + // to the above, since if the processing of the above hints + // yields no change, the update will not propagate to the + // parent. + if (hint & nsChangeHint_UpdateParentOverflow) { + MOZ_ASSERT(frame->GetParent(), + "shouldn't get style hints for the root frame"); + for (nsIFrame *cont = frame; cont; cont = + nsLayoutUtils::GetNextContinuationOrIBSplitSibling(cont)) { + mOverflowChangedTracker.AddFrame(cont->GetParent(), + OverflowChangedTracker::CHILDREN_CHANGED); + } } } } @@ -4079,6 +4101,7 @@ RestyleManager::ChangeHintToString(nsChangeHint aHint) "UpdateCursor", "UpdateEffects", "UpdateOpacityLayer", "UpdateTransformLayer", "ReconstructFrame", "UpdateOverflow", "UpdateSubtreeOverflow", "UpdatePostTransformOverflow", + "UpdateParentOverflow", "ChildrenOnlyTransform", "RecomputePosition", "AddOrRemoveTransform", "BorderStyleNoneChange", "UpdateTextPath", "NeutralChange", "InvalidateRenderingObservers" diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index 65a7431c4a63..24762c692238 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -86,15 +86,27 @@ enum nsChangeHint { /** * The frame's overflow area has changed, through a change in its transform. + * In other words, the frame's pre-transform overflow is unchanged, but + * its post-transform overflow has changed, and thus its effect on its + * parent's overflow has changed. If the pre-transform overflow has + * changed, see nsChangeHint_UpdateOverflow. * Does not update any descendant frames. */ nsChangeHint_UpdatePostTransformOverflow = 0x2000, + /** + * This frame's effect on its parent's overflow area has changed. + * (But neither its pre-transform nor post-transform overflow have + * changed; if those are the case, see + * nsChangeHint_UpdatePostTransformOverflow.) + */ + nsChangeHint_UpdateParentOverflow = 0x4000, + /** * The children-only transform of an SVG frame changed, requiring the * overflow rects of the frame's immediate children to be updated. */ - nsChangeHint_ChildrenOnlyTransform = 0x4000, + nsChangeHint_ChildrenOnlyTransform = 0x8000, /** * The frame's offsets have changed, while its dimensions might have @@ -106,7 +118,7 @@ enum nsChangeHint { * nsChangeHint_UpdateOverflow in order to get the overflow areas of * the ancestors updated as well. */ - nsChangeHint_RecomputePosition = 0x8000, + nsChangeHint_RecomputePosition = 0x10000, /** * Behaves like ReconstructFrame, but only if the frame has descendants @@ -114,7 +126,7 @@ enum nsChangeHint { * has changed whether the frame is a container for fixed-pos or abs-pos * elements, but reframing is otherwise not needed. */ - nsChangeHint_AddOrRemoveTransform = 0x10000, + nsChangeHint_AddOrRemoveTransform = 0x20000, /** * This change hint has *no* change handling behavior. However, it @@ -122,19 +134,19 @@ enum nsChangeHint { * changes, and it's inherited by a child, that might require a reflow * due to the border-width change on the child. */ - nsChangeHint_BorderStyleNoneChange = 0x20000, + nsChangeHint_BorderStyleNoneChange = 0x40000, /** * SVG textPath needs to be recomputed because the path has changed. * This means that the glyph positions of the text need to be recomputed. */ - nsChangeHint_UpdateTextPath = 0x40000, + nsChangeHint_UpdateTextPath = 0x80000, /** * This will schedule an invalidating paint. This is useful if something * has changed which will be invalidated by DLBI. */ - nsChangeHint_SchedulePaint = 0x80000, + nsChangeHint_SchedulePaint = 0x100000, /** * A hint reflecting that style data changed with no change handling @@ -150,12 +162,12 @@ enum nsChangeHint { * different data would be cached information that would be re-calculated * to the same values, such as nsStyleBorder::mSubImages.) */ - nsChangeHint_NeutralChange = 0x100000, + nsChangeHint_NeutralChange = 0x200000, /** * This will cause rendering observers to be invalidated. */ - nsChangeHint_InvalidateRenderingObservers = 0x200000 + nsChangeHint_InvalidateRenderingObservers = 0x400000 // IMPORTANT NOTE: When adding new hints, consider whether you need to // add them to NS_HintsNotHandledForDescendantsIn() below. Please also @@ -214,6 +226,7 @@ inline bool NS_IsHintSubset(nsChangeHint aSubset, nsChangeHint aSuperSet) { nsChangeHint_UpdateOpacityLayer | \ nsChangeHint_UpdateOverflow | \ nsChangeHint_UpdatePostTransformOverflow | \ + nsChangeHint_UpdateParentOverflow | \ nsChangeHint_ChildrenOnlyTransform | \ nsChangeHint_RecomputePosition | \ nsChangeHint_AddOrRemoveTransform | \ @@ -229,6 +242,7 @@ inline nsChangeHint NS_HintsNotHandledForDescendantsIn(nsChangeHint aChangeHint) nsChangeHint_UpdateOpacityLayer | nsChangeHint_UpdateOverflow | nsChangeHint_UpdatePostTransformOverflow | + nsChangeHint_UpdateParentOverflow | nsChangeHint_ChildrenOnlyTransform | nsChangeHint_RecomputePosition | nsChangeHint_AddOrRemoveTransform |