Index: third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp |
diff --git a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp |
index 183c283f6643d581e622967a72eaaa90dd9ddf8c..209f8a7334eba7e0c8ed143a40d18e23369d72b0 100644 |
--- a/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp |
+++ b/third_party/WebKit/Source/core/layout/compositing/CompositedLayerMapping.cpp |
@@ -173,6 +173,61 @@ static ScrollingCoordinator* scrollingCoordinatorFromLayer(PaintLayer& layer) { |
return (!page) ? nullptr : page->scrollingCoordinator(); |
} |
+static const LayoutBoxModelObject* nearestCompositedStickyAncestor( |
+ const StickyConstraintsMap& constraintsMap, |
+ const StickyPositionScrollingConstraints& constraints) { |
+ const LayoutBoxModelObject* obj = constraints.nearestStickyAncestor(); |
+ while (obj && !obj->layer()->compositedLayerMapping()) { |
+ DCHECK(constraintsMap.contains(obj->layer())); |
+ obj = constraintsMap.at(obj->layer()).nearestStickyAncestor(); |
+ } |
+ return obj; |
+} |
+ |
+// Return the id of the nearest composited sticky layer that shifts |
+// |constraints| sticky box, or kInvalidLayerId if no such layer exists. |
+static int nearestCompositedStickyLayerShiftingStickyBox( |
+ const StickyConstraintsMap& constraintsMap, |
+ const StickyPositionScrollingConstraints& constraints) { |
+ LayoutBoxModelObject* obj = constraints.nearestStickyBoxShiftingStickyBox(); |
+ while (obj && !obj->layer()->compositedLayerMapping()) { |
+ DCHECK(constraintsMap.contains(obj->layer())); |
+ obj = constraintsMap.at(obj->layer()).nearestStickyBoxShiftingStickyBox(); |
+ } |
+ |
+ if (!obj) |
+ return WebLayer::kInvalidLayerId; |
+ |
+ return obj->layer() |
+ ->compositedLayerMapping() |
+ ->mainGraphicsLayer() |
+ ->platformLayer() |
+ ->id(); |
+} |
+ |
+// Return the id of the nearest composited sticky layer that shifts |
+// |constraints| containing block, or kInvalidLayerId if no such layer exists. |
+static int nearestCompositedStickyLayerShiftingContainingBlock( |
+ const StickyConstraintsMap& constraintsMap, |
+ const StickyPositionScrollingConstraints& constraints) { |
+ LayoutBoxModelObject* obj = |
+ constraints.nearestStickyBoxShiftingContainingBlock(); |
+ while (obj && !obj->layer()->compositedLayerMapping()) { |
+ DCHECK(constraintsMap.contains(obj->layer())); |
+ obj = constraintsMap.at(obj->layer()) |
+ .nearestStickyBoxShiftingContainingBlock(); |
+ } |
+ |
+ if (!obj) |
+ return WebLayer::kInvalidLayerId; |
+ |
+ return obj->layer() |
+ ->compositedLayerMapping() |
+ ->mainGraphicsLayer() |
+ ->platformLayer() |
+ ->id(); |
+} |
+ |
CompositedLayerMapping::CompositedLayerMapping(PaintLayer& layer) |
: m_owningLayer(layer), |
m_contentOffsetInCompositingLayerDirty(false), |
@@ -308,14 +363,24 @@ void CompositedLayerMapping::updateStickyConstraints( |
WebLayerStickyPositionConstraint webConstraint; |
if (sticky) { |
+ const StickyConstraintsMap& constraintsMap = |
+ ancestorOverflowLayer->getScrollableArea()->stickyConstraintsMap(); |
const StickyPositionScrollingConstraints& constraints = |
- ancestorOverflowLayer->getScrollableArea()->stickyConstraintsMap().at( |
- &m_owningLayer); |
+ constraintsMap.at(&m_owningLayer); |
- // Find the layout offset of the unshifted sticky box within its |
- // compositingContainer. If the enclosing layer is not the scroller, then |
- // the offset must be adjusted to include the scroll offset to keep it |
- // relative to compositingContainer. |
+ // Find the layout offset of the unshifted sticky box within its parent |
+ // composited layer. This information is used by the compositor side to |
+ // compute the additional offset required to keep the element stuck under |
+ // compositor scrolling. |
+ // |
+ // Starting from the scroll container relative location, removing the |
+ // enclosing layers offset and the content offset in the composited layer |
+ // results in the parent-layer relative offset. |
+ FloatPoint parentRelativeStickyBoxOffset = |
+ constraints.scrollContainerRelativeStickyBoxRect().location(); |
+ |
+ // The enclosing layers offset returned from |convertToLayerCoords| must be |
+ // adjusted for both scroll and ancestor sticky elements. |
LayoutPoint enclosingLayerOffset; |
compositingContainer->convertToLayerCoords(ancestorOverflowLayer, |
enclosingLayerOffset); |
@@ -323,12 +388,17 @@ void CompositedLayerMapping::updateStickyConstraints( |
enclosingLayerOffset += LayoutSize( |
ancestorOverflowLayer->getScrollableArea()->getScrollOffset()); |
} |
+ if (const LayoutBoxModelObject* ancestor = |
+ nearestCompositedStickyAncestor(constraintsMap, constraints)) { |
+ enclosingLayerOffset -= |
+ roundedIntSize(constraintsMap.at(ancestor->layer()) |
+ .getTotalContainingBlockStickyOffset()); |
+ } |
- FloatPoint stickyBoxOffset = |
- constraints.scrollContainerRelativeStickyBoxRect().location(); |
DCHECK(!m_contentOffsetInCompositingLayerDirty); |
- stickyBoxOffset.moveBy(FloatPoint(-enclosingLayerOffset) - |
- FloatSize(contentOffsetInCompositingLayer())); |
+ parentRelativeStickyBoxOffset.moveBy( |
+ FloatPoint(-enclosingLayerOffset) - |
+ FloatSize(contentOffsetInCompositingLayer())); |
webConstraint.isSticky = true; |
webConstraint.isAnchoredLeft = |
@@ -347,13 +417,17 @@ void CompositedLayerMapping::updateStickyConstraints( |
webConstraint.rightOffset = constraints.rightOffset(); |
webConstraint.topOffset = constraints.topOffset(); |
webConstraint.bottomOffset = constraints.bottomOffset(); |
- webConstraint.parentRelativeStickyBoxOffset = |
- roundedIntPoint(stickyBoxOffset); |
+ webConstraint.parentRelativeStickyBoxOffset = parentRelativeStickyBoxOffset; |
webConstraint.scrollContainerRelativeStickyBoxRect = |
- enclosingIntRect(constraints.scrollContainerRelativeStickyBoxRect()); |
- webConstraint.scrollContainerRelativeContainingBlockRect = enclosingIntRect( |
- constraints.scrollContainerRelativeContainingBlockRect()); |
- // TODO(smcgruer): Copy fields for nested sticky in cc (crbug.com/672710) |
+ constraints.scrollContainerRelativeStickyBoxRect(); |
+ webConstraint.scrollContainerRelativeContainingBlockRect = |
+ constraints.scrollContainerRelativeContainingBlockRect(); |
+ webConstraint.nearestLayerShiftingStickyBox = |
+ nearestCompositedStickyLayerShiftingStickyBox(constraintsMap, |
+ constraints); |
+ webConstraint.nearestLayerShiftingContainingBlock = |
+ nearestCompositedStickyLayerShiftingContainingBlock(constraintsMap, |
+ constraints); |
} |
m_graphicsLayer->setStickyPositionConstraint(webConstraint); |