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/layout/ScrollAnchor.h" | 5 #include "core/layout/ScrollAnchor.h" |
6 | 6 |
7 #include "core/dom/ClientRect.h" | 7 #include "core/dom/ClientRect.h" |
8 #include "core/frame/VisualViewport.h" | 8 #include "core/frame/VisualViewport.h" |
9 #include "core/layout/LayoutBox.h" | 9 #include "core/layout/LayoutBox.h" |
10 #include "core/layout/LayoutTestHelper.h" | 10 #include "core/layout/LayoutTestHelper.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 ASSERT(scroller->isFrameView() || scroller->isPaintLayerScrollableArea()); | 46 ASSERT(scroller->isFrameView() || scroller->isPaintLayerScrollableArea()); |
47 return *(scroller->scrollAnchor()); | 47 return *(scroller->scrollAnchor()); |
48 } | 48 } |
49 | 49 |
50 void setHeight(Element* element, int height) { | 50 void setHeight(Element* element, int height) { |
51 element->setAttribute(HTMLNames::styleAttr, | 51 element->setAttribute(HTMLNames::styleAttr, |
52 AtomicString(String::format("height: %dpx", height))); | 52 AtomicString(String::format("height: %dpx", height))); |
53 update(); | 53 update(); |
54 } | 54 } |
55 | 55 |
56 void scrollLayoutViewport(DoubleSize delta) { | 56 void scrollLayoutViewport(ScrollOffset delta) { |
57 Element* scrollingElement = document().scrollingElement(); | 57 Element* scrollingElement = document().scrollingElement(); |
58 if (delta.width()) | 58 if (delta.width()) |
59 scrollingElement->setScrollLeft(scrollingElement->scrollLeft() + | 59 scrollingElement->setScrollLeft(scrollingElement->scrollLeft() + |
60 delta.width()); | 60 delta.width()); |
61 if (delta.height()) | 61 if (delta.height()) |
62 scrollingElement->setScrollTop(scrollingElement->scrollTop() + | 62 scrollingElement->setScrollTop(scrollingElement->scrollTop() + |
63 delta.height()); | 63 delta.height()); |
64 } | 64 } |
65 }; | 65 }; |
66 | 66 |
67 // TODO(ymalik): Currently, this should be the first test in the file to avoid | 67 // TODO(ymalik): Currently, this should be the first test in the file to avoid |
68 // failure when running with other tests. Dig into this more and fix. | 68 // failure when running with other tests. Dig into this more and fix. |
69 TEST_F(ScrollAnchorTest, UMAMetricUpdated) { | 69 TEST_F(ScrollAnchorTest, UMAMetricUpdated) { |
70 HistogramTester histogramTester; | 70 HistogramTester histogramTester; |
71 setBodyInnerHTML( | 71 setBodyInnerHTML( |
72 "<style> body { height: 1000px } div { height: 100px } </style>" | 72 "<style> body { height: 1000px } div { height: 100px } </style>" |
73 "<div id='block1'>abc</div>" | 73 "<div id='block1'>abc</div>" |
74 "<div id='block2'>def</div>"); | 74 "<div id='block2'>def</div>"); |
75 | 75 |
76 ScrollableArea* viewport = layoutViewport(); | 76 ScrollableArea* viewport = layoutViewport(); |
77 | 77 |
78 // Scroll position not adjusted, metric not updated. | 78 // Scroll position not adjusted, metric not updated. |
79 scrollLayoutViewport(DoubleSize(0, 150)); | 79 scrollLayoutViewport(ScrollOffset(0, 150)); |
80 histogramTester.expectTotalCount("Layout.ScrollAnchor.AdjustedScrollOffset", | 80 histogramTester.expectTotalCount("Layout.ScrollAnchor.AdjustedScrollOffset", |
81 0); | 81 0); |
82 | 82 |
83 // Height changed, verify metric updated once. | 83 // Height changed, verify metric updated once. |
84 setHeight(document().getElementById("block1"), 200); | 84 setHeight(document().getElementById("block1"), 200); |
85 histogramTester.expectUniqueSample("Layout.ScrollAnchor.AdjustedScrollOffset", | 85 histogramTester.expectUniqueSample("Layout.ScrollAnchor.AdjustedScrollOffset", |
86 1, 1); | 86 1, 1); |
87 | 87 |
88 EXPECT_EQ(250, viewport->scrollPosition().y()); | 88 EXPECT_EQ(250, viewport->scrollOffsetInt().height()); |
89 EXPECT_EQ(document().getElementById("block2")->layoutObject(), | 89 EXPECT_EQ(document().getElementById("block2")->layoutObject(), |
90 scrollAnchor(viewport).anchorObject()); | 90 scrollAnchor(viewport).anchorObject()); |
91 } | 91 } |
92 | 92 |
93 TEST_F(ScrollAnchorTest, Basic) { | 93 TEST_F(ScrollAnchorTest, Basic) { |
94 setBodyInnerHTML( | 94 setBodyInnerHTML( |
95 "<style> body { height: 1000px } div { height: 100px } </style>" | 95 "<style> body { height: 1000px } div { height: 100px } </style>" |
96 "<div id='block1'>abc</div>" | 96 "<div id='block1'>abc</div>" |
97 "<div id='block2'>def</div>"); | 97 "<div id='block2'>def</div>"); |
98 | 98 |
99 ScrollableArea* viewport = layoutViewport(); | 99 ScrollableArea* viewport = layoutViewport(); |
100 | 100 |
101 // No anchor at origin (0,0). | 101 // No anchor at origin (0,0). |
102 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 102 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
103 | 103 |
104 scrollLayoutViewport(DoubleSize(0, 150)); | 104 scrollLayoutViewport(ScrollOffset(0, 150)); |
105 setHeight(document().getElementById("block1"), 200); | 105 setHeight(document().getElementById("block1"), 200); |
106 | 106 |
107 EXPECT_EQ(250, viewport->scrollPosition().y()); | 107 EXPECT_EQ(250, viewport->scrollOffsetInt().height()); |
108 EXPECT_EQ(document().getElementById("block2")->layoutObject(), | 108 EXPECT_EQ(document().getElementById("block2")->layoutObject(), |
109 scrollAnchor(viewport).anchorObject()); | 109 scrollAnchor(viewport).anchorObject()); |
110 | 110 |
111 // ScrollableArea::userScroll should clear the anchor. | 111 // ScrollableArea::userScroll should clear the anchor. |
112 viewport->userScroll(ScrollByPrecisePixel, FloatSize(0, 100)); | 112 viewport->userScroll(ScrollByPrecisePixel, FloatSize(0, 100)); |
113 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 113 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
114 } | 114 } |
115 | 115 |
116 TEST_F(ScrollAnchorTest, VisualViewportAnchors) { | 116 TEST_F(ScrollAnchorTest, VisualViewportAnchors) { |
117 setBodyInnerHTML( | 117 setBodyInnerHTML( |
(...skipping 12 matching lines...) Expand all Loading... |
130 // No anchor at origin (0,0). | 130 // No anchor at origin (0,0). |
131 EXPECT_EQ(nullptr, scrollAnchor(lViewport).anchorObject()); | 131 EXPECT_EQ(nullptr, scrollAnchor(lViewport).anchorObject()); |
132 | 132 |
133 // Scroll the visual viewport to bring #text to the top. | 133 // Scroll the visual viewport to bring #text to the top. |
134 int top = document().getElementById("text")->getBoundingClientRect()->top(); | 134 int top = document().getElementById("text")->getBoundingClientRect()->top(); |
135 vViewport.setLocation(FloatPoint(0, top)); | 135 vViewport.setLocation(FloatPoint(0, top)); |
136 | 136 |
137 setHeight(document().getElementById("div"), 10); | 137 setHeight(document().getElementById("div"), 10); |
138 EXPECT_EQ(document().getElementById("text")->layoutObject(), | 138 EXPECT_EQ(document().getElementById("text")->layoutObject(), |
139 scrollAnchor(lViewport).anchorObject()); | 139 scrollAnchor(lViewport).anchorObject()); |
140 EXPECT_EQ(top - 90, vViewport.scrollPosition().y()); | 140 EXPECT_EQ(top - 90, vViewport.scrollOffsetInt().height()); |
141 | 141 |
142 setHeight(document().getElementById("div"), 100); | 142 setHeight(document().getElementById("div"), 100); |
143 EXPECT_EQ(document().getElementById("text")->layoutObject(), | 143 EXPECT_EQ(document().getElementById("text")->layoutObject(), |
144 scrollAnchor(lViewport).anchorObject()); | 144 scrollAnchor(lViewport).anchorObject()); |
145 EXPECT_EQ(top, vViewport.scrollPosition().y()); | 145 EXPECT_EQ(top, vViewport.scrollOffsetInt().height()); |
146 | 146 |
147 // Scrolling the visual viewport should clear the anchor. | 147 // Scrolling the visual viewport should clear the anchor. |
148 vViewport.setLocation(FloatPoint(0, 0)); | 148 vViewport.setLocation(FloatPoint(0, 0)); |
149 EXPECT_EQ(nullptr, scrollAnchor(lViewport).anchorObject()); | 149 EXPECT_EQ(nullptr, scrollAnchor(lViewport).anchorObject()); |
150 } | 150 } |
151 | 151 |
152 // Test that we ignore the clipped content when computing visibility otherwise | 152 // Test that we ignore the clipped content when computing visibility otherwise |
153 // we may end up with an anchor that we think is in the viewport but is not. | 153 // we may end up with an anchor that we think is in the viewport but is not. |
154 TEST_F(ScrollAnchorTest, ClippedScrollersSkipped) { | 154 TEST_F(ScrollAnchorTest, ClippedScrollersSkipped) { |
155 setBodyInnerHTML( | 155 setBodyInnerHTML( |
(...skipping 12 matching lines...) Expand all Loading... |
168 " <div id='forceScrolling'></div>" | 168 " <div id='forceScrolling'></div>" |
169 "</div>" | 169 "</div>" |
170 "<div id='outerChanger'></div>" | 170 "<div id='outerChanger'></div>" |
171 "<div id='outerAnchor' class='anchor'></div>"); | 171 "<div id='outerAnchor' class='anchor'></div>"); |
172 | 172 |
173 ScrollableArea* scroller = | 173 ScrollableArea* scroller = |
174 scrollerForElement(document().getElementById("scroller")); | 174 scrollerForElement(document().getElementById("scroller")); |
175 ScrollableArea* viewport = layoutViewport(); | 175 ScrollableArea* viewport = layoutViewport(); |
176 | 176 |
177 document().getElementById("scroller")->setScrollTop(100); | 177 document().getElementById("scroller")->setScrollTop(100); |
178 scrollLayoutViewport(DoubleSize(0, 350)); | 178 scrollLayoutViewport(ScrollOffset(0, 350)); |
179 | 179 |
180 setHeight(document().getElementById("innerChanger"), 200); | 180 setHeight(document().getElementById("innerChanger"), 200); |
181 setHeight(document().getElementById("outerChanger"), 150); | 181 setHeight(document().getElementById("outerChanger"), 150); |
182 | 182 |
183 EXPECT_EQ(300, scroller->scrollPosition().y()); | 183 EXPECT_EQ(300, scroller->scrollOffsetInt().height()); |
184 EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), | 184 EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), |
185 scrollAnchor(scroller).anchorObject()); | 185 scrollAnchor(scroller).anchorObject()); |
186 EXPECT_EQ(500, viewport->scrollPosition().y()); | 186 EXPECT_EQ(500, viewport->scrollOffsetInt().height()); |
187 EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), | 187 EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), |
188 scrollAnchor(viewport).anchorObject()); | 188 scrollAnchor(viewport).anchorObject()); |
189 } | 189 } |
190 | 190 |
191 // Test that scroll anchoring causes no visible jump when a layout change | 191 // Test that scroll anchoring causes no visible jump when a layout change |
192 // (such as removal of a DOM element) changes the scroll bounds. | 192 // (such as removal of a DOM element) changes the scroll bounds. |
193 TEST_F(ScrollAnchorTest, AnchoringWhenContentRemoved) { | 193 TEST_F(ScrollAnchorTest, AnchoringWhenContentRemoved) { |
194 setBodyInnerHTML( | 194 setBodyInnerHTML( |
195 "<style>" | 195 "<style>" |
196 " #changer { height: 1500px; }" | 196 " #changer { height: 1500px; }" |
197 " #anchor {" | 197 " #anchor {" |
198 " width: 150px; height: 1000px; background-color: pink;" | 198 " width: 150px; height: 1000px; background-color: pink;" |
199 " }" | 199 " }" |
200 "</style>" | 200 "</style>" |
201 "<div id='changer'></div>" | 201 "<div id='changer'></div>" |
202 "<div id='anchor'></div>"); | 202 "<div id='anchor'></div>"); |
203 | 203 |
204 ScrollableArea* viewport = layoutViewport(); | 204 ScrollableArea* viewport = layoutViewport(); |
205 scrollLayoutViewport(DoubleSize(0, 1600)); | 205 scrollLayoutViewport(ScrollOffset(0, 1600)); |
206 | 206 |
207 setHeight(document().getElementById("changer"), 0); | 207 setHeight(document().getElementById("changer"), 0); |
208 | 208 |
209 EXPECT_EQ(100, viewport->scrollPosition().y()); | 209 EXPECT_EQ(100, viewport->scrollOffsetInt().height()); |
210 EXPECT_EQ(document().getElementById("anchor")->layoutObject(), | 210 EXPECT_EQ(document().getElementById("anchor")->layoutObject(), |
211 scrollAnchor(viewport).anchorObject()); | 211 scrollAnchor(viewport).anchorObject()); |
212 } | 212 } |
213 | 213 |
214 // Test that scroll anchoring causes no visible jump when a layout change | 214 // Test that scroll anchoring causes no visible jump when a layout change |
215 // (such as removal of a DOM element) changes the scroll bounds of a scrolling | 215 // (such as removal of a DOM element) changes the scroll bounds of a scrolling |
216 // div. | 216 // div. |
217 TEST_F(ScrollAnchorTest, AnchoringWhenContentRemovedFromScrollingDiv) { | 217 TEST_F(ScrollAnchorTest, AnchoringWhenContentRemovedFromScrollingDiv) { |
218 setBodyInnerHTML( | 218 setBodyInnerHTML( |
219 "<style>" | 219 "<style>" |
220 " #scroller { height: 500px; width: 200px; overflow: scroll; }" | 220 " #scroller { height: 500px; width: 200px; overflow: scroll; }" |
221 " #changer { height: 1500px; }" | 221 " #changer { height: 1500px; }" |
222 " #anchor {" | 222 " #anchor {" |
223 " width: 150px; height: 1000px; overflow: scroll;" | 223 " width: 150px; height: 1000px; overflow: scroll;" |
224 " }" | 224 " }" |
225 "</style>" | 225 "</style>" |
226 "<div id='scroller'>" | 226 "<div id='scroller'>" |
227 " <div id='changer'></div>" | 227 " <div id='changer'></div>" |
228 " <div id='anchor'></div>" | 228 " <div id='anchor'></div>" |
229 "</div>"); | 229 "</div>"); |
230 | 230 |
231 ScrollableArea* scroller = | 231 ScrollableArea* scroller = |
232 scrollerForElement(document().getElementById("scroller")); | 232 scrollerForElement(document().getElementById("scroller")); |
233 | 233 |
234 document().getElementById("scroller")->setScrollTop(1600); | 234 document().getElementById("scroller")->setScrollTop(1600); |
235 | 235 |
236 setHeight(document().getElementById("changer"), 0); | 236 setHeight(document().getElementById("changer"), 0); |
237 | 237 |
238 EXPECT_EQ(100, scroller->scrollPosition().y()); | 238 EXPECT_EQ(100, scroller->scrollOffsetInt().height()); |
239 EXPECT_EQ(document().getElementById("anchor")->layoutObject(), | 239 EXPECT_EQ(document().getElementById("anchor")->layoutObject(), |
240 scrollAnchor(scroller).anchorObject()); | 240 scrollAnchor(scroller).anchorObject()); |
241 } | 241 } |
242 | 242 |
243 TEST_F(ScrollAnchorTest, FractionalOffsetsAreRoundedBeforeComparing) { | 243 TEST_F(ScrollAnchorTest, FractionalOffsetsAreRoundedBeforeComparing) { |
244 setBodyInnerHTML( | 244 setBodyInnerHTML( |
245 "<style> body { height: 1000px } </style>" | 245 "<style> body { height: 1000px } </style>" |
246 "<div id='block1' style='height: 50.4px'>abc</div>" | 246 "<div id='block1' style='height: 50.4px'>abc</div>" |
247 "<div id='block2' style='height: 100px'>def</div>"); | 247 "<div id='block2' style='height: 100px'>def</div>"); |
248 | 248 |
249 ScrollableArea* viewport = layoutViewport(); | 249 ScrollableArea* viewport = layoutViewport(); |
250 scrollLayoutViewport(DoubleSize(0, 100)); | 250 scrollLayoutViewport(ScrollOffset(0, 100)); |
251 | 251 |
252 document().getElementById("block1")->setAttribute(HTMLNames::styleAttr, | 252 document().getElementById("block1")->setAttribute(HTMLNames::styleAttr, |
253 "height: 50.6px"); | 253 "height: 50.6px"); |
254 update(); | 254 update(); |
255 | 255 |
256 EXPECT_EQ(101, viewport->scrollPosition().y()); | 256 EXPECT_EQ(101, viewport->scrollOffsetInt().height()); |
257 } | 257 } |
258 | 258 |
259 TEST_F(ScrollAnchorTest, AnchorWithLayerInScrollingDiv) { | 259 TEST_F(ScrollAnchorTest, AnchorWithLayerInScrollingDiv) { |
260 setBodyInnerHTML( | 260 setBodyInnerHTML( |
261 "<style>" | 261 "<style>" |
262 " #scroller { overflow: scroll; width: 500px; height: 400px; }" | 262 " #scroller { overflow: scroll; width: 500px; height: 400px; }" |
263 " div { height: 100px }" | 263 " div { height: 100px }" |
264 " #block2 { overflow: hidden }" | 264 " #block2 { overflow: hidden }" |
265 " #space { height: 1000px; }" | 265 " #space { height: 1000px; }" |
266 "</style>" | 266 "</style>" |
267 "<div id='scroller'><div id='space'>" | 267 "<div id='scroller'><div id='space'>" |
268 "<div id='block1'>abc</div>" | 268 "<div id='block1'>abc</div>" |
269 "<div id='block2'>def</div>" | 269 "<div id='block2'>def</div>" |
270 "</div></div>"); | 270 "</div></div>"); |
271 | 271 |
272 ScrollableArea* scroller = | 272 ScrollableArea* scroller = |
273 scrollerForElement(document().getElementById("scroller")); | 273 scrollerForElement(document().getElementById("scroller")); |
274 Element* block1 = document().getElementById("block1"); | 274 Element* block1 = document().getElementById("block1"); |
275 Element* block2 = document().getElementById("block2"); | 275 Element* block2 = document().getElementById("block2"); |
276 | 276 |
277 scroller->scrollBy(DoubleSize(0, 150), UserScroll); | 277 scroller->scrollBy(ScrollOffset(0, 150), UserScroll); |
278 | 278 |
279 // In this layout pass we will anchor to #block2 which has its own PaintLayer. | 279 // In this layout pass we will anchor to #block2 which has its own PaintLayer. |
280 setHeight(block1, 200); | 280 setHeight(block1, 200); |
281 EXPECT_EQ(250, scroller->scrollPosition().y()); | 281 EXPECT_EQ(250, scroller->scrollOffsetInt().height()); |
282 EXPECT_EQ(block2->layoutObject(), scrollAnchor(scroller).anchorObject()); | 282 EXPECT_EQ(block2->layoutObject(), scrollAnchor(scroller).anchorObject()); |
283 | 283 |
284 // Test that the anchor object can be destroyed without affecting the scroll p
osition. | 284 // Test that the anchor object can be destroyed without affecting the scroll p
osition. |
285 block2->remove(); | 285 block2->remove(); |
286 update(); | 286 update(); |
287 EXPECT_EQ(250, scroller->scrollPosition().y()); | 287 EXPECT_EQ(250, scroller->scrollOffsetInt().height()); |
288 } | 288 } |
289 | 289 |
290 TEST_F(ScrollAnchorTest, ExcludeAnonymousCandidates) { | 290 TEST_F(ScrollAnchorTest, ExcludeAnonymousCandidates) { |
291 setBodyInnerHTML( | 291 setBodyInnerHTML( |
292 "<style>" | 292 "<style>" |
293 " body { height: 3500px }" | 293 " body { height: 3500px }" |
294 " #div {" | 294 " #div {" |
295 " position: relative; background-color: pink;" | 295 " position: relative; background-color: pink;" |
296 " top: 5px; left: 5px; width: 100px; height: 3500px;" | 296 " top: 5px; left: 5px; width: 100px; height: 3500px;" |
297 " }" | 297 " }" |
(...skipping 30 matching lines...) Expand all Loading... |
328 " body { height: 1000px }" | 328 " body { height: 1000px }" |
329 " #outer { line-height: 100px }" | 329 " #outer { line-height: 100px }" |
330 " #ib1, #ib2 { display: inline-block }" | 330 " #ib1, #ib2 { display: inline-block }" |
331 "</style>" | 331 "</style>" |
332 "<span id=outer>" | 332 "<span id=outer>" |
333 " <span id=ib1>abc</span>" | 333 " <span id=ib1>abc</span>" |
334 " <br><br>" | 334 " <br><br>" |
335 " <span id=ib2>def</span>" | 335 " <span id=ib2>def</span>" |
336 "</span>"); | 336 "</span>"); |
337 | 337 |
338 scrollLayoutViewport(DoubleSize(0, 150)); | 338 scrollLayoutViewport(ScrollOffset(0, 150)); |
339 | 339 |
340 Element* ib1 = document().getElementById("ib1"); | 340 Element* ib1 = document().getElementById("ib1"); |
341 ib1->setAttribute(HTMLNames::styleAttr, "line-height: 150px"); | 341 ib1->setAttribute(HTMLNames::styleAttr, "line-height: 150px"); |
342 update(); | 342 update(); |
343 EXPECT_EQ(document().getElementById("ib2")->layoutObject(), | 343 EXPECT_EQ(document().getElementById("ib2")->layoutObject(), |
344 scrollAnchor(layoutViewport()).anchorObject()); | 344 scrollAnchor(layoutViewport()).anchorObject()); |
345 } | 345 } |
346 | 346 |
347 TEST_F(ScrollAnchorTest, TextBounds) { | 347 TEST_F(ScrollAnchorTest, TextBounds) { |
348 setBodyInnerHTML( | 348 setBodyInnerHTML( |
349 "<style>" | 349 "<style>" |
350 " body {" | 350 " body {" |
351 " position: absolute;" | 351 " position: absolute;" |
352 " font-size: 100px;" | 352 " font-size: 100px;" |
353 " width: 200px;" | 353 " width: 200px;" |
354 " height: 1000px;" | 354 " height: 1000px;" |
355 " line-height: 100px;" | 355 " line-height: 100px;" |
356 " }" | 356 " }" |
357 "</style>" | 357 "</style>" |
358 "abc <b id=b>def</b> ghi" | 358 "abc <b id=b>def</b> ghi" |
359 "<div id=a>after</div>"); | 359 "<div id=a>after</div>"); |
360 | 360 |
361 scrollLayoutViewport(DoubleSize(0, 150)); | 361 scrollLayoutViewport(ScrollOffset(0, 150)); |
362 | 362 |
363 setHeight(document().getElementById("a"), 100); | 363 setHeight(document().getElementById("a"), 100); |
364 EXPECT_EQ(document().getElementById("b")->layoutObject()->slowFirstChild(), | 364 EXPECT_EQ(document().getElementById("b")->layoutObject()->slowFirstChild(), |
365 scrollAnchor(layoutViewport()).anchorObject()); | 365 scrollAnchor(layoutViewport()).anchorObject()); |
366 } | 366 } |
367 | 367 |
368 TEST_F(ScrollAnchorTest, ExcludeFixedPosition) { | 368 TEST_F(ScrollAnchorTest, ExcludeFixedPosition) { |
369 setBodyInnerHTML( | 369 setBodyInnerHTML( |
370 "<style>" | 370 "<style>" |
371 " body { height: 1000px; padding: 20px; }" | 371 " body { height: 1000px; padding: 20px; }" |
372 " div { position: relative; top: 100px; }" | 372 " div { position: relative; top: 100px; }" |
373 " #f { position: fixed }" | 373 " #f { position: fixed }" |
374 "</style>" | 374 "</style>" |
375 "<div id=f>fixed</div>" | 375 "<div id=f>fixed</div>" |
376 "<div id=c>content</div>" | 376 "<div id=c>content</div>" |
377 "<div id=a>after</div>"); | 377 "<div id=a>after</div>"); |
378 | 378 |
379 scrollLayoutViewport(DoubleSize(0, 50)); | 379 scrollLayoutViewport(ScrollOffset(0, 50)); |
380 | 380 |
381 setHeight(document().getElementById("a"), 100); | 381 setHeight(document().getElementById("a"), 100); |
382 EXPECT_EQ(document().getElementById("c")->layoutObject(), | 382 EXPECT_EQ(document().getElementById("c")->layoutObject(), |
383 scrollAnchor(layoutViewport()).anchorObject()); | 383 scrollAnchor(layoutViewport()).anchorObject()); |
384 } | 384 } |
385 | 385 |
386 // This test verifies that position:absolute elements that stick to the viewport | 386 // This test verifies that position:absolute elements that stick to the viewport |
387 // are not selected as anchors. | 387 // are not selected as anchors. |
388 TEST_F(ScrollAnchorTest, ExcludeAbsolutePositionThatSticksToViewport) { | 388 TEST_F(ScrollAnchorTest, ExcludeAbsolutePositionThatSticksToViewport) { |
389 setBodyInnerHTML( | 389 setBodyInnerHTML( |
(...skipping 14 matching lines...) Expand all Loading... |
404 " <div id='abs'></div>" | 404 " <div id='abs'></div>" |
405 " <div id='rel'></div>" | 405 " <div id='rel'></div>" |
406 " <div id=a>after</div>" | 406 " <div id=a>after</div>" |
407 "</div></div>"); | 407 "</div></div>"); |
408 | 408 |
409 Element* scrollerElement = document().getElementById("scroller"); | 409 Element* scrollerElement = document().getElementById("scroller"); |
410 ScrollableArea* scroller = scrollerForElement(scrollerElement); | 410 ScrollableArea* scroller = scrollerForElement(scrollerElement); |
411 Element* absPos = document().getElementById("abs"); | 411 Element* absPos = document().getElementById("abs"); |
412 Element* relPos = document().getElementById("rel"); | 412 Element* relPos = document().getElementById("rel"); |
413 | 413 |
414 scroller->scrollBy(DoubleSize(0, 25), UserScroll); | 414 scroller->scrollBy(ScrollOffset(0, 25), UserScroll); |
415 setHeight(document().getElementById("a"), 100); | 415 setHeight(document().getElementById("a"), 100); |
416 | 416 |
417 // When the scroller is position:static, the anchor cannot be position:absolut
e. | 417 // When the scroller is position:static, the anchor cannot be position:absolut
e. |
418 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject()); | 418 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject()); |
419 | 419 |
420 scrollerElement->setAttribute(HTMLNames::styleAttr, "position: relative"); | 420 scrollerElement->setAttribute(HTMLNames::styleAttr, "position: relative"); |
421 update(); | 421 update(); |
422 scroller->scrollBy(DoubleSize(0, 25), UserScroll); | 422 scroller->scrollBy(ScrollOffset(0, 25), UserScroll); |
423 setHeight(document().getElementById("a"), 125); | 423 setHeight(document().getElementById("a"), 125); |
424 | 424 |
425 // When the scroller is position:relative, the anchor may be position:absolute
. | 425 // When the scroller is position:relative, the anchor may be position:absolute
. |
426 EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject()); | 426 EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject()); |
427 } | 427 } |
428 | 428 |
429 // Test that we descend into zero-height containers that have overflowing conten
t. | 429 // Test that we descend into zero-height containers that have overflowing conten
t. |
430 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithOverflow) { | 430 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithOverflow) { |
431 setBodyInnerHTML( | 431 setBodyInnerHTML( |
432 "<style>" | 432 "<style>" |
433 " body { height: 1000; }" | 433 " body { height: 1000; }" |
434 " #outer { width: 300px; }" | 434 " #outer { width: 300px; }" |
435 " #zeroheight { height: 0px; }" | 435 " #zeroheight { height: 0px; }" |
436 " #changer { height: 100px; background-color: red; }" | 436 " #changer { height: 100px; background-color: red; }" |
437 " #bottom { margin-top: 600px; }" | 437 " #bottom { margin-top: 600px; }" |
438 "</style>" | 438 "</style>" |
439 "<div id='outer'>" | 439 "<div id='outer'>" |
440 " <div id='zeroheight'>" | 440 " <div id='zeroheight'>" |
441 " <div id='changer'></div>" | 441 " <div id='changer'></div>" |
442 " <div id='bottom'>bottom</div>" | 442 " <div id='bottom'>bottom</div>" |
443 " </div>" | 443 " </div>" |
444 "</div>"); | 444 "</div>"); |
445 | 445 |
446 ScrollableArea* viewport = layoutViewport(); | 446 ScrollableArea* viewport = layoutViewport(); |
447 | 447 |
448 scrollLayoutViewport(DoubleSize(0, 200)); | 448 scrollLayoutViewport(ScrollOffset(0, 200)); |
449 setHeight(document().getElementById("changer"), 200); | 449 setHeight(document().getElementById("changer"), 200); |
450 | 450 |
451 EXPECT_EQ(300, viewport->scrollPosition().y()); | 451 EXPECT_EQ(300, viewport->scrollOffsetInt().height()); |
452 EXPECT_EQ(document().getElementById("bottom")->layoutObject(), | 452 EXPECT_EQ(document().getElementById("bottom")->layoutObject(), |
453 scrollAnchor(viewport).anchorObject()); | 453 scrollAnchor(viewport).anchorObject()); |
454 } | 454 } |
455 | 455 |
456 // Test that we descend into zero-height containers that have floating content. | 456 // Test that we descend into zero-height containers that have floating content. |
457 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithFloat) { | 457 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithFloat) { |
458 setBodyInnerHTML( | 458 setBodyInnerHTML( |
459 "<style>" | 459 "<style>" |
460 " body { height: 1000; }" | 460 " body { height: 1000; }" |
461 " #outer { width: 300px; }" | 461 " #outer { width: 300px; }" |
(...skipping 13 matching lines...) Expand all Loading... |
475 "</div>" | 475 "</div>" |
476 "<div id=a>after</div>"); | 476 "<div id=a>after</div>"); |
477 | 477 |
478 EXPECT_EQ(0, | 478 EXPECT_EQ(0, |
479 toLayoutBox(document().getElementById("zeroheight")->layoutObject()) | 479 toLayoutBox(document().getElementById("zeroheight")->layoutObject()) |
480 ->size() | 480 ->size() |
481 .height()); | 481 .height()); |
482 | 482 |
483 ScrollableArea* viewport = layoutViewport(); | 483 ScrollableArea* viewport = layoutViewport(); |
484 | 484 |
485 scrollLayoutViewport(DoubleSize(0, 200)); | 485 scrollLayoutViewport(ScrollOffset(0, 200)); |
486 setHeight(document().getElementById("a"), 100); | 486 setHeight(document().getElementById("a"), 100); |
487 | 487 |
488 EXPECT_EQ(200, viewport->scrollPosition().y()); | 488 EXPECT_EQ(200, viewport->scrollOffsetInt().height()); |
489 EXPECT_EQ(document().getElementById("float")->layoutObject(), | 489 EXPECT_EQ(document().getElementById("float")->layoutObject(), |
490 scrollAnchor(viewport).anchorObject()); | 490 scrollAnchor(viewport).anchorObject()); |
491 } | 491 } |
492 | 492 |
493 // This test verifies that scroll anchoring is disabled when any element within | 493 // This test verifies that scroll anchoring is disabled when any element within |
494 // the main scroller changes its in-flow state. | 494 // the main scroller changes its in-flow state. |
495 TEST_F(ScrollAnchorTest, ChangeInFlowStateDisablesAnchoringForMainScroller) { | 495 TEST_F(ScrollAnchorTest, ChangeInFlowStateDisablesAnchoringForMainScroller) { |
496 setBodyInnerHTML( | 496 setBodyInnerHTML( |
497 "<style>" | 497 "<style>" |
498 " body { height: 1000px; }" | 498 " body { height: 1000px; }" |
499 " #header { background-color: #F5B335; height: 50px; width: 100%; }" | 499 " #header { background-color: #F5B335; height: 50px; width: 100%; }" |
500 " #content { background-color: #D3D3D3; height: 200px; }" | 500 " #content { background-color: #D3D3D3; height: 200px; }" |
501 "</style>" | 501 "</style>" |
502 "<div id='header'></div>" | 502 "<div id='header'></div>" |
503 "<div id='content'></div>"); | 503 "<div id='content'></div>"); |
504 | 504 |
505 ScrollableArea* viewport = layoutViewport(); | 505 ScrollableArea* viewport = layoutViewport(); |
506 scrollLayoutViewport(DoubleSize(0, 200)); | 506 scrollLayoutViewport(ScrollOffset(0, 200)); |
507 | 507 |
508 document().getElementById("header")->setAttribute(HTMLNames::styleAttr, | 508 document().getElementById("header")->setAttribute(HTMLNames::styleAttr, |
509 "position: fixed;"); | 509 "position: fixed;"); |
510 update(); | 510 update(); |
511 | 511 |
512 EXPECT_EQ(200, viewport->scrollPosition().y()); | 512 EXPECT_EQ(200, viewport->scrollOffsetInt().height()); |
513 } | 513 } |
514 | 514 |
515 // This test verifies that scroll anchoring is disabled when any element within | 515 // This test verifies that scroll anchoring is disabled when any element within |
516 // a scrolling div changes its in-flow state. | 516 // a scrolling div changes its in-flow state. |
517 TEST_F(ScrollAnchorTest, ChangeInFlowStateDisablesAnchoringForScrollingDiv) { | 517 TEST_F(ScrollAnchorTest, ChangeInFlowStateDisablesAnchoringForScrollingDiv) { |
518 setBodyInnerHTML( | 518 setBodyInnerHTML( |
519 "<style>" | 519 "<style>" |
520 " #container { position: relative; width: 500px; }" | 520 " #container { position: relative; width: 500px; }" |
521 " #scroller { height: 200px; overflow: scroll; }" | 521 " #scroller { height: 200px; overflow: scroll; }" |
522 " #changer { background-color: #F5B335; height: 50px; width: 100%; }" | 522 " #changer { background-color: #F5B335; height: 50px; width: 100%; }" |
523 " #anchor { background-color: #D3D3D3; height: 300px; }" | 523 " #anchor { background-color: #D3D3D3; height: 300px; }" |
524 "</style>" | 524 "</style>" |
525 "<div id='container'>" | 525 "<div id='container'>" |
526 " <div id='scroller'>" | 526 " <div id='scroller'>" |
527 " <div id='changer'></div>" | 527 " <div id='changer'></div>" |
528 " <div id='anchor'></div>" | 528 " <div id='anchor'></div>" |
529 " </div>" | 529 " </div>" |
530 "</div>"); | 530 "</div>"); |
531 | 531 |
532 ScrollableArea* scroller = | 532 ScrollableArea* scroller = |
533 scrollerForElement(document().getElementById("scroller")); | 533 scrollerForElement(document().getElementById("scroller")); |
534 document().getElementById("scroller")->setScrollTop(100); | 534 document().getElementById("scroller")->setScrollTop(100); |
535 | 535 |
536 document().getElementById("changer")->setAttribute(HTMLNames::styleAttr, | 536 document().getElementById("changer")->setAttribute(HTMLNames::styleAttr, |
537 "position: absolute;"); | 537 "position: absolute;"); |
538 update(); | 538 update(); |
539 | 539 |
540 EXPECT_EQ(100, scroller->scrollPosition().y()); | 540 EXPECT_EQ(100, scroller->scrollOffsetInt().height()); |
541 } | 541 } |
542 | 542 |
543 TEST_F(ScrollAnchorTest, FlexboxDelayedClampingAlsoDelaysAdjustment) { | 543 TEST_F(ScrollAnchorTest, FlexboxDelayedClampingAlsoDelaysAdjustment) { |
544 setBodyInnerHTML( | 544 setBodyInnerHTML( |
545 "<style>" | 545 "<style>" |
546 " html { overflow: hidden; }" | 546 " html { overflow: hidden; }" |
547 " body {" | 547 " body {" |
548 " position: absolute; display: flex;" | 548 " position: absolute; display: flex;" |
549 " top: 0; bottom: 0; margin: 0;" | 549 " top: 0; bottom: 0; margin: 0;" |
550 " }" | 550 " }" |
551 " #scroller { overflow: auto; }" | 551 " #scroller { overflow: auto; }" |
552 " #spacer { width: 600px; height: 1200px; }" | 552 " #spacer { width: 600px; height: 1200px; }" |
553 " #before { height: 50px; }" | 553 " #before { height: 50px; }" |
554 " #anchor {" | 554 " #anchor {" |
555 " width: 100px; height: 100px;" | 555 " width: 100px; height: 100px;" |
556 " background-color: #8f8;" | 556 " background-color: #8f8;" |
557 " }" | 557 " }" |
558 "</style>" | 558 "</style>" |
559 "<div id='scroller'>" | 559 "<div id='scroller'>" |
560 " <div id='spacer'>" | 560 " <div id='spacer'>" |
561 " <div id='before'></div>" | 561 " <div id='before'></div>" |
562 " <div id='anchor'></div>" | 562 " <div id='anchor'></div>" |
563 " </div>" | 563 " </div>" |
564 "</div>"); | 564 "</div>"); |
565 | 565 |
566 Element* scroller = document().getElementById("scroller"); | 566 Element* scroller = document().getElementById("scroller"); |
567 scroller->setScrollTop(100); | 567 scroller->setScrollTop(100); |
568 | 568 |
569 setHeight(document().getElementById("before"), 100); | 569 setHeight(document().getElementById("before"), 100); |
570 EXPECT_EQ(150, scrollerForElement(scroller)->scrollPosition().y()); | 570 EXPECT_EQ(150, scrollerForElement(scroller)->scrollOffsetInt().height()); |
571 } | 571 } |
572 | 572 |
573 TEST_F(ScrollAnchorTest, FlexboxDelayedAdjustmentRespectsSANACLAP) { | 573 TEST_F(ScrollAnchorTest, FlexboxDelayedAdjustmentRespectsSANACLAP) { |
574 setBodyInnerHTML( | 574 setBodyInnerHTML( |
575 "<style>" | 575 "<style>" |
576 " html { overflow: hidden; }" | 576 " html { overflow: hidden; }" |
577 " body {" | 577 " body {" |
578 " position: absolute; display: flex;" | 578 " position: absolute; display: flex;" |
579 " top: 0; bottom: 0; margin: 0;" | 579 " top: 0; bottom: 0; margin: 0;" |
580 " }" | 580 " }" |
(...skipping 10 matching lines...) Expand all Loading... |
591 " <div id='anchor'></div>" | 591 " <div id='anchor'></div>" |
592 " </div>" | 592 " </div>" |
593 "</div>"); | 593 "</div>"); |
594 | 594 |
595 Element* scroller = document().getElementById("scroller"); | 595 Element* scroller = document().getElementById("scroller"); |
596 scroller->setScrollTop(100); | 596 scroller->setScrollTop(100); |
597 | 597 |
598 document().getElementById("spacer")->setAttribute(HTMLNames::styleAttr, | 598 document().getElementById("spacer")->setAttribute(HTMLNames::styleAttr, |
599 "margin-top: 50px"); | 599 "margin-top: 50px"); |
600 update(); | 600 update(); |
601 EXPECT_EQ(100, scrollerForElement(scroller)->scrollPosition().y()); | 601 EXPECT_EQ(100, scrollerForElement(scroller)->scrollOffsetInt().height()); |
602 } | 602 } |
603 | 603 |
604 // Test then an element and its children are not selected as the anchor when | 604 // Test then an element and its children are not selected as the anchor when |
605 // it has the overflow-anchor property set to none. | 605 // it has the overflow-anchor property set to none. |
606 TEST_F(ScrollAnchorTest, OptOutElement) { | 606 TEST_F(ScrollAnchorTest, OptOutElement) { |
607 setBodyInnerHTML( | 607 setBodyInnerHTML( |
608 "<style>" | 608 "<style>" |
609 " body { height: 1000px }" | 609 " body { height: 1000px }" |
610 " .div {" | 610 " .div {" |
611 " height: 100px; width: 100px;" | 611 " height: 100px; width: 100px;" |
612 " border: 1px solid gray; background-color: #afa;" | 612 " border: 1px solid gray; background-color: #afa;" |
613 " }" | 613 " }" |
614 " #innerDiv {" | 614 " #innerDiv {" |
615 " height: 50px; width: 50px;" | 615 " height: 50px; width: 50px;" |
616 " border: 1px solid gray; background-color: pink;" | 616 " border: 1px solid gray; background-color: pink;" |
617 " }" | 617 " }" |
618 "</style>" | 618 "</style>" |
619 "<div id='changer'></div>" | 619 "<div id='changer'></div>" |
620 "<div class='div' id='firstDiv'><div id='innerDiv'></div></div>" | 620 "<div class='div' id='firstDiv'><div id='innerDiv'></div></div>" |
621 "<div class='div' id='secondDiv'></div>"); | 621 "<div class='div' id='secondDiv'></div>"); |
622 | 622 |
623 ScrollableArea* viewport = layoutViewport(); | 623 ScrollableArea* viewport = layoutViewport(); |
624 scrollLayoutViewport(DoubleSize(0, 50)); | 624 scrollLayoutViewport(ScrollOffset(0, 50)); |
625 | 625 |
626 // No opt-out. | 626 // No opt-out. |
627 setHeight(document().getElementById("changer"), 100); | 627 setHeight(document().getElementById("changer"), 100); |
628 EXPECT_EQ(150, viewport->scrollPosition().y()); | 628 EXPECT_EQ(150, viewport->scrollOffsetInt().height()); |
629 EXPECT_EQ(document().getElementById("innerDiv")->layoutObject(), | 629 EXPECT_EQ(document().getElementById("innerDiv")->layoutObject(), |
630 scrollAnchor(viewport).anchorObject()); | 630 scrollAnchor(viewport).anchorObject()); |
631 | 631 |
632 // Clear anchor and opt-out element. | 632 // Clear anchor and opt-out element. |
633 scrollLayoutViewport(DoubleSize(0, 10)); | 633 scrollLayoutViewport(ScrollOffset(0, 10)); |
634 document() | 634 document() |
635 .getElementById("firstDiv") | 635 .getElementById("firstDiv") |
636 ->setAttribute(HTMLNames::styleAttr, | 636 ->setAttribute(HTMLNames::styleAttr, |
637 AtomicString("overflow-anchor: none")); | 637 AtomicString("overflow-anchor: none")); |
638 update(); | 638 update(); |
639 | 639 |
640 // Opted out element and it's children skipped. | 640 // Opted out element and it's children skipped. |
641 setHeight(document().getElementById("changer"), 200); | 641 setHeight(document().getElementById("changer"), 200); |
642 EXPECT_EQ(260, viewport->scrollPosition().y()); | 642 EXPECT_EQ(260, viewport->scrollOffsetInt().height()); |
643 EXPECT_EQ(document().getElementById("secondDiv")->layoutObject(), | 643 EXPECT_EQ(document().getElementById("secondDiv")->layoutObject(), |
644 scrollAnchor(viewport).anchorObject()); | 644 scrollAnchor(viewport).anchorObject()); |
645 } | 645 } |
646 | 646 |
647 TEST_F(ScrollAnchorTest, | 647 TEST_F(ScrollAnchorTest, |
648 SuppressAnchorNodeAncestorChangingLayoutAffectingProperty) { | 648 SuppressAnchorNodeAncestorChangingLayoutAffectingProperty) { |
649 setBodyInnerHTML( | 649 setBodyInnerHTML( |
650 "<style> body { height: 1000px } div { height: 100px } </style>" | 650 "<style> body { height: 1000px } div { height: 100px } </style>" |
651 "<div id='block1'>abc</div>"); | 651 "<div id='block1'>abc</div>"); |
652 | 652 |
653 ScrollableArea* viewport = layoutViewport(); | 653 ScrollableArea* viewport = layoutViewport(); |
654 | 654 |
655 scrollLayoutViewport(DoubleSize(0, 50)); | 655 scrollLayoutViewport(ScrollOffset(0, 50)); |
656 document().body()->setAttribute(HTMLNames::styleAttr, "padding-top: 20px"); | 656 document().body()->setAttribute(HTMLNames::styleAttr, "padding-top: 20px"); |
657 update(); | 657 update(); |
658 | 658 |
659 EXPECT_EQ(50, viewport->scrollPosition().y()); | 659 EXPECT_EQ(50, viewport->scrollOffsetInt().height()); |
660 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 660 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
661 } | 661 } |
662 | 662 |
663 TEST_F(ScrollAnchorTest, AnchorNodeAncestorChangingNonLayoutAffectingProperty) { | 663 TEST_F(ScrollAnchorTest, AnchorNodeAncestorChangingNonLayoutAffectingProperty) { |
664 setBodyInnerHTML( | 664 setBodyInnerHTML( |
665 "<style> body { height: 1000px } div { height: 100px } </style>" | 665 "<style> body { height: 1000px } div { height: 100px } </style>" |
666 "<div id='block1'>abc</div>" | 666 "<div id='block1'>abc</div>" |
667 "<div id='block2'>def</div>"); | 667 "<div id='block2'>def</div>"); |
668 | 668 |
669 ScrollableArea* viewport = layoutViewport(); | 669 ScrollableArea* viewport = layoutViewport(); |
670 scrollLayoutViewport(DoubleSize(0, 150)); | 670 scrollLayoutViewport(ScrollOffset(0, 150)); |
671 | 671 |
672 document().body()->setAttribute(HTMLNames::styleAttr, "color: red"); | 672 document().body()->setAttribute(HTMLNames::styleAttr, "color: red"); |
673 setHeight(document().getElementById("block1"), 200); | 673 setHeight(document().getElementById("block1"), 200); |
674 | 674 |
675 EXPECT_EQ(250, viewport->scrollPosition().y()); | 675 EXPECT_EQ(250, viewport->scrollOffsetInt().height()); |
676 EXPECT_EQ(document().getElementById("block2")->layoutObject(), | 676 EXPECT_EQ(document().getElementById("block2")->layoutObject(), |
677 scrollAnchor(viewport).anchorObject()); | 677 scrollAnchor(viewport).anchorObject()); |
678 } | 678 } |
679 | 679 |
680 TEST_F(ScrollAnchorTest, TransformIsLayoutAffecting) { | 680 TEST_F(ScrollAnchorTest, TransformIsLayoutAffecting) { |
681 setBodyInnerHTML( | 681 setBodyInnerHTML( |
682 "<style>" | 682 "<style>" |
683 " body { height: 1000px }" | 683 " body { height: 1000px }" |
684 " #block1 { height: 100px }" | 684 " #block1 { height: 100px }" |
685 "</style>" | 685 "</style>" |
686 "<div id='block1'>abc</div>" | 686 "<div id='block1'>abc</div>" |
687 "<div id=a>after</div>"); | 687 "<div id=a>after</div>"); |
688 | 688 |
689 ScrollableArea* viewport = layoutViewport(); | 689 ScrollableArea* viewport = layoutViewport(); |
690 | 690 |
691 scrollLayoutViewport(DoubleSize(0, 50)); | 691 scrollLayoutViewport(ScrollOffset(0, 50)); |
692 document().getElementById("block1")->setAttribute( | 692 document().getElementById("block1")->setAttribute( |
693 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 25, 25);"); | 693 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 25, 25);"); |
694 update(); | 694 update(); |
695 | 695 |
696 document().getElementById("block1")->setAttribute( | 696 document().getElementById("block1")->setAttribute( |
697 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 50, 50);"); | 697 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 50, 50);"); |
698 setHeight(document().getElementById("a"), 100); | 698 setHeight(document().getElementById("a"), 100); |
699 update(); | 699 update(); |
700 | 700 |
701 EXPECT_EQ(50, viewport->scrollPosition().y()); | 701 EXPECT_EQ(50, viewport->scrollOffsetInt().height()); |
702 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 702 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
703 } | 703 } |
704 | 704 |
705 TEST_F(ScrollAnchorTest, OptOutBody) { | 705 TEST_F(ScrollAnchorTest, OptOutBody) { |
706 setBodyInnerHTML( | 706 setBodyInnerHTML( |
707 "<style>" | 707 "<style>" |
708 " body { height: 2000px; overflow-anchor: none; }" | 708 " body { height: 2000px; overflow-anchor: none; }" |
709 " #scroller { overflow: scroll; width: 500px; height: 300px; }" | 709 " #scroller { overflow: scroll; width: 500px; height: 300px; }" |
710 " .anchor {" | 710 " .anchor {" |
711 " position:relative; height: 100px; width: 150px;" | 711 " position:relative; height: 100px; width: 150px;" |
712 " background-color: #afa; border: 1px solid gray;" | 712 " background-color: #afa; border: 1px solid gray;" |
713 " }" | 713 " }" |
714 " #forceScrolling { height: 500px; background-color: #fcc; }" | 714 " #forceScrolling { height: 500px; background-color: #fcc; }" |
715 "</style>" | 715 "</style>" |
716 "<div id='outerChanger'></div>" | 716 "<div id='outerChanger'></div>" |
717 "<div id='outerAnchor' class='anchor'></div>" | 717 "<div id='outerAnchor' class='anchor'></div>" |
718 "<div id='scroller'>" | 718 "<div id='scroller'>" |
719 " <div id='innerChanger'></div>" | 719 " <div id='innerChanger'></div>" |
720 " <div id='innerAnchor' class='anchor'></div>" | 720 " <div id='innerAnchor' class='anchor'></div>" |
721 " <div id='forceScrolling'></div>" | 721 " <div id='forceScrolling'></div>" |
722 "</div>"); | 722 "</div>"); |
723 | 723 |
724 ScrollableArea* scroller = | 724 ScrollableArea* scroller = |
725 scrollerForElement(document().getElementById("scroller")); | 725 scrollerForElement(document().getElementById("scroller")); |
726 ScrollableArea* viewport = layoutViewport(); | 726 ScrollableArea* viewport = layoutViewport(); |
727 | 727 |
728 document().getElementById("scroller")->setScrollTop(100); | 728 document().getElementById("scroller")->setScrollTop(100); |
729 scrollLayoutViewport(DoubleSize(0, 100)); | 729 scrollLayoutViewport(ScrollOffset(0, 100)); |
730 | 730 |
731 setHeight(document().getElementById("innerChanger"), 200); | 731 setHeight(document().getElementById("innerChanger"), 200); |
732 setHeight(document().getElementById("outerChanger"), 150); | 732 setHeight(document().getElementById("outerChanger"), 150); |
733 | 733 |
734 // Scroll anchoring should apply within #scroller. | 734 // Scroll anchoring should apply within #scroller. |
735 EXPECT_EQ(300, scroller->scrollPosition().y()); | 735 EXPECT_EQ(300, scroller->scrollOffsetInt().height()); |
736 EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), | 736 EXPECT_EQ(document().getElementById("innerAnchor")->layoutObject(), |
737 scrollAnchor(scroller).anchorObject()); | 737 scrollAnchor(scroller).anchorObject()); |
738 // Scroll anchoring should not apply within main frame. | 738 // Scroll anchoring should not apply within main frame. |
739 EXPECT_EQ(100, viewport->scrollPosition().y()); | 739 EXPECT_EQ(100, viewport->scrollOffsetInt().height()); |
740 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 740 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
741 } | 741 } |
742 | 742 |
743 TEST_F(ScrollAnchorTest, OptOutScrollingDiv) { | 743 TEST_F(ScrollAnchorTest, OptOutScrollingDiv) { |
744 setBodyInnerHTML( | 744 setBodyInnerHTML( |
745 "<style>" | 745 "<style>" |
746 " body { height: 2000px; }" | 746 " body { height: 2000px; }" |
747 " #scroller {" | 747 " #scroller {" |
748 " overflow: scroll; width: 500px; height: 300px;" | 748 " overflow: scroll; width: 500px; height: 300px;" |
749 " overflow-anchor: none;" | 749 " overflow-anchor: none;" |
(...skipping 10 matching lines...) Expand all Loading... |
760 " <div id='innerChanger'></div>" | 760 " <div id='innerChanger'></div>" |
761 " <div id='innerAnchor' class='anchor'></div>" | 761 " <div id='innerAnchor' class='anchor'></div>" |
762 " <div id='forceScrolling'></div>" | 762 " <div id='forceScrolling'></div>" |
763 "</div>"); | 763 "</div>"); |
764 | 764 |
765 ScrollableArea* scroller = | 765 ScrollableArea* scroller = |
766 scrollerForElement(document().getElementById("scroller")); | 766 scrollerForElement(document().getElementById("scroller")); |
767 ScrollableArea* viewport = layoutViewport(); | 767 ScrollableArea* viewport = layoutViewport(); |
768 | 768 |
769 document().getElementById("scroller")->setScrollTop(100); | 769 document().getElementById("scroller")->setScrollTop(100); |
770 scrollLayoutViewport(DoubleSize(0, 100)); | 770 scrollLayoutViewport(ScrollOffset(0, 100)); |
771 | 771 |
772 setHeight(document().getElementById("innerChanger"), 200); | 772 setHeight(document().getElementById("innerChanger"), 200); |
773 setHeight(document().getElementById("outerChanger"), 150); | 773 setHeight(document().getElementById("outerChanger"), 150); |
774 | 774 |
775 // Scroll anchoring should not apply within #scroller. | 775 // Scroll anchoring should not apply within #scroller. |
776 EXPECT_EQ(100, scroller->scrollPosition().y()); | 776 EXPECT_EQ(100, scroller->scrollOffsetInt().height()); |
777 EXPECT_EQ(nullptr, scrollAnchor(scroller).anchorObject()); | 777 EXPECT_EQ(nullptr, scrollAnchor(scroller).anchorObject()); |
778 // Scroll anchoring should apply within main frame. | 778 // Scroll anchoring should apply within main frame. |
779 EXPECT_EQ(250, viewport->scrollPosition().y()); | 779 EXPECT_EQ(250, viewport->scrollOffsetInt().height()); |
780 EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), | 780 EXPECT_EQ(document().getElementById("outerAnchor")->layoutObject(), |
781 scrollAnchor(viewport).anchorObject()); | 781 scrollAnchor(viewport).anchorObject()); |
782 } | 782 } |
783 | 783 |
784 TEST_F(ScrollAnchorTest, NonDefaultRootScroller) { | 784 TEST_F(ScrollAnchorTest, NonDefaultRootScroller) { |
785 setBodyInnerHTML( | 785 setBodyInnerHTML( |
786 "<style>" | 786 "<style>" |
787 " ::-webkit-scrollbar {" | 787 " ::-webkit-scrollbar {" |
788 " width: 0px; height: 0px;" | 788 " width: 0px; height: 0px;" |
789 " }" | 789 " }" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 &document().view()->getRootFrameViewport()->layoutViewport()); | 821 &document().view()->getRootFrameViewport()->layoutViewport()); |
822 | 822 |
823 // The #rootScroller DIV's anchor should have the RootFrameViewport set as | 823 // The #rootScroller DIV's anchor should have the RootFrameViewport set as |
824 // the scroller, rather than the FrameView's anchor. | 824 // the scroller, rather than the FrameView's anchor. |
825 | 825 |
826 rootScrollerElement->setScrollTop(600); | 826 rootScrollerElement->setScrollTop(600); |
827 | 827 |
828 setHeight(document().getElementById("firstChild"), 1000); | 828 setHeight(document().getElementById("firstChild"), 1000); |
829 | 829 |
830 // Scroll anchoring should be applied to #rootScroller. | 830 // Scroll anchoring should be applied to #rootScroller. |
831 EXPECT_EQ(1000, scroller->scrollPosition().y()); | 831 EXPECT_EQ(1000, scroller->scrollOffset().height()); |
832 EXPECT_EQ(document().getElementById("target")->layoutObject(), | 832 EXPECT_EQ(document().getElementById("target")->layoutObject(), |
833 scrollAnchor(scroller).anchorObject()); | 833 scrollAnchor(scroller).anchorObject()); |
834 // Scroll anchoring should not apply within main frame. | 834 // Scroll anchoring should not apply within main frame. |
835 EXPECT_EQ(0, layoutViewport()->scrollPosition().y()); | 835 EXPECT_EQ(0, layoutViewport()->scrollOffset().height()); |
836 EXPECT_EQ(nullptr, scrollAnchor(layoutViewport()).anchorObject()); | 836 EXPECT_EQ(nullptr, scrollAnchor(layoutViewport()).anchorObject()); |
837 } | 837 } |
838 | 838 |
839 class ScrollAnchorCornerTest : public ScrollAnchorTest { | 839 class ScrollAnchorCornerTest : public ScrollAnchorTest { |
840 protected: | 840 protected: |
841 void checkCorner(Corner corner, | 841 void checkCorner(Corner corner, |
842 DoublePoint startPos, | 842 ScrollOffset startOffset, |
843 DoubleSize expectedAdjustment) { | 843 ScrollOffset expectedAdjustment) { |
844 ScrollableArea* viewport = layoutViewport(); | 844 ScrollableArea* viewport = layoutViewport(); |
845 Element* element = document().getElementById("changer"); | 845 Element* element = document().getElementById("changer"); |
846 | 846 |
847 viewport->setScrollPosition(startPos, UserScroll); | 847 viewport->setScrollOffset(startOffset, UserScroll); |
848 element->setAttribute(HTMLNames::classAttr, "change"); | 848 element->setAttribute(HTMLNames::classAttr, "change"); |
849 update(); | 849 update(); |
850 | 850 |
851 DoublePoint endPos = startPos; | 851 ScrollOffset endPos = startOffset; |
852 endPos.move(expectedAdjustment); | 852 endPos += expectedAdjustment; |
853 | 853 |
854 EXPECT_EQ(endPos, viewport->scrollPositionDouble()); | 854 EXPECT_EQ(endPos, viewport->scrollOffset()); |
855 EXPECT_EQ(document().getElementById("a")->layoutObject(), | 855 EXPECT_EQ(document().getElementById("a")->layoutObject(), |
856 scrollAnchor(viewport).anchorObject()); | 856 scrollAnchor(viewport).anchorObject()); |
857 EXPECT_EQ(corner, scrollAnchor(viewport).corner()); | 857 EXPECT_EQ(corner, scrollAnchor(viewport).corner()); |
858 | 858 |
859 element->removeAttribute(HTMLNames::classAttr); | 859 element->removeAttribute(HTMLNames::classAttr); |
860 update(); | 860 update(); |
861 } | 861 } |
862 }; | 862 }; |
863 | 863 |
864 // Verify that we anchor to the top left corner of an element for LTR. | 864 // Verify that we anchor to the top left corner of an element for LTR. |
865 TEST_F(ScrollAnchorCornerTest, CornersLTR) { | 865 TEST_F(ScrollAnchorCornerTest, CornersLTR) { |
866 setBodyInnerHTML( | 866 setBodyInnerHTML( |
867 "<style>" | 867 "<style>" |
868 " body { position: relative; width: 1220px; height: 920px; }" | 868 " body { position: relative; width: 1220px; height: 920px; }" |
869 " #a { width: 400px; height: 300px; }" | 869 " #a { width: 400px; height: 300px; }" |
870 " .change { height: 100px; }" | 870 " .change { height: 100px; }" |
871 "</style>" | 871 "</style>" |
872 "<div id='changer'></div>" | 872 "<div id='changer'></div>" |
873 "<div id='a'></div>"); | 873 "<div id='a'></div>"); |
874 | 874 |
875 checkCorner(Corner::TopLeft, DoublePoint(20, 20), DoubleSize(0, 100)); | 875 checkCorner(Corner::TopLeft, ScrollOffset(20, 20), ScrollOffset(0, 100)); |
876 } | 876 } |
877 | 877 |
878 // Verify that we anchor to the top left corner of an anchor element for | 878 // Verify that we anchor to the top left corner of an anchor element for |
879 // vertical-lr writing mode. | 879 // vertical-lr writing mode. |
880 TEST_F(ScrollAnchorCornerTest, CornersVerticalLR) { | 880 TEST_F(ScrollAnchorCornerTest, CornersVerticalLR) { |
881 setBodyInnerHTML( | 881 setBodyInnerHTML( |
882 "<style>" | 882 "<style>" |
883 " html { writing-mode: vertical-lr; }" | 883 " html { writing-mode: vertical-lr; }" |
884 " body { position: relative; width: 1220px; height: 920px; }" | 884 " body { position: relative; width: 1220px; height: 920px; }" |
885 " #a { width: 400px; height: 300px; }" | 885 " #a { width: 400px; height: 300px; }" |
886 " .change { width: 100px; }" | 886 " .change { width: 100px; }" |
887 "</style>" | 887 "</style>" |
888 "<div id='changer'></div>" | 888 "<div id='changer'></div>" |
889 "<div id='a'></div>"); | 889 "<div id='a'></div>"); |
890 | 890 |
891 checkCorner(Corner::TopLeft, DoublePoint(20, 20), DoubleSize(100, 0)); | 891 checkCorner(Corner::TopLeft, ScrollOffset(20, 20), ScrollOffset(100, 0)); |
892 } | 892 } |
893 | 893 |
894 // Verify that we anchor to the top right corner of an anchor element for RTL. | 894 // Verify that we anchor to the top right corner of an anchor element for RTL. |
895 TEST_F(ScrollAnchorCornerTest, CornersRTL) { | 895 TEST_F(ScrollAnchorCornerTest, CornersRTL) { |
896 setBodyInnerHTML( | 896 setBodyInnerHTML( |
897 "<style>" | 897 "<style>" |
898 " html { direction: rtl; }" | 898 " html { direction: rtl; }" |
899 " body { position: relative; width: 1220px; height: 920px; }" | 899 " body { position: relative; width: 1220px; height: 920px; }" |
900 " #a { width: 400px; height: 300px; }" | 900 " #a { width: 400px; height: 300px; }" |
901 " .change { height: 100px; }" | 901 " .change { height: 100px; }" |
902 "</style>" | 902 "</style>" |
903 "<div id='changer'></div>" | 903 "<div id='changer'></div>" |
904 "<div id='a'></div>"); | 904 "<div id='a'></div>"); |
905 | 905 |
906 checkCorner(Corner::TopRight, DoublePoint(-20, 20), DoubleSize(0, 100)); | 906 checkCorner(Corner::TopRight, ScrollOffset(-20, 20), ScrollOffset(0, 100)); |
907 } | 907 } |
908 | 908 |
909 // Verify that we anchor to the top right corner of an anchor element for | 909 // Verify that we anchor to the top right corner of an anchor element for |
910 // vertical-lr writing mode. | 910 // vertical-lr writing mode. |
911 TEST_F(ScrollAnchorCornerTest, CornersVerticalRL) { | 911 TEST_F(ScrollAnchorCornerTest, CornersVerticalRL) { |
912 setBodyInnerHTML( | 912 setBodyInnerHTML( |
913 "<style>" | 913 "<style>" |
914 " html { writing-mode: vertical-rl; }" | 914 " html { writing-mode: vertical-rl; }" |
915 " body { position: relative; width: 1220px; height: 920px; }" | 915 " body { position: relative; width: 1220px; height: 920px; }" |
916 " #a { width: 400px; height: 300px; }" | 916 " #a { width: 400px; height: 300px; }" |
917 " .change { width: 100px; }" | 917 " .change { width: 100px; }" |
918 "</style>" | 918 "</style>" |
919 "<div id='changer'></div>" | 919 "<div id='changer'></div>" |
920 "<div id='a'></div>"); | 920 "<div id='a'></div>"); |
921 | 921 |
922 checkCorner(Corner::TopRight, DoublePoint(-20, 20), DoubleSize(-100, 0)); | 922 checkCorner(Corner::TopRight, ScrollOffset(-20, 20), ScrollOffset(-100, 0)); |
923 } | 923 } |
924 | 924 |
925 TEST_F(ScrollAnchorTest, IgnoreNonBlockLayoutAxis) { | 925 TEST_F(ScrollAnchorTest, IgnoreNonBlockLayoutAxis) { |
926 setBodyInnerHTML( | 926 setBodyInnerHTML( |
927 "<style>" | 927 "<style>" |
928 " body {" | 928 " body {" |
929 " margin: 0; line-height: 0;" | 929 " margin: 0; line-height: 0;" |
930 " width: 1200px; height: 1200px;" | 930 " width: 1200px; height: 1200px;" |
931 " }" | 931 " }" |
932 " div {" | 932 " div {" |
933 " width: 100px; height: 100px;" | 933 " width: 100px; height: 100px;" |
934 " border: 5px solid gray;" | 934 " border: 5px solid gray;" |
935 " display: inline-block;" | 935 " display: inline-block;" |
936 " box-sizing: border-box;" | 936 " box-sizing: border-box;" |
937 " }" | 937 " }" |
938 "</style>" | 938 "</style>" |
939 "<div id='a'></div><br>" | 939 "<div id='a'></div><br>" |
940 "<div id='b'></div><div id='c'></div>"); | 940 "<div id='b'></div><div id='c'></div>"); |
941 | 941 |
942 ScrollableArea* viewport = layoutViewport(); | 942 ScrollableArea* viewport = layoutViewport(); |
943 scrollLayoutViewport(DoubleSize(150, 0)); | 943 scrollLayoutViewport(ScrollOffset(150, 0)); |
944 | 944 |
945 Element* a = document().getElementById("a"); | 945 Element* a = document().getElementById("a"); |
946 Element* b = document().getElementById("b"); | 946 Element* b = document().getElementById("b"); |
947 Element* c = document().getElementById("c"); | 947 Element* c = document().getElementById("c"); |
948 | 948 |
949 a->setAttribute(HTMLNames::styleAttr, "height: 150px"); | 949 a->setAttribute(HTMLNames::styleAttr, "height: 150px"); |
950 update(); | 950 update(); |
951 EXPECT_EQ(DoublePoint(150, 0), viewport->scrollPositionDouble()); | 951 EXPECT_EQ(ScrollOffset(150, 0), viewport->scrollOffset()); |
952 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 952 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
953 | 953 |
954 scrollLayoutViewport(DoubleSize(0, 50)); | 954 scrollLayoutViewport(ScrollOffset(0, 50)); |
955 | 955 |
956 a->setAttribute(HTMLNames::styleAttr, "height: 200px"); | 956 a->setAttribute(HTMLNames::styleAttr, "height: 200px"); |
957 b->setAttribute(HTMLNames::styleAttr, "width: 150px"); | 957 b->setAttribute(HTMLNames::styleAttr, "width: 150px"); |
958 update(); | 958 update(); |
959 EXPECT_EQ(DoublePoint(150, 100), viewport->scrollPositionDouble()); | 959 EXPECT_EQ(ScrollOffset(150, 100), viewport->scrollOffset()); |
960 EXPECT_EQ(c->layoutObject(), scrollAnchor(viewport).anchorObject()); | 960 EXPECT_EQ(c->layoutObject(), scrollAnchor(viewport).anchorObject()); |
961 | 961 |
962 a->setAttribute(HTMLNames::styleAttr, "height: 100px"); | 962 a->setAttribute(HTMLNames::styleAttr, "height: 100px"); |
963 b->setAttribute(HTMLNames::styleAttr, "width: 100px"); | 963 b->setAttribute(HTMLNames::styleAttr, "width: 100px"); |
964 document().documentElement()->setAttribute(HTMLNames::styleAttr, | 964 document().documentElement()->setAttribute(HTMLNames::styleAttr, |
965 "writing-mode: vertical-rl"); | 965 "writing-mode: vertical-rl"); |
966 document().scrollingElement()->setScrollLeft(0); | 966 document().scrollingElement()->setScrollLeft(0); |
967 document().scrollingElement()->setScrollTop(0); | 967 document().scrollingElement()->setScrollTop(0); |
968 scrollLayoutViewport(DoubleSize(0, 150)); | 968 scrollLayoutViewport(ScrollOffset(0, 150)); |
969 | 969 |
970 a->setAttribute(HTMLNames::styleAttr, "width: 150px"); | 970 a->setAttribute(HTMLNames::styleAttr, "width: 150px"); |
971 update(); | 971 update(); |
972 EXPECT_EQ(DoublePoint(0, 150), viewport->scrollPositionDouble()); | 972 EXPECT_EQ(ScrollOffset(0, 150), viewport->scrollOffset()); |
973 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); | 973 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject()); |
974 | 974 |
975 scrollLayoutViewport(DoubleSize(-50, 0)); | 975 scrollLayoutViewport(ScrollOffset(-50, 0)); |
976 | 976 |
977 a->setAttribute(HTMLNames::styleAttr, "width: 200px"); | 977 a->setAttribute(HTMLNames::styleAttr, "width: 200px"); |
978 b->setAttribute(HTMLNames::styleAttr, "height: 150px"); | 978 b->setAttribute(HTMLNames::styleAttr, "height: 150px"); |
979 update(); | 979 update(); |
980 EXPECT_EQ(DoublePoint(-100, 150), viewport->scrollPositionDouble()); | 980 EXPECT_EQ(ScrollOffset(-100, 150), viewport->scrollOffset()); |
981 EXPECT_EQ(c->layoutObject(), scrollAnchor(viewport).anchorObject()); | 981 EXPECT_EQ(c->layoutObject(), scrollAnchor(viewport).anchorObject()); |
982 } | 982 } |
983 } | 983 } |
OLD | NEW |