Chromium Code Reviews| Index: ui/chromeos/touch_exploration_controller_unittest.cc |
| diff --git a/ui/chromeos/touch_exploration_controller_unittest.cc b/ui/chromeos/touch_exploration_controller_unittest.cc |
| index 6b1f3dea84621539f4b272c9c94ed4bd714e37d3..e017bb4dcf562451fbec40e03076de8bd74197f1 100644 |
| --- a/ui/chromeos/touch_exploration_controller_unittest.cc |
| +++ b/ui/chromeos/touch_exploration_controller_unittest.cc |
| @@ -71,6 +71,24 @@ int Factorial(int n) { |
| return n * Factorial(n - 1); |
| } |
| +class MockTouchExplorationControllerDelegate |
| + : public ui::TouchExplorationControllerDelegate { |
| + public: |
| + virtual void PlayVolumeAdjustSound() OVERRIDE { |
| + ++num_times_adjust_sound_played_; |
| + } |
| + virtual void SetOutputLevel(int volume) OVERRIDE { |
| + volume_changes_.push_back(volume); |
| + } |
| + |
| + const std::vector<float> VolumeChanges() { return volume_changes_; } |
| + const size_t NumAdjustSounds() { return num_times_adjust_sound_played_; } |
| + |
| + private: |
| + std::vector<float> volume_changes_; |
| + size_t num_times_adjust_sound_played_ = 0; |
| +}; |
| + |
| } // namespace |
| class TouchExplorationTest : public aura::test::AuraTestBase { |
| @@ -85,6 +103,7 @@ class TouchExplorationTest : public aura::test::AuraTestBase { |
| if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) |
| gfx::GLSurface::InitializeOneOffForTests(); |
| aura::test::AuraTestBase::SetUp(); |
| + delegate_ = new MockTouchExplorationControllerDelegate(); |
|
James Cook
2014/07/21 21:05:35
I think this causes a memory leak. delegate_ shoul
lisayin
2014/07/22 16:22:47
Done.
|
| cursor_client_.reset(new aura::test::TestCursorClient(root_window())); |
| root_window()->AddPreTargetHandler(&event_capturer_); |
| generator_.reset(new aura::test::EventGenerator(root_window())); |
| @@ -164,7 +183,7 @@ class TouchExplorationTest : public aura::test::AuraTestBase { |
| touch_exploration_controller_.reset(); |
| } else if (on && !touch_exploration_controller_.get()) { |
| touch_exploration_controller_.reset( |
| - new ui::TouchExplorationController(root_window())); |
| + new ui::TouchExplorationController(root_window(), delegate_)); |
| touch_exploration_controller_->SetEventHandlerForTesting( |
| &event_capturer_); |
| cursor_client()->ShowCursor(); |
| @@ -207,6 +226,14 @@ class TouchExplorationTest : public aura::test::AuraTestBase { |
| ->IsInGestureInProgressStateForTesting(); |
| } |
| + bool IsInSlideGestureState() { |
| + return touch_exploration_controller_->IsInSlideGestureStateForTesting(); |
| + } |
| + |
| + gfx::Rect BoundsOfRootWindowInDIP() { |
| + return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting(); |
| + } |
| + |
| base::TimeDelta Now() { |
| // This is the same as what EventTimeForNow() does, but here we do it |
| // with our simulated clock. |
| @@ -218,6 +245,7 @@ class TouchExplorationTest : public aura::test::AuraTestBase { |
| ui::GestureDetector::Config gesture_detector_config_; |
| // Owned by |generator_|. |
| base::SimpleTestTickClock* simulated_clock_; |
| + MockTouchExplorationControllerDelegate* delegate_; |
| private: |
| EventCapturer event_capturer_; |
| @@ -460,6 +488,7 @@ TEST_F(TouchExplorationTest, TimerFiresLateDuringTouchExploration) { |
| SwitchTouchExplorationMode(true); |
| // Send a press, then add another finger after the double-tap timeout. |
| + generator_->MoveTouch(gfx::Point(100, 200)); |
| generator_->PressTouchId(1); |
| simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000)); |
| generator_->PressTouchId(2); |
| @@ -1307,10 +1336,11 @@ TEST_F(TouchExplorationTest, FromGestureToPassthrough) { |
| EXPECT_FALSE(IsInGestureInProgressState()); |
| float distance = gesture_detector_config_.touch_slop + 1; |
| - ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, gfx::Point(0, 1), 0, Now()); |
| + ui::TouchEvent first_press( |
| + ui::ET_TOUCH_PRESSED, gfx::Point(100, 200), 0, Now()); |
| generator_->Dispatch(&first_press); |
| simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| - gfx::Point second_location(distance, 1); |
| + gfx::Point second_location(100 + distance, 200); |
| generator_->MoveTouch(second_location); |
| EXPECT_TRUE(IsInGestureInProgressState()); |
| EXPECT_FALSE(IsInTouchToMouseMode()); |
| @@ -1338,4 +1368,205 @@ TEST_F(TouchExplorationTest, FromGestureToPassthrough) { |
| ASSERT_EQ(0U, captured_events.size()); |
| } |
| +TEST_F(TouchExplorationTest, EnterSlideGestureState) { |
| + SwitchTouchExplorationMode(true); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + |
| + gfx::Rect window = BoundsOfRootWindowInDIP(); |
| + float distance = gesture_detector_config_.touch_slop + 1; |
| + ui::TouchEvent first_press( |
| + ui::ET_TOUCH_PRESSED, gfx::Point(window.right(), 1), 0, Now()); |
| + gfx::Point second_location(window.right(), 1 + distance / 2); |
| + gfx::Point third_location(window.right(), 1 + distance); |
| + |
| + generator_->Dispatch(&first_press); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + // Since we haven't moved past slop yet, we should not be in slide gesture. |
| + generator_->MoveTouch(second_location); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + // Once we are out of slop, we should be in slide gesture since we are along |
| + // the edge of the screen. |
| + generator_->MoveTouch(third_location); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_TRUE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + const ScopedVector<ui::Event>& captured_events = GetCapturedEvents(); |
| + ASSERT_EQ(0U, captured_events.size()); |
| + |
| + // Since we are at the right edge of the screen, but the sound timer has not |
| + // elapsed, there should have two sounds that fired and two volume |
| + // changes (one for each movement). |
| + size_t num_adjust_sounds = delegate_->NumAdjustSounds(); |
| + ASSERT_EQ(2U, num_adjust_sounds); |
| + ASSERT_EQ(2U, delegate_->VolumeChanges().size()); |
| + |
| + // Exit out of slide gesture once touch is lifted, but not before even if the |
| + // grace period is over. |
| + |
| + AdvanceSimulatedTimePastPotentialTapDelay(); |
| + ASSERT_EQ(0U, captured_events.size()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_TRUE(IsInSlideGestureState()); |
| + |
| + generator_->ReleaseTouch(); |
| + ASSERT_EQ(0U, captured_events.size()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| +} |
| + |
| +// If a press + move occurred outside the boundaries, but within the slop |
| +// boundaries and then moved into the boundaries of an edge, there still should |
| +// not be a slide gesture. |
| +TEST_F(TouchExplorationTest, AvoidEnteringSlideGesture) { |
| + SwitchTouchExplorationMode(true); |
| + |
| + // DO SOMETHING TO MAKE THESE CONSTANTS ACCESSIBLE FROM ORIGINAL FILE |
| + const float kMaxDistanceFromEdge = 75; |
| + const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40; |
| + |
| + gfx::Rect window = BoundsOfRootWindowInDIP(); |
| + float distance = gesture_detector_config_.touch_slop + 1; |
| + ui::TouchEvent first_press( |
| + ui::ET_TOUCH_PRESSED, |
| + gfx::Point(window.right() - kSlopDistanceFromEdge, 1), |
| + 0, |
| + Now()); |
| + gfx::Point out_of_slop(window.right() - kSlopDistanceFromEdge + distance, 1); |
| + gfx::Point into_boundaries(window.right() - kMaxDistanceFromEdge / 2, 1); |
| + |
| + generator_->Dispatch(&first_press); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + generator_->MoveTouch(out_of_slop); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_TRUE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + // Since we did not start moving while in the boundaries, we should not be in |
| + // slide gestures. |
| + generator_->MoveTouch(into_boundaries); |
| + EXPECT_TRUE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + const ScopedVector<ui::Event>& captured_events = GetCapturedEvents(); |
| + ASSERT_EQ(0U, captured_events.size()); |
| + |
| + generator_->ReleaseTouch(); |
| +} |
| + |
| +// If the slide gesture begins within the boundaries and then moves |
| +// SlopDistanceFromEdge there should still be a sound change. If the finger |
| +// moves into the center screen, there should no longer be a sound change but it |
| +// should still be in slide gesture. If the finger moves back into the edges |
| +// without lifting, it should start changing sound again. |
| +TEST_F(TouchExplorationTest, TestingBoundaries) { |
| + SwitchTouchExplorationMode(true); |
| + |
| + const float kMaxDistanceFromEdge = 75; |
| + const float kSlopDistanceFromEdge = kMaxDistanceFromEdge + 40; |
| + |
| + gfx::Rect window = BoundsOfRootWindowInDIP(); |
| + gfx::Point initial_press(window.right() - kMaxDistanceFromEdge / 2, 1); |
| + ui::TouchEvent first_press( |
| + ui::ET_TOUCH_PRESSED, |
| + initial_press, |
| + 0, |
| + Now()); |
| + gfx::Point touch_move(initial_press.x() + gesture_detector_config_.touch_slop, |
| + 1); |
| + gfx::Point into_slop_boundaries(window.right() - kSlopDistanceFromEdge / 2, |
| + 1); |
| + gfx::Point center_screen(window.right() / 2, window.bottom() / 2); |
| + |
| + generator_->Dispatch(&first_press); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + generator_->MoveTouch(touch_move); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10)); |
| + |
| + // Move the touch into slop boundaries. It should stil be in slide gestures |
| + // and adjust the volume. |
| + generator_->MoveTouch(into_slop_boundaries); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_TRUE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + |
| + // The sound is rate limiting so it only activates every 150ms. |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); |
| + |
| + size_t num_adjust_sounds = delegate_->NumAdjustSounds(); |
| + ASSERT_EQ(2U, num_adjust_sounds); |
| + ASSERT_EQ(2U, delegate_->VolumeChanges().size()); |
| + |
| + // Move the touch into the center of the window. It should still be in slide |
| + // gestures, but there should not be anymore volume adjustments. |
| + generator_->MoveTouch(center_screen); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_TRUE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); |
| + num_adjust_sounds = delegate_->NumAdjustSounds(); |
| + ASSERT_EQ(2U, num_adjust_sounds); |
| + ASSERT_EQ(2U, delegate_->VolumeChanges().size()); |
| + |
| + // Move the touch back into slop edge distance and volume should be changing |
| + // again. |
| + generator_->MoveTouch(into_slop_boundaries); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_TRUE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + |
| + generator_->MoveTouch( |
| + gfx::Point(into_slop_boundaries.x() + gesture_detector_config_.touch_slop, |
| + into_slop_boundaries.y())); |
| + simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200)); |
| + |
| + num_adjust_sounds = delegate_->NumAdjustSounds(); |
| + ASSERT_EQ(3U, num_adjust_sounds); |
| + ASSERT_EQ(3U, delegate_->VolumeChanges().size()); |
| + |
| + const ScopedVector<ui::Event>& captured_events = GetCapturedEvents(); |
| + ASSERT_EQ(0U, captured_events.size()); |
| + |
| + generator_->ReleaseTouch(); |
| +} |
| + |
| +// Even if the gesture starts within bounds, if it has not moved past slop |
| +// within the grace period, it should go to touch exploration. |
| +TEST_F(TouchExplorationTest, InBoundariesTouchExploration) { |
| + SwitchTouchExplorationMode(true); |
| + |
| + const float kMaxDistanceFromEdge = 75; |
| + |
| + gfx::Rect window = BoundsOfRootWindowInDIP(); |
| + gfx::Point initial_press(window.right() - kMaxDistanceFromEdge / 2, 1); |
| + ui::TouchEvent first_press( |
| + ui::ET_TOUCH_PRESSED, |
| + initial_press, |
| + 0, |
| + Now()); |
| + generator_->Dispatch(&first_press); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + EXPECT_FALSE(IsInTouchToMouseMode()); |
| + |
| + AdvanceSimulatedTimePastTapDelay(); |
| + EXPECT_FALSE(IsInGestureInProgressState()); |
| + EXPECT_FALSE(IsInSlideGestureState()); |
| + EXPECT_TRUE(IsInTouchToMouseMode()); |
| +} |
| + |
| } // namespace ui |