| 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..5cc134d1e23a970c7c067c18d8c28c37d5368aa6 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();
|
| + }
|
| +
|
| + // 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())
|
| + .getTotalStickyBoxStickyOffset();
|
| + }
|
| +
|
| + 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(
|
| @@ -1058,11 +1122,12 @@ LayoutPoint LayoutBoxModelObject::adjustedPositionRelativeTo(
|
| return referencePoint;
|
| }
|
|
|
| -LayoutSize LayoutBoxModelObject::offsetForInFlowPosition() const {
|
| +LayoutSize LayoutBoxModelObject::offsetForInFlowPosition(
|
| + bool ignoreSticky) const {
|
| if (isRelPositioned())
|
| return relativePositionOffset();
|
|
|
| - if (isStickyPositioned())
|
| + if (!ignoreSticky && isStickyPositioned())
|
| return stickyPositionOffset();
|
|
|
| return LayoutSize();
|
|
|