--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -417,17 +417,17 @@ public:
PaintedLayerData() :
mAnimatedGeometryRoot(nullptr),
mScrollClip(nullptr),
mReferenceFrame(nullptr),
mLayer(nullptr),
mSolidColor(NS_RGBA(0, 0, 0, 0)),
mIsSolidColorInVisibleRegion(false),
mFontSmoothingBackgroundColor(NS_RGBA(0,0,0,0)),
- mClipMovesWithLayer(true),
+ mSingleItemFixedToViewport(false),
mIsCaret(false),
mNeedComponentAlpha(false),
mForceTransparentSurface(false),
mHideAllLayersBelow(false),
mOpaqueForAnimatedGeometryRootParent(false),
mDisableFlattening(false),
mBackfaceHidden(false),
mImage(nullptr),
@@ -577,20 +577,20 @@ public:
*/
bool mIsSolidColorInVisibleRegion;
/**
* The target background color for smoothing fonts that are drawn on top of
* transparent parts of the layer.
*/
nscolor mFontSmoothingBackgroundColor;
/**
- * True unless the layer contains exactly one item whose clip scrolls
- * relative to the layer rather than moving with the layer.
+ * True if the layer contains exactly one item that returned true for
+ * ShouldFixToViewport.
*/
- bool mClipMovesWithLayer;
+ bool mSingleItemFixedToViewport;
/**
* True if the layer contains exactly one item for the caret.
*/
bool mIsCaret;
/**
* True if there is any text visible in the layer that's over
* transparent pixels in the layer.
*/
@@ -3101,17 +3101,17 @@ void ContainerState::FinishPaintedLayerD
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get());
}
// If the layer is a fixed background layer, the clip on the fixed background
// display item was not applied to the opaque region in
// ContainerState::ComputeOpaqueRect(), but was saved in data->mItemClip.
// Apply it to the opaque region now. Note that it's important to do this
// before the opaque region is propagated to the NewLayerEntry below.
- if (!data->mClipMovesWithLayer && data->mItemClip.HasClip()) {
+ if (data->mSingleItemFixedToViewport && data->mItemClip.HasClip()) {
nsRect clipRect = data->mItemClip.GetClipRect();
nsRect insideRoundedCorners = data->mItemClip.ApproximateIntersectInward(clipRect);
nsIntRect insideRoundedCornersScaled = ScaleToInsidePixels(insideRoundedCorners);
data->mOpaqueRegion.AndWith(insideRoundedCornersScaled);
}
if (mLayerBuilder->IsBuildingRetainedLayers()) {
newLayerEntry->mVisibleRegion = data->mVisibleRegion;
@@ -3175,17 +3175,17 @@ void ContainerState::FinishPaintedLayerD
// use a mask layer for rounded rect clipping.
// data->mCommonClipCount may be -1 if we haven't put any actual
// drawable items in this layer (i.e. it's only catching events).
int32_t commonClipCount;
// If the layer contains a single item fixed to the viewport, we removed
// its clip in ProcessDisplayItems() and saved it to set on the layer instead.
// Set the clip on the layer now.
- if (!data->mClipMovesWithLayer && data->mItemClip.HasClip()) {
+ if (data->mSingleItemFixedToViewport && data->mItemClip.HasClip()) {
nsIntRect layerClipRect = ScaleToNearestPixels(data->mItemClip.GetClipRect());
layerClipRect.MoveBy(mParameters.mOffset);
// The clip from such an item becomes part of the layer's scrolled clip,
// and the associated mask layer one of the layer's "ancestor mask layers".
LayerClip scrolledClip;
scrolledClip.SetClipRect(ViewAs<ParentLayerPixel>(layerClipRect));
scrolledClip.SetMaskLayerIndex(
SetupMaskLayerForScrolledClip(data->mLayer, data->mItemClip));
@@ -3517,24 +3517,24 @@ PaintedLayerData::AccumulateEventRegions
mScaledMaybeHitRegionBounds = aState->ScaleToOutsidePixels(mMaybeHitRegion.GetBounds());
}
PaintedLayerData
ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemScrollClip* aScrollClip,
const nsPoint& aTopLeft,
- bool aClipMovesWithLayer)
+ bool aShouldFixToViewport)
{
PaintedLayerData data;
data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
data.mScrollClip = aScrollClip;
data.mAnimatedGeometryRootOffset = aTopLeft;
data.mReferenceFrame = aItem->ReferenceFrame();
- data.mClipMovesWithLayer = aClipMovesWithLayer;
+ data.mSingleItemFixedToViewport = aShouldFixToViewport;
data.mBackfaceHidden = aItem->Frame()->In3DContextAndBackfaceIsHidden();
data.mIsCaret = aItem->GetType() == nsDisplayItem::TYPE_CARET;
data.mNewChildLayersIndex = mNewChildLayers.Length();
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
newLayerEntry->mScrollClip = aScrollClip;
newLayerEntry->mIsCaret = data.mIsCaret;
@@ -3881,23 +3881,27 @@ ContainerState::ProcessDisplayItems(nsDi
clip.IntersectWith(*scrollClip->mClip);
}
}
item->SetClip(mBuilder, clip);
}
bool clipMovesWithLayer = (animatedGeometryRoot == animatedGeometryRootForClip);
- // For items whose clip scrolls relative to the layer rather than moving
- // with the layer, remove their clip at the display item level because
- // additional areas could be brought into view by async scrolling.
- // Save the clip so we can set it on the layer instead later.
- DisplayItemClip scrollingClip = DisplayItemClip::NoClip();
- if (!clipMovesWithLayer) {
- scrollingClip = item->GetClip();
+ bool shouldFixToViewport = !clipMovesWithLayer &&
+ !(*animatedGeometryRoot)->GetParent() &&
+ item->ShouldFixToViewport(mBuilder);
+
+ // For items that are fixed to the viewport, remove their clip at the
+ // display item level because additional areas could be brought into
+ // view by async scrolling. Save the clip so we can set it on the layer
+ // instead later.
+ DisplayItemClip fixedToViewportClip = DisplayItemClip::NoClip();
+ if (shouldFixToViewport) {
+ fixedToViewportClip = item->GetClip();
item->SetClip(mBuilder, DisplayItemClip::NoClip());
}
bool snap;
nsRect itemContent = item->GetBounds(mBuilder, &snap);
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
@@ -3920,17 +3924,17 @@ ContainerState::ProcessDisplayItems(nsDi
nsRect bounds = itemContent;
bool dummy;
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
bounds = item->GetBounds(mBuilder, &dummy);
if (itemClip.HasClip()) {
bounds.IntersectRect(bounds, itemClip.GetClipRect());
}
}
- bounds = scrollingClip.ApplyNonRoundedIntersection(bounds);
+ bounds = fixedToViewportClip.ApplyNonRoundedIntersection(bounds);
if (!bounds.IsEmpty()) {
for (const DisplayItemScrollClip* scrollClip = itemScrollClip;
scrollClip && scrollClip != mContainerScrollClip;
scrollClip = scrollClip->mParent) {
if (scrollClip->mClip) {
if (scrollClip->mIsAsyncScrollable) {
bounds = scrollClip->mClip->GetClipRect();
} else {
@@ -4013,17 +4017,17 @@ ContainerState::ProcessDisplayItems(nsDi
// geometry root that we give it, but it can't easily figure about
// overflow:hidden clips on ancestors just by looking at the frame.
// So we'll do a little hand holding and pass the clip instead of the
// visible rect for the two important cases.
nscolor uniformColor = NS_RGBA(0,0,0,0);
nscolor* uniformColorPtr = (mayDrawOutOfOrder || IsInInactiveLayer()) ? nullptr :
&uniformColor;
nsIntRect clipRectUntyped;
- const DisplayItemClip& layerClip = clipMovesWithLayer ? itemClip : scrollingClip;
+ const DisplayItemClip& layerClip = shouldFixToViewport ? fixedToViewportClip : itemClip;
ParentLayerIntRect layerClipRect;
nsIntRect* clipPtr = nullptr;
if (layerClip.HasClip()) {
layerClipRect = ViewAs<ParentLayerPixel>(
ScaleToNearestPixels(layerClip.GetClipRect()) + mParameters.mOffset);
clipRectUntyped = layerClipRect.ToUnknownRect();
clipPtr = &clipRectUntyped;
}
@@ -4033,17 +4037,17 @@ ContainerState::ProcessDisplayItems(nsDi
// clip we care about is the overflow:hidden clip on the scrollbar.
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR,
clipPtr,
uniformColorPtr);
} else if (prerenderedTransform) {
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot,
clipPtr,
uniformColorPtr);
- } else if (!clipMovesWithLayer) {
+ } else if (shouldFixToViewport) {
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRootForClip,
clipPtr,
uniformColorPtr);
} else {
// Using itemVisibleRect here isn't perfect. itemVisibleRect can be
// larger or smaller than the potential bounds of item's contents in
// animatedGeometryRoot: It's too large if there's a clipped display
// port somewhere among item's contents (see bug 1147673), and it can
@@ -4117,34 +4121,34 @@ ContainerState::ProcessDisplayItems(nsDi
layerClip.GetRoundedRectCount() == 0,
"If we have rounded rects, we must have a clip rect");
// It has its own layer. Update that layer's clip and visible rects.
ownLayer->SetClipRect(Nothing());
ownLayer->SetScrolledClip(Nothing());
if (layerClip.HasClip()) {
- // If the clip moves with the layer, it becomes part of the layer
- // clip. Otherwise, it becomes part of the scrolled clip.
- if (clipMovesWithLayer) {
+ // For layers fixed to the viewport, the clip becomes part of the
+ // layer's scrolled clip. Otherwise, it becomes part of the layer clip.
+ if (shouldFixToViewport) {
+ LayerClip scrolledClip;
+ scrolledClip.SetClipRect(layerClipRect);
+ if (layerClip.GetRoundedRectCount() > 0) {
+ scrolledClip.SetMaskLayerIndex(
+ SetupMaskLayerForScrolledClip(ownLayer.get(), layerClip));
+ }
+ ownLayer->SetScrolledClip(Some(scrolledClip));
+ } else {
ownLayer->SetClipRect(Some(layerClipRect));
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
if (layerClip.GetRoundedRectCount() > 0) {
SetupMaskLayer(ownLayer, layerClip);
}
- } else {
- LayerClip scrolledClip;
- scrolledClip.SetClipRect(layerClipRect);
- if (layerClip.GetRoundedRectCount() > 0) {
- scrolledClip.SetMaskLayerIndex(
- SetupMaskLayerForScrolledClip(ownLayer.get(), layerClip));
- }
- ownLayer->SetScrolledClip(Some(scrolledClip));
}
}
ContainerLayer* oldContainer = ownLayer->GetParent();
if (oldContainer && oldContainer != mContainerLayer) {
oldContainer->RemoveChild(ownLayer);
}
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, ownLayer) < 0,
@@ -4225,17 +4229,17 @@ ContainerState::ProcessDisplayItems(nsDi
mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nullptr);
} else {
PaintedLayerData* paintedLayerData =
mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, agrScrollClip,
itemVisibleRect,
item->Frame()->In3DContextAndBackfaceIsHidden(),
[&]() {
return NewPaintedLayerData(item, animatedGeometryRoot, agrScrollClip,
- topLeft, clipMovesWithLayer);
+ topLeft, shouldFixToViewport);
});
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
paintedLayerData->AccumulateEventRegions(this, eventRegions);
} else {
// check to see if the new item has rounded rect clips in common with
@@ -4250,18 +4254,18 @@ ContainerState::ProcessDisplayItems(nsDi
MOZ_ASSERT(nsIntRegion(itemDrawRect).Contains(opaquePixels));
opaquePixels.AndWith(itemVisibleRect);
paintedLayerData->Accumulate(this, item, opaquePixels,
itemVisibleRect, itemClip, layerState);
// If we removed the clip from the display item above because it's
// fixed to the viewport, save it on the PaintedLayerData so we can
// set it on the layer later.
- if (scrollingClip.HasClip()) {
- paintedLayerData->mItemClip = scrollingClip;
+ if (fixedToViewportClip.HasClip()) {
+ paintedLayerData->mItemClip = fixedToViewportClip;
}
if (!paintedLayerData->mLayer) {
// Try to recycle the old layer of this display item.
RefPtr<PaintedLayer> layer =
AttemptToRecyclePaintedLayer(animatedGeometryRoot, item, topLeft);
if (layer) {
paintedLayerData->mLayer = layer;