mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 946502. Part 3: Extend FrameLayerBuilder to set fixed-pos metadata on layers created for background-attachment:fixed content. r=mattwoodrow
--HG-- extra : rebase_source : dbaab718d7a358bfaa40124913bcd5acf0255aa1
This commit is contained in:
parent
6136dbc17c
commit
cac6eb1c2d
@ -607,6 +607,8 @@ protected:
|
||||
* has a displayport. Updates *aVisibleRegion to be the intersection of
|
||||
* aDrawRegion and the displayport, and updates *aIsSolidColorInVisibleRegion
|
||||
* (if non-null) to false if the visible region grows.
|
||||
* This can return the actual viewport frame for layers whose display items
|
||||
* are directly on the viewport (e.g. background-attachment:fixed backgrounds).
|
||||
*/
|
||||
const nsIFrame* FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryRoot,
|
||||
const nsIntRegion& aDrawRegion,
|
||||
@ -1661,15 +1663,31 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
|
||||
nsIntRegion* aVisibleRegion,
|
||||
bool* aIsSolidColorInVisibleRegion)
|
||||
{
|
||||
nsIFrame *viewport = mContainerFrame->PresContext()->PresShell()->GetRootFrame();
|
||||
nsPresContext* presContext = mContainerFrame->PresContext();
|
||||
nsIFrame* viewport = presContext->PresShell()->GetRootFrame();
|
||||
const nsIFrame* result = nullptr;
|
||||
nsRect displayPort;
|
||||
|
||||
if (viewport == aAnimatedGeometryRoot &&
|
||||
nsLayoutUtils::ViewportHasDisplayPort(presContext, &displayPort)) {
|
||||
// Probably a background-attachment:fixed item
|
||||
result = viewport;
|
||||
} else {
|
||||
// Viewports with no fixed-pos frames are not relevant.
|
||||
if (!viewport->GetFirstChild(nsIFrame::kFixedList)) {
|
||||
return nullptr;
|
||||
}
|
||||
nsRect displayPort;
|
||||
for (const nsIFrame* f = aAnimatedGeometryRoot; f; f = f->GetParent()) {
|
||||
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(f, &displayPort)) {
|
||||
result = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Display ports are relative to the viewport, convert it to be relative
|
||||
// to our reference frame.
|
||||
displayPort += viewport->GetOffsetToCrossDoc(mContainerReferenceFrame);
|
||||
@ -1682,10 +1700,7 @@ ContainerState::FindFixedPosFrameForLayerData(const nsIFrame* aAnimatedGeometryR
|
||||
}
|
||||
*aVisibleRegion = newVisibleRegion;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1697,19 +1712,31 @@ ContainerState::SetFixedPositionLayerData(Layer* aLayer,
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* viewportFrame = aFixedPosFrame->GetParent();
|
||||
nsPresContext* presContext = aFixedPosFrame->PresContext();
|
||||
|
||||
const nsIFrame* viewportFrame = aFixedPosFrame->GetParent();
|
||||
// anchorRect will be in the container's coordinate system (aLayer's parent layer).
|
||||
// This is the same as the display items' reference frame.
|
||||
nsRect anchorRect;
|
||||
if (viewportFrame) {
|
||||
// Fixed position frames are reflowed into the scroll-port size if one has
|
||||
// been set.
|
||||
nsSize viewportSize = viewportFrame->GetSize();
|
||||
if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
viewportSize = presContext->PresShell()->
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
anchorRect.SizeTo(presContext->PresShell()->GetScrollPositionClampingScrollPortSize());
|
||||
} else {
|
||||
anchorRect.SizeTo(viewportFrame->GetSize());
|
||||
}
|
||||
} else {
|
||||
// A display item directly attached to the viewport.
|
||||
// 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, viewportSize, aFixedPosFrame, presContext, mParameters);
|
||||
viewportFrame, anchorRect, aFixedPosFrame, presContext, mParameters);
|
||||
}
|
||||
|
||||
static gfx3DMatrix
|
||||
@ -2131,6 +2158,14 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
|
||||
thebesLayerData->mLayer = layer;
|
||||
thebesLayerData->mAnimatedGeometryRoot = aActiveScrolledRoot;
|
||||
thebesLayerData->mReferenceFrame = aItem->ReferenceFrame();
|
||||
if (!aActiveScrolledRoot->GetParent() &&
|
||||
nsLayoutUtils::ViewportHasDisplayPort(aActiveScrolledRoot->PresContext())) {
|
||||
// The active scrolled root is the viewport, so this is background-attachment:fixed
|
||||
// or fixed-pos elements or something like that. Async scrolling may
|
||||
// do magic things to move these layers, so don't allow any regular content
|
||||
// to be pushed to layers below them; that might turn out to be incorrect.
|
||||
thebesLayerData->SetAllDrawingAbove();
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???");
|
||||
*mNewChildLayers.AppendElement() = layer.forget();
|
||||
|
@ -3455,9 +3455,9 @@ nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
}
|
||||
|
||||
nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame, scrollFrameSize,
|
||||
mStickyPosFrame,
|
||||
presContext, aContainerParameters);
|
||||
nsLayoutUtils::SetFixedPositionLayerData(layer, scrollFrame,
|
||||
nsRect(scrollFrame->GetOffsetToCrossDoc(ReferenceFrame()), scrollFrameSize),
|
||||
mStickyPosFrame, presContext, aContainerParameters);
|
||||
|
||||
ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor(
|
||||
stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent());
|
||||
|
@ -1203,7 +1203,7 @@ nsLayoutUtils::GetScrollableFrameFor(const nsIFrame *aScrolledFrame)
|
||||
/* static */ void
|
||||
nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
|
||||
const nsIFrame* aViewportFrame,
|
||||
nsSize aViewportSize,
|
||||
const nsRect& aAnchorRect,
|
||||
const nsIFrame* aFixedPosFrame,
|
||||
nsPresContext* aPresContext,
|
||||
const ContainerLayerParameters& aContainerParameters) {
|
||||
@ -1211,22 +1211,43 @@ nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
|
||||
// This, in conjunction with the container scale, will correspond to the
|
||||
// coordinate-space of the built layer.
|
||||
float factor = aPresContext->AppUnitsPerDevPixel();
|
||||
nsPoint origin = aViewportFrame->GetOffsetToCrossDoc(aFixedPosFrame);
|
||||
LayerRect anchorRect(NSAppUnitsToFloatPixels(origin.x, factor) *
|
||||
Rect anchorRect(NSAppUnitsToFloatPixels(aAnchorRect.x, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(origin.y, factor) *
|
||||
NSAppUnitsToFloatPixels(aAnchorRect.y, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(aViewportSize.width, factor) *
|
||||
NSAppUnitsToFloatPixels(aAnchorRect.width, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(aViewportSize.height, factor) *
|
||||
NSAppUnitsToFloatPixels(aAnchorRect.height, factor) *
|
||||
aContainerParameters.mYScale);
|
||||
// Need to transform anchorRect from the container layer's coordinate system
|
||||
// into aLayer's coordinate system.
|
||||
Matrix transform2d;
|
||||
if (aLayer->GetTransform().Is2D(&transform2d)) {
|
||||
transform2d.Invert();
|
||||
anchorRect = transform2d.TransformBounds(anchorRect);
|
||||
} else {
|
||||
NS_ERROR("3D transform found between fixedpos content and its viewport (should never happen)");
|
||||
anchorRect = Rect(0,0,0,0);
|
||||
}
|
||||
|
||||
// Work out the anchor point for this fixed position layer. We assume that
|
||||
// any positioning set (left/top/right/bottom) indicates that the
|
||||
// corresponding side of its container should be the anchor point,
|
||||
// defaulting to top-left.
|
||||
LayerPoint anchor = anchorRect.TopLeft();
|
||||
LayerPoint anchor(anchorRect.x, anchorRect.y);
|
||||
// Make sure the layer is aware of any fixed position margins that have
|
||||
// been set.
|
||||
nsMargin fixedMargins = aPresContext->PresShell()->GetContentDocumentFixedPositionMargins();
|
||||
LayerMargin fixedLayerMargins(NSAppUnitsToFloatPixels(fixedMargins.top, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.right, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.bottom, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.left, factor) *
|
||||
aContainerParameters.mXScale);
|
||||
|
||||
if (aFixedPosFrame != aViewportFrame) {
|
||||
const nsStylePosition* position = aFixedPosFrame->StylePosition();
|
||||
if (position->mOffset.GetRightUnit() != eStyleUnit_Auto) {
|
||||
if (position->mOffset.GetLeftUnit() != eStyleUnit_Auto) {
|
||||
@ -1243,20 +1264,6 @@ nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
|
||||
}
|
||||
}
|
||||
|
||||
aLayer->SetFixedPositionAnchor(anchor);
|
||||
|
||||
// Also make sure the layer is aware of any fixed position margins that have
|
||||
// been set.
|
||||
nsMargin fixedMargins = aPresContext->PresShell()->GetContentDocumentFixedPositionMargins();
|
||||
LayerMargin fixedLayerMargins(NSAppUnitsToFloatPixels(fixedMargins.top, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.right, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.bottom, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.left, factor) *
|
||||
aContainerParameters.mXScale);
|
||||
|
||||
// If the frame is auto-positioned on either axis, set the top/left layer
|
||||
// margins to -1, to indicate to the compositor that this layer is
|
||||
// unaffected by fixed margins.
|
||||
@ -1268,10 +1275,21 @@ nsLayoutUtils::SetFixedPositionLayerData(Layer* aLayer,
|
||||
position->mOffset.GetBottomUnit() == eStyleUnit_Auto) {
|
||||
fixedLayerMargins.top = -1;
|
||||
}
|
||||
}
|
||||
|
||||
aLayer->SetFixedPositionAnchor(anchor);
|
||||
aLayer->SetFixedPositionMargins(fixedLayerMargins);
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::ViewportHasDisplayPort(nsPresContext* aPresContext, nsRect* aDisplayPort)
|
||||
{
|
||||
nsIFrame* rootScrollFrame =
|
||||
aPresContext->PresShell()->GetRootScrollFrame();
|
||||
return rootScrollFrame &&
|
||||
nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), aDisplayPort);
|
||||
}
|
||||
|
||||
bool
|
||||
nsLayoutUtils::IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, nsRect* aDisplayPort)
|
||||
{
|
||||
@ -1283,12 +1301,7 @@ nsLayoutUtils::IsFixedPosFrameInDisplayPort(const nsIFrame* aFrame, nsRect* aDis
|
||||
aFrame->StyleDisplay()->mPosition != NS_STYLE_POSITION_FIXED) {
|
||||
return false;
|
||||
}
|
||||
nsIFrame* rootScrollFrame =
|
||||
aFrame->PresContext()->PresShell()->GetRootScrollFrame();
|
||||
// Treat a fixed-pos frame as an animated geometry root if it belongs to
|
||||
// a viewport which has a scrollframe and a displayport.
|
||||
return rootScrollFrame &&
|
||||
nsLayoutUtils::GetDisplayPort(rootScrollFrame->GetContent(), aDisplayPort);
|
||||
return ViewportHasDisplayPort(aFrame->PresContext(), aDisplayPort);
|
||||
}
|
||||
|
||||
nsIFrame*
|
||||
|
@ -375,12 +375,29 @@ public:
|
||||
static bool IsAncestorFrameCrossDoc(const nsIFrame* aAncestorFrame, const nsIFrame* aFrame,
|
||||
const nsIFrame* aCommonAncestor = nullptr);
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
static void SetFixedPositionLayerData(Layer* aLayer, const nsIFrame* aViewportFrame,
|
||||
nsSize aViewportSize,
|
||||
const nsRect& aAnchorRect,
|
||||
const nsIFrame* aFixedPosFrame,
|
||||
nsPresContext* aPresContext,
|
||||
const ContainerLayerParameters& aContainerParameters);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Return true if aFrame is a fixed-pos frame and is a child of a viewport
|
||||
* which has a displayport. These frames get special treatment from the compositor.
|
||||
|
Loading…
Reference in New Issue
Block a user