| 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 70bac63e756ee6fb2fd0954e6db0c243400f5534..b00814b1eb6efc7f6d197292016f8956e693d1a7 100644
|
| --- a/ui/chromeos/touch_exploration_controller_unittest.cc
|
| +++ b/ui/chromeos/touch_exploration_controller_unittest.cc
|
| @@ -72,6 +72,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 TouchExplorationControllerTestApi {
|
| @@ -110,12 +128,29 @@ class TouchExplorationControllerTestApi {
|
| touch_exploration_controller_->GESTURE_IN_PROGRESS;
|
| }
|
|
|
| + bool IsInSlideGestureStateForTesting() const {
|
| + return touch_exploration_controller_->state_ ==
|
| + touch_exploration_controller_->SLIDE_GESTURE;
|
| + }
|
| +
|
| + gfx::Rect BoundsOfRootWindowInDIPForTesting() const {
|
| + return touch_exploration_controller_->root_window_->GetBoundsInScreen();
|
| + }
|
| +
|
| // VLOGs should be suppressed in tests that generate a lot of logs,
|
| // for example permutations of nine touch events.
|
| void SuppressVLOGsForTesting(bool suppress) {
|
| touch_exploration_controller_->VLOG_on_ = !suppress;
|
| }
|
|
|
| + float GetMaxDistanceFromEdge() const {
|
| + return touch_exploration_controller_->kMaxDistanceFromEdge;
|
| + }
|
| +
|
| + float GetSlopDistanceFromEdge() const {
|
| + return touch_exploration_controller_->kSlopDistanceFromEdge;
|
| + }
|
| +
|
| private:
|
| scoped_ptr<TouchExplorationController> touch_exploration_controller_;
|
|
|
| @@ -212,8 +247,9 @@ class TouchExplorationTest : public aura::test::AuraTestBase {
|
| if (!on && touch_exploration_controller_.get()) {
|
| touch_exploration_controller_.reset();
|
| } else if (on && !touch_exploration_controller_.get()) {
|
| - touch_exploration_controller_.reset(new TouchExplorationControllerTestApi(
|
| - new ui::TouchExplorationController(root_window())));
|
| + touch_exploration_controller_.reset(
|
| + new ui::TouchExplorationControllerTestApi(
|
| + new TouchExplorationController(root_window(), &delegate_)));
|
| touch_exploration_controller_->SetEventHandlerForTesting(
|
| &event_capturer_);
|
| cursor_client()->ShowCursor();
|
| @@ -256,6 +292,22 @@ class TouchExplorationTest : public aura::test::AuraTestBase {
|
| ->IsInGestureInProgressStateForTesting();
|
| }
|
|
|
| + bool IsInSlideGestureState() {
|
| + return touch_exploration_controller_->IsInSlideGestureStateForTesting();
|
| + }
|
| +
|
| + gfx::Rect BoundsOfRootWindowInDIP() {
|
| + return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting();
|
| + }
|
| +
|
| + float GetMaxDistanceFromEdge() const{
|
| + return touch_exploration_controller_->GetMaxDistanceFromEdge();
|
| + }
|
| +
|
| + float GetSlopDistanceFromEdge() const{
|
| + return touch_exploration_controller_->GetSlopDistanceFromEdge();
|
| + }
|
| +
|
| base::TimeDelta Now() {
|
| // This is the same as what EventTimeForNow() does, but here we do it
|
| // with our simulated clock.
|
| @@ -267,6 +319,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_;
|
| @@ -509,6 +562,9 @@ TEST_F(TouchExplorationTest, TurnOnMidTouch) {
|
| TEST_F(TouchExplorationTest, TimerFiresLateDuringTouchExploration) {
|
| SwitchTouchExplorationMode(true);
|
|
|
| + // Make sure the touch is not in a corner of the screen.
|
| + generator_->MoveTouch(gfx::Point(100, 200));
|
| +
|
| // Send a press, then add another finger after the double-tap timeout.
|
| generator_->PressTouchId(1);
|
| simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
|
| @@ -1357,10 +1413,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());
|
| @@ -1388,4 +1445,193 @@ TEST_F(TouchExplorationTest, FromGestureToPassthrough) {
|
| ASSERT_EQ(0U, captured_events.size());
|
| }
|
|
|
| +TEST_F(TouchExplorationTest, EnterSlideGestureState) {
|
| + SwitchTouchExplorationMode(true);
|
| + EXPECT_FALSE(IsInTouchToMouseMode());
|
| + EXPECT_FALSE(IsInGestureInProgressState());
|
| +
|
| + int window_right = BoundsOfRootWindowInDIP().right();
|
| + 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);
|
| +
|
| + gfx::Rect window = BoundsOfRootWindowInDIP();
|
| + float distance = gesture_detector_config_.touch_slop + 1;
|
| + ui::TouchEvent first_press(
|
| + ui::ET_TOUCH_PRESSED,
|
| + gfx::Point(window.right() - GetSlopDistanceFromEdge(), 1),
|
| + 0,
|
| + Now());
|
| + gfx::Point out_of_slop(window.right() - GetSlopDistanceFromEdge() + distance,
|
| + 1);
|
| + gfx::Point into_boundaries(window.right() - GetMaxDistanceFromEdge() / 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);
|
| +
|
| + gfx::Rect window = BoundsOfRootWindowInDIP();
|
| + gfx::Point initial_press(window.right() - GetMaxDistanceFromEdge() / 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() - GetSlopDistanceFromEdge() / 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);
|
| +
|
| + gfx::Rect window = BoundsOfRootWindowInDIP();
|
| + gfx::Point initial_press(window.right() - GetMaxDistanceFromEdge() / 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
|
|
|