| Index: third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp
|
| diff --git a/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp b/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp
|
| index 61150ecbbc4485b164011349d4eae3a78b547eee..10e8efd6d8af6b5a69391c36e7f4a21d55a93945 100644
|
| --- a/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp
|
| +++ b/third_party/WebKit/Source/core/page/scrolling/StickyPositionScrollingConstraints.cpp
|
| @@ -8,33 +8,43 @@
|
| namespace blink {
|
|
|
| FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
| - const FloatRect& viewport_rect,
|
| - const StickyPositionScrollingConstraints* ancestor_sticky_box_constraints,
|
| - const StickyPositionScrollingConstraints*
|
| - ancestor_containing_block_constraints) {
|
| - // Adjust the constraint rect locations based on our ancestor sticky elements
|
| - // These adjustments are necessary to avoid double offsetting in the case of
|
| - // nested sticky elements.
|
| - FloatSize ancestor_sticky_box_offset =
|
| - ancestor_sticky_box_constraints
|
| - ? ancestor_sticky_box_constraints->GetTotalStickyBoxStickyOffset()
|
| - : FloatSize();
|
| - FloatSize ancestor_containing_block_offset =
|
| - ancestor_containing_block_constraints
|
| - ? ancestor_containing_block_constraints
|
| - ->GetTotalContainingBlockStickyOffset()
|
| - : FloatSize();
|
| + const FloatRect& overflow_clip_rect,
|
| + const StickyConstraintsMap& constraints_map) {
|
| FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect_;
|
| FloatRect containing_block_rect =
|
| scroll_container_relative_containing_block_rect_;
|
| + FloatSize ancestor_sticky_box_offset =
|
| + AncestorStickyBoxOffset(constraints_map);
|
| + FloatSize ancestor_containing_block_offset =
|
| + AncestorContainingBlockOffset(constraints_map);
|
| +
|
| + // Adjust the cached rect locations for any sticky ancestor elements. The
|
| + // sticky offset applied to those ancestors affects us as follows:
|
| + //
|
| + // 1. |nearest_sticky_layer_shifting_sticky_box_| is a sticky layer between
|
| + // ourselves and our containing block, e.g. a nested inline parent.
|
| + // It shifts only the sticky_box_rect and not the containing_block_rect.
|
| + // 2. |nearest_sticky_layer_shifting_containing_block_| is a sticky layer
|
| + // between our containing block (inclusive) and our scroll ancestor
|
| + // (exclusive). As such, it shifts both the sticky_box_rect and the
|
| + // containing_block_rect.
|
| + //
|
| + // Note that this calculation assumes that |ComputeStickyOffset| is being
|
| + // called top down, e.g. it has been called on any ancestors we have before
|
| + // being called on us.
|
| sticky_box_rect.Move(ancestor_sticky_box_offset +
|
| ancestor_containing_block_offset);
|
| containing_block_rect.Move(ancestor_containing_block_offset);
|
|
|
| + // We now attempt to shift sticky_box_rect to obey the specified sticky
|
| + // constraints, whilst always staying within our containing block. This
|
| + // shifting produces the final sticky offset below.
|
| + //
|
| + // As per the spec, 'left' overrides 'right' and 'top' overrides 'bottom'.
|
| FloatRect box_rect = sticky_box_rect;
|
|
|
| if (HasAnchorEdge(kAnchorEdgeRight)) {
|
| - float right_limit = viewport_rect.MaxX() - right_offset_;
|
| + float right_limit = overflow_clip_rect.MaxX() - right_offset_;
|
| float right_delta =
|
| std::min<float>(0, right_limit - sticky_box_rect.MaxX());
|
| float available_space =
|
| @@ -46,7 +56,7 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
| }
|
|
|
| if (HasAnchorEdge(kAnchorEdgeLeft)) {
|
| - float left_limit = viewport_rect.X() + left_offset_;
|
| + float left_limit = overflow_clip_rect.X() + left_offset_;
|
| float left_delta = std::max<float>(0, left_limit - sticky_box_rect.X());
|
| float available_space = std::max<float>(
|
| 0, containing_block_rect.MaxX() - sticky_box_rect.MaxX());
|
| @@ -57,7 +67,7 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
| }
|
|
|
| if (HasAnchorEdge(kAnchorEdgeBottom)) {
|
| - float bottom_limit = viewport_rect.MaxY() - bottom_offset_;
|
| + float bottom_limit = overflow_clip_rect.MaxY() - bottom_offset_;
|
| float bottom_delta =
|
| std::min<float>(0, bottom_limit - sticky_box_rect.MaxY());
|
| float available_space =
|
| @@ -69,7 +79,7 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
| }
|
|
|
| if (HasAnchorEdge(kAnchorEdgeTop)) {
|
| - float top_limit = viewport_rect.Y() + top_offset_;
|
| + float top_limit = overflow_clip_rect.Y() + top_offset_;
|
| float top_delta = std::max<float>(0, top_limit - sticky_box_rect.Y());
|
| float available_space = std::max<float>(
|
| 0, containing_block_rect.MaxY() - sticky_box_rect.MaxY());
|
| @@ -81,6 +91,8 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
|
|
| FloatSize sticky_offset = box_rect.Location() - sticky_box_rect.Location();
|
|
|
| + // Now that we have computed our current sticky offset, update the cached
|
| + // accumulated sticky offsets.
|
| total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset;
|
| total_containing_block_sticky_offset_ = ancestor_sticky_box_offset +
|
| ancestor_containing_block_offset +
|
| @@ -91,14 +103,34 @@ FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset(
|
|
|
| FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition(
|
| const StickyConstraintsMap& constraints_map) const {
|
| - FloatSize nearest_sticky_box_shifting_sticky_box_constraints_offset;
|
| - if (nearest_sticky_box_shifting_sticky_box_) {
|
| - nearest_sticky_box_shifting_sticky_box_constraints_offset =
|
| - constraints_map.at(nearest_sticky_box_shifting_sticky_box_->Layer())
|
| - .GetTotalStickyBoxStickyOffset();
|
| + FloatSize nearest_sticky_layer_shifting_sticky_box_constraints_offset;
|
| + if (nearest_sticky_layer_shifting_sticky_box_) {
|
| + nearest_sticky_layer_shifting_sticky_box_constraints_offset =
|
| + constraints_map.at(nearest_sticky_layer_shifting_sticky_box_)
|
| + .total_sticky_box_sticky_offset_;
|
| }
|
| return total_sticky_box_sticky_offset_ -
|
| - nearest_sticky_box_shifting_sticky_box_constraints_offset;
|
| + nearest_sticky_layer_shifting_sticky_box_constraints_offset;
|
| +}
|
| +
|
| +FloatSize StickyPositionScrollingConstraints::AncestorStickyBoxOffset(
|
| + const StickyConstraintsMap& constraints_map) {
|
| + if (!nearest_sticky_layer_shifting_sticky_box_)
|
| + return FloatSize();
|
| + DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box_));
|
| + return constraints_map.at(nearest_sticky_layer_shifting_sticky_box_)
|
| + .total_sticky_box_sticky_offset_;
|
| +}
|
| +
|
| +FloatSize StickyPositionScrollingConstraints::AncestorContainingBlockOffset(
|
| + const StickyConstraintsMap& constraints_map) {
|
| + if (!nearest_sticky_layer_shifting_containing_block_) {
|
| + return FloatSize();
|
| + }
|
| + DCHECK(constraints_map.Contains(
|
| + nearest_sticky_layer_shifting_containing_block_));
|
| + return constraints_map.at(nearest_sticky_layer_shifting_containing_block_)
|
| + .total_containing_block_sticky_offset_;
|
| }
|
|
|
| } // namespace blink
|
|
|