1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/basictypes.h" 6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/logging.h" 7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/time/time.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/events/gesture_detection/velocity_tracker_state.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "ui/events/test/mock_motion_event.h" 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/geometry/point_f.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/geometry/vector2d_f.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::TimeDelta; 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)using base::TimeTicks; 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing ui::test::MockMotionEvent; 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ui { 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 21a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const TimeDelta kTenMillis = TimeDelta::FromMilliseconds(10); 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const TimeDelta kOneSecond = TimeDelta::FromSeconds(1); 24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const float kEpsilson = .01f; 25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char* GetStrategyName(VelocityTracker::Strategy strategy) { 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (strategy) { 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::LSQ1: return "LSQ1"; 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::LSQ2: return "LSQ2"; 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::LSQ3: return "LSQ3"; 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::WLSQ2_DELTA: return "WLSQ2_DELTA"; 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::WLSQ2_CENTRAL: return "WLSQ2_CENTRAL"; 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::WLSQ2_RECENT: return "WLSQ2_RECENT"; 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::INT1: return "INT1"; 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case VelocityTracker::INT2: return "INT2"; 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) }; 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED() << "Invalid strategy"; 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return ""; 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class VelocityTrackerTest : public testing::Test { 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public: 45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTrackerTest() {} 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual ~VelocityTrackerTest() {} 47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) protected: 49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static MockMotionEvent Sample(MotionEvent::Action action, 50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::PointF p0, 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeTicks t0, 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Vector2dF v, 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeDelta dt) { 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::PointF p = p0 + ScaleVector2d(v, dt.InSecondsF()); 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return MockMotionEvent(action, t0 + dt, p.x(), p.y()); 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void ApplyMovementSequence(VelocityTrackerState* state, 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::PointF p0, 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Vector2dF v, 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeTicks t0, 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeDelta t, 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t samples) { 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(!!samples); 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!samples) 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::TimeDelta dt = t / samples; 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->AddMovement(Sample(MotionEvent::ACTION_DOWN, p0, t0, v, dt * 0)); 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovement(state, p0, v, t0, t, samples); 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->AddMovement(Sample(MotionEvent::ACTION_UP, p0, t0, v, t)); 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static void ApplyMovement(VelocityTrackerState* state, 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::PointF p0, 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::Vector2dF v, 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeTicks t0, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeDelta t, 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) size_t samples) { 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_TRUE(!!samples); 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!samples) 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::TimeDelta dt = t / samples; 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = 0; i < samples; ++i) 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->AddMovement(Sample(MotionEvent::ACTION_MOVE, p0, t0, v, dt * i)); 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(VelocityTrackerTest, Basic) { 89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::PointF p0(0, 0); 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Vector2dF v(0, 500); 91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t samples = 60; 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i <= VelocityTracker::STRATEGY_MAX; ++i) { 94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTracker::Strategy strategy = 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<VelocityTracker::Strategy>(i); 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SCOPED_TRACE(GetStrategyName(strategy)); 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTrackerState state(strategy); 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Default state should report zero velocity. 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetXVelocity(0)); 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetYVelocity(0)); 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Sample a constant velocity sequence. 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovementSequence(&state, p0, v, TimeTicks::Now(), kOneSecond, samples); 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The computed velocity should match that of the input. 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 20000); 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(v.x(), state.GetXVelocity(0), kEpsilson * v.x()); 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(v.y(), state.GetYVelocity(0), kEpsilson * v.y()); 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // A pointer ID of -1 should report the velocity of the active pointer. 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(v.x(), state.GetXVelocity(-1), kEpsilson * v.x()); 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(v.y(), state.GetYVelocity(-1), kEpsilson * v.y()); 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Invalid pointer ID's should report zero velocity. 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetXVelocity(1)); 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetYVelocity(1)); 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetXVelocity(7)); 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(0, state.GetYVelocity(7)); 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(VelocityTrackerTest, MaxVelocity) { 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::PointF p0(0, 0); 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Vector2dF v(-50000, 50000); 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t samples = 3; 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const base::TimeDelta dt = kTenMillis * 2; 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTrackerState state; 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovementSequence(&state, p0, v, TimeTicks::Now(), dt, samples); 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The computed velocity should be restricted to the provided maximum. 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 100); 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(-100, state.GetXVelocity(0), kEpsilson); 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(100, state.GetYVelocity(0), kEpsilson); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 1000); 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(-1000, state.GetXVelocity(0), kEpsilson); 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_NEAR(1000, state.GetYVelocity(0), kEpsilson); 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(VelocityTrackerTest, VaryingVelocity) { 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::PointF p0(0, 0); 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Vector2dF vFast(0, 500); 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const gfx::Vector2dF vSlow = ScaleVector2d(vFast, 0.5f); 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t samples = 12; 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i <= VelocityTracker::STRATEGY_MAX; ++i) { 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTracker::Strategy strategy = 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<VelocityTracker::Strategy>(i); 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SCOPED_TRACE(GetStrategyName(strategy)); 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) VelocityTrackerState state(strategy); 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks t0 = base::TimeTicks::Now(); 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta dt = kTenMillis * 10; 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.AddMovement( 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Sample(MotionEvent::ACTION_DOWN, p0, t0, vFast, base::TimeDelta())); 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Apply some fast movement and compute the velocity. 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gfx::PointF pCurr = p0; 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeTicks tCurr = t0; 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovement(&state, pCurr, vFast, tCurr, dt, samples); 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 20000); 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float vOldY = state.GetYVelocity(0); 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Apply some slow movement. 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pCurr += ScaleVector2d(vFast, dt.InSecondsF()); 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) tCurr += dt; 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovement(&state, pCurr, vSlow, tCurr, dt, samples); 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The computed velocity should have decreased. 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 20000); 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float vCurrentY = state.GetYVelocity(0); 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_GT(vFast.y(), vCurrentY); 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_GT(vOldY, vCurrentY); 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) vOldY = vCurrentY; 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Apply some additional fast movement. 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) pCurr += ScaleVector2d(vSlow, dt.InSecondsF()); 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) tCurr += dt; 183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ApplyMovement(&state, pCurr, vFast, tCurr, dt, samples); 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The computed velocity should have increased. 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state.ComputeCurrentVelocity(1000, 20000); 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) vCurrentY = state.GetYVelocity(0); 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_LT(vSlow.y(), vCurrentY); 189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_LT(vOldY, vCurrentY); 190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 193116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_F(VelocityTrackerTest, DelayedActionUp) { 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::PointF p0(0, 0); 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::Vector2dF v(-50000, 50000); 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t samples = 10; 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeTicks t0 = base::TimeTicks::Now(); 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeDelta dt = kTenMillis * 2; 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VelocityTrackerState state; 201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state.AddMovement( 202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Sample(MotionEvent::ACTION_DOWN, p0, t0, v, base::TimeDelta())); 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Apply the movement and verify a (non-zero) velocity. 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ApplyMovement(&state, p0, v, t0, dt, samples); 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state.ComputeCurrentVelocity(1000, 1000); 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_NEAR(-1000, state.GetXVelocity(0), kEpsilson); 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_NEAR(1000, state.GetYVelocity(0), kEpsilson); 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Apply the delayed ACTION_UP. 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const gfx::PointF p1 = p0 + ScaleVector2d(v, dt.InSecondsF()); 212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const base::TimeTicks t1 = t0 + dt + kTenMillis * 10; 213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state.AddMovement(Sample( 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MotionEvent::ACTION_UP, p1, t1, v, base::TimeDelta())); 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The tracked velocity should have been reset. 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch state.ComputeCurrentVelocity(1000, 1000); 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(0.f, state.GetXVelocity(0)); 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(0.f, state.GetYVelocity(0)); 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace ui 223