Index: third_party/WebKit/Source/web/ResizeViewportAnchor.cpp |
diff --git a/third_party/WebKit/Source/web/ResizeViewportAnchor.cpp b/third_party/WebKit/Source/web/ResizeViewportAnchor.cpp |
index 8c79f083d325094e0a910dd469f64936fe9b733a..d262e08301a275144238bcc9960ea802665ebfba 100644 |
--- a/third_party/WebKit/Source/web/ResizeViewportAnchor.cpp |
+++ b/third_party/WebKit/Source/web/ResizeViewportAnchor.cpp |
@@ -14,13 +14,54 @@ namespace blink { |
ResizeViewportAnchor::ResizeViewportAnchor(FrameView& rootFrameView, VisualViewport& visualViewport) |
: ViewportAnchor(rootFrameView, visualViewport) |
- , m_visualViewportInDocument(rootFrameView.getScrollableArea()->visibleContentRectDouble().location()) |
+ , m_visualViewportInDocument(rootFrameView.getScrollableArea()->scrollPositionDouble()) |
{ |
} |
ResizeViewportAnchor::~ResizeViewportAnchor() |
{ |
- m_rootFrameView->getScrollableArea()->setScrollPosition(m_visualViewportInDocument, ProgrammaticScroll); |
+ // TODO(bokan): Don't use RootFrameViewport::setScrollPosition since it |
+ // assumes we can just set a sub-pixel precision offset on the FrameView. |
+ // While we "can" do this, the offset that will be shipped to CC will be the |
+ // truncated number and this class is used to handle TopControl movement |
+ // which needs the two threads to match exactly pixel-for-pixel. We can |
+ // replace this with RFV::setScrollPosition once Blink is sub-pixel scroll |
+ // offset aware. crbug.com/414283. |
+ |
+ ScrollableArea* rootViewport = m_rootFrameView->getScrollableArea(); |
+ ScrollableArea* layoutViewport = |
+ m_rootFrameView->layoutViewportScrollableArea(); |
+ |
+ // Clamp the scroll offset of each viewport now so that we force any invalid |
+ // offsets to become valid so we can compute the correct deltas. |
+ m_visualViewport->clampToBoundaries(); |
+ layoutViewport->setScrollPosition( |
+ layoutViewport->scrollPositionDouble(), ProgrammaticScroll); |
+ |
+ DoubleSize delta = m_visualViewportInDocument |
+ - rootViewport->scrollPositionDouble(); |
+ |
+ m_visualViewport->move(toFloatSize(delta)); |
+ |
+ delta = m_visualViewportInDocument |
+ - rootViewport->scrollPositionDouble(); |
+ |
+ // Since the main thread FrameView has integer scroll offsets, scroll it to |
+ // the next pixel and then we'll scroll the visual viewport again to |
+ // compensate for the sub-pixel offset. We need this "overscroll" to ensure |
+ // the pixel of which we want to be partially in appears fully inside the |
+ // FrameView since the VisualViewport is bounded by the FrameView. |
+ IntSize layoutDelta = IntSize( |
+ delta.width() < 0 ? floor(delta.width()) : ceil(delta.width()), |
+ delta.height() < 0 ? floor(delta.height()) : ceil(delta.height())); |
+ |
+ layoutViewport->setScrollPosition( |
+ layoutViewport->scrollPosition() + layoutDelta, |
+ ProgrammaticScroll); |
+ |
+ delta = m_visualViewportInDocument |
+ - rootViewport->scrollPositionDouble(); |
+ m_visualViewport->move(toFloatSize(delta)); |
} |
} // namespace blink |