// Tests that scrolling the viewport when the layout viewport is // !userInputScrollable (as happens when overflow:hidden is set) works // correctly, that is, the visual viewport can scroll, but not the layout. TEST_F(RootFrameViewportTest, UserInputScrollable) { IntSize viewportSize(100, 150); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(200, 300)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); visualViewport->setScale(2); // Disable just the layout viewport's horizontal scrolling, the // RootFrameViewport should remain scrollable overall. layoutViewport->setUserInputScrollable(false, true); visualViewport->setUserInputScrollable(true, true); EXPECT_TRUE(rootFrameViewport->userInputScrollable(HorizontalScrollbar)); EXPECT_TRUE(rootFrameViewport->userInputScrollable(VerticalScrollbar)); // Layout viewport shouldn't scroll since it's not horizontally scrollable, // but visual viewport should. rootFrameViewport->userScroll(ScrollByPixel, FloatSize(300, 0)); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 0), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 0), rootFrameViewport->getScrollOffset()); // Vertical scrolling should be unaffected. rootFrameViewport->userScroll(ScrollByPixel, FloatSize(0, 300)); EXPECT_SIZE_EQ(ScrollOffset(0, 150), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 225), rootFrameViewport->getScrollOffset()); // Try the same checks as above but for the vertical direction. // =============================================== rootFrameViewport->setScrollOffset(ScrollOffset(), ProgrammaticScroll); // Disable just the layout viewport's vertical scrolling, the // RootFrameViewport should remain scrollable overall. layoutViewport->setUserInputScrollable(true, false); visualViewport->setUserInputScrollable(true, true); EXPECT_TRUE(rootFrameViewport->userInputScrollable(HorizontalScrollbar)); EXPECT_TRUE(rootFrameViewport->userInputScrollable(VerticalScrollbar)); // Layout viewport shouldn't scroll since it's not vertically scrollable, // but visual viewport should. rootFrameViewport->userScroll(ScrollByPixel, FloatSize(0, 300)); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 75), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 75), rootFrameViewport->getScrollOffset()); // Horizontal scrolling should be unaffected. rootFrameViewport->userScroll(ScrollByPixel, FloatSize(300, 0)); EXPECT_SIZE_EQ(ScrollOffset(100, 0), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(150, 75), rootFrameViewport->getScrollOffset()); }
// Tests that scrolls on the root frame scroll the visual viewport before // trying to scroll the layout viewport. TEST_F(RootFrameViewportTest, ViewportScrollOrder) { IntSize viewportSize(100, 100); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(200, 300)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); visualViewport->setScale(2); rootFrameViewport->setScrollOffset(ScrollOffset(40, 40), UserScroll); EXPECT_SIZE_EQ(ScrollOffset(40, 40), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); rootFrameViewport->setScrollOffset(ScrollOffset(60, 60), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(50, 50), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(10, 10), layoutViewport->getScrollOffset()); }
// Make sure scrolls using the scroll animator (scroll(), setScrollOffset()) // work correctly when one of the subviewports is explicitly scrolled without // using the // RootFrameViewport interface. TEST_F(RootFrameViewportTest, TestScrollAnimatorUpdatedBeforeScroll) { IntSize viewportSize(100, 150); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(200, 300)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); visualViewport->setScale(2); visualViewport->setScrollOffset(ScrollOffset(50, 75), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(50, 75), rootFrameViewport->getScrollOffset()); // If the scroll animator doesn't update, it will still think it's at (0, 0) // and so it may early exit. rootFrameViewport->setScrollOffset(ScrollOffset(0, 0), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(0, 0), rootFrameViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), visualViewport->getScrollOffset()); // Try again for userScroll() visualViewport->setScrollOffset(ScrollOffset(50, 75), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(50, 75), rootFrameViewport->getScrollOffset()); rootFrameViewport->userScroll(ScrollByPixel, FloatSize(-50, 0)); EXPECT_SIZE_EQ(ScrollOffset(0, 75), rootFrameViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 75), visualViewport->getScrollOffset()); // Make sure the layout viewport is also accounted for. rootFrameViewport->setScrollOffset(ScrollOffset(0, 0), ProgrammaticScroll); layoutViewport->setScrollOffset(ScrollOffset(100, 150), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(100, 150), rootFrameViewport->getScrollOffset()); rootFrameViewport->userScroll(ScrollByPixel, FloatSize(-100, 0)); EXPECT_SIZE_EQ(ScrollOffset(0, 150), rootFrameViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 150), layoutViewport->getScrollOffset()); }
// Tests that the setScrollOffset method works correctly with both viewports. TEST_F(RootFrameViewportTest, SetScrollOffset) { IntSize viewportSize(500, 500); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(1000, 2000)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); visualViewport->setScale(2); // Ensure that the visual viewport scrolls first. rootFrameViewport->setScrollOffset(ScrollOffset(100, 100), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(100, 100), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); // Scroll to the visual viewport's extent, the layout viewport should scroll // the remainder. rootFrameViewport->setScrollOffset(ScrollOffset(300, 400), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(250, 250), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 150), layoutViewport->getScrollOffset()); // Only the layout viewport should scroll further. Make sure it doesn't scroll // out of bounds. rootFrameViewport->setScrollOffset(ScrollOffset(780, 1780), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(250, 250), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(500, 1500), layoutViewport->getScrollOffset()); // Scroll all the way back. rootFrameViewport->setScrollOffset(ScrollOffset(0, 0), ProgrammaticScroll); EXPECT_SIZE_EQ(ScrollOffset(0, 0), visualViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); }
// Tests that the visible rect (i.e. visual viewport rect) is correctly // calculated, taking into account both viewports and page scale. TEST_F(RootFrameViewportTest, VisibleContentRect) { IntSize viewportSize(500, 401); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(1000, 2000)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); rootFrameViewport->setScrollOffset(ScrollOffset(100, 75), ProgrammaticScroll); EXPECT_POINT_EQ(IntPoint(100, 75), rootFrameViewport->visibleContentRect().location()); EXPECT_SIZE_EQ(ScrollOffset(500, 401), rootFrameViewport->visibleContentRect().size()); visualViewport->setScale(2); EXPECT_POINT_EQ(IntPoint(100, 75), rootFrameViewport->visibleContentRect().location()); EXPECT_SIZE_EQ(ScrollOffset(250, 201), rootFrameViewport->visibleContentRect().size()); }
// Test that the scrollIntoView correctly scrolls the main frame // and visual viewport such that the given rect is centered in the viewport. TEST_F(RootFrameViewportTest, ScrollIntoView) { IntSize viewportSize(100, 150); RootFrameViewStub* layoutViewport = RootFrameViewStub::create(viewportSize, IntSize(200, 300)); VisualViewportStub* visualViewport = VisualViewportStub::create(viewportSize, viewportSize); ScrollableArea* rootFrameViewport = RootFrameViewport::create(*visualViewport, *layoutViewport); // Test that the visual viewport is scrolled if the viewport has been // resized (as is the case when the ChromeOS keyboard comes up) but not // scaled. visualViewport->setViewportSize(IntSize(100, 100)); rootFrameViewport->scrollIntoView(LayoutRect(100, 250, 50, 50), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); EXPECT_SIZE_EQ(ScrollOffset(50, 150), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 50), visualViewport->getScrollOffset()); rootFrameViewport->scrollIntoView(LayoutRect(25, 75, 50, 50), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); EXPECT_SIZE_EQ(ScrollOffset(25, 75), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 0), visualViewport->getScrollOffset()); // Reset the visual viewport's size, scale the page, and repeat the test visualViewport->setViewportSize(IntSize(100, 150)); visualViewport->setScale(2); rootFrameViewport->setScrollOffset(ScrollOffset(), ProgrammaticScroll); rootFrameViewport->scrollIntoView(LayoutRect(50, 75, 50, 75), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); EXPECT_SIZE_EQ(ScrollOffset(0, 0), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visualViewport->getScrollOffset()); rootFrameViewport->scrollIntoView(LayoutRect(190, 290, 10, 10), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); EXPECT_SIZE_EQ(ScrollOffset(100, 150), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(50, 75), visualViewport->getScrollOffset()); // Scrolling into view the viewport rect itself should be a no-op. visualViewport->setViewportSize(IntSize(100, 100)); visualViewport->setScale(1.5f); visualViewport->setScrollOffset(ScrollOffset(0, 10), ProgrammaticScroll); layoutViewport->setScrollOffset(ScrollOffset(50, 50), ProgrammaticScroll); rootFrameViewport->setScrollOffset(rootFrameViewport->getScrollOffset(), ProgrammaticScroll); rootFrameViewport->scrollIntoView( LayoutRect(rootFrameViewport->visibleContentRect(ExcludeScrollbars)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visualViewport->getScrollOffset()); rootFrameViewport->scrollIntoView( LayoutRect(rootFrameViewport->visibleContentRect(ExcludeScrollbars)), ScrollAlignment::alignCenterAlways, ScrollAlignment::alignCenterAlways); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visualViewport->getScrollOffset()); rootFrameViewport->scrollIntoView( LayoutRect(rootFrameViewport->visibleContentRect(ExcludeScrollbars)), ScrollAlignment::alignTopAlways, ScrollAlignment::alignTopAlways); EXPECT_SIZE_EQ(ScrollOffset(50, 50), layoutViewport->getScrollOffset()); EXPECT_SIZE_EQ(ScrollOffset(0, 10), visualViewport->getScrollOffset()); }