Commit aa703718 authored by Sandra Sun's avatar Sandra Sun Committed by Commit Bot

Move snap fling logic to cc.

We plan to share the snap fling logic between cc and blink. But with the
dependency restrictions, we can only put the shared logic under cc/.
This patch moves the logic from ui/ to cc/, in preparation for blink to
use the same logic to make snap fling works there.

As cc/ doesn't accept blink::WebGestureEvent and blink::WebInputEvent,
we create GestureScrollType and GestureScrollUpdateInfo to pass in the
necessary messages.

Bug: 778259
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I0df8cf1002d51646404310ca50eb00a536e0b5d1
Reviewed-on: https://chromium-review.googlesource.com/1024198Reviewed-by: default avatarDave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarMajid Valipour <majidvp@chromium.org>
Commit-Queue: Sandra Sun <sunyunjia@chromium.org>
Cr-Commit-Position: refs/heads/master@{#559533}
parent dec5afdd
......@@ -49,6 +49,10 @@ cc_component("cc") {
"input/scrollbar_animation_controller.h",
"input/single_scrollbar_animation_controller_thinning.cc",
"input/single_scrollbar_animation_controller_thinning.h",
"input/snap_fling_controller.cc",
"input/snap_fling_controller.h",
"input/snap_fling_curve.cc",
"input/snap_fling_curve.h",
"input/touch_action.h",
"layers/append_quads_data.cc",
"layers/append_quads_data.h",
......@@ -585,6 +589,8 @@ cc_test("cc_unittests") {
"input/scroll_state_unittest.cc",
"input/scrollbar_animation_controller_unittest.cc",
"input/single_scrollbar_animation_controller_thinning_unittest.cc",
"input/snap_fling_controller_unittest.cc",
"input/snap_fling_curve_unittest.cc",
"layers/effect_tree_layer_list_iterator_unittest.cc",
"layers/heads_up_display_layer_impl_unittest.cc",
"layers/heads_up_display_unittest.cc",
......
......@@ -2,12 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/blink/snap_fling_controller.h"
#include "cc/input/snap_fling_controller.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "ui/events/blink/snap_fling_curve.h"
#include "cc/input/snap_fling_curve.h"
namespace ui {
namespace cc {
SnapFlingController::SnapFlingController(SnapFlingClient* client)
: client_(client), state_(State::kIdle) {}
......@@ -15,20 +14,18 @@ SnapFlingController::SnapFlingController(SnapFlingClient* client)
SnapFlingController::~SnapFlingController() = default;
bool SnapFlingController::FilterEventForSnap(
const blink::WebInputEvent& event) {
switch (event.GetType()) {
case blink::WebInputEvent::kGestureScrollBegin: {
SnapFlingController::GestureScrollType gesture_scroll_type) {
switch (gesture_scroll_type) {
case GestureScrollType::kBegin: {
ClearSnapFling();
return false;
}
// TODO(sunyunjia): Need to update the existing snap curve if the GSU is
// from a fling boosting event.
case blink::WebInputEvent::kGestureScrollUpdate:
case blink::WebInputEvent::kGestureScrollEnd: {
case GestureScrollType::kUpdate:
case GestureScrollType::kEnd: {
return state_ == State::kActive || state_ == State::kFinished;
}
default:
return false;
}
}
......@@ -41,20 +38,16 @@ void SnapFlingController::ClearSnapFling() {
}
bool SnapFlingController::HandleGestureScrollUpdate(
const blink::WebGestureEvent& event) {
const SnapFlingController::GestureScrollUpdateInfo& info) {
DCHECK(state_ != State::kActive && state_ != State::kFinished);
if (state_ != State::kIdle)
return false;
if (event.data.scroll_update.inertial_phase !=
blink::WebGestureEvent::kMomentumPhase) {
if (!info.is_in_inertial_phase)
return false;
}
gfx::Vector2dF event_delta(-event.data.scroll_update.delta_x,
-event.data.scroll_update.delta_y);
gfx::Vector2dF ending_displacement =
SnapFlingCurve::EstimateDisplacement(event_delta);
SnapFlingCurve::EstimateDisplacement(info.delta);
gfx::Vector2dF target_offset, start_offset;
if (!client_->GetSnapFlingInfo(ending_displacement, &start_offset,
......@@ -69,9 +62,9 @@ bool SnapFlingController::HandleGestureScrollUpdate(
}
curve_ = std::make_unique<SnapFlingCurve>(start_offset, target_offset,
event.TimeStamp());
info.event_time);
state_ = State::kActive;
Animate(event.TimeStamp());
Animate(info.event_time);
return true;
}
......@@ -96,4 +89,4 @@ void SnapFlingController::SetCurveForTest(
state_ = State::kActive;
}
} // namespace ui
} // namespace cc
......@@ -2,20 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
#define UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
#ifndef CC_INPUT_SNAP_FLING_CONTROLLER_H_
#define CC_INPUT_SNAP_FLING_CONTROLLER_H_
#include <memory>
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace blink {
class WebGestureEvent;
class WebInputEvent;
} // namespace blink
namespace ui {
namespace cc {
namespace test {
class SnapFlingControllerTest;
}
......@@ -35,8 +31,22 @@ class SnapFlingClient {
virtual void RequestAnimationForSnapFling() = 0;
};
class SnapFlingController {
// SnapFlingController ensures that an incoming fling event (or inertial-phase
// scroll event) would land on a snap position if there is a valid one nearby.
// It takes an input event, filters it if it conflicts with the current fling,
// or generates a curve if the SnapFlingClient finds a valid snap position.
// It also animates the curve by notifying the client to scroll when clock
// ticks.
class CC_EXPORT SnapFlingController {
public:
enum class GestureScrollType { kBegin, kUpdate, kEnd };
struct GestureScrollUpdateInfo {
gfx::Vector2dF delta;
bool is_in_inertial_phase;
base::TimeTicks event_time;
};
explicit SnapFlingController(SnapFlingClient* client);
static std::unique_ptr<SnapFlingController> CreateForTests(
......@@ -47,12 +57,12 @@ class SnapFlingController {
// Returns true if the event should be consumed for snapping and should not be
// processed further.
bool FilterEventForSnap(const blink::WebInputEvent& event);
bool FilterEventForSnap(GestureScrollType gesture_scroll_type);
// Creates the snap fling curve from the first inertial GSU. Returns true if
// the event if a snap fling curve has been created and the event should not
// be processed further.
bool HandleGestureScrollUpdate(const blink::WebGestureEvent& event);
bool HandleGestureScrollUpdate(const GestureScrollUpdateInfo& info);
// Notifies the snap fling controller to update or end the scroll animation.
void Animate(base::TimeTicks time);
......@@ -91,6 +101,6 @@ class SnapFlingController {
DISALLOW_COPY_AND_ASSIGN(SnapFlingController);
};
} // namespace ui
} // namespace cc
#endif // UI_EVENTS_BLINK_SNAP_FLING_CONTROLLER_H_
\ No newline at end of file
#endif // CC_INPUT_SNAP_FLING_CONTROLLER_H_
......@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/blink/snap_fling_controller.h"
#include "cc/input/snap_fling_controller.h"
#include "cc/input/snap_fling_curve.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "ui/events/blink/snap_fling_curve.h"
namespace ui {
namespace cc {
namespace test {
namespace {
......@@ -52,37 +51,29 @@ class SnapFlingControllerTest : public testing::Test {
};
TEST_F(SnapFlingControllerTest, DoesNotFilterGSBWhenIdle) {
blink::WebGestureEvent event(
blink::WebInputEvent::kGestureScrollBegin, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
EXPECT_FALSE(controller_->FilterEventForSnap(event));
EXPECT_FALSE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kBegin));
}
TEST_F(SnapFlingControllerTest, FiltersGSUAndGSEDependingOnState) {
blink::WebGestureEvent scroll_update(
blink::WebInputEvent::kGestureScrollUpdate, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
blink::WebGestureEvent scroll_end(
blink::WebInputEvent::kGestureScrollEnd, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
// Should not filter GSU and GSE if the fling is not active.
EXPECT_FALSE(controller_->FilterEventForSnap(scroll_update));
EXPECT_FALSE(controller_->FilterEventForSnap(scroll_end));
EXPECT_FALSE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kUpdate));
EXPECT_FALSE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kEnd));
// Should filter GSU and GSE if the fling is active.
SetActiveState();
EXPECT_TRUE(controller_->FilterEventForSnap(scroll_update));
EXPECT_TRUE(controller_->FilterEventForSnap(scroll_end));
EXPECT_TRUE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kUpdate));
EXPECT_TRUE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kEnd));
}
TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) {
blink::WebGestureEvent event(
blink::WebInputEvent::kGestureScrollUpdate, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
event.data.scroll_update.delta_x = 0;
event.data.scroll_update.delta_y = -10;
event.data.scroll_update.inertial_phase =
blink::WebGestureEvent::kMomentumPhase;
SnapFlingController::GestureScrollUpdateInfo gsu;
gsu.delta = gfx::Vector2dF(0, -10);
gsu.is_in_inertial_phase = true;
EXPECT_CALL(mock_client_,
GetSnapFlingInfo(testing::_, testing::_, testing::_))
......@@ -91,25 +82,21 @@ TEST_F(SnapFlingControllerTest, CreatesAndAnimatesCurveOnFirstInertialGSU) {
testing::Return(true)));
EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(1);
EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(1);
EXPECT_TRUE(controller_->HandleGestureScrollUpdate(event));
EXPECT_TRUE(controller_->HandleGestureScrollUpdate(gsu));
testing::Mock::VerifyAndClearExpectations(&mock_client_);
}
TEST_F(SnapFlingControllerTest, DoesNotHandleNonInertialGSU) {
blink::WebGestureEvent event(
blink::WebInputEvent::kGestureScrollUpdate, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
event.data.scroll_update.delta_x = 0;
event.data.scroll_update.delta_y = -10;
event.data.scroll_update.inertial_phase =
blink::WebGestureEvent::kNonMomentumPhase;
SnapFlingController::GestureScrollUpdateInfo gsu;
gsu.delta = gfx::Vector2dF(0, -10);
gsu.is_in_inertial_phase = false;
EXPECT_CALL(mock_client_,
GetSnapFlingInfo(testing::_, testing::_, testing::_))
.Times(0);
EXPECT_CALL(mock_client_, RequestAnimationForSnapFling()).Times(0);
EXPECT_CALL(mock_client_, ScrollByForSnapFling(testing::_)).Times(0);
EXPECT_FALSE(controller_->HandleGestureScrollUpdate(event));
EXPECT_FALSE(controller_->HandleGestureScrollUpdate(gsu));
testing::Mock::VerifyAndClearExpectations(&mock_client_);
}
......@@ -154,22 +141,17 @@ TEST_F(SnapFlingControllerTest, FinishesTheCurve) {
TEST_F(SnapFlingControllerTest, GSBNotFilteredAndResetsStateWhenActive) {
SetActiveState();
blink::WebGestureEvent update_event(
blink::WebInputEvent::kGestureScrollUpdate, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
update_event.data.scroll_update.inertial_phase =
blink::WebGestureEvent::kMomentumPhase;
EXPECT_TRUE(controller_->FilterEventForSnap(update_event));
EXPECT_TRUE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kUpdate));
EXPECT_CALL(mock_client_, ScrollEndForSnapFling()).Times(1);
blink::WebGestureEvent begin_event(
blink::WebInputEvent::kGestureScrollBegin, 0,
blink::WebInputEvent::GetStaticTimeStampForTests());
EXPECT_FALSE(controller_->FilterEventForSnap(begin_event));
EXPECT_FALSE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kBegin));
testing::Mock::VerifyAndClearExpectations(&mock_client_);
EXPECT_FALSE(controller_->FilterEventForSnap(update_event));
EXPECT_FALSE(controller_->FilterEventForSnap(
SnapFlingController::GestureScrollType::kUpdate));
}
} // namespace test
} // namespace ui
} // namespace cc
......@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/blink/snap_fling_curve.h"
#include "cc/input/snap_fling_curve.h"
#include <cmath>
#include "build/build_config.h"
namespace ui {
namespace cc {
namespace {
#if defined(OS_ANDROID)
......@@ -116,4 +116,4 @@ bool SnapFlingCurve::IsFinished() const {
return is_finished_;
}
} // namespace ui
} // namespace cc
......@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
#define UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
#ifndef CC_INPUT_SNAP_FLING_CURVE_H_
#define CC_INPUT_SNAP_FLING_CURVE_H_
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace ui {
namespace cc {
// The curve for the snap fling animation. The curve would generate a geometric
// sequence of deltas to be scrolled at each frame.
class SnapFlingCurve {
class CC_EXPORT SnapFlingCurve {
public:
// Creates the curve based on the start offset, target offset, and the first
// inertial GSU's time_stamp.
......@@ -72,6 +73,6 @@ class SnapFlingCurve {
double ratio_y_;
};
} // namespace ui
} // namespace cc
#endif // UI_EVENTS_BLINK_SNAP_FLING_CURVE_H_
#endif // CC_INPUT_SNAP_FLING_CURVE_H_
......@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/events/blink/snap_fling_curve.h"
#include "cc/input/snap_fling_curve.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ui {
namespace cc {
namespace test {
TEST(SnapFlingCurveTest, CurveInitialization) {
......@@ -68,4 +68,4 @@ TEST(SnapFlingCurveTest, ReturnsZeroAfterFinished) {
}
} // namespace test
} // namespace ui
\ No newline at end of file
} // namespace cc
......@@ -406,8 +406,6 @@ if (!is_ios) {
"blink/fling_booster_unittest.cc",
"blink/input_handler_proxy_unittest.cc",
"blink/input_scroll_elasticity_controller_unittest.cc",
"blink/snap_fling_controller_unittest.cc",
"blink/snap_fling_curve_unittest.cc",
"blink/web_input_event_traits_unittest.cc",
"blink/web_input_event_unittest.cc",
"cocoa/events_mac_unittest.mm",
......
......@@ -27,10 +27,6 @@ jumbo_source_set("blink") {
"prediction/empty_predictor.cc",
"prediction/empty_predictor.h",
"prediction/input_predictor.h",
"snap_fling_controller.cc",
"snap_fling_controller.h",
"snap_fling_curve.cc",
"snap_fling_curve.h",
"synchronous_input_handler_proxy.h",
"web_input_event.cc",
"web_input_event.h",
......
......@@ -3,6 +3,7 @@ include_rules = [
"+cc/input/main_thread_scrolling_reason.h",
"+cc/input/overscroll_behavior.h",
"+cc/input/scroll_elasticity_helper.h",
"+cc/input/snap_fling_controller.h",
"+cc/trees/swap_promise_monitor.h",
"+third_party/blink/public/platform/web_gesture_curve.h",
......
......@@ -1130,6 +1130,17 @@ bool IsGestureScrollOrFlingOrPinch(WebInputEvent::Type type) {
}
}
bool IsGestureScroll(WebInputEvent::Type type) {
switch (type) {
case blink::WebGestureEvent::kGestureScrollBegin:
case blink::WebGestureEvent::kGestureScrollUpdate:
case blink::WebGestureEvent::kGestureScrollEnd:
return true;
default:
return false;
}
}
bool IsContinuousGestureEvent(WebInputEvent::Type type) {
switch (type) {
case blink::WebGestureEvent::kGestureScrollUpdate:
......
......@@ -95,6 +95,8 @@ blink::WebInputEvent::Modifiers DomCodeToWebInputEventModifiers(
bool IsGestureScrollOrFlingOrPinch(blink::WebInputEvent::Type);
bool IsGestureScroll(blink::WebInputEvent::Type);
bool IsContinuousGestureEvent(blink::WebInputEvent::Type);
EventPointerType WebPointerTypeToEventPointerType(
......
......@@ -136,6 +136,32 @@ cc::InputHandler::ScrollInputType GestureScrollInputType(
: cc::InputHandler::TOUCHSCREEN;
}
cc::SnapFlingController::GestureScrollType GestureScrollEventType(
WebInputEvent::Type web_event_type) {
switch (web_event_type) {
case WebInputEvent::kGestureScrollBegin:
return cc::SnapFlingController::GestureScrollType::kBegin;
case WebInputEvent::kGestureScrollUpdate:
return cc::SnapFlingController::GestureScrollType::kUpdate;
case WebInputEvent::kGestureScrollEnd:
return cc::SnapFlingController::GestureScrollType::kEnd;
default:
NOTREACHED();
return cc::SnapFlingController::GestureScrollType::kBegin;
}
}
cc::SnapFlingController::GestureScrollUpdateInfo GetGestureScrollUpdateInfo(
const WebGestureEvent& event) {
cc::SnapFlingController::GestureScrollUpdateInfo info;
info.delta = gfx::Vector2dF(-event.data.scroll_update.delta_x,
-event.data.scroll_update.delta_y);
info.is_in_inertial_phase = event.data.scroll_update.inertial_phase ==
blink::WebGestureEvent::kMomentumPhase;
info.event_time = event.TimeStamp();
return info;
}
enum ScrollingThreadStatus {
SCROLLING_ON_COMPOSITOR,
SCROLLING_ON_COMPOSITOR_BLOCKED_ON_MAIN,
......@@ -177,7 +203,7 @@ InputHandlerProxy::InputHandlerProxy(
has_ongoing_compositor_scroll_fling_pinch_(false),
is_first_gesture_scroll_update_(false),
tick_clock_(base::DefaultTickClock::GetInstance()),
snap_fling_controller_(std::make_unique<SnapFlingController>(this)) {
snap_fling_controller_(std::make_unique<cc::SnapFlingController>(this)) {
DCHECK(client);
input_handler_->BindToClient(this,
touchpad_and_wheel_scroll_latching_enabled_);
......@@ -391,8 +417,11 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
}
}
if (snap_fling_controller_->FilterEventForSnap(event))
if (IsGestureScroll(event.GetType()) &&
(snap_fling_controller_->FilterEventForSnap(
GestureScrollEventType(event.GetType())))) {
return DROP_EVENT;
}
switch (event.GetType()) {
case WebInputEvent::kMouseWheel:
......@@ -806,7 +835,8 @@ InputHandlerProxy::HandleGestureScrollUpdate(
}
}
if (snap_fling_controller_->HandleGestureScrollUpdate(gesture_event)) {
if (snap_fling_controller_->HandleGestureScrollUpdate(
GetGestureScrollUpdateInfo(gesture_event))) {
#ifndef NDEBUG
expect_scroll_update_end_ = false;
#endif
......
......@@ -10,13 +10,13 @@
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "cc/input/input_handler.h"
#include "cc/input/snap_fling_controller.h"
#include "third_party/blink/public/platform/web_gesture_curve.h"
#include "third_party/blink/public/platform/web_gesture_curve_target.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/web/web_active_fling_parameters.h"
#include "ui/events/blink/blink_features.h"
#include "ui/events/blink/input_scroll_elasticity_controller.h"
#include "ui/events/blink/snap_fling_controller.h"
#include "ui/events/blink/synchronous_input_handler_proxy.h"
#include "ui/events/blink/web_input_event_traits.h"
......@@ -53,7 +53,7 @@ struct DidOverscrollParams;
class InputHandlerProxy : public cc::InputHandlerClient,
public SynchronousInputHandlerProxy,
public blink::WebGestureCurveTarget,
public SnapFlingClient {
public cc::SnapFlingClient {
public:
InputHandlerProxy(cc::InputHandler* input_handler,
InputHandlerProxyClient* client,
......@@ -275,7 +275,7 @@ class InputHandlerProxy : public cc::InputHandlerClient,
std::unique_ptr<FlingBooster> fling_booster_;
std::unique_ptr<SnapFlingController> snap_fling_controller_;
std::unique_ptr<cc::SnapFlingController> snap_fling_controller_;
DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
};
......
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