summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc')
-rw-r--r--chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc239
1 files changed, 47 insertions, 192 deletions
diff --git a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index 74356de121e..ec73eb3807d 100644
--- a/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/chromium/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -6,6 +6,7 @@
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node.h"
+#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/layout/layout_block.h"
#include "third_party/blink/renderer/core/layout/layout_box.h"
#include "third_party/blink/renderer/core/layout/layout_view.h"
@@ -114,8 +115,8 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
if (!scrollable_area)
return;
- FloatPoint max_position = ScrollOffsetToPosition(
- scrollable_area->MaximumScrollOffset(), scrollable_area->ScrollOrigin());
+ FloatPoint max_position = scrollable_area->ScrollOffsetToPosition(
+ scrollable_area->MaximumScrollOffset());
snap_container_data.set_max_position(
gfx::ScrollOffset(max_position.X(), max_position.Y()));
@@ -151,6 +152,7 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
MinimumValueForLength(container_style->ScrollPaddingLeft(),
container_rect.Width()));
container_rect.Contract(container_padding);
+ snap_container_data.set_rect(FloatRect(container_rect));
if (snap_container_data.scroll_snap_type().strictness ==
SnapStrictness::kProximity) {
@@ -162,158 +164,13 @@ void SnapCoordinator::UpdateSnapContainerData(const LayoutBox& snap_container) {
if (SnapAreaSet* snap_areas = snap_container.SnapAreas()) {
for (const LayoutBox* snap_area : *snap_areas) {
- snap_container_data.AddSnapAreaData(CalculateSnapAreaData(
- *snap_area, snap_container, container_rect, max_position));
+ snap_container_data.AddSnapAreaData(
+ CalculateSnapAreaData(*snap_area, snap_container));
}
}
snap_container_map_.Set(&snap_container, snap_container_data);
}
-static float ClipInContainer(LayoutUnit unit, float max) {
- float value = unit.ClampNegativeToZero().ToFloat();
- return value > max ? max : value;
-}
-
-// Returns scroll offset at which the snap area and snap containers meet the
-// requested snapping alignment on the given axis.
-// If the scroll offset required for the alignment is outside the valid range
-// then it will be clamped.
-// alignment - The scroll-snap-align specified on the snap area.
-// https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-align
-// axis - The axis for which we consider alignment on. Should be either X or Y
-// container - The snap_container rect relative to the container_element's
-// boundary. Note that this rect is represented by the dotted box below,
-// which is contracted by the scroll-padding from the element's original
-// boundary.
-// max_position - The maximal scrollable offset of the container. The
-// calculated snap_position can not be larger than this value.
-// area - The snap area rect relative to the snap container's boundary. Note
-// that this rect is represented by the dotted box below, which is expanded
-// by the scroll-margin from the element's original boundary.
-static float CalculateSnapPosition(SnapAlignment alignment,
- SearchAxis axis,
- const LayoutRect& container,
- const FloatPoint& max_position,
- const LayoutRect& area) {
- if (alignment == SnapAlignment::kNone)
- return SnapAreaData::kInvalidScrollPosition;
- switch (alignment) {
- /* Start alignment aligns the area's start edge with container's start edge.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-start
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- + ^ +
- + | +
- + |snap_position +
- + | +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ scroll-padding \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | | . . \ +
- + \ . . | snap_area | . . \ +
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . . . . . .snap_container . . . . . . . . . \ +
- + \ \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + scrollable_content +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kStart:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.X() - container.X(), max_position.X());
- }
- return ClipInContainer(area.Y() - container.Y(), max_position.Y());
-
- /* Center alignment aligns the snap_area(with margin)'s center line with
- snap_container(without padding)'s center line.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-center
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- + ^ +
- + | snap_position +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ scroll-padding \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | snap_area | . . \ +
- + \* *.* * * *.* * * * * * * * * * * *.* * * * * * * * * * Center line
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . \ +
- + \ . . . . . . snap_container. . . . . . . . . . \ +
- + \ \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + +
- + scrollable_content +
- + +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kCenter:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.Center().X() - container.Center().X(),
- max_position.X());
- }
- return ClipInContainer(area.Center().Y() - container.Center().Y(),
- max_position.Y());
-
- /* End alignment aligns the snap_area(with margin)'s end edge with
- snap_container(without padding)'s end edge.
- https://www.w3.org/TR/css-scroll-snap-1/#valdef-scroll-snap-align-end
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + . .
- + ^ +
- + | snap_position +
- + v +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + \ \ +
- + \ . . . . . . . . snap_container. . . . . . . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . \ +
- + \ . . . . . . . . . . . . . . . \ +
- + \ . . scroll-margin . . \ +
- + \ . . |=================| . . \ +
- + \ . . | | . . \ +
- + \ . . | snap_area | . . \ +
- + \ . . | | . . \ +
- + \ . . |=================| . . \ +
- + \ . . . . \ +
- + \ . . . . . . . . . . . . . . . . . . . . . . . \ +
- + \ scroll-padding \ +
- + \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ +
- + +
- + scrollable_content +
- + +
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-
- */
- case SnapAlignment::kEnd:
- if (axis == SearchAxis::kX) {
- return ClipInContainer(area.MaxX() - container.MaxX(),
- max_position.X());
- }
- return ClipInContainer(area.MaxY() - container.MaxY(), max_position.Y());
- default:
- return LayoutUnit(SnapAreaData::kInvalidScrollPosition);
- }
-}
-
static ScrollSnapAlign GetPhysicalAlignment(
const ComputedStyle& area_style,
const ComputedStyle& container_style) {
@@ -335,32 +192,9 @@ static ScrollSnapAlign GetPhysicalAlignment(
return align;
}
-static FloatRect GetVisibleRegion(const LayoutRect& container,
- const LayoutRect& area) {
- float left = area.X() - container.MaxX();
- float right = area.MaxX() - container.X();
- float top = area.Y() - container.MaxY();
- float bottom = area.MaxY() - container.Y();
- return FloatRect(left, top, right - left, bottom - top);
-}
-
-static SnapAxis ToSnapAxis(ScrollSnapAlign align) {
- if (align.alignment_inline != SnapAlignment::kNone &&
- align.alignment_block != SnapAlignment::kNone)
- return SnapAxis::kBoth;
-
- if (align.alignment_inline != SnapAlignment::kNone &&
- align.alignment_block == SnapAlignment::kNone)
- return SnapAxis::kX;
-
- return SnapAxis::kY;
-}
-
SnapAreaData SnapCoordinator::CalculateSnapAreaData(
const LayoutBox& snap_area,
- const LayoutBox& snap_container,
- const LayoutRect& container_rect,
- const FloatPoint& max_position) {
+ const LayoutBox& snap_container) {
const ComputedStyle* container_style = snap_container.Style();
const ComputedStyle* area_style = snap_area.Style();
SnapAreaData snap_area_data;
@@ -381,7 +215,7 @@ SnapAreaData SnapCoordinator::CalculateSnapAreaData(
ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
if (scrollable_area) {
if (snap_container.IsLayoutView())
- area_rect = snap_container.GetFrameView()->AbsoluteToDocument(area_rect);
+ area_rect = snap_container.GetFrameView()->FrameToDocument(area_rect);
else
area_rect.MoveBy(LayoutPoint(scrollable_area->ScrollPosition()));
}
@@ -390,44 +224,37 @@ SnapAreaData SnapCoordinator::CalculateSnapAreaData(
area_style->ScrollMarginTop(), area_style->ScrollMarginRight(),
area_style->ScrollMarginBottom(), area_style->ScrollMarginLeft());
area_rect.Expand(area_margin);
+ snap_area_data.rect = FloatRect(area_rect);
ScrollSnapAlign align = GetPhysicalAlignment(*area_style, *container_style);
+ snap_area_data.scroll_snap_align = align;
- snap_area_data.snap_position.set_x(
- CalculateSnapPosition(align.alignment_inline, SearchAxis::kX,
- container_rect, max_position, area_rect));
- snap_area_data.snap_position.set_y(
- CalculateSnapPosition(align.alignment_block, SearchAxis::kY,
- container_rect, max_position, area_rect));
-
- snap_area_data.snap_axis = ToSnapAxis(align);
-
- snap_area_data.visible_region = GetVisibleRegion(container_rect, area_rect);
snap_area_data.must_snap =
(area_style->ScrollSnapStop() == EScrollSnapStop::kAlways);
return snap_area_data;
}
-FloatPoint SnapCoordinator::GetSnapPositionForPoint(
+base::Optional<FloatPoint> SnapCoordinator::GetSnapPositionForPoint(
const LayoutBox& snap_container,
const FloatPoint& point,
bool did_scroll_x,
bool did_scroll_y) {
auto iter = snap_container_map_.find(&snap_container);
if (iter == snap_container_map_.end())
- return point;
+ return base::nullopt;
const SnapContainerData& data = iter->value;
if (!data.size())
- return point;
+ return base::nullopt;
gfx::ScrollOffset snap_position;
if (data.FindSnapPosition(gfx::ScrollOffset(point.X(), point.Y()),
did_scroll_x, did_scroll_y, &snap_position)) {
- return FloatPoint(snap_position.x(), snap_position.y());
+ FloatPoint snap_point(snap_position.x(), snap_position.y());
+ return snap_point;
}
- return point;
+ return base::nullopt;
}
void SnapCoordinator::PerformSnapping(const LayoutBox& snap_container,
@@ -438,12 +265,16 @@ void SnapCoordinator::PerformSnapping(const LayoutBox& snap_container,
return;
FloatPoint current_position = scrollable_area->ScrollPosition();
- FloatPoint snap_position = GetSnapPositionForPoint(
+ base::Optional<FloatPoint> snap_point = GetSnapPositionForPoint(
snap_container, current_position, did_scroll_x, did_scroll_y);
+ if (!snap_point.has_value())
+ return;
- if (snap_position != current_position) {
+ scrollable_area->CancelScrollAnimation();
+ scrollable_area->CancelProgrammaticScrollAnimation();
+ if (snap_point.value() != current_position) {
scrollable_area->SetScrollOffset(
- ScrollPositionToOffset(snap_position, scrollable_area->ScrollOrigin()),
+ scrollable_area->ScrollPositionToOffset(snap_point.value()),
kProgrammaticScroll, kScrollBehaviorSmooth);
}
}
@@ -476,6 +307,30 @@ base::Optional<SnapContainerData> SnapCoordinator::GetSnapContainerData(
return base::nullopt;
}
+bool SnapCoordinator::GetSnapFlingInfo(
+ const LayoutBox& snap_container,
+ const gfx::Vector2dF& natural_displacement,
+ gfx::Vector2dF* out_initial_offset,
+ gfx::Vector2dF* out_target_offset) {
+ ScrollableArea* scrollable_area = ScrollableAreaForSnapping(snap_container);
+ if (!scrollable_area)
+ return false;
+
+ FloatPoint current_position = scrollable_area->ScrollPosition();
+ *out_initial_offset = gfx::Vector2dF(current_position);
+ FloatPoint original_end =
+ current_position +
+ FloatPoint(natural_displacement.x(), natural_displacement.y());
+ bool did_scroll_x = natural_displacement.x() != 0;
+ bool did_scroll_y = natural_displacement.y() != 0;
+ base::Optional<FloatPoint> snap_end = GetSnapPositionForPoint(
+ snap_container, original_end, did_scroll_x, did_scroll_y);
+ if (!snap_end.has_value())
+ return false;
+ *out_target_offset = gfx::Vector2dF(snap_end.value());
+ return true;
+}
+
#ifndef NDEBUG
void SnapCoordinator::ShowSnapAreaMap() {