Commit 1d469b09 authored by chaopeng's avatar chaopeng Committed by Commit Bot

Allow overscroll completion by inertial scroll event (fling)

To support Windows Touchpad swipe left/right navigation change, we need
to allow completing the overscroll by inertial scroll event (fling). Also
after overscroll completion, we need to ignore the rest of the inertial
scroll events (flings) in the same sequence.

Bug: 647140
Change-Id: I20542bd3fe95689eb2dfd8922aef077b9d64d139
Reviewed-on: https://chromium-review.googlesource.com/982101
Commit-Queue: Jianpeng Chao <chaopeng@chromium.org>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarMohsen Izadi <mohsen@chromium.org>
Reviewed-by: default avatarSahel Sharifymoghaddam <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#548434}
parent 0abbd025
......@@ -85,6 +85,9 @@ bool OverscrollController::ShouldProcessEvent(
}
bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
if (event.GetType() == blink::WebInputEvent::kGestureScrollBegin)
ignore_following_inertial_events_ = false;
if (!ShouldProcessEvent(event))
return false;
......@@ -99,6 +102,18 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
return false;
}
// Consume the scroll-update events if they are from a inertial scroll (fling)
// event that completed an overscroll gesture.
if (ignore_following_inertial_events_ &&
event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
const blink::WebGestureEvent& gesture =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase) {
return true;
}
}
bool reset_scroll_state = false;
if (scroll_state_ != ScrollState::NONE || overscroll_delta_x_ ||
overscroll_delta_y_) {
......@@ -199,7 +214,7 @@ void OverscrollController::Cancel() {
ResetScrollState();
}
bool OverscrollController::DispatchEventCompletesAction (
bool OverscrollController::DispatchEventCompletesAction(
const blink::WebInputEvent& event) const {
if (overscroll_mode_ == OVERSCROLL_NONE)
return false;
......@@ -209,9 +224,23 @@ bool OverscrollController::DispatchEventCompletesAction (
// after the threshold.
if (event.GetType() != blink::WebInputEvent::kMouseMove &&
event.GetType() != blink::WebInputEvent::kGestureScrollEnd &&
event.GetType() != blink::WebInputEvent::kGestureFlingStart)
event.GetType() != blink::WebInputEvent::kGestureFlingStart &&
event.GetType() != blink::WebInputEvent::kGestureScrollUpdate)
return false;
// Complete the overscroll gesture for inertial scroll (fling) event from
// touchpad.
if (event.GetType() == blink::WebInputEvent::kGestureScrollUpdate) {
if (overscroll_source_ != OverscrollSource::TOUCHPAD)
return false;
DCHECK(IsGestureEventFromTouchpad(event));
const blink::WebGestureEvent gesture_event =
static_cast<const blink::WebGestureEvent&>(event);
if (gesture_event.data.scroll_update.inertial_phase !=
blink::WebGestureEvent::kMomentumPhase)
return false;
}
if (event.GetType() == blink::WebInputEvent::kGestureScrollEnd &&
overscroll_source_ == OverscrollSource::TOUCHPAD) {
DCHECK(IsGestureEventFromTouchpad(event));
......@@ -469,6 +498,7 @@ bool OverscrollController::ProcessOverscroll(float delta_x,
}
void OverscrollController::CompleteAction() {
ignore_following_inertial_events_ = true;
if (delegate_)
delegate_->OnOverscrollComplete(overscroll_mode_);
Reset();
......
......@@ -97,8 +97,7 @@ class CONTENT_EXPORT OverscrollController {
// Returns true if the event indicates that the in-progress overscroll gesture
// can now be completed.
bool DispatchEventCompletesAction(
const blink::WebInputEvent& event) const;
bool DispatchEventCompletesAction(const blink::WebInputEvent& event) const;
// Returns true to indicate that dispatching the event should reset the
// overscroll gesture status.
......@@ -158,6 +157,11 @@ class CONTENT_EXPORT OverscrollController {
bool wheel_scroll_latching_enabled_;
// A inertial scroll (fling) event may complete an overscroll gesture and
// navigate to a new page, but the inertial scroll can continue to generate
// scroll-update events. These events need to be ignored.
bool ignore_following_inertial_events_ = false;
DISALLOW_COPY_AND_ASSIGN(OverscrollController);
};
......
......@@ -11,6 +11,7 @@
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/test/test_overscroll_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebInputEvent.h"
namespace content {
......@@ -39,15 +40,31 @@ class OverscrollControllerTest : public ::testing::Test {
return controller_->WillHandleEvent(*current_event_);
}
// Creates and sends a gesture event to the overscroll controller. Returns
// |true| if the event is consumed by the overscroll controller.
bool SimulateGestureEvent(blink::WebInputEvent::Type type,
blink::WebGestureDevice source_device) {
DCHECK(!current_event_);
current_event_ = std::make_unique<blink::WebGestureEvent>(
SyntheticWebGestureEventBuilder::Build(type, source_device));
return controller_->WillHandleEvent(*current_event_);
}
// Creates and sends a gesture-scroll-update event to the overscroll
// controller. Returns |true| if the event is consumed by the overscroll
// controller.
bool SimulateGestureScrollUpdate(float dx,
float dy,
blink::WebGestureDevice device) {
blink::WebGestureDevice device,
bool inertial_update) {
DCHECK(!current_event_);
current_event_ = std::make_unique<blink::WebGestureEvent>(
auto event = std::make_unique<blink::WebGestureEvent>(
SyntheticWebGestureEventBuilder::BuildScrollUpdate(dx, dy, 0, device));
if (inertial_update) {
event->data.scroll_update.inertial_phase =
blink::WebGestureEvent::kMomentumPhase;
}
current_event_ = std::move(event);
return controller_->WillHandleEvent(*current_event_);
}
......@@ -88,8 +105,8 @@ TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
// passing the start threshold, no overscroll should happen.
EXPECT_FALSE(SimulateMouseWheel(10, 0));
SimulateAck(false);
EXPECT_FALSE(
SimulateGestureScrollUpdate(10, 0, blink::kWebGestureDeviceTouchpad));
EXPECT_FALSE(SimulateGestureScrollUpdate(
10, 0, blink::kWebGestureDeviceTouchpad, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
......@@ -111,8 +128,8 @@ TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
// marked as processed.
EXPECT_FALSE(SimulateMouseWheel(100, 0));
SimulateAck(false);
EXPECT_FALSE(
SimulateGestureScrollUpdate(100, 0, blink::kWebGestureDeviceTouchpad));
EXPECT_FALSE(SimulateGestureScrollUpdate(
100, 0, blink::kWebGestureDeviceTouchpad, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_NONE, controller_mode());
EXPECT_EQ(OverscrollSource::NONE, controller_source());
......@@ -120,4 +137,34 @@ TEST_F(OverscrollControllerTest, MouseWheelConsumedPreventsOverscroll) {
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
}
// Verifying the inertial scroll event completes overscroll. After that we will
// ignore the following inertial scroll events until new sequence start.
TEST_F(OverscrollControllerTest,
InertialGestureScrollUpdateCompletesOverscroll) {
EXPECT_FALSE(SimulateGestureEvent(blink::WebInputEvent::kGestureScrollBegin,
blink::kWebGestureDeviceTouchpad));
SimulateAck(false);
EXPECT_FALSE(SimulateGestureScrollUpdate(
200, 0, blink::kWebGestureDeviceTouchpad, false));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_NONE, delegate()->completed_mode());
// Inertial update event complete the overscroll action.
EXPECT_FALSE(SimulateGestureScrollUpdate(
100, 0, blink::kWebGestureDeviceTouchpad, true));
SimulateAck(false);
EXPECT_EQ(OVERSCROLL_EAST, controller_mode());
EXPECT_EQ(OverscrollSource::TOUCHPAD, controller_source());
EXPECT_EQ(OVERSCROLL_EAST, delegate()->current_mode());
EXPECT_EQ(OVERSCROLL_EAST, delegate()->completed_mode());
// Next Inertial update event would be consumed by overscroll controller.
EXPECT_TRUE(SimulateGestureScrollUpdate(
100, 0, blink::kWebGestureDeviceTouchpad, true));
}
} // namespace content
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