Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp |
| index 3c99a4f3c5eb3da5913a534299fbc9bd5576aa89..d339e12ae601deea458f82910cff79dc9f09c932 100644 |
| --- a/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp |
| +++ b/third_party/WebKit/Source/core/layout/LayoutBoxModelObject.cpp |
| @@ -787,7 +787,7 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const { |
| while (containingBlock->isAnonymous()) { |
| containingBlock = containingBlock->containingBlock(); |
| } |
| - MapCoordinatesFlags flags = 0; |
| + MapCoordinatesFlags flags = IgnoreSticky; |
| skippedContainersOffset = |
| toFloatSize(locationContainer |
| ->localToAncestorQuadWithoutTransforms( |
| @@ -885,6 +885,46 @@ void LayoutBoxModelObject::updateStickyPositionConstraints() const { |
| toFloatSize(stickyLocation), |
| flippedStickyBoxRect.size())); |
| + // To correctly compute the offsets, the constraints need to know about any |
| + // nested position:sticky between themselves and their containingBlock, and |
| + // between the containingBlock and their scrollAncestor. |
| + // |
| + // The respective search ranges are [container, containingBlock) and |
| + // [containingBlock, scrollAncestor). |
| + |
| + // TODO(smcgruer): Fold these into the walks to find the containingBlock and |
| + // scrollAncestor. |
| + LayoutObject* maybeStickyAncestor = locationContainer; |
| + while (maybeStickyAncestor && maybeStickyAncestor != containingBlock) { |
| + if (maybeStickyAncestor->isStickyPositioned()) { |
| + constraints.setNearestStickyElementShiftingStickyBox( |
| + toLayoutBoxModelObject(maybeStickyAncestor)); |
| + break; |
| + } |
| + maybeStickyAncestor = |
| + maybeStickyAncestor->isLayoutInline() |
| + ? maybeStickyAncestor->containingBlock() |
| + : toLayoutBox(maybeStickyAncestor)->locationContainer(); |
| + } |
|
flackr
2017/01/31 18:33:00
Create a function for this common loop code, maybe
smcgruer
2017/01/31 20:42:16
I was intended to look at folding these into the w
flackr
2017/02/02 18:18:11
Yes, we should just clean it up with a helper func
|
| + |
| + // NOTE(smcgruer): We cannot use |scrollAncestor| here as it disregards the |
| + // root ancestorOverflowLayer(), which we should include for the purposes of |
| + // finding the nearest sticky element that shifts the containing block rect. |
| + LayoutObject* ancestorOverflowLayer = |
| + layer()->ancestorOverflowLayer()->layoutObject(); |
| + maybeStickyAncestor = containingBlock; |
| + while (maybeStickyAncestor && maybeStickyAncestor != ancestorOverflowLayer) { |
| + if (maybeStickyAncestor->isStickyPositioned()) { |
| + constraints.setNearestStickyElementShiftingContainingBlock( |
| + toLayoutBoxModelObject(maybeStickyAncestor)); |
| + break; |
| + } |
| + maybeStickyAncestor = |
| + maybeStickyAncestor->isLayoutInline() |
| + ? maybeStickyAncestor->containingBlock() |
| + : toLayoutBox(maybeStickyAncestor)->locationContainer(); |
| + } |
| + |
| // We skip the right or top sticky offset if there is not enough space to |
| // honor both the left/right or top/bottom offsets. |
| LayoutUnit horizontalOffsets = |
| @@ -982,15 +1022,39 @@ LayoutSize LayoutBoxModelObject::stickyPositionOffset() const { |
| PaintLayerScrollableArea* scrollableArea = |
| ancestorOverflowLayer->getScrollableArea(); |
| + auto it = scrollableArea->stickyConstraintsMap().find(layer()); |
| + |
| // The sticky offset is physical, so we can just return the delta computed in |
| // absolute coords (though it may be wrong with transforms). |
| // TODO: Force compositing input update if we ask for offset with stale |
| // compositing inputs. |
| - if (!scrollableArea->stickyConstraintsMap().contains(layer())) |
| + if (it == scrollableArea->stickyConstraintsMap().end()) |
| return LayoutSize(); |
| + |
| + StickyPositionScrollingConstraints& constraints = it->value; |
| + |
| + FloatSize ancestorStickyBoxOffset; |
| + FloatSize ancestorContainingBlockOffset; |
| + |
| + const LayoutBoxModelObject* toContainingBlock = |
| + constraints.nearestStickyElementShiftingStickyBox(); |
| + if (toContainingBlock) { |
| + ancestorStickyBoxOffset = scrollableArea->stickyConstraintsMap() |
| + .get(toContainingBlock->layer()) |
|
flackr
2017/01/31 18:33:00
nit: Helper function to get sticky constraints for
smcgruer
2017/01/31 20:42:16
Done.
|
| + .getTotalStickyBoxStickyOffset(); |
|
flackr
2017/01/31 18:33:00
It'd probably be cleaner to get these as part of c
smcgruer
2017/01/31 20:42:16
Done.
|
| + } |
| + |
| + const LayoutBoxModelObject* toViewport = |
| + constraints.nearestStickyElementShiftingContainingBlock(); |
| + if (toViewport) { |
| + ancestorContainingBlockOffset = scrollableArea->stickyConstraintsMap() |
| + .get(toViewport->layer()) |
| + .getTotalContainingBlockStickyOffset(); |
| + } |
| + |
| return LayoutSize( |
| - scrollableArea->stickyConstraintsMap().get(layer()).computeStickyOffset( |
| - constrainingRect)); |
| + constraints.computeStickyOffset(constrainingRect, ancestorStickyBoxOffset, |
| + ancestorContainingBlockOffset)); |
| } |
| LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo( |