| 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/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/LayoutBlockFlow.h" | 9 #include "core/layout/LayoutBlockFlow.h" |
| 10 #include "core/layout/api/LayoutBoxItem.h" | 10 #include "core/layout/api/LayoutBoxItem.h" |
| 11 #include "core/layout/line/InlineTextBox.h" | 11 #include "core/layout/line/InlineTextBox.h" |
| 12 #include "core/paint/PaintLayer.h" |
| 12 #include "core/paint/PaintLayerScrollableArea.h" | 13 #include "core/paint/PaintLayerScrollableArea.h" |
| 13 #include "platform/Histogram.h" | 14 #include "platform/Histogram.h" |
| 14 | 15 |
| 15 namespace blink { | 16 namespace blink { |
| 16 | 17 |
| 17 using Corner = ScrollAnchor::Corner; | 18 using Corner = ScrollAnchor::Corner; |
| 18 | 19 |
| 19 ScrollAnchor::ScrollAnchor() | 20 ScrollAnchor::ScrollAnchor() |
| 20 : m_anchorObject(nullptr), | 21 : m_anchorObject(nullptr), |
| 21 m_corner(Corner::TopLeft), | 22 m_corner(Corner::TopLeft), |
| 22 m_scrollAnchorDisablingStyleChanged(false), | 23 m_scrollAnchorDisablingStyleChanged(false), |
| 23 m_saved(false) {} | 24 m_saved(false) {} |
| 24 | 25 |
| 25 ScrollAnchor::ScrollAnchor(ScrollableArea* scroller) : ScrollAnchor() { | 26 ScrollAnchor::ScrollAnchor(ScrollableArea* scroller) : ScrollAnchor() { |
| 26 setScroller(scroller); | 27 setScroller(scroller); |
| 27 } | 28 } |
| 28 | 29 |
| 29 ScrollAnchor::~ScrollAnchor() {} | 30 ScrollAnchor::~ScrollAnchor() {} |
| 30 | 31 |
| 31 void ScrollAnchor::setScroller(ScrollableArea* scroller) { | 32 void ScrollAnchor::setScroller(ScrollableArea* scroller) { |
| 32 DCHECK(m_scroller != scroller); | 33 DCHECK(m_scroller != scroller); |
| 33 DCHECK(scroller); | 34 DCHECK(scroller); |
| 34 DCHECK(scroller->isRootFrameViewport() || scroller->isFrameView() || | 35 DCHECK(scroller->isRootFrameViewport() || scroller->isFrameView() || |
| 35 scroller->isPaintLayerScrollableArea()); | 36 scroller->isPaintLayerScrollableArea()); |
| 36 m_scroller = scroller; | 37 m_scroller = scroller; |
| 37 clear(); | 38 clearSelf(); |
| 38 } | 39 } |
| 39 | 40 |
| 40 // TODO(pilgrim): Replace all instances of scrollerLayoutBox with | 41 // TODO(pilgrim): Replace all instances of scrollerLayoutBox with |
| 41 // scrollerLayoutBoxItem, https://crbug.com/499321 | 42 // scrollerLayoutBoxItem, https://crbug.com/499321 |
| 42 static LayoutBox* scrollerLayoutBox(const ScrollableArea* scroller) { | 43 static LayoutBox* scrollerLayoutBox(const ScrollableArea* scroller) { |
| 43 LayoutBox* box = scroller->layoutBox(); | 44 LayoutBox* box = scroller->layoutBox(); |
| 44 DCHECK(box); | 45 DCHECK(box); |
| 45 return box; | 46 return box; |
| 46 } | 47 } |
| 47 | 48 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 if (m_saved) | 216 if (m_saved) |
| 216 return; | 217 return; |
| 217 m_saved = true; | 218 m_saved = true; |
| 218 DCHECK(m_scroller); | 219 DCHECK(m_scroller); |
| 219 ScrollOffset scrollOffset = m_scroller->scrollOffset(); | 220 ScrollOffset scrollOffset = m_scroller->scrollOffset(); |
| 220 float blockDirectionScrollOffset = | 221 float blockDirectionScrollOffset = |
| 221 scrollerLayoutBox(m_scroller)->isHorizontalWritingMode() | 222 scrollerLayoutBox(m_scroller)->isHorizontalWritingMode() |
| 222 ? scrollOffset.height() | 223 ? scrollOffset.height() |
| 223 : scrollOffset.width(); | 224 : scrollOffset.width(); |
| 224 if (blockDirectionScrollOffset == 0) { | 225 if (blockDirectionScrollOffset == 0) { |
| 225 clear(); | 226 clearSelf(); |
| 226 return; | 227 return; |
| 227 } | 228 } |
| 228 | 229 |
| 229 if (!m_anchorObject) { | 230 if (!m_anchorObject) { |
| 230 findAnchor(); | 231 findAnchor(); |
| 231 if (!m_anchorObject) | 232 if (!m_anchorObject) |
| 232 return; | 233 return; |
| 233 | 234 |
| 234 m_anchorObject->setIsScrollAnchorObject(); | 235 m_anchorObject->setIsScrollAnchorObject(); |
| 235 m_savedRelativeOffset = | 236 m_savedRelativeOffset = |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 if (!m_anchorObject) | 272 if (!m_anchorObject) |
| 272 return; | 273 return; |
| 273 IntSize adjustment = computeAdjustment(); | 274 IntSize adjustment = computeAdjustment(); |
| 274 if (adjustment.isZero()) | 275 if (adjustment.isZero()) |
| 275 return; | 276 return; |
| 276 | 277 |
| 277 if (m_scrollAnchorDisablingStyleChanged) { | 278 if (m_scrollAnchorDisablingStyleChanged) { |
| 278 // Note that we only clear if the adjustment would have been non-zero. | 279 // Note that we only clear if the adjustment would have been non-zero. |
| 279 // This minimizes redundant calls to findAnchor. | 280 // This minimizes redundant calls to findAnchor. |
| 280 // TODO(skobes): add UMA metric for this. | 281 // TODO(skobes): add UMA metric for this. |
| 281 clear(); | 282 clearSelf(); |
| 282 | 283 |
| 283 DEFINE_STATIC_LOCAL(EnumerationHistogram, suppressedBySanaclapHistogram, | 284 DEFINE_STATIC_LOCAL(EnumerationHistogram, suppressedBySanaclapHistogram, |
| 284 ("Layout.ScrollAnchor.SuppressedBySanaclap", 2)); | 285 ("Layout.ScrollAnchor.SuppressedBySanaclap", 2)); |
| 285 suppressedBySanaclapHistogram.count(1); | 286 suppressedBySanaclapHistogram.count(1); |
| 286 | 287 |
| 287 return; | 288 return; |
| 288 } | 289 } |
| 289 | 290 |
| 290 m_scroller->setScrollOffset( | 291 m_scroller->setScrollOffset( |
| 291 m_scroller->scrollOffset() + FloatSize(adjustment), AnchoringScroll); | 292 m_scroller->scrollOffset() + FloatSize(adjustment), AnchoringScroll); |
| 292 | 293 |
| 293 // Update UMA metric. | 294 // Update UMA metric. |
| 294 DEFINE_STATIC_LOCAL(EnumerationHistogram, adjustedOffsetHistogram, | 295 DEFINE_STATIC_LOCAL(EnumerationHistogram, adjustedOffsetHistogram, |
| 295 ("Layout.ScrollAnchor.AdjustedScrollOffset", 2)); | 296 ("Layout.ScrollAnchor.AdjustedScrollOffset", 2)); |
| 296 adjustedOffsetHistogram.count(1); | 297 adjustedOffsetHistogram.count(1); |
| 297 UseCounter::count(scrollerLayoutBox(m_scroller)->document(), | 298 UseCounter::count(scrollerLayoutBox(m_scroller)->document(), |
| 298 UseCounter::ScrollAnchored); | 299 UseCounter::ScrollAnchored); |
| 299 } | 300 } |
| 300 | 301 |
| 301 void ScrollAnchor::clear() { | 302 void ScrollAnchor::clearSelf(bool unconditionally) { |
| 302 LayoutObject* anchorObject = m_anchorObject; | 303 LayoutObject* anchorObject = m_anchorObject; |
| 303 m_anchorObject = nullptr; | 304 m_anchorObject = nullptr; |
| 304 | 305 |
| 305 if (anchorObject) | 306 if (anchorObject) |
| 306 anchorObject->maybeClearIsScrollAnchorObject(); | 307 anchorObject->clearIsScrollAnchorObject(unconditionally); |
| 308 } |
| 309 |
| 310 void ScrollAnchor::clear() { |
| 311 LayoutObject* layoutObject = |
| 312 m_anchorObject ? m_anchorObject : scrollerLayoutBox(m_scroller); |
| 313 PaintLayer* layer = nullptr; |
| 314 if (LayoutObject* parent = layoutObject->parent()) |
| 315 layer = parent->enclosingLayer(); |
| 316 |
| 317 // Walk up the layer tree to clear any scroll anchors. |
| 318 while (layer) { |
| 319 if (PaintLayerScrollableArea* scrollableArea = layer->getScrollableArea()) { |
| 320 ScrollAnchor* anchor = scrollableArea->scrollAnchor(); |
| 321 DCHECK(anchor); |
| 322 anchor->clearSelf(true); |
| 323 } |
| 324 layer = layer->parent(); |
| 325 } |
| 326 |
| 327 if (FrameView* view = layoutObject->frameView()) { |
| 328 ScrollAnchor* anchor = view->scrollAnchor(); |
| 329 DCHECK(anchor); |
| 330 anchor->clearSelf(true); |
| 331 } |
| 307 } | 332 } |
| 308 | 333 |
| 309 bool ScrollAnchor::refersTo(const LayoutObject* layoutObject) const { | 334 bool ScrollAnchor::refersTo(const LayoutObject* layoutObject) const { |
| 310 return m_anchorObject == layoutObject; | 335 return m_anchorObject == layoutObject; |
| 311 } | 336 } |
| 312 | 337 |
| 313 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) { | 338 void ScrollAnchor::notifyRemoved(LayoutObject* layoutObject) { |
| 314 if (m_anchorObject == layoutObject) | 339 if (m_anchorObject == layoutObject) |
| 315 clear(); | 340 clearSelf(); |
| 316 } | 341 } |
| 317 | 342 |
| 318 } // namespace blink | 343 } // namespace blink |
| OLD | NEW |