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

Side by Side Diff: third_party/WebKit/Source/core/layout/ScrollAnchor.cpp

Issue 2245873002: Disable anchoring if ancestor changes padding or margin (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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/layout/ScrollAnchor.h" 5 #include "core/layout/ScrollAnchor.h"
6 6
7 #include "core/frame/FrameView.h" 7 #include "core/frame/FrameView.h"
8 #include "core/frame/UseCounter.h" 8 #include "core/frame/UseCounter.h"
9 #include "core/layout/line/InlineTextBox.h" 9 #include "core/layout/line/InlineTextBox.h"
10 #include "core/paint/PaintLayerScrollableArea.h" 10 #include "core/paint/PaintLayerScrollableArea.h"
11 #include "platform/Histogram.h" 11 #include "platform/Histogram.h"
12 12
13 namespace blink { 13 namespace blink {
14 14
15 using Corner = ScrollAnchor::Corner; 15 using Corner = ScrollAnchor::Corner;
16 16
17 static const int kMaxAdjustments = 20; 17 static const int kMaxAdjustments = 20;
18 18
19 ScrollAnchor::ScrollAnchor() 19 ScrollAnchor::ScrollAnchor()
20 : m_hasBounced(false) 20 : m_hasBounced(false)
21 , m_adjustmentCount(0) 21 , m_adjustmentCount(0)
22 , m_anyAncestorChangedPaddingOrMargin(false)
22 { 23 {
23 } 24 }
24 25
25 ScrollAnchor::ScrollAnchor(ScrollableArea* scroller) 26 ScrollAnchor::ScrollAnchor(ScrollableArea* scroller)
26 : ScrollAnchor() 27 : ScrollAnchor()
27 { 28 {
28 setScroller(scroller); 29 setScroller(scroller);
29 } 30 }
30 31
31 ScrollAnchor::~ScrollAnchor() 32 ScrollAnchor::~ScrollAnchor()
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 } 193 }
193 } 194 }
194 195
195 void ScrollAnchor::save() 196 void ScrollAnchor::save()
196 { 197 {
197 DCHECK(m_scroller); 198 DCHECK(m_scroller);
198 if (m_scroller->scrollPosition() == IntPoint::zero()) { 199 if (m_scroller->scrollPosition() == IntPoint::zero()) {
199 clear(); 200 clear();
200 return; 201 return;
201 } 202 }
202 if (m_current) 203
204 if (m_current) {
205 m_anyAncestorChangedPaddingOrMargin = paddingOrBorderChanged();
203 return; 206 return;
207 }
204 208
205 findAnchor(); 209 findAnchor();
206 if (!m_current) 210 if (!m_current)
207 return; 211 return;
208 212
213 m_anyAncestorChangedPaddingOrMargin = paddingOrBorderChanged();
214
209 m_current.m_anchorObject->setIsScrollAnchorObject(); 215 m_current.m_anchorObject->setIsScrollAnchorObject();
210 m_current.m_savedRelativeOffset = computeRelativeOffset( 216 m_current.m_savedRelativeOffset = computeRelativeOffset(
211 m_current.m_anchorObject, m_scroller, m_current.m_corner); 217 m_current.m_anchorObject, m_scroller, m_current.m_corner);
212 218
213 if (m_lastAdjusted) { 219 if (m_lastAdjusted) {
214 // We need to update m_lastAdjusted.m_savedRelativeOffset, since it is 220 // We need to update m_lastAdjusted.m_savedRelativeOffset, since it is
215 // relative to the visible rect and the user may have scrolled since the 221 // relative to the visible rect and the user may have scrolled since the
216 // last adjustment. 222 // last adjustment.
217 if (!candidateMayMoveWithScroller(m_lastAdjusted.m_anchorObject, m_scrol ler)) { 223 if (!candidateMayMoveWithScroller(m_lastAdjusted.m_anchorObject, m_scrol ler)) {
218 m_lastAdjusted.clear(); 224 m_lastAdjusted.clear();
(...skipping 14 matching lines...) Expand all
233 // visual delta. If we scroll by the delta in LayoutUnits, the snapping of t he 239 // visual delta. If we scroll by the delta in LayoutUnits, the snapping of t he
234 // anchor node may round differently from the snapping of the scroll positio n. 240 // anchor node may round differently from the snapping of the scroll positio n.
235 // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so we 241 // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so we
236 // should scroll by 1px instead of 0.2px.) This is true regardless of whethe r 242 // should scroll by 1px instead of 0.2px.) This is true regardless of whethe r
237 // the ScrollableArea actually uses fractional scroll positions. 243 // the ScrollableArea actually uses fractional scroll positions.
238 return roundedIntSize(computeRelativeOffset( 244 return roundedIntSize(computeRelativeOffset(
239 anchorPoint.m_anchorObject, m_scroller, anchorPoint.m_corner)) - 245 anchorPoint.m_anchorObject, m_scroller, anchorPoint.m_corner)) -
240 roundedIntSize(anchorPoint.m_savedRelativeOffset); 246 roundedIntSize(anchorPoint.m_savedRelativeOffset);
241 } 247 }
242 248
249 bool ScrollAnchor::paddingOrBorderChanged() const
250 {
251 LayoutObject* current = anchorObject();
252 while (current && current != scrollerLayoutBox(m_scroller)) {
253 if (current->isLayoutBlock()
254 && (toLayoutBlock(current)->heightAvailableToChildrenChanged()))
255 return true;
256 current = current->parent();
257 }
258 return false;
259 }
260
243 void ScrollAnchor::restore() 261 void ScrollAnchor::restore()
244 { 262 {
245 DCHECK(m_scroller); 263 DCHECK(m_scroller);
246 if (m_lastAdjusted && m_lastAdjusted.m_anchorObject != m_current.m_anchorObj ect 264 if (m_lastAdjusted && m_lastAdjusted.m_anchorObject != m_current.m_anchorObj ect
247 && !m_hasBounced && computeAdjustment(m_lastAdjusted) == -m_lastAdjustme nt) { 265 && !m_hasBounced && computeAdjustment(m_lastAdjusted) == -m_lastAdjustme nt) {
248 // If previous anchor point has bounced, follow the bounce. 266 // If previous anchor point has bounced, follow the bounce.
249 clear(); 267 clear();
250 adjust(-m_lastAdjustment); 268 adjust(-m_lastAdjustment);
251 return; 269 return;
252 } 270 }
271
253 if (!m_current) 272 if (!m_current)
254 return; 273 return;
274
275 // Authors often change the padding or margin when trying to simulate
276 // position:sticky on headers. Use this as a heuristic to disable scroll
277 // anchoring so that we don't conflict with JS changes.
278 // TODO(ymalik): Does this change allow us to remove the de-bouncing hack?
279 if (m_anyAncestorChangedPaddingOrMargin) {
280 clear();
281 return;
282 }
283
255 IntSize adjustment = computeAdjustment(m_current); 284 IntSize adjustment = computeAdjustment(m_current);
256 if (adjustment.isZero()) 285 if (adjustment.isZero())
257 return; 286 return;
287
258 if (adjustment == -m_lastAdjustment && m_hasBounced) { 288 if (adjustment == -m_lastAdjustment && m_hasBounced) {
259 // Don't bounce more than once. 289 // Don't bounce more than once.
260 clear(); 290 clear();
261 m_hasBounced = false; 291 m_hasBounced = false;
262 m_lastAdjustment = IntSize(); 292 m_lastAdjustment = IntSize();
263 m_lastAdjusted.clear(); 293 m_lastAdjusted.clear();
264 return; 294 return;
265 } 295 }
266 // We impose a limit on the number of adjustments between user scrolls, to 296 // We impose a limit on the number of adjustments between user scrolls, to
267 // mitigate the impact of pathological feedback loops with event handlers. 297 // mitigate the impact of pathological feedback loops with event handlers.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 340
311 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) 341 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject)
312 { 342 {
313 if (m_current.m_anchorObject == layoutObject) 343 if (m_current.m_anchorObject == layoutObject)
314 m_current.clear(); 344 m_current.clear();
315 if (m_lastAdjusted.m_anchorObject == layoutObject) 345 if (m_lastAdjusted.m_anchorObject == layoutObject)
316 m_lastAdjusted.clear(); 346 m_lastAdjusted.clear();
317 } 347 }
318 348
319 } // namespace blink 349 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ScrollAnchor.h ('k') | third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698