Bug 1166301 - Store a flag on Layer to tell fixed background layers apart from fixed position layers. r=mattwoodrow
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -1158,27 +1158,30 @@ public:
* with respect to.
*
* - |aAnchor| is the point on the layer that is considered the "anchor"
* point, that is, the point which remains in the same position when
* compositing the layer tree with a transformation (such as when
* asynchronously scrolling and zooming).
*/
void SetFixedPositionData(FrameMetrics::ViewID aScrollId,
- const LayerPoint& aAnchor)
+ const LayerPoint& aAnchor,
+ bool aFixedBackground)
{
if (!mFixedPositionData ||
mFixedPositionData->mScrollId != aScrollId ||
- mFixedPositionData->mAnchor != aAnchor) {
+ mFixedPositionData->mAnchor != aAnchor ||
+ mFixedPositionData->mFixedBackground != aFixedBackground) {
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) FixedPositionData", this));
if (!mFixedPositionData) {
mFixedPositionData = MakeUnique<FixedPositionData>();
}
mFixedPositionData->mScrollId = aScrollId;
mFixedPositionData->mAnchor = aAnchor;
+ mFixedPositionData->mFixedBackground = aFixedBackground;
Mutated();
}
}
/**
* CONSTRUCTION PHASE ONLY
* If a layer is "sticky position", |aScrollId| holds the scroll identifier
* of the scrollable content that contains it. The difference between the two
@@ -1262,16 +1265,17 @@ public:
const gfx::Matrix4x4& GetBaseTransform() const { return mTransform; }
// Note: these are virtual because ContainerLayerComposite overrides them.
virtual float GetPostXScale() const { return mPostXScale; }
virtual float GetPostYScale() const { return mPostYScale; }
bool GetIsFixedPosition() { return mIsFixedPosition; }
bool GetIsStickyPosition() { return mStickyPositionData; }
FrameMetrics::ViewID GetFixedPositionScrollContainerId() { return mFixedPositionData ? mFixedPositionData->mScrollId : FrameMetrics::NULL_SCROLL_ID; }
LayerPoint GetFixedPositionAnchor() { return mFixedPositionData ? mFixedPositionData->mAnchor : LayerPoint(); }
+ bool IsFixedBackground() { return mFixedPositionData ? mFixedPositionData->mFixedBackground : false; }
FrameMetrics::ViewID GetStickyScrollContainerId() { return mStickyPositionData->mScrollId; }
const LayerRect& GetStickyScrollRangeOuter() { return mStickyPositionData->mOuter; }
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
float GetScrollbarThumbRatio() { return mScrollbarThumbRatio; }
bool IsScrollbarContainer() { return mIsScrollbarContainer; }
Layer* GetMaskLayer() const { return mMaskLayer; }
@@ -1765,16 +1769,21 @@ protected:
nsIntRegion mInvalidRegion;
nsTArray<nsRefPtr<AsyncPanZoomController> > mApzcs;
uint32_t mContentFlags;
bool mUseTileSourceRect;
bool mIsFixedPosition;
struct FixedPositionData {
FrameMetrics::ViewID mScrollId;
LayerPoint mAnchor;
+ // This is true for fixed background layers, and false for fixed position
+ // layers. The compositor needs to tell them apart because async scroll
+ // transforms should be applied to the clip rects of fixed background
+ // layers, but not to the clip rects of fixed position layers.
+ bool mFixedBackground;
};
UniquePtr<FixedPositionData> mFixedPositionData;
struct StickyPositionData {
FrameMetrics::ViewID mScrollId;
LayerRect mOuter;
LayerRect mInner;
};
nsAutoPtr<StickyPositionData> mStickyPositionData;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -326,17 +326,18 @@ LayerTransactionParent::RecvUpdate(Infal
layer->SetContentFlags(common.contentFlags());
layer->SetOpacity(common.opacity());
layer->SetClipRect(common.useClipRect() ? Some(common.clipRect()) : Nothing());
layer->SetBaseTransform(common.transform().value());
layer->SetPostScale(common.postXScale(), common.postYScale());
layer->SetIsFixedPosition(common.isFixedPosition());
if (common.isFixedPosition()) {
layer->SetFixedPositionData(common.fixedPositionScrollContainerId(),
- common.fixedPositionAnchor());
+ common.fixedPositionAnchor(),
+ common.isFixedBackground());
}
if (common.isStickyPosition()) {
layer->SetStickyPositionData(common.stickyScrollContainerId(),
common.stickyScrollRangeOuter(),
common.stickyScrollRangeInner());
}
layer->SetScrollbarData(common.scrollbarTargetContainerId(),
static_cast<Layer::ScrollDirection>(common.scrollbarDirection()),
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -212,16 +212,17 @@ struct CommonLayerAttributes {
float postYScale;
uint32_t contentFlags;
float opacity;
bool useClipRect;
ParentLayerIntRect clipRect;
bool isFixedPosition;
uint64_t fixedPositionScrollContainerId;
LayerPoint fixedPositionAnchor;
+ bool isFixedBackground;
bool isStickyPosition;
uint64_t stickyScrollContainerId;
LayerRect stickyScrollRangeOuter;
LayerRect stickyScrollRangeInner;
uint64_t scrollbarTargetContainerId;
uint32_t scrollbarDirection;
float scrollbarThumbRatio;
int8_t mixBlendMode;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1222,17 +1222,18 @@ protected:
* are directly on the viewport (e.g. background-attachment:fixed backgrounds).
*/
const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
bool aDisplayItemFixedToViewport);
/**
* Set fixed-pos layer metadata on aLayer according to the data for aFixedPosFrame.
*/
void SetFixedPositionLayerData(Layer* aLayer,
- const nsIFrame* aFixedPosFrame);
+ const nsIFrame* aFixedPosFrame,
+ bool aFixedBackground);
/**
* Returns true if aItem's opaque area (in aOpaque) covers the entire
* scrollable area of its presshell.
*/
bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
/**
@@ -2912,17 +2913,18 @@ ContainerState::FindFixedPosFrameForLaye
return nullptr;
}
}
return nullptr;
}
void
ContainerState::SetFixedPositionLayerData(Layer* aLayer,
- const nsIFrame* aFixedPosFrame)
+ const nsIFrame* aFixedPosFrame,
+ bool aFixedBackground)
{
aLayer->SetIsFixedPosition(aFixedPosFrame != nullptr);
if (!aFixedPosFrame) {
return;
}
nsPresContext* presContext = aFixedPosFrame->PresContext();
@@ -2943,17 +2945,18 @@ ContainerState::SetFixedPositionLayerDat
// For background-attachment:fixed items, the anchor point is always the
// top-left of the viewport currently.
viewportFrame = aFixedPosFrame;
}
// The anchorRect top-left is always the viewport top-left.
anchorRect.MoveTo(viewportFrame->GetOffsetToCrossDoc(mContainerReferenceFrame));
nsLayoutUtils::SetFixedPositionLayerData(aLayer,
- viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters);
+ viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters,
+ aFixedBackground);
}
static bool
CanOptimizeAwayPaintedLayer(PaintedLayerData* aData,
FrameLayerBuilder* aLayerBuilder)
{
if (!aLayerBuilder->IsBuildingRetainedLayers()) {
return false;
@@ -3210,17 +3213,18 @@ void ContainerState::FinishPaintedLayerD
} else if (data->mNeedComponentAlpha && !hidpi) {
flags |= Layer::CONTENT_COMPONENT_ALPHA;
}
if (data->mDisableFlattening) {
flags |= Layer::CONTENT_DISABLE_FLATTENING;
}
layer->SetContentFlags(flags);
- SetFixedPositionLayerData(layer, data->mFixedPosFrameForLayerData);
+ SetFixedPositionLayerData(layer, data->mFixedPosFrameForLayerData,
+ data->mSingleItemFixedToViewport);
PaintedLayerData* containingPaintedLayerData =
mLayerBuilder->GetContainingPaintedLayerData();
if (containingPaintedLayerData) {
if (!data->mDispatchToContentHitRegion.GetBounds().IsEmpty()) {
nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
mContainerReferenceFrame,
data->mDispatchToContentHitRegion.GetBounds(),
@@ -3940,17 +3944,17 @@ ContainerState::ProcessDisplayItems(nsDi
continue;
}
NS_ASSERTION(!ownLayer->AsPaintedLayer(),
"Should never have created a dedicated Painted layer!");
const nsIFrame* fixedPosFrame =
FindFixedPosFrameForLayerData(animatedGeometryRoot, shouldFixToViewport);
- SetFixedPositionLayerData(ownLayer, fixedPosFrame);
+ SetFixedPositionLayerData(ownLayer, fixedPosFrame, shouldFixToViewport);
nsRect invalid;
if (item->IsInvalid(invalid)) {
ownLayer->SetInvalidRectToVisibleRegion();
}
// If it's not a ContainerLayer, we need to apply the scale transform
// ourselves.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -4412,17 +4412,17 @@ nsDisplayStickyPosition::BuildLayer(nsDi
if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() &&
presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
scrollFrameSize = presContext->PresShell()->
GetScrollPositionClampingScrollPortSize();
}
nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame,
nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize),
- mFrame, presContext, aContainerParameters);
+ mFrame, presContext, aContainerParameters, /* fixed background = */ false);
ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor(
stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent());
float factor = presContext->AppUnitsPerDevPixel();
nsRect outer;
nsRect inner;
stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1708,17 +1708,18 @@ nsLayoutUtils::GetScrollableFrameFor(con
}
/* static */ void
nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
const nsIFrame* aViewportFrame,
const nsRect& aAnchorRect,
const nsIFrame* aFixedPosFrame,
nsPresContext* aPresContext,
- const ContainerLayerParameters& aContainerParameters) {
+ const ContainerLayerParameters& aContainerParameters,
+ bool aFixedBackground) {
// Find out the rect of the viewport frame relative to the reference frame.
// This, in conjunction with the container scale, will correspond to the
// coordinate-space of the built layer.
float factor = aPresContext->AppUnitsPerDevPixel();
Rect anchorRect(NSAppUnitsToFloatPixels(aAnchorRect.x, factor) *
aContainerParameters.mXScale,
NSAppUnitsToFloatPixels(aAnchorRect.y, factor) *
aContainerParameters.mYScale,
@@ -1762,17 +1763,17 @@ nsLayoutUtils::SetFixedPositionLayerData
}
ViewID id = FrameMetrics::NULL_SCROLL_ID;
if (nsIFrame* rootScrollFrame = aPresContext->PresShell()->GetRootScrollFrame()) {
if (nsIContent* content = rootScrollFrame->GetContent()) {
id = FindOrCreateIDFor(content);
}
}
- aLayer->SetFixedPositionData(id, anchor);
+ aLayer->SetFixedPositionData(id, anchor, aFixedBackground);
}
bool
nsLayoutUtils::ViewportHasDisplayPort(nsPresContext* aPresContext, nsRect* aDisplayPort)
{
nsIFrame* rootScrollFrame =
aPresContext->PresShell()->GetRootScrollFrame();
return rootScrollFrame &&
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -490,22 +490,25 @@ public:
* Sets the fixed-pos metadata properties on aLayer.
* aAnchorRect is the basic anchor rectangle. If aFixedPosFrame is not a viewport
* frame, then we pick a corner of aAnchorRect to as the anchor point for the
* fixed-pos layer (i.e. the point to remain stable during zooming), based
* on which of the fixed-pos frame's CSS absolute positioning offset
* properties (top, left, right, bottom) are auto. aAnchorRect is in the
* coordinate space of aLayer's container layer (i.e. relative to the reference
* frame of the display item which is building aLayer's container layer).
+ * aFixedBackground if true if the layer is for a fixed background (as opposed
+ * to a fixed position-element).
*/
static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame,
const nsRect& aAnchorRect,
const nsIFrame* aFixedPosFrame,
nsPresContext* aPresContext,
- const ContainerLayerParameters& aContainerParameters);
+ const ContainerLayerParameters& aContainerParameters,
+ bool aFixedBackground);
/**
* Return true if aPresContext's viewport has a displayport.
* Fills in aDisplayPort with the displayport rectangle if non-null.
*/
static bool ViewportHasDisplayPort(nsPresContext* aPresContext,
nsRect* aDisplayPort = nullptr);