blob: 71e5bfc1d74d2635c087c52aaf1b46ff8684da23 [file] [log] [blame]
dmazzoni16d2dec2016-12-19 23:27:571// Copyright 2016 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/chromeos/touch_accessibility_enabler.h"
6
7#include "base/macros.h"
8#include "base/test/simple_test_tick_clock.h"
9#include "base/time/time.h"
10#include "ui/aura/test/aura_test_base.h"
11#include "ui/aura/window.h"
Dominic Mazzoni51c65f22017-08-22 19:36:0612#include "ui/chromeos/touch_exploration_controller.h"
dmazzoni16d2dec2016-12-19 23:27:5713#include "ui/events/event.h"
14#include "ui/events/event_utils.h"
15#include "ui/events/gestures/gesture_provider_aura.h"
16#include "ui/events/test/event_generator.h"
17#include "ui/events/test/events_test_utils.h"
18#include "ui/gfx/geometry/point.h"
19
20namespace ui {
21
22namespace {
23
24class MockTouchAccessibilityEnablerDelegate
25 : public ui::TouchAccessibilityEnablerDelegate {
26 public:
27 MockTouchAccessibilityEnablerDelegate() {}
28 ~MockTouchAccessibilityEnablerDelegate() override {}
29
dmazzonidf9a1e922017-04-13 05:10:4430 void OnTwoFingerTouchStart() override { started_ = true; }
31
32 void OnTwoFingerTouchStop() override { stopped_ = true; }
33
dmazzoni16d2dec2016-12-19 23:27:5734 void PlaySpokenFeedbackToggleCountdown(int tick_count) override {
35 ++feedback_progress_sound_count_;
36 }
37 void ToggleSpokenFeedback() override { toggle_spoken_feedback_ = true; }
38
dmazzonidf9a1e922017-04-13 05:10:4439 bool started() { return started_; }
40 bool stopped() { return stopped_; }
dmazzoni16d2dec2016-12-19 23:27:5741 size_t feedback_progress_sound_count() const {
42 return feedback_progress_sound_count_;
43 }
44 bool toggle_spoken_feedback() const { return toggle_spoken_feedback_; }
45
46 private:
dmazzonidf9a1e922017-04-13 05:10:4447 bool started_ = false;
48 bool stopped_ = false;
dmazzoni16d2dec2016-12-19 23:27:5749 size_t feedback_progress_sound_count_ = 0;
50 bool toggle_spoken_feedback_ = false;
51
52 DISALLOW_COPY_AND_ASSIGN(MockTouchAccessibilityEnablerDelegate);
53};
54
55class TouchAccessibilityEnablerTest : public aura::test::AuraTestBase {
56 public:
57 TouchAccessibilityEnablerTest() {}
58 ~TouchAccessibilityEnablerTest() override {}
59
60 void SetUp() override {
61 aura::test::AuraTestBase::SetUp();
62
63 generator_.reset(new test::EventGenerator(root_window()));
64
65 simulated_clock_ = new base::SimpleTestTickClock();
66 // Tests fail if time is ever 0.
67 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
68 // ui takes ownership of the tick clock.
69 ui::SetEventTickClockForTesting(
70 std::unique_ptr<base::TickClock>(simulated_clock_));
71
72 enabler_.reset(new TouchAccessibilityEnabler(root_window(), &delegate_));
73 }
74
75 void TearDown() override {
76 enabler_.reset(nullptr);
77 ui::SetEventTickClockForTesting(nullptr);
78 aura::test::AuraTestBase::TearDown();
79 }
80
81 protected:
82 base::TimeTicks Now() {
83 // This is the same as what EventTimeForNow() does, but here we do it
84 // with our simulated clock.
85 return simulated_clock_->NowTicks();
86 }
87
88 std::unique_ptr<test::EventGenerator> generator_;
89 // Owned by |ui|.
90 base::SimpleTestTickClock* simulated_clock_ = nullptr;
91 MockTouchAccessibilityEnablerDelegate delegate_;
92 std::unique_ptr<TouchAccessibilityEnabler> enabler_;
93 ui::GestureDetector::Config gesture_detector_config_;
94
95 DISALLOW_COPY_AND_ASSIGN(TouchAccessibilityEnablerTest);
96};
97
98} // namespace
99
Dominic Mazzoni51c65f22017-08-22 19:36:06100TEST_F(TouchAccessibilityEnablerTest, InteractsWithTouchExplorationController) {
101 // This test ensures that if TouchExplorationController starts and stops,
102 // TouchAccessibilityEnabler continues to work correctly. Because
103 // TouchExplorationController rewrites most touch events, it can screw up
104 // TouchAccessibilityEnabler if they don't explicitly coordinate.
105
106 std::unique_ptr<TouchExplorationController> controller(
107 new TouchExplorationController(root_window(), nullptr,
108 enabler_->GetWeakPtr()));
109
110 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
111 generator_->set_current_location(gfx::Point(11, 12));
112 generator_->PressTouchId(1);
113
114 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(500));
115
116 generator_->set_current_location(gfx::Point(22, 34));
117 generator_->PressTouchId(2);
118
119 EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
120
121 controller.reset();
122
123 generator_->ReleaseTouchId(1);
124 generator_->ReleaseTouchId(2);
125 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
126}
127
dmazzoni16d2dec2016-12-19 23:27:57128TEST_F(TouchAccessibilityEnablerTest, EntersOneFingerDownMode) {
129 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
130 EXPECT_FALSE(enabler_->IsInOneFingerDownForTesting());
131 generator_->set_current_location(gfx::Point(11, 12));
132 generator_->PressTouch();
133
134 EXPECT_FALSE(enabler_->IsInNoFingersDownForTesting());
135 EXPECT_TRUE(enabler_->IsInOneFingerDownForTesting());
136}
137
138TEST_F(TouchAccessibilityEnablerTest, EntersTwoFingersDownMode) {
139 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
140 generator_->set_current_location(gfx::Point(11, 12));
141 generator_->PressTouchId(1);
142
143 generator_->set_current_location(gfx::Point(22, 34));
144 generator_->PressTouchId(2);
145
146 EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
147}
148
149TEST_F(TouchAccessibilityEnablerTest, PlaysProgressSound) {
150 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
151 generator_->set_current_location(gfx::Point(11, 12));
152 generator_->PressTouchId(1);
153
154 generator_->set_current_location(gfx::Point(22, 34));
155 generator_->PressTouchId(2);
156
157 EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
158 EXPECT_EQ(0U, delegate_.feedback_progress_sound_count());
159
160 enabler_->TriggerOnTimerForTesting();
161 EXPECT_EQ(0U, delegate_.feedback_progress_sound_count());
162
163 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(3000));
164 enabler_->TriggerOnTimerForTesting();
165 EXPECT_EQ(1U, delegate_.feedback_progress_sound_count());
166}
167
168TEST_F(TouchAccessibilityEnablerTest, TogglesSpokenFeedback) {
169 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
170 generator_->set_current_location(gfx::Point(11, 12));
171 generator_->PressTouchId(1);
172
173 generator_->set_current_location(gfx::Point(22, 34));
174 generator_->PressTouchId(2);
175
176 EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
177 EXPECT_FALSE(delegate_.toggle_spoken_feedback());
dmazzonidf9a1e922017-04-13 05:10:44178 EXPECT_TRUE(delegate_.started());
179 EXPECT_FALSE(delegate_.stopped());
dmazzoni16d2dec2016-12-19 23:27:57180
181 enabler_->TriggerOnTimerForTesting();
182 EXPECT_FALSE(delegate_.toggle_spoken_feedback());
183
184 simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(5000));
185 enabler_->TriggerOnTimerForTesting();
186 EXPECT_TRUE(delegate_.toggle_spoken_feedback());
dmazzonidf9a1e922017-04-13 05:10:44187 EXPECT_TRUE(delegate_.started());
188 EXPECT_FALSE(delegate_.stopped());
dmazzoni16d2dec2016-12-19 23:27:57189}
190
191TEST_F(TouchAccessibilityEnablerTest, ThreeFingersCancelsDetection) {
192 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
193 generator_->set_current_location(gfx::Point(11, 12));
194 generator_->PressTouchId(1);
195
196 generator_->set_current_location(gfx::Point(22, 34));
197 generator_->PressTouchId(2);
198
199 EXPECT_TRUE(enabler_->IsInTwoFingersDownForTesting());
dmazzonidf9a1e922017-04-13 05:10:44200 EXPECT_TRUE(delegate_.started());
201 EXPECT_FALSE(delegate_.stopped());
dmazzoni16d2dec2016-12-19 23:27:57202
203 generator_->set_current_location(gfx::Point(33, 56));
204 generator_->PressTouchId(3);
205
206 EXPECT_TRUE(enabler_->IsInWaitForNoFingersForTesting());
dmazzonidf9a1e922017-04-13 05:10:44207 EXPECT_TRUE(delegate_.started());
208 EXPECT_TRUE(delegate_.stopped());
dmazzoni16d2dec2016-12-19 23:27:57209}
210
211TEST_F(TouchAccessibilityEnablerTest, MovingFingerPastSlopCancelsDetection) {
212 EXPECT_TRUE(enabler_->IsInNoFingersDownForTesting());
213 generator_->set_current_location(gfx::Point(11, 12));
214 generator_->PressTouch();
215
216 int slop = gesture_detector_config_.double_tap_slop;
217 int half_slop = slop / 2;
218
219 generator_->MoveTouch(gfx::Point(11 + half_slop, 12));
220 EXPECT_TRUE(enabler_->IsInOneFingerDownForTesting());
221
222 generator_->MoveTouch(gfx::Point(11 + slop + 1, 12));
223 EXPECT_TRUE(enabler_->IsInWaitForNoFingersForTesting());
224}
225
226} // namespace ui