Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(111)

Side by Side Diff: chrome/browser/chromeos/accessibility/touch_exploration_controller_unittest.cc

Issue 240333007: wip: Second crack at implementing the touch exploration mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding a flag to disable the touch exploration mode. Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2014 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_exploration_controller.h"
6
7 #include "ash/accessibility_delegate.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/test/root_window_controller_test_api_chromeos.h"
12 #include "base/time/time.h"
13 #include "ui/aura/test/event_generator.h"
14 #include "ui/events/event.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/gfx/geometry/point.h"
17
18 namespace ui {
19
20 // Records all mouse and touch events.
21 class EventCapturer : public ui::EventHandler {
22 public:
23 EventCapturer() { Reset(); }
24 virtual ~EventCapturer() {
25 Reset();
26 }
27
28 void Reset() {
29 std::vector<ui::LocatedEvent*>::iterator it;
30 for (it = events_.begin(); it != events_.end(); ++it) {
31 delete *it;
32 }
33 events_.clear();
34 }
35
36 virtual void OnEvent(ui::Event* event) OVERRIDE {
37 ui::LocatedEvent* event_copy;
38 if (event->IsMouseEvent())
39 event_copy = new ui::MouseEvent(static_cast<ui::MouseEvent&>(*event));
40 else if (event->IsTouchEvent())
41 event_copy = new ui::TouchEvent(static_cast<ui::TouchEvent&>(*event));
42 else
43 return;
44 events_.push_back(event_copy);
45 // Stop event propagation so we don't click on random stuff that
46 // might break test assumptions.
47 event->StopPropagation();
48 // If there is a possibility that we're in an infinite loop, we should
49 // exit early with a sensible error rather than letting the test time out.
50 ASSERT_LT(events_.size(), 100u);
51 }
52 const std::vector<ui::LocatedEvent*>& captured_events() const {
53 return events_;
54 }
55
56 private:
57 std::vector<ui::LocatedEvent*> events_;
58
59 DISALLOW_COPY_AND_ASSIGN(EventCapturer);
60 };
61
62 class TouchExplorationTest : public ash::test::AshTestBase {
63 public:
64 TouchExplorationTest() : root_window_(NULL) {}
65 virtual ~TouchExplorationTest() {}
66
67 virtual void SetUp() OVERRIDE {
68 ash::test::AshTestBase::SetUp();
69 root_window_ = ash::Shell::GetInstance()->GetPrimaryRootWindow();
70 ash::Shell::GetInstance()->AddPreTargetHandler(&event_capturer_);
71 }
72
73 virtual void TearDown() OVERRIDE {
74 ash::Shell::GetInstance()->RemovePreTargetHandler(&event_capturer_);
75 SwitchTouchExplorationMode(false);
76 ash::test::AshTestBase::TearDown();
77 }
78
79 const std::vector<ui::LocatedEvent*>& GetCapturedEvents() {
80 return event_capturer_.captured_events();
81 }
82
83 void ClearCapturedEvents() {
84 event_capturer_.Reset();
85 }
86
87 protected:
88 aura::Window* root_window() {return root_window_;}
89
90 void SwitchTouchExplorationMode(bool on) {
91 ash::AccessibilityDelegate* ad =
92 ash::Shell::GetInstance()->accessibility_delegate();
93 if (on != ad->IsSpokenFeedbackEnabled())
94 ad->ToggleSpokenFeedback(ash::A11Y_NOTIFICATION_NONE);
95 ash::test::RootWindowControllerTestApi root_window_controller_test_api(
96 ash::Shell::GetPrimaryRootWindowController());
97 root_window_controller_test_api.UpdateTouchExplorationState();
98 EXPECT_EQ(on, ad->IsSpokenFeedbackEnabled());
99 }
100
101 bool IsMouseCursorVisible() {
102 aura::client::CursorClient* cursor_client =
103 aura::client::GetCursorClient(root_window_);
104 return cursor_client && cursor_client->IsCursorVisible();
105 }
106
107 bool IsInTouchToMouseMode() {
108 aura::client::CursorClient* cursor_client =
109 aura::client::GetCursorClient(root_window_);
110 return cursor_client &&
111 cursor_client->IsMouseEventsEnabled() &&
112 !cursor_client->IsCursorVisible();
113 }
114
115 private:
116 aura::Window* root_window_;
117 EventCapturer event_capturer_;
118
119 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
120 };
121
122 // Executes a number of assertions to confirm that |e1| and |e2| are touch
123 // events and are equal to each other.
124 void ConfirmEventsAreTouchAndEqual(ui::Event* e1, ui::Event* e2) {
125 EXPECT_TRUE(e1->IsTouchEvent());
126 EXPECT_TRUE(e2->IsTouchEvent());
127 ui::TouchEvent* touch_event1 = static_cast<ui::TouchEvent*>(e1);
128 ui::TouchEvent* touch_event2 = static_cast<ui::TouchEvent*>(e2);
129 EXPECT_EQ(touch_event1->type(), touch_event2->type());
130 EXPECT_EQ(touch_event1->location(), touch_event2->location());
131 EXPECT_EQ(touch_event1->touch_id(), touch_event2->touch_id());
132 EXPECT_EQ(touch_event1->flags(), touch_event2->flags());
133 EXPECT_EQ(touch_event1->time_stamp(), touch_event2->time_stamp());
134 }
135
136 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
137 // events and are equal to each other.
138 void ConfirmEventsAreMouseAndEqual(ui::Event* e1, ui::Event* e2) {
139 EXPECT_TRUE(e1->IsMouseEvent());
140 EXPECT_TRUE(e2->IsMouseEvent());
141 ui::MouseEvent* mouse_event1 = static_cast<ui::MouseEvent*>(e1);
142 ui::MouseEvent* mouse_event2 = static_cast<ui::MouseEvent*>(e2);
143 EXPECT_EQ(mouse_event1->type(), mouse_event2->type());
144 EXPECT_EQ(mouse_event1->location(), mouse_event2->location());
145 EXPECT_EQ(mouse_event1->root_location(), mouse_event2->root_location());
146 EXPECT_EQ(mouse_event1->flags(), mouse_event2->flags());
147 }
148
149 // Simple test to confirm one-finger touches are transformed into mouse moves.
150 TEST_F(TouchExplorationTest, OneFingerTouch) {
151 SwitchTouchExplorationMode(true);
152 gfx::Point location_start = GetEventGenerator().current_location();
153 gfx::Point location_end(11, 12);
154 gfx::Point location_mouse_move(13, 14);
155 GetEventGenerator().PressTouch();
156 EXPECT_TRUE(IsInTouchToMouseMode());
157 GetEventGenerator().MoveTouch(location_end);
158 // Confirm the actual mouse moves are unaffected.
159 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
160 gfx::Point(13, 14),
161 gfx::Point(13, 14),
162 0,
163 0);
164 GetEventGenerator().Dispatch(&mouse_move);
165 EXPECT_TRUE(IsMouseCursorVisible());
166 GetEventGenerator().ReleaseTouch();
167
168 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
169 std::vector<ui::LocatedEvent*>::const_iterator it;
170 int num_mouse_moves = 0;
171 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
172 int type = (*it)->type();
173 // Ignore enter and exit mouse events synthesized when the mouse cursor is
174 // shown or hidden.
175 if (type == ui::ET_MOUSE_ENTERED || type == ui::ET_MOUSE_EXITED)
176 continue;
177 EXPECT_EQ((*it)->type(), ui::ET_MOUSE_MOVED);
178 if (num_mouse_moves == 0)
179 EXPECT_EQ((*it)->location(), location_start);
180 if (num_mouse_moves == 1 || num_mouse_moves == 3)
181 EXPECT_EQ((*it)->location(), location_end);
182 if (num_mouse_moves == 2)
183 ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
184 if (num_mouse_moves != 2) {
185 EXPECT_TRUE((*it)->flags() & ui::EF_IS_SYNTHESIZED);
186 EXPECT_TRUE((*it)->flags() & ui::EF_FROM_TOUCH);
187 }
188 num_mouse_moves++;
189 }
190 EXPECT_EQ(num_mouse_moves, 4);
191 }
192
193 // Turn the touch exploration mode on in the middle of the touch gesture.
194 // Confirm that events from the finger which was touching when the mode was
195 // turned on don't get rewritten.
196 TEST_F(TouchExplorationTest, TurnOnMidTouch) {
197 SwitchTouchExplorationMode(false);
198 GetEventGenerator().PressTouchId(1);
199 EXPECT_FALSE(IsInTouchToMouseMode());
200 ClearCapturedEvents();
201
202 // Enable touch exploration mode while the first finger is touching the
203 // screen. Ensure that subsequent events from that first finger are not
204 // affected by the touch exploration mode, while the touch events from another
205 // finger get rewritten.
206 SwitchTouchExplorationMode(true);
207 ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
208 gfx::Point(11, 12),
209 1,
210 ui::EventTimeForNow());
211 GetEventGenerator().Dispatch(&touch_move);
212 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
213 EXPECT_EQ(captured_events.size(), 1u);
214 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
215 ClearCapturedEvents();
216
217 // The press from the second finger should get rewritten.
218 GetEventGenerator().PressTouchId(2);
219 EXPECT_TRUE(IsInTouchToMouseMode());
220 captured_events = GetCapturedEvents();
221 std::vector<ui::LocatedEvent*>::const_iterator it;
222 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
223 if ((*it)->type() == ui::ET_MOUSE_MOVED)
224 break;
225 }
226 EXPECT_FALSE(it == captured_events.end());
227 ClearCapturedEvents();
228
229 // The release of the first finger shouldn't be affected.
230 ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
231 gfx::Point(11, 12),
232 1,
233 ui::EventTimeForNow());
234 GetEventGenerator().Dispatch(&touch_release);
235 captured_events = GetCapturedEvents();
236 EXPECT_EQ(captured_events.size(), 1u);
237 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
238 ClearCapturedEvents();
239
240 // The move and release from the second finger should get rewritten.
241 GetEventGenerator().MoveTouchId(gfx::Point(13, 14), 2);
242 GetEventGenerator().ReleaseTouchId(2);
243 captured_events = GetCapturedEvents();
244 EXPECT_EQ(captured_events.size(), 2u);
245 EXPECT_EQ(captured_events[0]->type(), ui::ET_MOUSE_MOVED);
246 EXPECT_EQ(captured_events[1]->type(), ui::ET_MOUSE_MOVED);
247 }
248
249 TEST_F(TouchExplorationTest, TwoFingerTouch) {
250 SwitchTouchExplorationMode(true);
251 GetEventGenerator().PressTouchId(1);
252 ClearCapturedEvents();
253
254 // Confirm events from the second finger go through as is.
255 ui::TouchEvent touch_press(ui::ET_TOUCH_PRESSED,
256 gfx::Point(10, 11),
257 2,
258 ui::EventTimeForNow());
259 GetEventGenerator().Dispatch(&touch_press);
260 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
261 // There will be a ET_MOUSE_EXITED event synthesized when the mouse cursor is
262 // hidden - ignore it.
263 std::vector<ui::LocatedEvent*>::const_iterator it;
264 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
265 if ((*it)->type() == ui::ET_TOUCH_PRESSED) {
266 ConfirmEventsAreTouchAndEqual(*it, &touch_press);
267 break;
268 }
269 }
270 EXPECT_FALSE(it == captured_events.end());
271 ClearCapturedEvents();
272 ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
273 gfx::Point(20, 21),
274 2,
275 ui::EventTimeForNow());
276 ui::TouchEvent touch_stationary(ui::ET_TOUCH_STATIONARY,
277 gfx::Point(20, 21),
278 2,
279 ui::EventTimeForNow());
280 GetEventGenerator().Dispatch(&touch_move);
281 GetEventGenerator().Dispatch(&touch_stationary);
282 captured_events = GetCapturedEvents();
283 EXPECT_EQ(captured_events.size(), 2u);
284 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_move);
285 ConfirmEventsAreTouchAndEqual(captured_events[1], &touch_stationary);
286 ClearCapturedEvents();
287
288 // Confirm mouse moves go through unaffected.
289 ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
290 gfx::Point(13, 14),
291 gfx::Point(13, 14),
292 0,
293 0);
294 GetEventGenerator().Dispatch(&mouse_move);
295 EXPECT_TRUE(IsMouseCursorVisible());
296 captured_events = GetCapturedEvents();
297 // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
298 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
299 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
300 ConfirmEventsAreMouseAndEqual(*it, &mouse_move);
301 break;
302 }
303 }
304 EXPECT_FALSE(it == captured_events.end());
305 ClearCapturedEvents();
306
307 // Have some other fingers touch/move/release
308 GetEventGenerator().PressTouchId(3);
309 EXPECT_FALSE(IsMouseCursorVisible());
310 GetEventGenerator().PressTouchId(4);
311 GetEventGenerator().MoveTouchId(gfx::Point(30, 31), 3);
312 GetEventGenerator().StationaryTouchId(4);
313 GetEventGenerator().ReleaseTouchId(3);
314 GetEventGenerator().ReleaseTouchId(4);
315 ClearCapturedEvents();
316
317 // Events from the first finger should not go through while the second finger
318 // is touching.
319 gfx::Point touch1_location = gfx::Point(15, 16);
320 GetEventGenerator().MoveTouchId(touch1_location, 1);
321 GetEventGenerator().StationaryTouchId(1);
322 EXPECT_EQ(GetCapturedEvents().size(), 0u);
323
324 // A release of the second finger should go through, plus there should be a
325 // mouse move at |touch1_location| generated.
326 ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
327 gfx::Point(25, 26),
328 2,
329 ui::EventTimeForNow());
330 GetEventGenerator().Dispatch(&touch_release);
331 captured_events = GetCapturedEvents();
332 EXPECT_GE(captured_events.size(), 2u);
333 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch_release);
334 // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
335 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
336 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
337 EXPECT_EQ((*it)->location(), touch1_location);
338 break;
339 }
340 }
341 EXPECT_FALSE(it == captured_events.end());
342 }
343
344 TEST_F(TouchExplorationTest, MultiFingerTouch) {
345 SwitchTouchExplorationMode(true);
346 GetEventGenerator().PressTouchId(1);
347 GetEventGenerator().PressTouchId(2);
348 ClearCapturedEvents();
349
350 // Confirm events from other fingers go through as is.
351 ui::TouchEvent touch3_press(ui::ET_TOUCH_PRESSED,
352 gfx::Point(10, 11),
353 3,
354 ui::EventTimeForNow());
355 ui::TouchEvent touch3_move1(ui::ET_TOUCH_MOVED,
356 gfx::Point(12, 13),
357 3,
358 ui::EventTimeForNow());
359 ui::TouchEvent touch4_press(ui::ET_TOUCH_PRESSED,
360 gfx::Point(20, 21),
361 4,
362 ui::EventTimeForNow());
363 ui::TouchEvent touch3_move2(ui::ET_TOUCH_MOVED,
364 gfx::Point(14, 15),
365 3,
366 ui::EventTimeForNow());
367 ui::TouchEvent touch4_move(ui::ET_TOUCH_MOVED,
368 gfx::Point(22, 23),
369 4,
370 ui::EventTimeForNow());
371 ui::TouchEvent touch3_release(ui::ET_TOUCH_RELEASED,
372 gfx::Point(14, 15),
373 3,
374 ui::EventTimeForNow());
375 ui::TouchEvent touch4_release(ui::ET_TOUCH_RELEASED,
376 gfx::Point(22, 23),
377 4,
378 ui::EventTimeForNow());
379 GetEventGenerator().Dispatch(&touch3_press);
380 GetEventGenerator().Dispatch(&touch3_move1);
381 GetEventGenerator().Dispatch(&touch4_press);
382 GetEventGenerator().Dispatch(&touch3_move2);
383 GetEventGenerator().Dispatch(&touch4_move);
384 GetEventGenerator().Dispatch(&touch3_release);
385 GetEventGenerator().Dispatch(&touch4_release);
386
387 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
388 EXPECT_EQ(captured_events.size(), 7u);
389 ConfirmEventsAreTouchAndEqual(captured_events[0], &touch3_press);
390 ConfirmEventsAreTouchAndEqual(captured_events[1], &touch3_move1);
391 ConfirmEventsAreTouchAndEqual(captured_events[2], &touch4_press);
392 ConfirmEventsAreTouchAndEqual(captured_events[3], &touch3_move2);
393 ConfirmEventsAreTouchAndEqual(captured_events[4], &touch4_move);
394 ConfirmEventsAreTouchAndEqual(captured_events[5], &touch3_release);
395 ConfirmEventsAreTouchAndEqual(captured_events[6], &touch4_release);
396 }
397
398 // Test the case when there are multiple fingers on the screen and the first
399 // finger is released. This should be rewritten as a release of the second
400 // finger. Additionally, if the second finger is the only finger left touching,
401 // we should enter a mouse move mode, and a mouse move event should be
402 // dispatched.
403 TEST_F(TouchExplorationTest, FirstFingerLifted) {
404 SwitchTouchExplorationMode(true);
405 GetEventGenerator().PressTouchId(1);
406 GetEventGenerator().PressTouchId(2);
407 gfx::Point touch2_location(10, 11);
408 GetEventGenerator().MoveTouchId(touch2_location, 2);
409 GetEventGenerator().PressTouchId(3);
410 gfx::Point touch3_location(20, 21);
411 GetEventGenerator().MoveTouchId(touch3_location, 3);
412 ClearCapturedEvents();
413
414 // Release of finger 1 should be rewritten as a release of finger 2.
415 GetEventGenerator().ReleaseTouchId(1);
416 EXPECT_FALSE(IsInTouchToMouseMode());
417 std::vector<ui::LocatedEvent*> captured_events = GetCapturedEvents();
418 EXPECT_EQ(captured_events.size(), 1u);
419 EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
420 ui::TouchEvent* touch_event =
421 static_cast<ui::TouchEvent*>(captured_events[0]);
422 EXPECT_EQ(touch_event->touch_id(), 2);
423 EXPECT_EQ(touch_event->location(), touch2_location);
424 ClearCapturedEvents();
425
426 // Release of finger 2 should be rewritten as a release of finger 3, plus
427 // we should enter the mouse move mode and a mouse move event should be
428 // dispatched.
429 GetEventGenerator().ReleaseTouchId(2);
430 EXPECT_TRUE(IsInTouchToMouseMode());
431 captured_events = GetCapturedEvents();
432 EXPECT_GE(captured_events.size(), 2u);
433 EXPECT_EQ(captured_events[0]->type(), ui::ET_TOUCH_RELEASED);
434 touch_event = static_cast<ui::TouchEvent*>(captured_events[0]);
435 EXPECT_EQ(touch_event->touch_id(), 3);
436 EXPECT_EQ(touch_event->location(), touch3_location);
437 std::vector<ui::LocatedEvent*>::const_iterator it;
438 for (it = captured_events.begin(); it != captured_events.end(); ++it) {
439 if ((*it)->type() == ui::ET_MOUSE_MOVED) {
440 EXPECT_EQ((*it)->location(), touch3_location);
441 break;
442 }
443 }
444 EXPECT_FALSE(it == captured_events.end());
445 }
446
447 } // namespace ui
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/accessibility/touch_exploration_controller_browsertest.cc ('k') | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698