| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/accessibility/touch_accessibility_enabler.h" |
| |
| #include "ash/accessibility/touch_exploration_controller.h" |
| #include "base/macros.h" |
| #include "base/test/simple_test_tick_clock.h" |
| #include "base/time/time.h" |
| #include "ui/aura/test/aura_test_base.h" |
| #include "ui/aura/window.h" |
| #include "ui/events/event.h" |
| #include "ui/events/event_utils.h" |
| #include "ui/events/gestures/gesture_provider_aura.h" |
| #include "ui/events/test/event_generator.h" |
| #include "ui/events/test/events_test_utils.h" |
| #include "ui/gfx/geometry/point.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| class MockTouchAccessibilityEnablerDelegate |
| : public TouchAccessibilityEnablerDelegate { |
| public: |
| MockTouchAccessibilityEnablerDelegate() {} |
| ~MockTouchAccessibilityEnablerDelegate() override {} |
| |
| void OnTwoFingerTouchStart() override { started_ = true; } |
| |
| void OnTwoFingerTouchStop() override { stopped_ = true; } |
| |
| void PlaySpokenFeedbackToggleCountdown(int tick_count) override { |
| ++feedback_progress_sound_count_; |
| } |
| void ToggleSpokenFeedback() override { toggle_spoken_feedback_ = true; } |
| |
| bool started() { return started_; } |
| bool stopped() { return stopped_; } |
| size_t feedback_progress_sound_count() const { |
| return feedback_progress_sound_count_; |
| } |
| bool toggle_spoken_feedback() const { return toggle_spoken_feedback_; } |
| |
| private: |
| bool started_ = false; |
| bool stopped_ = false; |
| size_t feedback_progress_sound_count_ = 0; |
| bool toggle_spoken_feedback_ = false; |
| |
| DISALLOW_COPY_AND_ASSIGN(MockTouchAccessibilityEnablerDelegate); |
| }; |
| |
| class TouchAccessibilityEnablerTest : public aura::test::AuraTestBase { |
| public: |
| TouchAccessibilityEnablerTest() {} |
| ~TouchAccessibilityEnablerTest() override {} |
| |
| void SetUp() override { |
| aura::test::AuraTestBase::SetUp(); |
| |
| generator_.reset(new ui::test::EventGenerator(root_window())); |
| |
| // Tests fail if time is ever 0. |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(10)); |
| ui::SetEventTickClockForTesting(&simulated_clock_); |
| |
| enabler_.reset(new TouchAccessibilityEnabler(root_window(), &delegate_)); |
| } |
| |
| void TearDown() override { |
| enabler_.reset(nullptr); |
| ui::SetEventTickClockForTesting(nullptr); |
| aura::test::AuraTestBase::TearDown(); |
| } |
| |
| protected: |
| base::TimeTicks Now() { |
| // This is the same as what EventTimeForNow() does, but here we do it |
| // with our simulated clock. |
| return simulated_clock_.NowTicks(); |
| } |
| |
| std::unique_ptr<ui::test::EventGenerator> generator_; |
| base::SimpleTestTickClock simulated_clock_; |
| MockTouchAccessibilityEnablerDelegate delegate_; |
| std::unique_ptr<TouchAccessibilityEnabler> enabler_; |
| ui::GestureDetector::Config gesture_detector_config_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TouchAccessibilityEnablerTest); |
| }; |
| |
| } // namespace |
| |
| TEST_F(TouchAccessibilityEnablerTest, InteractsWithTouchExplorationController) { |
| // This test ensures that if TouchExplorationController starts and stops, |
| // TouchAccessibilityEnabler continues to work correctly. Because |
| // TouchExplorationController rewrites most touch events, it can screw up |
| // TouchAccessibilityEnabler if they don't explicitly coordinate. |
| |
| std::unique_ptr<TouchExplorationController> controller( |
| new TouchExplorationController(root_window(), nullptr, |
| enabler_->GetWeakPtr())); |
| |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouchId(1); |
| |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(500)); |
| |
| generator_->set_current_location(gfx::Point(22, 34)); |
| generator_->PressTouchId(2); |
| |
| EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting()); |
| |
| controller.reset(); |
| |
| generator_->ReleaseTouchId(1); |
| generator_->ReleaseTouchId(2); |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, EntersOneFingerDownMode) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| EXPECT_FALSE(enabler_->IsInOneFingerDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouch(); |
| |
| EXPECT_FALSE(enabler_->IsInNoFingersDownForTesting()); |
| EXPECT_TRUE(enabler_->IsInOneFingerDownForTesting()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, EntersTwoFingersDownMode) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouchId(1); |
| |
| generator_->set_current_location(gfx::Point(22, 34)); |
| generator_->PressTouchId(2); |
| |
| EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, PlaysProgressSound) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouchId(1); |
| |
| generator_->set_current_location(gfx::Point(22, 34)); |
| generator_->PressTouchId(2); |
| |
| EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting()); |
| EXPECT_EQ(0U, delegate_.feedback_progress_sound_count()); |
| |
| enabler_->TriggerOnTimerForTesting(); |
| EXPECT_EQ(0U, delegate_.feedback_progress_sound_count()); |
| |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(3000)); |
| enabler_->TriggerOnTimerForTesting(); |
| EXPECT_EQ(1U, delegate_.feedback_progress_sound_count()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, TogglesSpokenFeedback) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouchId(1); |
| |
| generator_->set_current_location(gfx::Point(22, 34)); |
| generator_->PressTouchId(2); |
| |
| EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting()); |
| EXPECT_FALSE(delegate_.toggle_spoken_feedback()); |
| EXPECT_TRUE(delegate_.started()); |
| EXPECT_FALSE(delegate_.stopped()); |
| |
| enabler_->TriggerOnTimerForTesting(); |
| EXPECT_FALSE(delegate_.toggle_spoken_feedback()); |
| |
| simulated_clock_.Advance(base::TimeDelta::FromMilliseconds(5000)); |
| enabler_->TriggerOnTimerForTesting(); |
| EXPECT_TRUE(delegate_.toggle_spoken_feedback()); |
| EXPECT_TRUE(delegate_.started()); |
| EXPECT_FALSE(delegate_.stopped()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, ThreeFingersCancelsDetection) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouchId(1); |
| |
| generator_->set_current_location(gfx::Point(22, 34)); |
| generator_->PressTouchId(2); |
| |
| EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting()); |
| EXPECT_TRUE(delegate_.started()); |
| EXPECT_FALSE(delegate_.stopped()); |
| |
| generator_->set_current_location(gfx::Point(33, 56)); |
| generator_->PressTouchId(3); |
| |
| EXPECT_TRUE(enabler_->IsInWaitForNoFingersForTesting()); |
| EXPECT_TRUE(delegate_.started()); |
| EXPECT_TRUE(delegate_.stopped()); |
| } |
| |
| TEST_F(TouchAccessibilityEnablerTest, MovingFingerPastSlopCancelsDetection) { |
| EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting()); |
| generator_->set_current_location(gfx::Point(11, 12)); |
| generator_->PressTouch(); |
| |
| int slop = gesture_detector_config_.double_tap_slop; |
| int half_slop = slop / 2; |
| |
| generator_->MoveTouch(gfx::Point(11 + half_slop, 12)); |
| EXPECT_TRUE(enabler_->IsInOneFingerDownForTesting()); |
| |
| generator_->MoveTouch(gfx::Point(11 + slop + 1, 12)); |
| EXPECT_TRUE(enabler_->IsInWaitForNoFingersForTesting()); |
| } |
| |
| } // namespace ash |