Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1277)

Unified Diff: ui/events/blink/input_scroll_elasticity_controller_unittest.cc

Issue 1749343004: Implement Wheel Gesture Scrolling on OSX. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ensure only high precision scroll begins are used Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/events/blink/input_scroll_elasticity_controller.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/blink/input_scroll_elasticity_controller_unittest.cc
diff --git a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
index 82b94343f8e061a2c1f14cbdf687b9e7a1df060c..4ce7b9494ed7dee8c1255430b3f0eff45df377a7 100644
--- a/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
+++ b/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -99,6 +99,53 @@ class ScrollElasticityControllerTest : public testing::Test {
input_event_count_ += 1;
}
+ void SendGestureScrollBegin(bool inertial) {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollBegin;
+ event.data.scrollBegin.inertial = inertial;
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ controller_.ObserveGestureEventAndResult(event,
+ cc::InputHandlerScrollResult());
+ input_event_count_ += 1;
+ }
+
+ void SendGestureScrollUpdate(
+ bool inertial,
+ const gfx::Vector2dF& event_delta = gfx::Vector2dF(),
+ const gfx::Vector2dF& overscroll_delta = gfx::Vector2dF()) {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollUpdate;
+ event.data.scrollUpdate.inertial = inertial;
+ event.data.scrollUpdate.deltaX = -event_delta.x();
+ event.data.scrollUpdate.deltaY = -event_delta.y();
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ cc::InputHandlerScrollResult scroll_result;
+ scroll_result.did_overscroll_root = !overscroll_delta.IsZero();
+ scroll_result.unused_scroll_delta = overscroll_delta;
+
+ controller_.ObserveGestureEventAndResult(event, scroll_result);
+ input_event_count_ += 1;
+ }
+
+ void SendGestureScrollEnd() {
+ blink::WebGestureEvent event;
+ event.sourceDevice = blink::WebGestureDeviceTouchpad;
+ event.type = blink::WebInputEvent::GestureScrollEnd;
+
+ TickCurrentTime();
+ event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
+
+ controller_.ObserveGestureEventAndResult(event,
+ cc::InputHandlerScrollResult());
+ input_event_count_ += 1;
+ }
+
const base::TimeTicks& TickCurrentTime() {
current_time_ += base::TimeDelta::FromSecondsD(1 / 60.f);
return current_time_;
@@ -148,6 +195,40 @@ TEST_F(ScrollElasticityControllerTest, Axis) {
EXPECT_EQ(0, helper_.request_begin_frame_count());
}
+// Verify that stretching only occurs in one axis at a time, and that it
+// is biased to the Y axis.
+TEST_F(ScrollElasticityControllerTest, GestureBased_Axis) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(0, 0));
+
+ // If we push equally in the X and Y directions, we should see a stretch only
+ // in the Y direction.
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(10, 10),
+ gfx::Vector2dF(10, 10));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+ EXPECT_LT(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(gfx::Vector2dF());
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+
+ // If we push more in the X direction than the Y direction, we should see a
+ // stretch only in the X direction. This decision should be based on the
+ // input delta, not the actual overscroll delta.
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(-25, 10),
+ gfx::Vector2dF(-25, 40));
+ EXPECT_EQ(3, helper_.set_stretch_amount_count());
+ EXPECT_GT(0.f, helper_.StretchAmount().x());
+ EXPECT_EQ(0.f, helper_.StretchAmount().y());
+ helper_.SetStretchAmount(gfx::Vector2dF());
+ EXPECT_EQ(4, helper_.set_stretch_amount_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+}
+
// Verify that we need a total overscroll delta of at least 10 in a pinned
// direction before we start stretching.
TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
@@ -201,7 +282,54 @@ TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
EXPECT_EQ(1, helper_.request_begin_frame_count());
}
-// Verify that an stretch caused by a momentum scroll will switch to the
+// Verify that we need a total overscroll delta of at least 10 in a pinned
+// direction before we start stretching.
+TEST_F(ScrollElasticityControllerTest, GestureBased_MinimumDeltaBeforeStretch) {
+ // We should not start stretching while we are not pinned in the direction
+ // of the scroll (even if there is an overscroll delta). We have to wait for
+ // the regular scroll to eat all of the events.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 10));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 10));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Now pin the -X and +Y direction. The first event will not generate a
+ // stretch
+ // because it is below the delta threshold of 10.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Make the next scroll be in the -X direction more than the +Y direction,
+ // which will erase the memory of the previous unused delta of 8.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(-10, 5),
+ gfx::Vector2dF(-8, 10));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Now push against the pinned +Y direction again by 8. We reset the
+ // previous delta, so this will not generate a stretch.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Push against +Y by another 8. This gets us above the delta threshold of
+ // 10, so we should now have had the stretch set, and it should be in the
+ // +Y direction. The scroll in the -X direction should have been forgotten.
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, 10), gfx::Vector2dF(0, 8));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0.f, helper_.StretchAmount().x());
+ EXPECT_LT(0.f, helper_.StretchAmount().y());
+
+ // End the gesture. Because there is a non-zero stretch, we should be in the
+ // animated state, and should have had a frame requested.
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+ SendGestureScrollEnd();
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+}
+
+// Verify that a stretch caused by a momentum scroll will switch to the
// animating mode, where input events are ignored, and the stretch is updated
// while animating.
TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
@@ -297,7 +425,93 @@ TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
}
-// Verify that an stretch opposing a scroll is correctly resolved.
+// Verify that a stretch caused by a momentum scroll will switch to the
+// animating mode, where input events are ignored, and the stretch is updated
+// while animating.
+TEST_F(ScrollElasticityControllerTest, GestureBased_MomentumAnimate) {
+ // Do an active scroll, then switch to the momentum phase and scroll for a
+ // bit.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(false, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollEnd();
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Hit the -Y edge and overscroll slightly, but not enough to go over the
+ // threshold to cause a stretch.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 0),
+ gfx::ScrollOffset(10, 10));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -8));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+ EXPECT_EQ(0, helper_.request_begin_frame_count());
+
+ // Take another step, this time going over the threshold. This should update
+ // the stretch amount, and then switch to the animating mode.
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+ EXPECT_GT(-1.f, helper_.StretchAmount().y());
+
+ // Subsequent momentum events should do nothing.
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollUpdate(true, gfx::Vector2dF(0, -80), gfx::Vector2dF(0, -80));
+ SendGestureScrollEnd();
+ EXPECT_EQ(1, helper_.set_stretch_amount_count());
+ EXPECT_EQ(1, helper_.request_begin_frame_count());
+
+ // Subsequent animate events should update the stretch amount and request
+ // another frame.
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(2, helper_.request_begin_frame_count());
+ EXPECT_GT(-1.f, helper_.StretchAmount().y());
+
+ // Touching the trackpad (a PhaseMayBegin event) should disable animation.
+ SendGestureScrollBegin(false);
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(2, helper_.request_begin_frame_count());
+
+ // Releasing the trackpad should re-enable animation.
+ SendGestureScrollEnd();
+ EXPECT_EQ(2, helper_.set_stretch_amount_count());
+ EXPECT_EQ(3, helper_.request_begin_frame_count());
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(3, helper_.set_stretch_amount_count());
+ EXPECT_EQ(4, helper_.request_begin_frame_count());
+
+ // Keep animating frames until the stretch returns to rest.
+ int stretch_count = 3;
+ int begin_frame_count = 4;
+ while (1) {
+ TickCurrentTimeAndAnimate();
+ if (helper_.StretchAmount().IsZero()) {
+ stretch_count += 1;
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+ break;
+ }
+ stretch_count += 1;
+ begin_frame_count += 1;
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+ }
+
+ // After coming to rest, no subsequent animate calls change anything.
+ TickCurrentTimeAndAnimate();
+ EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
+ EXPECT_EQ(begin_frame_count, helper_.request_begin_frame_count());
+}
+
+// Verify that a stretch opposing a scroll is correctly resolved.
TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
SendMouseWheelEvent(PhaseBegan, PhaseNone);
@@ -334,14 +548,50 @@ TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
}
+// Verify that a stretch opposing a scroll is correctly resolved.
+TEST_F(ScrollElasticityControllerTest, GestureBased_ReconcileStretchAndScroll) {
+ SendGestureScrollBegin(false);
+
+ // Verify completely knocking out the scroll in the -Y direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(0, -10));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, -5));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 0));
+
+ // Verify partially knocking out the scroll in the -Y direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 8),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(0, -5));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 3));
+
+ // Verify completely knocking out the scroll in the +X direction.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(10, 0));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(5, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(10, 5));
+
+ // Verify partially knocking out the scroll in the +X and +Y directions.
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(2, 3),
+ gfx::ScrollOffset(10, 10));
+ helper_.SetStretchAmount(gfx::Vector2dF(5, 5));
+ controller_.ReconcileStretchAndScroll();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
+}
+
// Verify that stretching only happens when the area is user scrollable.
TEST_F(ScrollElasticityControllerTest, UserScrollableRequiredForStretch) {
helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
gfx::ScrollOffset(10, 10));
gfx::Vector2dF delta(0, -15);
- // Do an active scroll, and ensure that the stretch amount doesn't change,
- // and also that the stretch amount isn't even ever changed.
+ // Do an active scroll, and ensure that the stretch amount doesn't change.
helper_.SetUserScrollable(false);
SendMouseWheelEvent(PhaseBegan, PhaseNone);
SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
@@ -384,5 +634,55 @@ TEST_F(ScrollElasticityControllerTest, UserScrollableRequiredForStretch) {
EXPECT_GT(ticks_to_zero, 3);
}
+// Verify that stretching only happens when the area is user scrollable.
+TEST_F(ScrollElasticityControllerTest,
+ GestureBased_UserScrollableRequiredForStretch) {
+ helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
+ gfx::ScrollOffset(10, 10));
+ gfx::Vector2dF delta(0, -15);
+
+ // Do an active scroll, and ensure that the stretch amount doesn't change.
+ helper_.SetUserScrollable(false);
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_EQ(0, helper_.set_stretch_amount_count());
+
+ // Re-enable user scrolling and ensure that stretching is re-enabled.
+ helper_.SetUserScrollable(true);
+ SendGestureScrollBegin(false);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollUpdate(false, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_GT(helper_.set_stretch_amount_count(), 0);
+ SendGestureScrollBegin(true);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollUpdate(true, delta, delta);
+ SendGestureScrollEnd();
+ EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
+ EXPECT_GT(helper_.set_stretch_amount_count(), 0);
+
+ // Disable user scrolling and tick the timer until the stretch goes back
+ // to zero. Ensure that the return to zero doesn't happen immediately.
+ helper_.SetUserScrollable(false);
+ int ticks_to_zero = 0;
+ while (1) {
+ TickCurrentTimeAndAnimate();
+ if (helper_.StretchAmount().IsZero())
+ break;
+ ticks_to_zero += 1;
+ }
+ EXPECT_GT(ticks_to_zero, 3);
+}
+
} // namespace
} // namespace ui
« no previous file with comments | « ui/events/blink/input_scroll_elasticity_controller.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698