Chromium Code Reviews| Index: third_party/WebKit/Source/core/layout/ScrollAnchor.cpp |
| diff --git a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp |
| index 2d805f19d6f25979023b1f490169cb57cc4a0e4d..97f4d7d29a409e428d8000b96240ec4564cd1cf5 100644 |
| --- a/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp |
| +++ b/third_party/WebKit/Source/core/layout/ScrollAnchor.cpp |
| @@ -89,8 +89,13 @@ static LayoutRect relativeBounds(const LayoutObject* layoutObject, const Scrolla |
| } |
| LayoutRect relativeBounds = LayoutRect(layoutObject->localToAncestorQuad( |
| FloatRect(localBounds), scrollerLayoutBox(scroller)).boundingBox()); |
| + // When the scroller is the FrameView, localToAncestorQuad returns document coords, |
| + // so we must subtract scroll offset to get viewport coords. We discard the fractional |
| + // part of the scroll offset so that the rounding in restore() matches the snapping of |
| + // the anchor node to the pixel grid of the layer it paints into. For non-FrameView |
| + // scrollers, we rely on the flooring behavior of LayoutBox::scrolledContentOffset. |
| if (scroller->isFrameView()) |
| - relativeBounds.moveBy(-LayoutPoint(scroller->scrollPositionDouble())); |
| + relativeBounds.moveBy(-flooredIntPoint(scroller->scrollPositionDouble())); |
|
eae
2016/05/10 23:09:18
We round scroll offsets in PaintLayerScrollableAre
skobes
2016/05/10 23:19:00
It's somewhat more subtle.
For the return value o
|
| return relativeBounds; |
| } |
| @@ -181,21 +186,27 @@ void ScrollAnchor::restore() |
| if (!m_anchorObject) |
| return; |
| - LayoutSize adjustment = computeRelativeOffset(m_anchorObject, m_scroller, m_corner) - m_savedRelativeOffset; |
| + // The anchor node can report fractional positions, but it is DIP-snapped when |
| + // painting (crbug.com/610805), so we must round the offsets to determine the |
| + // visual delta. If we scroll by the delta in LayoutUnits, the snapping of the |
| + // anchor node may round differently from the snapping of the scroll position. |
| + // (For example, anchor moving from 2.4px -> 2.6px is really 2px -> 3px, so we |
| + // should scroll by 1px instead of 0.2px.) This is true regardless of whether |
| + // the ScrollableArea actually uses fractional scroll positions. |
| + IntSize adjustment = |
| + roundedIntSize(computeRelativeOffset(m_anchorObject, m_scroller, m_corner)) - |
| + roundedIntSize(m_savedRelativeOffset); |
| if (!adjustment.isZero()) { |
| + DoublePoint desiredPos = m_scroller->scrollPositionDouble() + adjustment; |
| ScrollAnimatorBase* animator = m_scroller->existingScrollAnimator(); |
| if (!animator || !animator->hasRunningAnimation()) { |
| - m_scroller->setScrollPosition( |
| - m_scroller->scrollPositionDouble() + DoubleSize(adjustment), |
| - AnchoringScroll); |
| + m_scroller->setScrollPosition(desiredPos, AnchoringScroll); |
| } else { |
| // If in the middle of a scroll animation, stop the animation, make |
| // the adjustment, and continue the animation on the pending delta. |
| FloatSize pendingDelta = animator->desiredTargetPosition() - FloatPoint(m_scroller->scrollPositionDouble()); |
| animator->cancelAnimation(); |
| - m_scroller->setScrollPosition( |
| - m_scroller->scrollPositionDouble() + DoubleSize(adjustment), |
| - AnchoringScroll); |
| + m_scroller->setScrollPosition(desiredPos, AnchoringScroll); |
| animator->userScroll(ScrollByPixel, pendingDelta); |
| } |
| // Update UMA metric. |