Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: third_party/WebKit/Source/core/frame/RootFrameViewport.cpp

Issue 2387883002: Use float for scroll offset. (Closed)
Patch Set: Fix README.md Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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.move(LayoutSize(layoutViewport().scrollOffset()));
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 119 // Fractionals are floored in the ScrollAnimatorBase but it's important that
124 // the ScrollAnimators of the visual and layout viewports get the precise 120 // the ScrollAnimators of the visual and layout viewports get the precise
125 // fractional number so never use integer scrolling for RootFrameViewport, 121 // fractional number so never use integer scrolling for RootFrameViewport,
126 // we'll let the truncation happen in the subviewports. 122 // we'll let the truncation happen in the subviewports.
127 return false; 123 return false;
128 } 124 }
129 125
130 bool RootFrameViewport::isActive() const { 126 bool RootFrameViewport::isActive() const {
131 return layoutViewport().isActive(); 127 return layoutViewport().isActive();
132 } 128 }
133 129
134 int RootFrameViewport::scrollSize(ScrollbarOrientation orientation) const { 130 int RootFrameViewport::scrollSize(ScrollbarOrientation orientation) const {
135 IntSize scrollDimensions = maximumScrollPosition() - minimumScrollPosition(); 131 IntSize scrollDimensions =
132 maximumScrollOffsetInt() - minimumScrollOffsetInt();
136 return (orientation == HorizontalScrollbar) ? scrollDimensions.width() 133 return (orientation == HorizontalScrollbar) ? scrollDimensions.width()
137 : scrollDimensions.height(); 134 : scrollDimensions.height();
138 } 135 }
139 136
140 bool RootFrameViewport::isScrollCornerVisible() const { 137 bool RootFrameViewport::isScrollCornerVisible() const {
141 return layoutViewport().isScrollCornerVisible(); 138 return layoutViewport().isScrollCornerVisible();
142 } 139 }
143 140
144 IntRect RootFrameViewport::scrollCornerRect() const { 141 IntRect RootFrameViewport::scrollCornerRect() const {
145 return layoutViewport().scrollCornerRect(); 142 return layoutViewport().scrollCornerRect();
146 } 143 }
147 144
148 void RootFrameViewport::setScrollPosition(const DoublePoint& position, 145 void RootFrameViewport::setScrollOffset(const ScrollOffset& offset,
149 ScrollType scrollType, 146 ScrollType scrollType,
150 ScrollBehavior scrollBehavior) { 147 ScrollBehavior scrollBehavior) {
151 updateScrollAnimator(); 148 updateScrollAnimator();
152 149
153 if (scrollBehavior == ScrollBehaviorAuto) 150 if (scrollBehavior == ScrollBehaviorAuto)
154 scrollBehavior = scrollBehaviorStyle(); 151 scrollBehavior = scrollBehaviorStyle();
155 152
156 if (scrollType == ProgrammaticScroll && 153 if (scrollType == ProgrammaticScroll &&
157 !layoutViewport().isProgrammaticallyScrollable()) 154 !layoutViewport().isProgrammaticallyScrollable())
158 return; 155 return;
159 156
160 if (scrollType == AnchoringScroll) { 157 if (scrollType == AnchoringScroll) {
161 distributeScrollBetweenViewports(position, scrollType, scrollBehavior, 158 distributeScrollBetweenViewports(offset, scrollType, scrollBehavior,
162 LayoutViewport); 159 LayoutViewport);
163 return; 160 return;
164 } 161 }
165 162
166 if (scrollBehavior == ScrollBehaviorSmooth) { 163 if (scrollBehavior == ScrollBehaviorSmooth) {
167 distributeScrollBetweenViewports(position, scrollType, scrollBehavior, 164 distributeScrollBetweenViewports(offset, scrollType, scrollBehavior,
168 VisualViewport); 165 VisualViewport);
169 return; 166 return;
170 } 167 }
171 168
172 DoublePoint clampedPosition = clampScrollPosition(position); 169 ScrollOffset clampedOffset = clampScrollOffset(offset);
173 ScrollableArea::setScrollPosition(clampedPosition, scrollType, 170 ScrollableArea::setScrollOffset(clampedOffset, scrollType, scrollBehavior);
174 scrollBehavior);
175 } 171 }
176 172
177 ScrollBehavior RootFrameViewport::scrollBehaviorStyle() const { 173 ScrollBehavior RootFrameViewport::scrollBehaviorStyle() const {
178 return layoutViewport().scrollBehaviorStyle(); 174 return layoutViewport().scrollBehaviorStyle();
179 } 175 }
180 176
181 LayoutRect RootFrameViewport::scrollIntoView(const LayoutRect& rectInContent, 177 LayoutRect RootFrameViewport::scrollIntoView(const LayoutRect& rectInContent,
182 const ScrollAlignment& alignX, 178 const ScrollAlignment& alignX,
183 const ScrollAlignment& alignY, 179 const ScrollAlignment& alignY,
184 ScrollType scrollType) { 180 ScrollType scrollType) {
185 // We want to move the rect into the viewport that excludes the scrollbars so 181 // We want to move the rect into the viewport that excludes the scrollbars so
186 // we intersect the visual viewport with the scrollbar-excluded frameView 182 // we intersect the visual viewport with the scrollbar-excluded frameView
187 // content rect. However, we don't use visibleContentRect directly since it 183 // content rect. However, we don't use visibleContentRect directly since it
188 // floors the scroll position. Instead, we use 184 // floors the scroll offset. Instead, we use ScrollAnimatorBase::currentOffset
189 // ScrollAnimatorBase::currentPosition and construct a LayoutRect from that. 185 // and construct a LayoutRect from that.
190
191 LayoutRect frameRectInContent = 186 LayoutRect frameRectInContent =
192 LayoutRect(layoutViewport().scrollAnimator().currentPosition(), 187 LayoutRect(FloatPoint(layoutViewport().scrollAnimator().currentOffset()),
193 layoutViewport().visibleContentRect().size()); 188 FloatSize(layoutViewport().visibleContentRect().size()));
194 LayoutRect visualRectInContent = 189 LayoutRect visualRectInContent =
195 LayoutRect(scrollOffsetFromScrollAnimators(), 190 LayoutRect(FloatPoint(scrollOffsetFromScrollAnimators()),
196 visualViewport().visibleContentRect().size()); 191 FloatSize(visualViewport().visibleContentRect().size()));
197 192
198 // Intersect layout and visual rects to exclude the scrollbar from the view 193 // Intersect layout and visual rects to exclude the scrollbar from the view
199 // rect. 194 // rect.
200 LayoutRect viewRectInContent = 195 LayoutRect viewRectInContent =
201 intersection(visualRectInContent, frameRectInContent); 196 intersection(visualRectInContent, frameRectInContent);
202 LayoutRect targetViewport = ScrollAlignment::getRectToExpose( 197 LayoutRect targetViewport = ScrollAlignment::getRectToExpose(
203 viewRectInContent, rectInContent, alignX, alignY); 198 viewRectInContent, rectInContent, alignX, alignY);
204 if (targetViewport != viewRectInContent) 199 if (targetViewport != viewRectInContent) {
205 setScrollPosition(DoublePoint(targetViewport.x(), targetViewport.y()), 200 setScrollOffset(ScrollOffset(targetViewport.x(), targetViewport.y()),
206 scrollType); 201 scrollType);
202 }
207 203
208 // RootFrameViewport only changes the viewport relative to the document so we 204 // RootFrameViewport only changes the viewport relative to the document so we
209 // can't change the input rect's location relative to the document origin. 205 // can't change the input rect's location relative to the document origin.
210 return rectInContent; 206 return rectInContent;
211 } 207 }
212 208
213 void RootFrameViewport::setScrollOffset(const DoublePoint& offset, 209 void RootFrameViewport::updateScrollOffset(const ScrollOffset& offset,
214 ScrollType scrollType) { 210 ScrollType scrollType) {
215 distributeScrollBetweenViewports(DoublePoint(offset), scrollType, 211 distributeScrollBetweenViewports(offset, scrollType, ScrollBehaviorInstant,
216 ScrollBehaviorInstant, VisualViewport); 212 VisualViewport);
217 } 213 }
218 214
219 void RootFrameViewport::distributeScrollBetweenViewports( 215 void RootFrameViewport::distributeScrollBetweenViewports(
220 const DoublePoint& offset, 216 const ScrollOffset& offset,
221 ScrollType scrollType, 217 ScrollType scrollType,
222 ScrollBehavior behavior, 218 ScrollBehavior behavior,
223 ViewportToScrollFirst scrollFirst) { 219 ViewportToScrollFirst scrollFirst) {
224 // Make sure we use the scroll positions as reported by each viewport's 220 // Make sure we use the scroll offsets as reported by each viewport's
225 // ScrollAnimatorBase, since its ScrollableArea's position may have the 221 // ScrollAnimatorBase, since its ScrollableArea's offset may have the
226 // fractional part truncated off. 222 // fractional part truncated off.
227 DoublePoint oldPosition = scrollOffsetFromScrollAnimators(); 223 // TODO(szager): Now that scroll offsets are stored as floats, can we take the
224 // scroll offset directly from the ScrollableArea's rather than the animators?
225 ScrollOffset oldOffset = scrollOffsetFromScrollAnimators();
228 226
229 DoubleSize delta = offset - oldPosition; 227 ScrollOffset delta = offset - oldOffset;
230 228
231 if (delta.isZero()) 229 if (delta.isZero())
232 return; 230 return;
233 231
234 ScrollableArea& primary = 232 ScrollableArea& primary =
235 scrollFirst == VisualViewport ? visualViewport() : layoutViewport(); 233 scrollFirst == VisualViewport ? visualViewport() : layoutViewport();
236 ScrollableArea& secondary = 234 ScrollableArea& secondary =
237 scrollFirst == VisualViewport ? layoutViewport() : visualViewport(); 235 scrollFirst == VisualViewport ? layoutViewport() : visualViewport();
238 236
239 DoublePoint targetPosition = primary.clampScrollPosition( 237 ScrollOffset targetOffset = primary.clampScrollOffset(
240 primary.scrollAnimator().currentPosition() + delta); 238 primary.scrollAnimator().currentOffset() + delta);
241 239
242 primary.setScrollPosition(targetPosition, scrollType, behavior); 240 primary.setScrollOffset(targetOffset, scrollType, behavior);
243 241
244 // Scroll the secondary viewport if all of the scroll was not applied to the 242 // Scroll the secondary viewport if all of the scroll was not applied to the
245 // primary viewport. 243 // primary viewport.
246 DoublePoint updatedPosition = 244 ScrollOffset updatedOffset =
247 secondary.scrollAnimator().currentPosition() + FloatPoint(targetPosition); 245 secondary.scrollAnimator().currentOffset() + FloatSize(targetOffset);
248 DoubleSize applied = updatedPosition - oldPosition; 246 ScrollOffset applied = updatedOffset - oldOffset;
249 delta -= applied; 247 delta -= applied;
250 248
251 if (delta.isZero()) 249 if (delta.isZero())
252 return; 250 return;
253 251
254 targetPosition = secondary.clampScrollPosition( 252 targetOffset = secondary.clampScrollOffset(
255 secondary.scrollAnimator().currentPosition() + delta); 253 secondary.scrollAnimator().currentOffset() + delta);
256 secondary.setScrollPosition(targetPosition, scrollType, behavior); 254 secondary.setScrollOffset(targetOffset, scrollType, behavior);
257 } 255 }
258 256
259 IntPoint RootFrameViewport::scrollPosition() const { 257 IntSize RootFrameViewport::scrollOffsetInt() const {
260 return flooredIntPoint(scrollPositionDouble()); 258 return flooredIntSize(scrollOffset());
261 } 259 }
262 260
263 DoublePoint RootFrameViewport::scrollPositionDouble() const { 261 ScrollOffset RootFrameViewport::scrollOffset() const {
264 return layoutViewport().scrollPositionDouble() + 262 return layoutViewport().scrollOffset() + visualViewport().scrollOffset();
265 toDoubleSize(visualViewport().scrollPositionDouble());
266 } 263 }
267 264
268 IntPoint RootFrameViewport::minimumScrollPosition() const { 265 IntSize RootFrameViewport::minimumScrollOffsetInt() const {
269 return IntPoint(layoutViewport().minimumScrollPosition() + 266 return IntSize(layoutViewport().minimumScrollOffsetInt() +
270 visualViewport().minimumScrollPosition()); 267 visualViewport().minimumScrollOffsetInt());
271 } 268 }
272 269
273 IntPoint RootFrameViewport::maximumScrollPosition() const { 270 IntSize RootFrameViewport::maximumScrollOffsetInt() const {
274 return layoutViewport().maximumScrollPosition() + 271 return layoutViewport().maximumScrollOffsetInt() +
275 visualViewport().maximumScrollPosition(); 272 visualViewport().maximumScrollOffsetInt();
276 } 273 }
277 274
278 DoublePoint RootFrameViewport::maximumScrollPositionDouble() const { 275 ScrollOffset RootFrameViewport::maximumScrollOffset() const {
279 return layoutViewport().maximumScrollPositionDouble() + 276 return layoutViewport().maximumScrollOffset() +
280 toDoubleSize(visualViewport().maximumScrollPositionDouble()); 277 visualViewport().maximumScrollOffset();
281 } 278 }
282 279
283 IntSize RootFrameViewport::contentsSize() const { 280 IntSize RootFrameViewport::contentsSize() const {
284 return layoutViewport().contentsSize(); 281 return layoutViewport().contentsSize();
285 } 282 }
286 283
287 bool RootFrameViewport::scrollbarsCanBeActive() const { 284 bool RootFrameViewport::scrollbarsCanBeActive() const {
288 return layoutViewport().scrollbarsCanBeActive(); 285 return layoutViewport().scrollbarsCanBeActive();
289 } 286 }
290 287
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 visualViewport().clearScrollAnimators(); 425 visualViewport().clearScrollAnimators();
429 } 426 }
430 427
431 DEFINE_TRACE(RootFrameViewport) { 428 DEFINE_TRACE(RootFrameViewport) {
432 visitor->trace(m_visualViewport); 429 visitor->trace(m_visualViewport);
433 visitor->trace(m_layoutViewport); 430 visitor->trace(m_layoutViewport);
434 ScrollableArea::trace(visitor); 431 ScrollableArea::trace(visitor);
435 } 432 }
436 433
437 } // namespace blink 434 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698