| 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.axis == kSnapAxisNone) { |
| 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 |