OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "core/frame/RootFrameViewport.h" | 5 #include "core/frame/RootFrameViewport.h" |
6 | 6 |
7 #include "core/frame/FrameView.h" | 7 #include "core/frame/FrameView.h" |
8 #include "core/layout/ScrollAlignment.h" | 8 #include "core/layout/ScrollAlignment.h" |
9 #include "core/layout/ScrollAnchor.h" | 9 #include "core/layout/ScrollAnchor.h" |
10 #include "platform/geometry/DoubleRect.h" | 10 #include "platform/geometry/DoubleRect.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
42 // If the root FrameView is the layout viewport then coordinates in the | 42 // If the root FrameView is the layout viewport then coordinates in the |
43 // root FrameView's content space are already in the layout viewport's | 43 // root FrameView's content space are already in the layout viewport's |
44 // content space. | 44 // content space. |
45 if (rootFrameView.layoutViewportScrollableArea() == &layoutViewport()) | 45 if (rootFrameView.layoutViewportScrollableArea() == &layoutViewport()) |
46 return ret; | 46 return ret; |
47 | 47 |
48 // Make the given rect relative to the top of the layout viewport's content | 48 // Make the given rect relative to the top of the layout viewport's content |
49 // by adding the scroll position. | 49 // by adding the scroll position. |
50 // TODO(bokan): This will have to be revisited if we ever remove the | 50 // TODO(bokan): This will have to be revisited if we ever remove the |
51 // restriction that a root scroller must be exactly screen filling. | 51 // restriction that a root scroller must be exactly screen filling. |
52 ret.moveBy(LayoutPoint(layoutViewport().scrollPositionDouble())); | 52 ret.moveBy(LayoutPoint(FloatPoint((layoutViewport().scrollOffset())))); |
bokan
2016/10/02 19:47:51
ret.move()
szager1
2016/10/05 07:43:36
Done.
| |
53 | 53 |
54 return ret; | 54 return ret; |
55 } | 55 } |
56 | 56 |
57 void RootFrameViewport::restoreToAnchor(const DoublePoint& targetPosition) { | 57 void RootFrameViewport::restoreToAnchor(const ScrollOffset& targetOffset) { |
58 // Clamp the scroll offset of each viewport now so that we force any invalid | 58 // Clamp the scroll offset of each viewport now so that we force any invalid |
59 // offsets to become valid so we can compute the correct deltas. | 59 // offsets to become valid so we can compute the correct deltas. |
60 visualViewport().setScrollPosition(visualViewport().scrollPositionDouble(), | 60 visualViewport().setScrollOffset(visualViewport().scrollOffset(), |
61 ProgrammaticScroll); | 61 ProgrammaticScroll); |
62 layoutViewport().setScrollPosition(layoutViewport().scrollPositionDouble(), | 62 layoutViewport().setScrollOffset(layoutViewport().scrollOffset(), |
63 ProgrammaticScroll); | 63 ProgrammaticScroll); |
64 | 64 |
65 DoubleSize delta = targetPosition - scrollPositionDouble(); | 65 ScrollOffset delta = targetOffset - scrollOffset(); |
66 | 66 |
67 visualViewport().setScrollPosition( | 67 visualViewport().setScrollOffset(visualViewport().scrollOffset() + delta, |
68 visualViewport().scrollPositionDouble() + delta, ProgrammaticScroll); | 68 ProgrammaticScroll); |
69 | 69 |
70 delta = targetPosition - scrollPositionDouble(); | 70 delta = targetOffset - scrollOffset(); |
71 | 71 |
72 // Since the main thread FrameView has integer scroll offsets, scroll it to | 72 // Since the main thread FrameView has integer scroll offsets, scroll it to |
73 // the next pixel and then we'll scroll the visual viewport again to | 73 // the next pixel and then we'll scroll the visual viewport again to |
74 // compensate for the sub-pixel offset. We need this "overscroll" to ensure | 74 // compensate for the sub-pixel offset. We need this "overscroll" to ensure |
75 // the pixel of which we want to be partially in appears fully inside the | 75 // the pixel of which we want to be partially in appears fully inside the |
76 // FrameView since the VisualViewport is bounded by the FrameView. | 76 // FrameView since the VisualViewport is bounded by the FrameView. |
77 IntSize layoutDelta = IntSize( | 77 IntSize layoutDelta = IntSize( |
78 delta.width() < 0 ? floor(delta.width()) : ceil(delta.width()), | 78 delta.width() < 0 ? floor(delta.width()) : ceil(delta.width()), |
79 delta.height() < 0 ? floor(delta.height()) : ceil(delta.height())); | 79 delta.height() < 0 ? floor(delta.height()) : ceil(delta.height())); |
80 | 80 |
81 layoutViewport().setScrollPosition( | 81 layoutViewport().setScrollOffset( |
82 layoutViewport().scrollPosition() + layoutDelta, ProgrammaticScroll); | 82 ScrollOffset(layoutViewport().scrollOffsetInt() + layoutDelta), |
83 ProgrammaticScroll); | |
83 | 84 |
84 delta = targetPosition - scrollPositionDouble(); | 85 delta = targetOffset - scrollOffset(); |
85 visualViewport().setScrollPosition( | 86 visualViewport().setScrollOffset(visualViewport().scrollOffset() + delta, |
86 visualViewport().scrollPositionDouble() + delta, ProgrammaticScroll); | 87 ProgrammaticScroll); |
87 } | 88 } |
88 | 89 |
89 void RootFrameViewport::didUpdateVisualViewport() { | 90 void RootFrameViewport::didUpdateVisualViewport() { |
90 if (RuntimeEnabledFeatures::scrollAnchoringEnabled()) { | 91 if (RuntimeEnabledFeatures::scrollAnchoringEnabled()) { |
91 if (ScrollAnchor* anchor = layoutViewport().scrollAnchor()) | 92 if (ScrollAnchor* anchor = layoutViewport().scrollAnchor()) |
92 anchor->clear(); | 93 anchor->clear(); |
93 } | 94 } |
94 } | 95 } |
95 | 96 |
96 LayoutBox* RootFrameViewport::layoutBox() const { | 97 LayoutBox* RootFrameViewport::layoutBox() const { |
97 return layoutViewport().layoutBox(); | 98 return layoutViewport().layoutBox(); |
98 } | 99 } |
99 | 100 |
100 void RootFrameViewport::updateScrollAnimator() { | 101 void RootFrameViewport::updateScrollAnimator() { |
101 scrollAnimator().setCurrentPosition( | 102 scrollAnimator().setCurrentOffset( |
102 toFloatPoint(scrollOffsetFromScrollAnimators())); | 103 toFloatSize(scrollOffsetFromScrollAnimators())); |
103 } | 104 } |
104 | 105 |
105 DoublePoint RootFrameViewport::scrollOffsetFromScrollAnimators() const { | 106 ScrollOffset RootFrameViewport::scrollOffsetFromScrollAnimators() const { |
106 return visualViewport().scrollAnimator().currentPosition() + | 107 return visualViewport().scrollAnimator().currentOffset() + |
107 layoutViewport().scrollAnimator().currentPosition(); | 108 layoutViewport().scrollAnimator().currentOffset(); |
108 } | |
109 | |
110 DoubleRect RootFrameViewport::visibleContentRectDouble( | |
111 IncludeScrollbarsInRect scrollbarInclusion) const { | |
112 return DoubleRect( | |
113 scrollPositionDouble(), | |
114 visualViewport().visibleContentRectDouble(scrollbarInclusion).size()); | |
115 } | 109 } |
116 | 110 |
117 IntRect RootFrameViewport::visibleContentRect( | 111 IntRect RootFrameViewport::visibleContentRect( |
118 IncludeScrollbarsInRect scrollbarInclusion) const { | 112 IncludeScrollbarsInRect scrollbarInclusion) const { |
119 return enclosingIntRect(visibleContentRectDouble(scrollbarInclusion)); | 113 return IntRect( |
114 IntPoint(scrollOffsetInt()), | |
115 visualViewport().visibleContentRect(scrollbarInclusion).size()); | |
120 } | 116 } |
121 | 117 |
122 bool RootFrameViewport::shouldUseIntegerScrollOffset() const { | 118 bool RootFrameViewport::shouldUseIntegerScrollOffset() const { |
123 // Fractionals are floored in the ScrollAnimatorBase but it's important that t he ScrollAnimators of the | 119 // Fractionals are floored in the ScrollAnimatorBase but it's important that t he ScrollAnimators of the |
124 // visual and layout viewports get the precise fractional number so never use integer scrolling for | 120 // visual and layout viewports get the precise fractional number so never use integer scrolling for |
125 // RootFrameViewport, we'll let the truncation happen in the subviewports. | 121 // RootFrameViewport, we'll let the truncation happen in the subviewports. |
126 return false; | 122 return false; |
127 } | 123 } |
128 | 124 |
129 bool RootFrameViewport::isActive() const { | 125 bool RootFrameViewport::isActive() const { |
130 return layoutViewport().isActive(); | 126 return layoutViewport().isActive(); |
131 } | 127 } |
132 | 128 |
133 int RootFrameViewport::scrollSize(ScrollbarOrientation orientation) const { | 129 int RootFrameViewport::scrollSize(ScrollbarOrientation orientation) const { |
134 IntSize scrollDimensions = maximumScrollPosition() - minimumScrollPosition(); | 130 IntSize scrollDimensions = |
131 maximumScrollOffsetInt() - minimumScrollOffsetInt(); | |
135 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() | 132 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() |
136 : scrollDimensions.height(); | 133 : scrollDimensions.height(); |
137 } | 134 } |
138 | 135 |
139 bool RootFrameViewport::isScrollCornerVisible() const { | 136 bool RootFrameViewport::isScrollCornerVisible() const { |
140 return layoutViewport().isScrollCornerVisible(); | 137 return layoutViewport().isScrollCornerVisible(); |
141 } | 138 } |
142 | 139 |
143 IntRect RootFrameViewport::scrollCornerRect() const { | 140 IntRect RootFrameViewport::scrollCornerRect() const { |
144 return layoutViewport().scrollCornerRect(); | 141 return layoutViewport().scrollCornerRect(); |
145 } | 142 } |
146 | 143 |
147 void RootFrameViewport::setScrollPosition(const DoublePoint& position, | 144 void RootFrameViewport::setScrollOffset(const ScrollOffset& offset, |
148 ScrollType scrollType, | 145 ScrollType scrollType, |
149 ScrollBehavior scrollBehavior) { | 146 ScrollBehavior scrollBehavior) { |
150 updateScrollAnimator(); | 147 updateScrollAnimator(); |
151 | 148 |
152 if (scrollBehavior == ScrollBehaviorAuto) | 149 if (scrollBehavior == ScrollBehaviorAuto) |
153 scrollBehavior = scrollBehaviorStyle(); | 150 scrollBehavior = scrollBehaviorStyle(); |
154 | 151 |
155 if (scrollType == ProgrammaticScroll && | 152 if (scrollType == ProgrammaticScroll && |
156 !layoutViewport().isProgrammaticallyScrollable()) | 153 !layoutViewport().isProgrammaticallyScrollable()) |
157 return; | 154 return; |
158 | 155 |
159 if (scrollType == AnchoringScroll) { | 156 if (scrollType == AnchoringScroll) { |
160 distributeScrollBetweenViewports(position, scrollType, scrollBehavior, | 157 distributeScrollBetweenViewports(offset, scrollType, scrollBehavior, |
161 LayoutViewport); | 158 LayoutViewport); |
162 return; | 159 return; |
163 } | 160 } |
164 | 161 |
165 if (scrollBehavior == ScrollBehaviorSmooth) { | 162 if (scrollBehavior == ScrollBehaviorSmooth) { |
166 distributeScrollBetweenViewports(position, scrollType, scrollBehavior, | 163 distributeScrollBetweenViewports(offset, scrollType, scrollBehavior, |
167 VisualViewport); | 164 VisualViewport); |
168 return; | 165 return; |
169 } | 166 } |
170 | 167 |
171 DoublePoint clampedPosition = clampScrollPosition(position); | 168 ScrollOffset clampedOffset = clampScrollOffset(offset); |
172 ScrollableArea::setScrollPosition(clampedPosition, scrollType, | 169 ScrollableArea::setScrollOffset(clampedOffset, scrollType, scrollBehavior); |
173 scrollBehavior); | |
174 } | 170 } |
175 | 171 |
176 ScrollBehavior RootFrameViewport::scrollBehaviorStyle() const { | 172 ScrollBehavior RootFrameViewport::scrollBehaviorStyle() const { |
177 return layoutViewport().scrollBehaviorStyle(); | 173 return layoutViewport().scrollBehaviorStyle(); |
178 } | 174 } |
179 | 175 |
180 LayoutRect RootFrameViewport::scrollIntoView(const LayoutRect& rectInContent, | 176 LayoutRect RootFrameViewport::scrollIntoView(const LayoutRect& rectInContent, |
181 const ScrollAlignment& alignX, | 177 const ScrollAlignment& alignX, |
182 const ScrollAlignment& alignY, | 178 const ScrollAlignment& alignY, |
183 ScrollType scrollType) { | 179 ScrollType scrollType) { |
184 // We want to move the rect into the viewport that excludes the scrollbars so we intersect | 180 // We want to move the rect into the viewport that excludes the scrollbars so we intersect |
185 // the visual viewport with the scrollbar-excluded frameView content rect. How ever, we don't | 181 // the visual viewport with the scrollbar-excluded frameView content rect. How ever, we don't |
186 // use visibleContentRect directly since it floors the scroll position. Instea d, we use | 182 // use visibleContentRect directly since it floors the scroll offset. Instead, we use |
187 // ScrollAnimatorBase::currentPosition and construct a LayoutRect from that. | 183 // ScrollAnimatorBase::currentOffset and construct a LayoutRect from that. |
188 | 184 |
189 LayoutRect frameRectInContent = | 185 LayoutRect frameRectInContent = |
190 LayoutRect(layoutViewport().scrollAnimator().currentPosition(), | 186 LayoutRect(FloatPoint(layoutViewport().scrollAnimator().currentOffset()), |
191 layoutViewport().visibleContentRect().size()); | 187 FloatSize(layoutViewport().visibleContentRect().size())); |
192 LayoutRect visualRectInContent = | 188 LayoutRect visualRectInContent = |
193 LayoutRect(scrollOffsetFromScrollAnimators(), | 189 LayoutRect(FloatPoint(scrollOffsetFromScrollAnimators()), |
194 visualViewport().visibleContentRect().size()); | 190 FloatSize(visualViewport().visibleContentRect().size())); |
195 | 191 |
196 // Intersect layout and visual rects to exclude the scrollbar from the view re ct. | 192 // Intersect layout and visual rects to exclude the scrollbar from the view re ct. |
197 LayoutRect viewRectInContent = | 193 LayoutRect viewRectInContent = |
198 intersection(visualRectInContent, frameRectInContent); | 194 intersection(visualRectInContent, frameRectInContent); |
199 LayoutRect targetViewport = ScrollAlignment::getRectToExpose( | 195 LayoutRect targetViewport = ScrollAlignment::getRectToExpose( |
200 viewRectInContent, rectInContent, alignX, alignY); | 196 viewRectInContent, rectInContent, alignX, alignY); |
201 if (targetViewport != viewRectInContent) | 197 if (targetViewport != viewRectInContent) { |
202 setScrollPosition(DoublePoint(targetViewport.x(), targetViewport.y()), | 198 setScrollOffset(ScrollOffset(targetViewport.x(), targetViewport.y()), |
203 scrollType); | 199 scrollType); |
200 } | |
204 | 201 |
205 // RootFrameViewport only changes the viewport relative to the document so we can't change the input | 202 // RootFrameViewport only changes the viewport relative to the document so we can't change the input |
206 // rect's location relative to the document origin. | 203 // rect's location relative to the document origin. |
207 return rectInContent; | 204 return rectInContent; |
208 } | 205 } |
209 | 206 |
210 void RootFrameViewport::updateScrollPosition(const DoublePoint& position, | 207 void RootFrameViewport::updateScrollOffset(const ScrollOffset& offset, |
211 ScrollType scrollType) { | 208 ScrollType scrollType) { |
212 distributeScrollBetweenViewports(DoublePoint(position), scrollType, | 209 distributeScrollBetweenViewports(offset, scrollType, ScrollBehaviorInstant, |
213 ScrollBehaviorInstant, VisualViewport); | 210 VisualViewport); |
214 } | 211 } |
215 | 212 |
216 void RootFrameViewport::distributeScrollBetweenViewports( | 213 void RootFrameViewport::distributeScrollBetweenViewports( |
217 const DoublePoint& position, | 214 const ScrollOffset& offset, |
218 ScrollType scrollType, | 215 ScrollType scrollType, |
219 ScrollBehavior behavior, | 216 ScrollBehavior behavior, |
220 ViewportToScrollFirst scrollFirst) { | 217 ViewportToScrollFirst scrollFirst) { |
221 // Make sure we use the scroll positions as reported by each viewport's Scroll AnimatorBase, since its | 218 // Make sure we use the scroll offsets as reported by each viewport's ScrollAn imatorBase, since its |
222 // ScrollableArea's position may have the fractional part truncated off. | 219 // ScrollableArea's offset may have the fractional part truncated off. |
bokan
2016/10/02 19:47:50
Please add a TODO to revisit this now that the off
szager1
2016/10/05 07:43:36
Done.
| |
223 DoublePoint oldPosition = scrollOffsetFromScrollAnimators(); | 220 ScrollOffset oldOffset = scrollOffsetFromScrollAnimators(); |
224 | 221 |
225 DoubleSize delta = position - oldPosition; | 222 ScrollOffset delta = offset - oldOffset; |
226 | 223 |
227 if (delta.isZero()) | 224 if (delta.isZero()) |
228 return; | 225 return; |
229 | 226 |
230 ScrollableArea& primary = | 227 ScrollableArea& primary = |
231 scrollFirst == VisualViewport ? visualViewport() : layoutViewport(); | 228 scrollFirst == VisualViewport ? visualViewport() : layoutViewport(); |
232 ScrollableArea& secondary = | 229 ScrollableArea& secondary = |
233 scrollFirst == VisualViewport ? layoutViewport() : visualViewport(); | 230 scrollFirst == VisualViewport ? layoutViewport() : visualViewport(); |
234 | 231 |
235 DoublePoint targetPosition = primary.clampScrollPosition( | 232 ScrollOffset targetOffset = primary.clampScrollOffset( |
236 primary.scrollAnimator().currentPosition() + delta); | 233 primary.scrollAnimator().currentOffset() + delta); |
237 | 234 |
238 primary.setScrollPosition(targetPosition, scrollType, behavior); | 235 primary.setScrollOffset(targetOffset, scrollType, behavior); |
239 | 236 |
240 // Scroll the secondary viewport if all of the scroll was not applied to the | 237 // Scroll the secondary viewport if all of the scroll was not applied to the |
241 // primary viewport. | 238 // primary viewport. |
242 DoublePoint updatedPosition = | 239 ScrollOffset updatedOffset = |
243 secondary.scrollAnimator().currentPosition() + FloatPoint(targetPosition); | 240 secondary.scrollAnimator().currentOffset() + FloatSize(targetOffset); |
244 DoubleSize applied = updatedPosition - oldPosition; | 241 ScrollOffset applied = updatedOffset - oldOffset; |
245 delta -= applied; | 242 delta -= applied; |
246 | 243 |
247 if (delta.isZero()) | 244 if (delta.isZero()) |
248 return; | 245 return; |
249 | 246 |
250 targetPosition = secondary.clampScrollPosition( | 247 targetOffset = secondary.clampScrollOffset( |
251 secondary.scrollAnimator().currentPosition() + delta); | 248 secondary.scrollAnimator().currentOffset() + delta); |
252 secondary.setScrollPosition(targetPosition, scrollType, behavior); | 249 secondary.setScrollOffset(targetOffset, scrollType, behavior); |
253 } | 250 } |
254 | 251 |
255 IntPoint RootFrameViewport::scrollPosition() const { | 252 IntSize RootFrameViewport::scrollOffsetInt() const { |
256 return flooredIntPoint(scrollPositionDouble()); | 253 return flooredIntSize(scrollOffset()); |
257 } | 254 } |
258 | 255 |
259 DoublePoint RootFrameViewport::scrollPositionDouble() const { | 256 ScrollOffset RootFrameViewport::scrollOffset() const { |
260 return layoutViewport().scrollPositionDouble() + | 257 return layoutViewport().scrollOffset() + visualViewport().scrollOffset(); |
261 toDoubleSize(visualViewport().scrollPositionDouble()); | |
262 } | 258 } |
263 | 259 |
264 IntPoint RootFrameViewport::minimumScrollPosition() const { | 260 IntSize RootFrameViewport::minimumScrollOffsetInt() const { |
265 return IntPoint(layoutViewport().minimumScrollPosition() + | 261 return IntSize(layoutViewport().minimumScrollOffsetInt() + |
266 visualViewport().minimumScrollPosition()); | 262 visualViewport().minimumScrollOffsetInt()); |
267 } | 263 } |
268 | 264 |
269 IntPoint RootFrameViewport::maximumScrollPosition() const { | 265 IntSize RootFrameViewport::maximumScrollOffsetInt() const { |
270 return layoutViewport().maximumScrollPosition() + | 266 return layoutViewport().maximumScrollOffsetInt() + |
271 visualViewport().maximumScrollPosition(); | 267 visualViewport().maximumScrollOffsetInt(); |
272 } | 268 } |
273 | 269 |
274 DoublePoint RootFrameViewport::maximumScrollPositionDouble() const { | 270 ScrollOffset RootFrameViewport::maximumScrollOffset() const { |
275 return layoutViewport().maximumScrollPositionDouble() + | 271 return layoutViewport().maximumScrollOffset() + |
276 toDoubleSize(visualViewport().maximumScrollPositionDouble()); | 272 visualViewport().maximumScrollOffset(); |
277 } | 273 } |
278 | 274 |
279 IntSize RootFrameViewport::contentsSize() const { | 275 IntSize RootFrameViewport::contentsSize() const { |
280 return layoutViewport().contentsSize(); | 276 return layoutViewport().contentsSize(); |
281 } | 277 } |
282 | 278 |
283 bool RootFrameViewport::scrollbarsCanBeActive() const { | 279 bool RootFrameViewport::scrollbarsCanBeActive() const { |
284 return layoutViewport().scrollbarsCanBeActive(); | 280 return layoutViewport().scrollbarsCanBeActive(); |
285 } | 281 } |
286 | 282 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
424 visualViewport().clearScrollAnimators(); | 420 visualViewport().clearScrollAnimators(); |
425 } | 421 } |
426 | 422 |
427 DEFINE_TRACE(RootFrameViewport) { | 423 DEFINE_TRACE(RootFrameViewport) { |
428 visitor->trace(m_visualViewport); | 424 visitor->trace(m_visualViewport); |
429 visitor->trace(m_layoutViewport); | 425 visitor->trace(m_layoutViewport); |
430 ScrollableArea::trace(visitor); | 426 ScrollableArea::trace(visitor); |
431 } | 427 } |
432 | 428 |
433 } // namespace blink | 429 } // namespace blink |
OLD | NEW |