Chromium Code Reviews| Index: cc/trees/layer_tree_host_impl_unittest.cc |
| diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc |
| index 7ecd6475f43260edfd6afefcf21ee14333239543..59f9711895383daa6c53d3f57c314464be98bec3 100644 |
| --- a/cc/trees/layer_tree_host_impl_unittest.cc |
| +++ b/cc/trees/layer_tree_host_impl_unittest.cc |
| @@ -6386,6 +6386,138 @@ TEST_F(LayerTreeHostImplTest, OverscrollOnMainThread) { |
| .thread); |
| } |
| +// Test that scroll chain correctly when a child scroller on the page (e.g. a |
|
tdresser
2016/08/15 13:37:41
Test that scroll*s*
bokan
2016/08/20 22:13:58
Done.
|
| +// scrolling div) is set as the outer viewport. This happens in the |
| +// rootScroller proposal. |
| +TEST_F(LayerTreeHostImplTest, ScrollChainingWithReplacedOuterViewport) { |
| + const gfx::Size content_size(200, 200); |
| + const gfx::Size viewport_size(100, 100); |
| + |
| + LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); |
| + |
| + LayerImpl* content_layer = |
| + CreateBasicVirtualViewportLayers(viewport_size, content_size); |
| + LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer(); |
| + LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer(); |
| + |
| + LayerImpl* scroll_layer = nullptr; |
| + LayerImpl* child_scroll_layer = nullptr; |
| + |
| + // Initialization: Add two nested scrolling layers, simulating a scrolling div |
| + // with another scrolling div inside it. Set the outer "div" to be the outer |
| + // viewport. |
| + { |
| + std::unique_ptr<LayerImpl> clip = LayerImpl::Create(layer_tree_impl, 10); |
| + clip->SetBounds(content_size); |
| + clip->SetPosition(gfx::PointF()); |
| + |
| + std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); |
| + scroll->SetBounds(gfx::Size(400, 400)); |
| + scroll->SetScrollClipLayer(clip->id()); |
| + scroll->SetDrawsContent(true); |
| + |
| + std::unique_ptr<LayerImpl> clip2 = LayerImpl::Create(layer_tree_impl, 12); |
| + clip2->SetBounds(gfx::Size(300, 300)); |
| + clip2->SetPosition(gfx::PointF()); |
| + clip2->SetDrawsContent(true); |
| + |
| + std::unique_ptr<LayerImpl> scroll2 = LayerImpl::Create(layer_tree_impl, 13); |
| + scroll2->SetBounds(gfx::Size(500, 500)); |
| + scroll2->SetScrollClipLayer(clip2->id()); |
| + scroll2->SetDrawsContent(true); |
| + |
| + scroll_layer = scroll.get(); |
| + child_scroll_layer = scroll2.get(); |
| + |
| + clip2->test_properties()->AddChild(std::move(scroll2)); |
| + scroll->test_properties()->AddChild(std::move(clip2)); |
| + |
| + clip->test_properties()->AddChild(std::move(scroll)); |
| + content_layer->test_properties()->AddChild(std::move(clip)); |
| + layer_tree_impl->SetViewportLayersFromIds( |
| + Layer::INVALID_ID, layer_tree_impl->PageScaleLayer()->id(), |
| + inner_scroll_layer->id(), scroll_layer->id()); |
| + layer_tree_impl->BuildPropertyTreesForTesting(); |
| + } |
| + |
| + // Scroll should target the nested scrolling layer in the content and then |
| + // chain to the parent scrolling layer which is now set as the outer |
| + // viewport. The original outer viewport layer shouldn't get any scroll here. |
| + { |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(200.f, 200.f), |
| + child_scroll_layer->CurrentScrollOffset()); |
| + |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), |
| + outer_scroll_layer->CurrentScrollOffset()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(200.f, 200.f), |
| + scroll_layer->CurrentScrollOffset()); |
| + } |
| + |
| + // Now that the nested scrolling layers are fully scrolled, further scrolls |
| + // would normally chain up to the "outer viewport" but since we've set the |
| + // scrolling content as the outer viewport, it should stop chaining there. |
| + { |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(), |
| + outer_scroll_layer->CurrentScrollOffset()); |
| + } |
| + |
| + // Zoom into the page by a 2X factor so that the inner viewport becomes |
| + // scrollable. |
| + float min_page_scale = 1.f, max_page_scale = 4.f; |
| + float page_scale_factor = 2.f; |
| + host_impl_->active_tree()->PushPageScaleFromMainThread( |
| + page_scale_factor, min_page_scale, max_page_scale); |
| + host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor); |
| + |
| + // Reset the parent scrolling layer (i.e. the current outer viewport) so that |
| + // we can ensure viewport scrolling works correctly. |
| + scroll_layer->SetCurrentScrollOffset(gfx::ScrollOffset(0, 0)); |
| + |
| + // Scrolling the content layer should now scroll the inner viewport first, |
| + // and then chain up to the current outer viewport (i.e. the parent scroll |
| + // layer). |
| + { |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(50.f, 50.f), |
| + inner_scroll_layer->CurrentScrollOffset()); |
| + |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), |
| + outer_scroll_layer->CurrentScrollOffset()); |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(50.f, 50.f), |
| + scroll_layer->CurrentScrollOffset()); |
| + } |
| +} |
| + |
| TEST_F(LayerTreeHostImplTest, OverscrollOnImplThread) { |
| InputHandlerScrollResult scroll_result; |
| LayerTreeSettings settings = DefaultSettings(); |
| @@ -9039,6 +9171,64 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, |
| host_impl_->ScrollEnd(EndState().get()); |
| } |
| +// Tests that when we set a child scroller (e.g. a scrolling div) as the outer |
| +// viewport, scrolling it controls the top controls. |
| +TEST_F(LayerTreeHostImplTopControlsTest, |
| + ReplacedOuterViewportScrollsTopControls) { |
| + const gfx::Size scroll_content_size(400, 400); |
| + const gfx::Size root_layer_size(200, 200); |
| + const gfx::Size viewport_size(100, 100); |
| + |
| + SetupTopControlsAndScrollLayerWithVirtualViewport( |
| + viewport_size, viewport_size, root_layer_size); |
| + |
| + LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer(); |
| + LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer(); |
| + LayerTreeImpl* layer_tree_impl = host_impl_->active_tree(); |
| + LayerImpl* scroll_layer = nullptr; |
| + |
| + // Initialization: Add a child scrolling layer to the outer scroll layer and |
| + // set its scroll layer as the outer viewport. This simulates setting a |
| + // scrolling element as the root scroller on the page. |
| + { |
| + std::unique_ptr<LayerImpl> clip = LayerImpl::Create(layer_tree_impl, 10); |
| + clip->SetBounds(root_layer_size); |
| + clip->SetPosition(gfx::PointF()); |
| + |
| + std::unique_ptr<LayerImpl> scroll = LayerImpl::Create(layer_tree_impl, 11); |
| + scroll->SetBounds(scroll_content_size); |
| + scroll->SetScrollClipLayer(clip->id()); |
| + scroll->SetDrawsContent(true); |
| + |
| + scroll_layer = scroll.get(); |
| + |
| + clip->test_properties()->AddChild(std::move(scroll)); |
| + outer_scroll->test_properties()->AddChild(std::move(clip)); |
| + layer_tree_impl->SetViewportLayersFromIds( |
| + Layer::INVALID_ID, layer_tree_impl->PageScaleLayer()->id(), |
| + inner_scroll->id(), scroll_layer->id()); |
| + layer_tree_impl->BuildPropertyTreesForTesting(); |
| + DrawFrame(); |
| + } |
| + |
| + ASSERT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); |
| + |
| + // Scrolling should scroll the child content and the top controls. The |
| + // original outer viewport should get no scroll. |
| + { |
| + host_impl_->ScrollBegin(BeginState(gfx::Point(0, 0)).get(), |
| + InputHandler::TOUCHSCREEN); |
| + host_impl_->ScrollBy( |
| + UpdateState(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f)).get()); |
| + host_impl_->ScrollEnd(EndState().get()); |
| + |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(), outer_scroll->CurrentScrollOffset()); |
| + EXPECT_VECTOR_EQ(gfx::Vector2dF(100.f, 50.f), |
| + scroll_layer->CurrentScrollOffset()); |
| + EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio()); |
| + } |
| +} |
| + |
| class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest { |
| public: |
| void SetupVirtualViewportLayers(const gfx::Size& content_size, |