Commit 7d25f2f7 authored by Sandra Sun's avatar Sandra Sun Committed by Commit Bot

Latch to the node with non-auto overscroll-behavior

When we overscroll a scroller with non-auto overscroll-behavior at its
scroll extent, no node will be added to the scroll chain, because the
scroller can not consume the current delta. However, if we then scroll
the scroller to the opposite direction in the same gesture, the scroller
won't respond to that because it's not the CurrentlyScrollingNode.

This patch adds the first node with non-auto overscroll-behavior to the
scroll chain regardlessly, as it's the only node we can latch to, even
if it cannot consume the current delta. So when we change the scroll
direction, the scroller can still respond to the later events.

Bug: 798543
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: I8baa77ae6690e095de3018cb112185f48f0854a8
Reviewed-on: https://chromium-review.googlesource.com/848314Reviewed-by: default avatarAli Juma <ajuma@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Commit-Queue: Sandra Sun <sunyunjia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#527068}
parent 25716157
...@@ -3615,6 +3615,12 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) { ...@@ -3615,6 +3615,12 @@ void LayerTreeHostImpl::DistributeScrollDelta(ScrollState* scroll_state) {
: scroll_state->delta_y(); : scroll_state->delta_y();
if (!CanPropagate(scroll_node, delta_x, delta_y)) { if (!CanPropagate(scroll_node, delta_x, delta_y)) {
// We should add the first node with non-auto overscroll-behavior to
// the scroll chain regardlessly, as it's the only node we can latch to.
if (current_scroll_chain.empty() ||
current_scroll_chain.front() != scroll_node) {
current_scroll_chain.push_front(scroll_node);
}
scroll_state->set_is_scroll_chain_cut(true); scroll_state->set_is_scroll_chain_cut(true);
break; break;
} }
......
...@@ -1645,6 +1645,31 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) { ...@@ -1645,6 +1645,31 @@ TEST_F(LayerTreeHostImplTest, OverscrollBehaviorPreventsPropagation) {
host_impl_->ScrollEnd(EndState().get()); host_impl_->ScrollEnd(EndState().get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset()); EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset()); EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
// Gesture scroll should latch to the first scroller that has non-auto
// overscroll-behavior.
overflow->test_properties()->overscroll_behavior =
OverscrollBehavior(OverscrollBehavior::kOverscrollBehaviorTypeContain,
OverscrollBehavior::kOverscrollBehaviorTypeContain);
host_impl_->active_tree()->BuildPropertyTreesForTesting();
DrawFrame();
EXPECT_EQ(
InputHandler::SCROLL_ON_IMPL_THREAD,
host_impl_
->ScrollBegin(BeginState(scroll_position).get(), InputHandler::WHEEL)
.thread);
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 0), overflow->CurrentScrollOffset());
host_impl_->ScrollBy(UpdateState(scroll_position, x_delta).get());
host_impl_->ScrollBy(UpdateState(scroll_position, -x_delta).get());
host_impl_->ScrollBy(UpdateState(scroll_position, y_delta).get());
host_impl_->ScrollBy(UpdateState(scroll_position, -y_delta).get());
host_impl_->ScrollEnd(EndState().get());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), scroll_layer->CurrentScrollOffset());
EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
} }
TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) { TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
......
...@@ -19,12 +19,12 @@ class OverscrollBehaviorTest : public SimTest { ...@@ -19,12 +19,12 @@ class OverscrollBehaviorTest : public SimTest {
void SetUp() override; void SetUp() override;
void SetInnerOverscrollBehavior(EOverscrollBehavior, EOverscrollBehavior); void SetInnerOverscrollBehavior(EOverscrollBehavior, EOverscrollBehavior);
void Scroll(double x, double y);
private: void ScrollBegin(double hint_x, double hint_y);
WebGestureEvent ScrollBegin(double hint_x, double hint_y); void ScrollUpdate(double x, double y);
WebGestureEvent ScrollUpdate(double delta_x, double delta_y); void ScrollEnd();
WebGestureEvent ScrollEnd();
void Scroll(double x, double y);
}; };
void OverscrollBehaviorTest::SetUp() { void OverscrollBehaviorTest::SetUp() {
...@@ -66,17 +66,7 @@ void OverscrollBehaviorTest::SetInnerOverscrollBehavior(EOverscrollBehavior x, ...@@ -66,17 +66,7 @@ void OverscrollBehaviorTest::SetInnerOverscrollBehavior(EOverscrollBehavior x,
inner->MutableComputedStyle()->SetOverscrollBehaviorY(y); inner->MutableComputedStyle()->SetOverscrollBehaviorY(y);
} }
void OverscrollBehaviorTest::Scroll(double x, double y) { void OverscrollBehaviorTest::ScrollBegin(double hint_x, double hint_y) {
GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(
ScrollBegin(x, y));
GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(
ScrollUpdate(x, y));
GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(
ScrollEnd());
}
WebGestureEvent OverscrollBehaviorTest::ScrollBegin(double hint_x,
double hint_y) {
WebGestureEvent event(WebInputEvent::kGestureScrollBegin, WebGestureEvent event(WebInputEvent::kGestureScrollBegin,
WebInputEvent::kNoModifiers, WebInputEvent::kNoModifiers,
CurrentTimeTicks().InSeconds()); CurrentTimeTicks().InSeconds());
...@@ -87,11 +77,10 @@ WebGestureEvent OverscrollBehaviorTest::ScrollBegin(double hint_x, ...@@ -87,11 +77,10 @@ WebGestureEvent OverscrollBehaviorTest::ScrollBegin(double hint_x,
event.data.scroll_begin.delta_y_hint = -hint_y; event.data.scroll_begin.delta_y_hint = -hint_y;
event.data.scroll_begin.pointer_count = 1; event.data.scroll_begin.pointer_count = 1;
event.SetFrameScale(1); event.SetFrameScale(1);
return event; GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(event);
} }
WebGestureEvent OverscrollBehaviorTest::ScrollUpdate(double delta_x, void OverscrollBehaviorTest::ScrollUpdate(double delta_x, double delta_y) {
double delta_y) {
WebGestureEvent event(WebInputEvent::kGestureScrollUpdate, WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
WebInputEvent::kNoModifiers, WebInputEvent::kNoModifiers,
CurrentTimeTicks().InSeconds()); CurrentTimeTicks().InSeconds());
...@@ -101,17 +90,23 @@ WebGestureEvent OverscrollBehaviorTest::ScrollUpdate(double delta_x, ...@@ -101,17 +90,23 @@ WebGestureEvent OverscrollBehaviorTest::ScrollUpdate(double delta_x,
event.data.scroll_update.delta_x = -delta_x; event.data.scroll_update.delta_x = -delta_x;
event.data.scroll_update.delta_y = -delta_y; event.data.scroll_update.delta_y = -delta_y;
event.SetFrameScale(1); event.SetFrameScale(1);
return event; GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(event);
} }
WebGestureEvent OverscrollBehaviorTest::ScrollEnd() { void OverscrollBehaviorTest::ScrollEnd() {
WebGestureEvent event(WebInputEvent::kGestureScrollEnd, WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
WebInputEvent::kNoModifiers, WebInputEvent::kNoModifiers,
CurrentTimeTicks().InSeconds()); CurrentTimeTicks().InSeconds());
event.x = event.global_x = 20; event.x = event.global_x = 20;
event.y = event.global_y = 20; event.y = event.global_y = 20;
event.source_device = WebGestureDevice::kWebGestureDeviceTouchscreen; event.source_device = WebGestureDevice::kWebGestureDeviceTouchscreen;
return event; GetDocument().GetFrame()->GetEventHandler().HandleGestureScrollEvent(event);
}
void OverscrollBehaviorTest::Scroll(double x, double y) {
ScrollBegin(x, y);
ScrollUpdate(x, y);
ScrollEnd();
} }
TEST_F(OverscrollBehaviorTest, AutoAllowsPropagation) { TEST_F(OverscrollBehaviorTest, AutoAllowsPropagation) {
...@@ -177,4 +172,19 @@ TEST_F(OverscrollBehaviorTest, ContainOnYPreventsDiagonalPropagations) { ...@@ -177,4 +172,19 @@ TEST_F(OverscrollBehaviorTest, ContainOnYPreventsDiagonalPropagations) {
ASSERT_EQ(outer->scrollTop(), 200); ASSERT_EQ(outer->scrollTop(), 200);
} }
TEST_F(OverscrollBehaviorTest, LatchToTheElementPreventedByOverscrollBehavior) {
SetInnerOverscrollBehavior(EOverscrollBehavior::kNone,
EOverscrollBehavior::kNone);
ScrollBegin(-100, 0);
ScrollUpdate(-100, 0);
ScrollUpdate(100, 0);
ScrollUpdate(0, -100);
ScrollUpdate(0, 100);
ScrollEnd();
Element* inner = GetDocument().getElementById("inner");
ASSERT_EQ(inner->scrollLeft(), 100);
ASSERT_EQ(inner->scrollTop(), 100);
}
} // namespace blink } // namespace blink
...@@ -131,8 +131,15 @@ void ScrollManager::RecomputeScrollChain(const Node& start_node, ...@@ -131,8 +131,15 @@ void ScrollManager::RecomputeScrollChain(const Node& start_node,
cur_element == document_element) cur_element == document_element)
break; break;
if (!CanPropagate(scroll_state, *cur_element)) if (!CanPropagate(scroll_state, *cur_element)) {
// We should add the first node with non-auto overscroll-behavior to
// the scroll chain regardlessly, as it's the only node we can latch to.
if (scroll_chain.empty() ||
scroll_chain.front() != (int)DOMNodeIds::IdForNode(cur_element)) {
scroll_chain.push_front(DOMNodeIds::IdForNode(cur_element));
}
break; break;
}
} }
cur_box = cur_box->ContainingBlock(); cur_box = cur_box->ContainingBlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment