TEST_F(ExternalPopupMenuTest, PopupAccountsForVisualViewportOffset) { registerMockedURLLoad("select_mid_screen.html"); loadFrame("select_mid_screen.html"); webView()->resize(WebSize(100, 100)); webView()->updateAllLifecyclePhases(); HTMLSelectElement* select = toHTMLSelectElement(mainFrame()->frame()->document()->getElementById("select")); LayoutMenuList* menuList = toLayoutMenuList(select->layoutObject()); ASSERT_TRUE(menuList); VisualViewport& visualViewport = webView()->page()->frameHost().visualViewport(); IntRect rectInDocument = menuList->absoluteBoundingBoxRect(); webView()->setPageScaleFactor(2); IntPoint scrollDelta(20, 30); visualViewport.move(scrollDelta); select->showPopup(); EXPECT_EQ(rectInDocument.x() - scrollDelta.x(), client().shownBounds().x); EXPECT_EQ(rectInDocument.y() - scrollDelta.y(), client().shownBounds().y); }
void ScrollableArea::scrollIntoRect(const LayoutRect& rectInContent, const FloatRect& targetRectInFrame) { // Use |pixelSnappedIntRect| for rounding to pixel as opposed to |enclosingIntRect|. It gives a better // combined (location and size) rounding error resulting in a more accurate scroll offset. // FIXME: It would probably be best to do the whole calculation in LayoutUnits but contentsToRootFrame // and friends don't have LayoutRect/Point versions yet. IntRect boundsInContent = pixelSnappedIntRect(rectInContent); IntRect boundsInFrame(boundsInContent.location() - toIntSize(scrollPosition()), boundsInContent.size()); int centeringOffsetX = (targetRectInFrame.width() - boundsInFrame.width()) / 2; int centeringOffsetY = (targetRectInFrame.height() - boundsInFrame.height()) / 2; IntSize scrollDelta( boundsInFrame.x() - centeringOffsetX - targetRectInFrame.x(), boundsInFrame.y() - centeringOffsetY - targetRectInFrame.y()); DoublePoint targetOffset = DoublePoint(scrollPosition() + scrollDelta); setScrollPosition(targetOffset, ProgrammaticScroll); }