From 8dab980fec8846c40c1c2608893d931303f96b5b Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Wed, 13 Jul 2016 01:08:18 -0500 Subject: [PATCH] Bug 1271714. When creating the wrap list item that contains the display list for a frame make sure to use a scroll clip that includes content in the display list. r=mstange In nsIFrame::BuildDisplayListForChild for certain types of frames we create wrap list items to wrap the constructed display list to make those items inseperable. We were using the current scroll clip by default when creating these items, but that scroll clip may not contain all the content in the display list if we traversed into an out of flow frame whose containing block is an ancestor of the current frame. The CurrentAncestorScrollClipForStackingContextContents keeps track of exactly this. (Its name might be a little misleading as we may not be dealing with a true stacking context here. Nevertheless it does contain the correct clip.) We also need to initialize the value of mStackingContextAncestorSC when we create an AutoSaveRestore because we are now using that value sometimes without calling Enter/ExitStackingContext (which initializes mStackingContextAncestorSC). --- layout/base/DisplayListClipState.cpp | 4 +++- layout/generic/nsFrame.cpp | 14 +++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/layout/base/DisplayListClipState.cpp b/layout/base/DisplayListClipState.cpp index 70ee47b3856f..e613a820bd48 100644 --- a/layout/base/DisplayListClipState.cpp +++ b/layout/base/DisplayListClipState.cpp @@ -216,6 +216,8 @@ DisplayListClipState::AutoSaveRestore::AutoSaveRestore(nsDisplayListBuilder* aBu , mRestored(false) #endif , mClearedForStackingContextContents(false) -{} +{ + mState.mStackingContextAncestorSC = mState.GetCurrentInnermostScrollClip(); +} } // namespace mozilla diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index d015646b035e..e8c6ca424515 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -2599,7 +2599,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder, static nsDisplayItem* WrapInWrapList(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, nsDisplayList* aList) + nsIFrame* aFrame, nsDisplayList* aList, + const DisplayItemScrollClip* aScrollClip) { nsDisplayItem* item = aList->GetBottom(); if (!item) { @@ -2617,7 +2618,7 @@ WrapInWrapList(nsDisplayListBuilder* aBuilder, } if (item->GetAbove() || itemFrame != aFrame) { - return new (aBuilder) nsDisplayWrapList(aBuilder, aFrame, aList); + return new (aBuilder) nsDisplayWrapList(aBuilder, aFrame, aList, aScrollClip); } aList->RemoveBottom(); return item; @@ -2908,17 +2909,20 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } buildingForChild.RestoreBuildingInvisibleItemsValue(); - + // Clear clip rect for the construction of the items below. Since we're // clipping all their contents, they themselves don't need to be clipped. clipState.Clear(); + const DisplayItemScrollClip* containerItemScrollClip = + aBuilder->ClipState().CurrentAncestorScrollClipForStackingContextContents(); + if (isPositioned || isVisuallyAtomic || (aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) { // Genuine stacking contexts, and positioned pseudo-stacking-contexts, // go in this level. if (!list.IsEmpty()) { - nsDisplayItem* item = WrapInWrapList(aBuilder, child, &list); + nsDisplayItem* item = WrapInWrapList(aBuilder, child, &list, containerItemScrollClip); if (isSVG) { aLists.Content()->AppendNewToTop(item); } else { @@ -2927,7 +2931,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder, } } else if (!isSVG && disp->IsFloating(child)) { if (!list.IsEmpty()) { - aLists.Floats()->AppendNewToTop(WrapInWrapList(aBuilder, child, &list)); + aLists.Floats()->AppendNewToTop(WrapInWrapList(aBuilder, child, &list, containerItemScrollClip)); } } else { aLists.Content()->AppendToTop(&list);