OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "SnapCoordinator.h" | 5 #include "SnapCoordinator.h" |
6 | 6 |
7 #include "core/dom/Element.h" | 7 #include "core/dom/Element.h" |
8 #include "core/dom/Node.h" | 8 #include "core/dom/Node.h" |
9 #include "core/dom/NodeComputedStyle.h" | 9 #include "core/dom/NodeComputedStyle.h" |
10 #include "core/layout/LayoutBlock.h" | 10 #include "core/layout/LayoutBlock.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 box->GetNode() != viewport_defining_element) | 36 box->GetNode() != viewport_defining_element) |
37 box = box->ContainingBlock(); | 37 box = box->ContainingBlock(); |
38 | 38 |
39 // If we reach to viewportDefiningElement then we dispatch to viewport | 39 // If we reach to viewportDefiningElement then we dispatch to viewport |
40 if (box && box->GetNode() == viewport_defining_element) | 40 if (box && box->GetNode() == viewport_defining_element) |
41 return snap_area.GetDocument().GetLayoutView(); | 41 return snap_area.GetDocument().GetLayoutView(); |
42 | 42 |
43 return box; | 43 return box; |
44 } | 44 } |
45 | 45 |
46 void SnapCoordinator::SnapAreaDidChange( | 46 void SnapCoordinator::SnapAreaDidChange(LayoutBox& snap_area, |
47 LayoutBox& snap_area, | 47 ScrollSnapAlign scroll_snap_align) { |
48 const Vector<LengthPoint>& snap_coordinates) { | 48 if (scroll_snap_align.alignmentX == kSnapAlignmentNone && |
49 if (snap_coordinates.IsEmpty()) { | 49 scroll_snap_align.alignmentY == kSnapAlignmentNone) { |
50 snap_area.SetSnapContainer(nullptr); | 50 snap_area.SetSnapContainer(nullptr); |
51 return; | 51 return; |
52 } | 52 } |
53 | 53 |
54 if (LayoutBox* snap_container = FindSnapContainer(snap_area)) { | 54 if (LayoutBox* snap_container = FindSnapContainer(snap_area)) { |
55 snap_area.SetSnapContainer(snap_container); | 55 snap_area.SetSnapContainer(snap_container); |
56 } else { | 56 } else { |
57 // TODO(majidvp): keep track of snap areas that do not have any | 57 // TODO(majidvp): keep track of snap areas that do not have any |
58 // container so that we check them again when a new container is | 58 // container so that we check them again when a new container is |
59 // added to the page. | 59 // added to the page. |
60 } | 60 } |
61 } | 61 } |
62 | 62 |
63 void SnapCoordinator::SnapContainerDidChange(LayoutBox& snap_container, | 63 void SnapCoordinator::SnapContainerDidChange(LayoutBox& snap_container, |
64 ScrollSnapType scroll_snap_type) { | 64 ScrollSnapType scroll_snap_type) { |
65 if (scroll_snap_type == kScrollSnapTypeNone) { | 65 if (scroll_snap_type.is_none) { |
66 // TODO(majidvp): Track and report these removals to CompositorWorker | 66 // TODO(majidvp): Track and report these removals to CompositorWorker |
67 // instance responsible for snapping | 67 // instance responsible for snapping |
68 snap_containers_.erase(&snap_container); | 68 snap_containers_.erase(&snap_container); |
69 snap_container.ClearSnapAreas(); | 69 snap_container.ClearSnapAreas(); |
70 } else { | 70 } else { |
71 snap_containers_.insert(&snap_container); | 71 snap_containers_.insert(&snap_container); |
72 } | 72 } |
73 | 73 |
74 // TODO(majidvp): Add logic to correctly handle orphaned snap areas here. | 74 // TODO(majidvp): Add logic to correctly handle orphaned snap areas here. |
75 // 1. Removing container: find a new snap container for its orphan snap | 75 // 1. Removing container: find a new snap container for its orphan snap |
76 // areas (most likely nearest ancestor of current container) otherwise add | 76 // areas (most likely nearest ancestor of current container) otherwise add |
77 // them to an orphan list. | 77 // them to an orphan list. |
78 // 2. Adding container: may take over snap areas from nearest ancestor snap | 78 // 2. Adding container: may take over snap areas from nearest ancestor snap |
79 // container or from existing areas in orphan pool. | 79 // container or from existing areas in orphan pool. |
80 } | 80 } |
81 | 81 |
82 // Translate local snap coordinates into snap container's scrolling content | |
83 // coordinate space. | |
84 static Vector<FloatPoint> LocalToContainerSnapCoordinates( | |
85 const LayoutBox& container_box, | |
86 const LayoutBox& snap_area) { | |
87 Vector<FloatPoint> result; | |
88 LayoutPoint scroll_offset(container_box.ScrollLeft(), | |
89 container_box.ScrollTop()); | |
90 | |
91 const Vector<LengthPoint>& snap_coordinates = | |
92 snap_area.Style()->ScrollSnapCoordinate(); | |
93 for (auto& coordinate : snap_coordinates) { | |
94 FloatPoint local_point = | |
95 FloatPointForLengthPoint(coordinate, FloatSize(snap_area.Size())); | |
96 FloatPoint container_point = | |
97 snap_area.LocalToAncestorPoint(local_point, &container_box); | |
98 container_point.MoveBy(scroll_offset); | |
99 result.push_back(container_point); | |
100 } | |
101 return result; | |
102 } | |
103 | |
104 Vector<double> SnapCoordinator::SnapOffsets(const ContainerNode& element, | |
105 ScrollbarOrientation orientation) { | |
106 const ComputedStyle* style = element.GetComputedStyle(); | |
107 const LayoutBox* snap_container = element.GetLayoutBox(); | |
108 DCHECK(style); | |
109 DCHECK(snap_container); | |
110 | |
111 Vector<double> result; | |
112 | |
113 if (style->GetScrollSnapType() == kScrollSnapTypeNone) | |
114 return result; | |
115 | |
116 const ScrollSnapPoints& snap_points = (orientation == kHorizontalScrollbar) | |
117 ? style->ScrollSnapPointsX() | |
118 : style->ScrollSnapPointsY(); | |
119 | |
120 LayoutUnit client_size = (orientation == kHorizontalScrollbar) | |
121 ? snap_container->ClientWidth() | |
122 : snap_container->ClientHeight(); | |
123 LayoutUnit scroll_size = (orientation == kHorizontalScrollbar) | |
124 ? snap_container->ScrollWidth() | |
125 : snap_container->ScrollHeight(); | |
126 | |
127 if (snap_points.has_repeat) { | |
128 LayoutUnit repeat = ValueForLength(snap_points.repeat_offset, client_size); | |
129 | |
130 // calc() values may be negative or zero in which case we clamp them to 1px. | |
131 // See: https://lists.w3.org/Archives/Public/www-style/2015Jul/0075.html | |
132 repeat = std::max<LayoutUnit>(repeat, LayoutUnit(1)); | |
133 for (LayoutUnit offset = repeat; offset <= (scroll_size - client_size); | |
134 offset += repeat) { | |
135 result.push_back(offset.ToFloat()); | |
136 } | |
137 } | |
138 | |
139 // Compute element-based snap points by mapping the snap coordinates from | |
140 // snap areas to snap container. | |
141 bool did_add_snap_area_offset = false; | |
142 if (SnapAreaSet* snap_areas = snap_container->SnapAreas()) { | |
143 for (auto& snap_area : *snap_areas) { | |
144 Vector<FloatPoint> snap_coordinates = | |
145 LocalToContainerSnapCoordinates(*snap_container, *snap_area); | |
146 for (const FloatPoint& snap_coordinate : snap_coordinates) { | |
147 float snap_offset = (orientation == kHorizontalScrollbar) | |
148 ? snap_coordinate.X() | |
149 : snap_coordinate.Y(); | |
150 if (snap_offset > scroll_size - client_size) | |
151 continue; | |
152 result.push_back(snap_offset); | |
153 did_add_snap_area_offset = true; | |
154 } | |
155 } | |
156 } | |
157 | |
158 if (did_add_snap_area_offset) | |
159 std::sort(result.begin(), result.end()); | |
160 | |
161 return result; | |
162 } | |
163 | |
164 #ifndef NDEBUG | 82 #ifndef NDEBUG |
165 | 83 |
166 void SnapCoordinator::ShowSnapAreaMap() { | 84 void SnapCoordinator::ShowSnapAreaMap() { |
167 for (auto& container : snap_containers_) | 85 for (auto& container : snap_containers_) |
168 ShowSnapAreasFor(container); | 86 ShowSnapAreasFor(container); |
169 } | 87 } |
170 | 88 |
171 void SnapCoordinator::ShowSnapAreasFor(const LayoutBox* container) { | 89 void SnapCoordinator::ShowSnapAreasFor(const LayoutBox* container) { |
172 LOG(INFO) << *container->GetNode(); | 90 LOG(INFO) << *container->GetNode(); |
173 if (SnapAreaSet* snap_areas = container->SnapAreas()) { | 91 if (SnapAreaSet* snap_areas = container->SnapAreas()) { |
174 for (auto& snap_area : *snap_areas) { | 92 for (auto& snap_area : *snap_areas) { |
175 LOG(INFO) << " " << *snap_area->GetNode(); | 93 LOG(INFO) << " " << *snap_area->GetNode(); |
176 } | 94 } |
177 } | 95 } |
178 } | 96 } |
179 | 97 |
180 #endif | 98 #endif |
181 | 99 |
182 } // namespace blink | 100 } // namespace blink |
OLD | NEW |