1 // Copyright 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.
5 #include "ui/chromeos/touch_exploration_controller.h"
7 #include "base/test/simple_test_tick_clock.h"
8 #include "base/time/time.h"
9 #include "ui/aura/client/cursor_client.h"
10 #include "ui/aura/test/aura_test_base.h"
11 #include "ui/aura/test/event_generator.h"
12 #include "ui/aura/test/test_cursor_client.h"
13 #include "ui/aura/window.h"
14 #include "ui/events/event.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/events/gestures/gesture_provider_aura.h"
17 #include "ui/events/test/events_test_utils.h"
18 #include "ui/gfx/geometry/point.h"
19 #include "ui/gl/gl_implementation.h"
20 #include "ui/gl/gl_surface.h"
26 // Records all mouse, touch, gesture, and key events.
27 class EventCapturer
: public ui::EventHandler
{
30 virtual ~EventCapturer() {}
36 virtual void OnEvent(ui::Event
* event
) OVERRIDE
{
37 if (event
->IsMouseEvent()) {
39 new ui::MouseEvent(static_cast<ui::MouseEvent
&>(*event
)));
40 } else if (event
->IsTouchEvent()) {
42 new ui::TouchEvent(static_cast<ui::TouchEvent
&>(*event
)));
43 } else if (event
->IsGestureEvent()) {
45 new ui::GestureEvent(static_cast<ui::GestureEvent
&>(*event
)));
46 } else if (event
->IsKeyEvent()) {
47 events_
.push_back(new ui::KeyEvent(static_cast<ui::KeyEvent
&>(*event
)));
51 // Stop event propagation so we don't click on random stuff that
52 // might break test assumptions.
53 event
->StopPropagation();
54 // If there is a possibility that we're in an infinite loop, we should
55 // exit early with a sensible error rather than letting the test time out.
56 ASSERT_LT(events_
.size(), 100u);
59 const ScopedVector
<ui::Event
>& captured_events() const { return events_
; }
62 ScopedVector
<ui::Event
> events_
;
64 DISALLOW_COPY_AND_ASSIGN(EventCapturer
);
67 int Factorial(int n
) {
72 return n
* Factorial(n
- 1);
77 class TouchExplorationControllerTestApi
{
79 TouchExplorationControllerTestApi(
80 TouchExplorationController
* touch_exploration_controller
)
81 : touch_exploration_controller_(touch_exploration_controller
) {}
83 void CallTapTimerNowForTesting() {
84 DCHECK(touch_exploration_controller_
->tap_timer_
.IsRunning());
85 touch_exploration_controller_
->tap_timer_
.Stop();
86 touch_exploration_controller_
->OnTapTimerFired();
89 void CallTapTimerNowIfRunningForTesting() {
90 if (touch_exploration_controller_
->tap_timer_
.IsRunning()) {
91 touch_exploration_controller_
->tap_timer_
.Stop();
92 touch_exploration_controller_
->OnTapTimerFired();
96 void SetEventHandlerForTesting(
97 ui::EventHandler
* event_handler_for_testing
) {
98 touch_exploration_controller_
->event_handler_for_testing_
=
99 event_handler_for_testing
;
102 bool IsInNoFingersDownStateForTesting() const {
103 return touch_exploration_controller_
->state_
==
104 touch_exploration_controller_
->NO_FINGERS_DOWN
;
107 bool IsInGestureInProgressStateForTesting() const {
108 return touch_exploration_controller_
->state_
==
109 touch_exploration_controller_
->GESTURE_IN_PROGRESS
;
112 // VLOGs should be suppressed in tests that generate a lot of logs,
113 // for example permutations of nine touch events.
114 void SuppressVLOGsForTesting(bool suppress
) {
115 touch_exploration_controller_
->VLOG_on_
= !suppress
;
119 TouchExplorationController
* touch_exploration_controller_
;
121 DISALLOW_COPY_AND_ASSIGN(TouchExplorationControllerTestApi
);
124 class TouchExplorationTest
: public aura::test::AuraTestBase
{
126 TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) {
127 // Tests fail if time is ever 0.
128 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
130 virtual ~TouchExplorationTest() {}
132 virtual void SetUp() OVERRIDE
{
133 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone
)
134 gfx::GLSurface::InitializeOneOffForTests();
135 aura::test::AuraTestBase::SetUp();
136 cursor_client_
.reset(new aura::test::TestCursorClient(root_window()));
137 root_window()->AddPreTargetHandler(&event_capturer_
);
138 generator_
.reset(new aura::test::EventGenerator(root_window()));
139 // The generator takes ownership of the clock.
140 generator_
->SetTickClock(scoped_ptr
<base::TickClock
>(simulated_clock_
));
141 cursor_client()->ShowCursor();
142 cursor_client()->DisableMouseEvents();
145 virtual void TearDown() OVERRIDE
{
146 root_window()->RemovePreTargetHandler(&event_capturer_
);
147 SwitchTouchExplorationMode(false);
148 cursor_client_
.reset();
149 aura::test::AuraTestBase::TearDown();
153 aura::client::CursorClient
* cursor_client() { return cursor_client_
.get(); }
155 const ScopedVector
<ui::Event
>& GetCapturedEvents() {
156 return event_capturer_
.captured_events();
159 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEvents() {
160 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
161 std::vector
<ui::LocatedEvent
*> located_events
;
162 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
163 if (all_events
[i
]->IsMouseEvent() ||
164 all_events
[i
]->IsTouchEvent() ||
165 all_events
[i
]->IsGestureEvent()) {
166 located_events
.push_back(static_cast<ui::LocatedEvent
*>(all_events
[i
]));
169 return located_events
;
172 std::vector
<ui::Event
*> GetCapturedEventsOfType(int type
) {
173 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
174 std::vector
<ui::Event
*> events
;
175 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
176 if (type
== all_events
[i
]->type())
177 events
.push_back(all_events
[i
]);
182 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEventsOfType(int type
) {
183 std::vector
<ui::LocatedEvent
*> located_events
= GetCapturedLocatedEvents();
184 std::vector
<ui::LocatedEvent
*> events
;
185 for (size_t i
= 0; i
< located_events
.size(); ++i
) {
186 if (type
== located_events
[i
]->type())
187 events
.push_back(located_events
[i
]);
192 void ClearCapturedEvents() {
193 event_capturer_
.Reset();
196 void AdvanceSimulatedTimePastTapDelay() {
197 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
198 touch_exploration_controller_
->CallTapTimerNowForTesting();
201 void AdvanceSimulatedTimePastPotentialTapDelay() {
202 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
203 touch_exploration_controller_
->CallTapTimerNowIfRunningForTesting();
206 void SuppressVLOGs(bool suppress
) {
207 touch_exploration_controller_
->SuppressVLOGsForTesting(suppress
);
210 void SwitchTouchExplorationMode(bool on
) {
211 if (!on
&& touch_exploration_controller_
.get()) {
212 touch_exploration_controller_
.reset();
213 } else if (on
&& !touch_exploration_controller_
.get()) {
214 touch_exploration_controller_
.reset(new TouchExplorationControllerTestApi(
215 new ui::TouchExplorationController(root_window())));
216 touch_exploration_controller_
->SetEventHandlerForTesting(
218 cursor_client()->ShowCursor();
219 cursor_client()->DisableMouseEvents();
223 void EnterTouchExplorationModeAtLocation(gfx::Point tap_location
) {
224 ui::TouchEvent
touch_press(ui::ET_TOUCH_PRESSED
, tap_location
, 0, Now());
225 generator_
->Dispatch(&touch_press
);
226 AdvanceSimulatedTimePastTapDelay();
227 EXPECT_TRUE(IsInTouchToMouseMode());
230 void EnterTwoToOne(gfx::Point first_touch_location
,
231 gfx::Point second_touch_location
) {
232 SwitchTouchExplorationMode(true);
233 ui::TouchEvent
first_touch_press(
234 ui::ET_TOUCH_PRESSED
, first_touch_location
, 0, Now());
235 generator_
->Dispatch(&first_touch_press
);
236 ui::TouchEvent
second_touch_press(
237 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
238 generator_
->Dispatch(&second_touch_press
);
241 bool IsInTouchToMouseMode() {
242 aura::client::CursorClient
* cursor_client
=
243 aura::client::GetCursorClient(root_window());
244 return cursor_client
&&
245 cursor_client
->IsMouseEventsEnabled() &&
246 !cursor_client
->IsCursorVisible();
249 bool IsInNoFingersDownState() {
250 return touch_exploration_controller_
->IsInNoFingersDownStateForTesting();
253 bool IsInGestureInProgressState() {
254 return touch_exploration_controller_
255 ->IsInGestureInProgressStateForTesting();
258 base::TimeDelta
Now() {
259 // This is the same as what EventTimeForNow() does, but here we do it
260 // with our simulated clock.
261 return base::TimeDelta::FromInternalValue(
262 simulated_clock_
->NowTicks().ToInternalValue());
265 scoped_ptr
<aura::test::EventGenerator
> generator_
;
266 ui::GestureDetector::Config gesture_detector_config_
;
267 // Owned by |generator_|.
268 base::SimpleTestTickClock
* simulated_clock_
;
271 EventCapturer event_capturer_
;
272 scoped_ptr
<TouchExplorationControllerTestApi
>
273 touch_exploration_controller_
;
274 scoped_ptr
<aura::test::TestCursorClient
> cursor_client_
;
276 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest
);
279 // Executes a number of assertions to confirm that |e1| and |e2| are touch
280 // events and are equal to each other.
281 void ConfirmEventsAreTouchAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
282 ASSERT_TRUE(e1
->IsTouchEvent());
283 ASSERT_TRUE(e2
->IsTouchEvent());
284 ui::TouchEvent
* touch_event1
= static_cast<ui::TouchEvent
*>(e1
);
285 ui::TouchEvent
* touch_event2
= static_cast<ui::TouchEvent
*>(e2
);
286 EXPECT_EQ(touch_event1
->type(), touch_event2
->type());
287 EXPECT_EQ(touch_event1
->location(), touch_event2
->location());
288 EXPECT_EQ(touch_event1
->touch_id(), touch_event2
->touch_id());
289 EXPECT_EQ(touch_event1
->flags(), touch_event2
->flags());
290 EXPECT_EQ(touch_event1
->time_stamp(), touch_event2
->time_stamp());
293 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
294 // events and are equal to each other.
295 void ConfirmEventsAreMouseAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
296 ASSERT_TRUE(e1
->IsMouseEvent());
297 ASSERT_TRUE(e2
->IsMouseEvent());
298 ui::MouseEvent
* mouse_event1
= static_cast<ui::MouseEvent
*>(e1
);
299 ui::MouseEvent
* mouse_event2
= static_cast<ui::MouseEvent
*>(e2
);
300 EXPECT_EQ(mouse_event1
->type(), mouse_event2
->type());
301 EXPECT_EQ(mouse_event1
->location(), mouse_event2
->location());
302 EXPECT_EQ(mouse_event1
->root_location(), mouse_event2
->root_location());
303 EXPECT_EQ(mouse_event1
->flags(), mouse_event2
->flags());
306 // Executes a number of assertions to confirm that |e1| and |e2| are key events
307 // and are equal to each other.
308 void ConfirmEventsAreKeyAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
309 ASSERT_TRUE(e1
->IsKeyEvent());
310 ASSERT_TRUE(e2
->IsKeyEvent());
311 ui::KeyEvent
* key_event1
= static_cast<ui::KeyEvent
*>(e1
);
312 ui::KeyEvent
* key_event2
= static_cast<ui::KeyEvent
*>(e2
);
313 EXPECT_EQ(key_event1
->type(), key_event2
->type());
314 EXPECT_EQ(key_event1
->key_code(), key_event2
->key_code());
315 EXPECT_EQ(key_event1
->code(), key_event2
->code());
316 EXPECT_EQ(key_event1
->flags(), key_event2
->flags());
319 #define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
320 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
322 #define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
323 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
325 #define CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(e1, e2) \
326 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreKeyAndEqual(e1, e2))
328 // TODO(mfomitchev): Need to investigate why we don't get mouse enter/exit
329 // events when running these tests as part of ui_unittests. We do get them when
330 // the tests are run as part of ash unit tests.
332 // If a swipe has been successfully completed, then six key events will be
333 // dispatched that correspond to shift+search+direction
334 void AssertDirectionalNavigationEvents(const ScopedVector
<ui::Event
>& events
,
335 ui::KeyboardCode direction
) {
336 ASSERT_EQ(6U, events
.size());
337 ui::KeyEvent
shift_pressed(
338 ui::ET_KEY_PRESSED
, ui::VKEY_SHIFT
, ui::EF_SHIFT_DOWN
, false);
339 ui::KeyEvent
search_pressed(
340 ui::ET_KEY_PRESSED
, ui::VKEY_LWIN
, ui::EF_SHIFT_DOWN
, false);
341 ui::KeyEvent
direction_pressed(
342 ui::ET_KEY_PRESSED
, direction
, ui::EF_SHIFT_DOWN
, false);
343 ui::KeyEvent
direction_released(
344 ui::ET_KEY_RELEASED
, direction
, ui::EF_SHIFT_DOWN
, false);
345 ui::KeyEvent
search_released(
346 ui::ET_KEY_RELEASED
, VKEY_LWIN
, ui::EF_SHIFT_DOWN
, false);
347 ui::KeyEvent
shift_released(
348 ui::ET_KEY_RELEASED
, ui::VKEY_SHIFT
, ui::EF_NONE
, false);
349 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_pressed
, events
[0]);
350 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_pressed
, events
[1]);
351 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_pressed
, events
[2]);
352 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_released
, events
[3]);
353 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_released
, events
[4]);
354 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_released
, events
[5]);
357 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterPressAndDelay
) {
358 SwitchTouchExplorationMode(true);
359 EXPECT_FALSE(IsInTouchToMouseMode());
360 generator_
->PressTouch();
361 AdvanceSimulatedTimePastTapDelay();
362 EXPECT_TRUE(IsInTouchToMouseMode());
365 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterMoveOutsideSlop
) {
366 int slop
= gesture_detector_config_
.touch_slop
;
367 int half_slop
= slop
/ 2;
369 SwitchTouchExplorationMode(true);
370 EXPECT_FALSE(IsInTouchToMouseMode());
371 generator_
->set_current_location(gfx::Point(11, 12));
372 generator_
->PressTouch();
373 generator_
->MoveTouch(gfx::Point(11 + half_slop
, 12));
374 EXPECT_FALSE(IsInTouchToMouseMode());
375 generator_
->MoveTouch(gfx::Point(11, 12 + half_slop
));
376 EXPECT_FALSE(IsInTouchToMouseMode());
377 AdvanceSimulatedTimePastTapDelay();
378 generator_
->MoveTouch(gfx::Point(11 + slop
+ 1, 12));
379 EXPECT_TRUE(IsInTouchToMouseMode());
382 TEST_F(TouchExplorationTest
, OneFingerTap
) {
383 SwitchTouchExplorationMode(true);
384 gfx::Point
location(11, 12);
385 generator_
->set_current_location(location
);
386 generator_
->PressTouch();
387 generator_
->ReleaseTouch();
388 AdvanceSimulatedTimePastTapDelay();
390 std::vector
<ui::LocatedEvent
*> events
=
391 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
392 ASSERT_EQ(1U, events
.size());
394 EXPECT_EQ(location
, events
[0]->location());
395 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
396 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
397 EXPECT_TRUE(IsInNoFingersDownState());
400 TEST_F(TouchExplorationTest
, ActualMouseMovesUnaffected
) {
401 SwitchTouchExplorationMode(true);
403 gfx::Point
location_start(11, 12);
404 gfx::Point
location_end(13, 14);
405 generator_
->set_current_location(location_start
);
406 generator_
->PressTouch();
407 AdvanceSimulatedTimePastTapDelay();
408 generator_
->MoveTouch(location_end
);
410 gfx::Point
location_real_mouse_move(15, 16);
411 ui::MouseEvent
mouse_move(ui::ET_MOUSE_MOVED
,
412 location_real_mouse_move
,
413 location_real_mouse_move
,
416 generator_
->Dispatch(&mouse_move
);
417 generator_
->ReleaseTouch();
418 AdvanceSimulatedTimePastTapDelay();
420 std::vector
<ui::LocatedEvent
*> events
=
421 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
422 ASSERT_EQ(4U, events
.size());
424 EXPECT_EQ(location_start
, events
[0]->location());
425 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
426 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
428 EXPECT_EQ(location_end
, events
[1]->location());
429 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
430 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
432 // The real mouse move goes through.
433 EXPECT_EQ(location_real_mouse_move
, events
[2]->location());
434 CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(events
[2], &mouse_move
);
435 EXPECT_FALSE(events
[2]->flags() & ui::EF_IS_SYNTHESIZED
);
436 EXPECT_FALSE(events
[2]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
438 // The touch release gets written as a mouse move.
439 EXPECT_EQ(location_end
, events
[3]->location());
440 EXPECT_TRUE(events
[3]->flags() & ui::EF_IS_SYNTHESIZED
);
441 EXPECT_TRUE(events
[3]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
442 EXPECT_TRUE(IsInNoFingersDownState());
445 // Turn the touch exploration mode on in the middle of the touch gesture.
446 // Confirm that events from the finger which was touching when the mode was
447 // turned on don't get rewritten.
448 TEST_F(TouchExplorationTest
, TurnOnMidTouch
) {
449 SwitchTouchExplorationMode(false);
450 generator_
->PressTouchId(1);
451 EXPECT_TRUE(cursor_client()->IsCursorVisible());
452 ClearCapturedEvents();
454 // Enable touch exploration mode while the first finger is touching the
455 // screen. Ensure that subsequent events from that first finger are not
456 // affected by the touch exploration mode, while the touch events from another
457 // finger get rewritten.
458 SwitchTouchExplorationMode(true);
459 ui::TouchEvent
touch_move(ui::ET_TOUCH_MOVED
,
463 generator_
->Dispatch(&touch_move
);
464 EXPECT_TRUE(cursor_client()->IsCursorVisible());
465 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
466 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
467 ASSERT_EQ(1u, captured_events
.size());
468 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_move
);
469 ClearCapturedEvents();
471 // The press from the second finger should get rewritten.
472 generator_
->PressTouchId(2);
473 AdvanceSimulatedTimePastTapDelay();
474 EXPECT_TRUE(IsInTouchToMouseMode());
475 captured_events
= GetCapturedLocatedEvents();
476 std::vector
<ui::LocatedEvent
*>::const_iterator it
;
477 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
478 if ((*it
)->type() == ui::ET_MOUSE_MOVED
)
481 EXPECT_NE(captured_events
.end(), it
);
482 ClearCapturedEvents();
484 // The release of the first finger shouldn't be affected.
485 ui::TouchEvent
touch_release(ui::ET_TOUCH_RELEASED
,
489 generator_
->Dispatch(&touch_release
);
490 captured_events
= GetCapturedLocatedEvents();
491 ASSERT_EQ(1u, captured_events
.size());
492 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_release
);
493 ClearCapturedEvents();
495 // The move and release from the second finger should get rewritten.
496 generator_
->MoveTouchId(gfx::Point(13, 14), 2);
497 generator_
->ReleaseTouchId(2);
498 AdvanceSimulatedTimePastTapDelay();
499 captured_events
= GetCapturedLocatedEvents();
500 ASSERT_EQ(2u, captured_events
.size());
501 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
502 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
503 EXPECT_TRUE(IsInNoFingersDownState());
506 // If an event is received after the double-tap timeout has elapsed, but
507 // before the timer has fired, a mouse move should still be generated.
508 TEST_F(TouchExplorationTest
, TimerFiresLateDuringTouchExploration
) {
509 SwitchTouchExplorationMode(true);
511 // Send a press, then add another finger after the double-tap timeout.
512 generator_
->PressTouchId(1);
513 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
514 generator_
->PressTouchId(2);
515 std::vector
<ui::LocatedEvent
*> events
=
516 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
517 ASSERT_EQ(1U, events
.size());
518 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
519 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
521 generator_
->ReleaseTouchId(2);
522 generator_
->ReleaseTouchId(1);
523 AdvanceSimulatedTimePastTapDelay();
524 EXPECT_TRUE(IsInNoFingersDownState());
527 // If a new tap is received after the double-tap timeout has elapsed from
528 // a previous tap, but before the timer has fired, a mouse move should
529 // still be generated from the old tap.
530 TEST_F(TouchExplorationTest
, TimerFiresLateAfterTap
) {
531 SwitchTouchExplorationMode(true);
533 // Send a tap at location1.
534 gfx::Point
location0(11, 12);
535 generator_
->set_current_location(location0
);
536 generator_
->PressTouch();
537 generator_
->ReleaseTouch();
539 // Send a tap at location2, after the double-tap timeout, but before the
541 gfx::Point
location1(33, 34);
542 generator_
->set_current_location(location1
);
543 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(301));
544 generator_
->PressTouch();
545 generator_
->ReleaseTouch();
546 AdvanceSimulatedTimePastTapDelay();
548 std::vector
<ui::LocatedEvent
*> events
=
549 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
550 ASSERT_EQ(2U, events
.size());
551 EXPECT_EQ(location0
, events
[0]->location());
552 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
553 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
554 EXPECT_EQ(location1
, events
[1]->location());
555 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
556 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
557 EXPECT_TRUE(IsInNoFingersDownState());
560 // Double-tapping should send a touch press and release through to the location
561 // of the last successful touch exploration.
562 TEST_F(TouchExplorationTest
, DoubleTap
) {
563 SwitchTouchExplorationMode(true);
565 // Tap at one location, and get a mouse move event.
566 gfx::Point
tap_location(11, 12);
567 generator_
->set_current_location(tap_location
);
568 generator_
->PressTouch();
569 generator_
->ReleaseTouch();
570 AdvanceSimulatedTimePastTapDelay();
572 std::vector
<ui::LocatedEvent
*> events
=
573 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
574 ASSERT_EQ(1U, events
.size());
576 EXPECT_EQ(tap_location
, events
[0]->location());
577 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
578 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
579 ClearCapturedEvents();
581 // Now double-tap at a different location. This should result in
582 // a single touch press and release at the location of the tap,
583 // not at the location of the double-tap.
584 gfx::Point
double_tap_location(33, 34);
585 generator_
->set_current_location(double_tap_location
);
586 generator_
->PressTouch();
587 generator_
->ReleaseTouch();
588 generator_
->PressTouch();
589 generator_
->ReleaseTouch();
591 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
592 ASSERT_EQ(2U, captured_events
.size());
593 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
594 EXPECT_EQ(tap_location
, captured_events
[0]->location());
595 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
596 EXPECT_EQ(tap_location
, captured_events
[1]->location());
597 EXPECT_TRUE(IsInNoFingersDownState());
600 // Double-tapping where the user holds their finger down for the second time
601 // for a longer press should send a touch press and released (right click)
602 // to the location of the last successful touch exploration.
603 TEST_F(TouchExplorationTest
, DoubleTapLongPress
) {
604 SwitchTouchExplorationMode(true);
606 // Tap at one location, and get a mouse move event.
607 gfx::Point
tap_location(11, 12);
608 generator_
->set_current_location(tap_location
);
609 generator_
->PressTouch();
610 generator_
->ReleaseTouch();
611 AdvanceSimulatedTimePastTapDelay();
613 std::vector
<ui::LocatedEvent
*> events
=
614 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
615 ASSERT_EQ(1U, events
.size());
617 EXPECT_EQ(tap_location
, events
[0]->location());
618 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
619 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
620 ClearCapturedEvents();
622 // Now double-tap and hold at a different location.
623 // This should result in a single touch long press and release
624 // at the location of the tap, not at the location of the double-tap.
625 // There should be a time delay between the touch press and release.
626 gfx::Point
first_tap_location(33, 34);
627 generator_
->set_current_location(first_tap_location
);
628 generator_
->PressTouch();
629 generator_
->ReleaseTouch();
630 gfx::Point
second_tap_location(23, 24);
631 generator_
->set_current_location(second_tap_location
);
632 generator_
->PressTouch();
633 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
634 generator_
->ReleaseTouch();
636 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
637 ASSERT_EQ(2U, captured_events
.size());
638 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
639 EXPECT_EQ(tap_location
, captured_events
[0]->location());
640 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
641 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
642 EXPECT_EQ(tap_location
, captured_events
[1]->location());
643 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
644 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
645 released_time
- pressed_time
);
648 // Single-tapping should send a touch press and release through to the location
649 // of the last successful touch exploration if the grace period has not
651 TEST_F(TouchExplorationTest
, SingleTap
) {
652 SwitchTouchExplorationMode(true);
654 // Tap once to simulate a mouse moved event.
655 gfx::Point
initial_location(11, 12);
656 generator_
->set_current_location(initial_location
);
657 generator_
->PressTouch();
658 AdvanceSimulatedTimePastTapDelay();
659 ClearCapturedEvents();
661 // Move to another location for single tap
662 gfx::Point
tap_location(22, 23);
663 generator_
->MoveTouch(tap_location
);
664 generator_
->ReleaseTouch();
666 // Allow time to pass within the grace period of releasing before
668 gfx::Point
final_location(33, 34);
669 generator_
->set_current_location(final_location
);
670 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(250));
671 generator_
->PressTouch();
672 generator_
->ReleaseTouch();
674 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
675 ASSERT_EQ(4U, captured_events
.size());
676 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
677 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
678 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
679 EXPECT_EQ(tap_location
, captured_events
[2]->location());
680 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[3]->type());
681 EXPECT_EQ(tap_location
, captured_events
[3]->location());
684 // Double-tapping without coming from touch exploration (no previous touch
685 // exploration event) should not generate any events.
686 TEST_F(TouchExplorationTest
, DoubleTapNoTouchExplore
) {
687 SwitchTouchExplorationMode(true);
689 // Double-tap without any previous touch.
690 // Touch exploration mode has not been entered, so there is no previous
691 // touch exploration event. The double-tap should be discarded, and no events
692 // should be generated at all.
693 gfx::Point
double_tap_location(33, 34);
694 generator_
->set_current_location(double_tap_location
);
695 generator_
->PressTouch();
696 generator_
->ReleaseTouch();
697 generator_
->PressTouch();
698 generator_
->ReleaseTouch();
700 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
701 ASSERT_EQ(0U, captured_events
.size());
704 // Tapping and releasing with a second finger when in touch exploration mode
705 // should send a touch press and released to the location of the last
706 // successful touch exploration and return to touch explore.
707 TEST_F(TouchExplorationTest
, SplitTap
) {
708 SwitchTouchExplorationMode(true);
709 gfx::Point
initial_touch_location(11, 12);
710 gfx::Point
second_touch_location(33, 34);
712 // Tap and hold at one location, and get a mouse move event in touch explore.
713 EnterTouchExplorationModeAtLocation(initial_touch_location
);
714 std::vector
<ui::LocatedEvent
*> events
=
715 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
716 ASSERT_EQ(1U, events
.size());
718 EXPECT_EQ(initial_touch_location
, events
[0]->location());
719 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
720 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
721 ClearCapturedEvents();
722 EXPECT_TRUE(IsInTouchToMouseMode());
724 // Now tap and release at a different location. This should result in a
725 // single touch and release at the location of the first (held) tap,
726 // not at the location of the second tap and release.
727 // After the release, there is still a finger in touch explore mode.
728 ui::TouchEvent
split_tap_press(
729 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
730 generator_
->Dispatch(&split_tap_press
);
731 // To simulate the behavior of the real device, we manually disable
732 // mouse events. To not rely on manually setting the state, this is also
733 // tested in touch_exploration_controller_browsertest.
734 cursor_client()->DisableMouseEvents();
735 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
736 EXPECT_FALSE(cursor_client()->IsCursorVisible());
737 EXPECT_FALSE(IsInGestureInProgressState());
738 ui::TouchEvent
split_tap_release(
739 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
740 generator_
->Dispatch(&split_tap_release
);
741 // Releasing the second finger should re-enable mouse events putting us
742 // back into the touch exploration mode.
743 EXPECT_TRUE(IsInTouchToMouseMode());
744 EXPECT_FALSE(IsInNoFingersDownState());
746 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
747 ASSERT_EQ(2U, captured_events
.size());
748 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
749 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
750 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
751 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
752 ClearCapturedEvents();
754 ui::TouchEvent
touch_explore_release(
755 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
756 generator_
->Dispatch(&touch_explore_release
);
757 AdvanceSimulatedTimePastTapDelay();
758 EXPECT_TRUE(IsInNoFingersDownState());
761 // If split tap is started but the touch explore finger is released first,
762 // there should still be a touch press and release sent to the location of
763 // the last successful touch exploration.
764 // Both fingers should be released after the click goes through.
765 TEST_F(TouchExplorationTest
, SplitTapRelease
) {
766 SwitchTouchExplorationMode(true);
768 gfx::Point
initial_touch_location(11, 12);
769 gfx::Point
second_touch_location(33, 34);
771 // Tap and hold at one location, and get a mouse move event in touch explore.
772 EnterTouchExplorationModeAtLocation(initial_touch_location
);
774 std::vector
<ui::LocatedEvent
*> events
=
775 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
776 ASSERT_EQ(1U, events
.size());
778 ClearCapturedEvents();
780 // Now tap at a different location. Release at the first location,
781 // then release at the second. This should result in a
782 // single touch and release at the location of the first (held) tap,
783 // not at the location of the second tap and release.
784 ui::TouchEvent
split_tap_press(
785 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
786 generator_
->Dispatch(&split_tap_press
);
787 ui::TouchEvent
touch_explore_release(
788 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
789 generator_
->Dispatch(&touch_explore_release
);
790 ui::TouchEvent
split_tap_release(
791 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
792 generator_
->Dispatch(&split_tap_release
);
793 EXPECT_TRUE(IsInNoFingersDownState());
795 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
796 ASSERT_EQ(2U, captured_events
.size());
797 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
798 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
799 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
800 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
803 // When in touch exploration mode, making a long press with a second finger
804 // should send a touch press and released to the location of the last
805 // successful touch exploration. There should be a delay between the
806 // touch and release events (right click).
807 TEST_F(TouchExplorationTest
, SplitTapLongPress
) {
808 SwitchTouchExplorationMode(true);
809 gfx::Point
initial_touch_location(11, 12);
810 gfx::Point
second_touch_location(33, 34);
812 // Tap and hold at one location, and get a mouse move event in touch explore.
813 EnterTouchExplorationModeAtLocation(initial_touch_location
);
814 std::vector
<ui::LocatedEvent
*> events
=
815 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
816 ASSERT_EQ(1U, events
.size());
818 ClearCapturedEvents();
820 // Now tap, hold, and release at a different location. This should result
821 // in a single touch and release (long press) at the location of the first
822 // (held) tap, not at the location of the second tap and release.
823 ui::TouchEvent
split_tap_press(
824 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
825 generator_
->Dispatch(&split_tap_press
);
826 // To simulate the behavior of the real device, we manually disable
827 // mouse events, like in the SplitTap test.
828 cursor_client()->DisableMouseEvents();
829 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
830 EXPECT_FALSE(cursor_client()->IsCursorVisible());
831 EXPECT_FALSE(IsInGestureInProgressState());
832 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
833 // After the release, there is still a finger in touch exploration, and
834 // mouse events should be enabled again.
835 ui::TouchEvent
split_tap_release(
836 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
837 generator_
->Dispatch(&split_tap_release
);
838 EXPECT_FALSE(IsInNoFingersDownState());
839 EXPECT_TRUE(IsInTouchToMouseMode());
841 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
842 ASSERT_EQ(2U, captured_events
.size());
843 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
844 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
845 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
846 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
847 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
848 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
849 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
850 released_time
- pressed_time
);
853 // If split tap is started but the touch explore finger is released first,
854 // there should still be a touch press and release sent to the location of
855 // the last successful touch exploration. If the remaining finger is held
856 // as a longpress, there should be a delay between the sent touch and release
857 // events (right click).All fingers should be released after the click
859 TEST_F(TouchExplorationTest
, SplitTapReleaseLongPress
) {
860 SwitchTouchExplorationMode(true);
861 gfx::Point
initial_touch_location(11, 12);
862 gfx::Point
second_touch_location(33, 34);
864 // Tap and hold at one location, and get a mouse move event in touch explore.
865 EnterTouchExplorationModeAtLocation(initial_touch_location
);
866 std::vector
<ui::LocatedEvent
*> events
=
867 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
868 ASSERT_EQ(1U, events
.size());
869 ClearCapturedEvents();
871 // Now tap at a different location. Release at the first location,
872 // then release at the second. This should result in a
873 // single touch and release at the location of the first (held) tap,
874 // not at the location of the second tap and release.
875 // After the release, TouchToMouseMode should still be on.
876 ui::TouchEvent
split_tap_press(
877 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
878 generator_
->Dispatch(&split_tap_press
);
879 ui::TouchEvent
touch_explore_release(
880 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
881 generator_
->Dispatch(&touch_explore_release
);
882 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
883 ui::TouchEvent
split_tap_release(
884 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
885 generator_
->Dispatch(&split_tap_release
);
886 EXPECT_TRUE(IsInTouchToMouseMode());
888 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
889 ASSERT_EQ(2U, captured_events
.size());
890 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
891 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
892 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
893 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
894 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
895 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
896 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
897 released_time
- pressed_time
);
900 TEST_F(TouchExplorationTest
, SplitTapLongPressMultiFinger
) {
901 SwitchTouchExplorationMode(true);
902 gfx::Point
initial_touch_location(11, 12);
903 gfx::Point
second_touch_location(33, 34);
904 gfx::Point
third_touch_location(16, 17);
906 // Tap and hold at one location, and get a mouse move event in touch explore.
907 EnterTouchExplorationModeAtLocation(initial_touch_location
);
909 std::vector
<ui::LocatedEvent
*> events
=
910 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
911 ASSERT_EQ(1U, events
.size());
913 EXPECT_EQ(initial_touch_location
, events
[0]->location());
914 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
915 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
916 ClearCapturedEvents();
918 // Now tap at a different location and hold for long press.
919 ui::TouchEvent
split_tap_press(
920 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
921 generator_
->Dispatch(&split_tap_press
);
922 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
924 // Placing a third finger on the screen should be discarded and not affect
925 // the events passed through.
926 ui::TouchEvent
third_press(
927 ui::ET_TOUCH_PRESSED
, third_touch_location
, 2, Now());
928 generator_
->Dispatch(&third_press
);
930 // When all three fingers are released, there should be only two captured
931 // events: touch press and touch release. All fingers should then be up.
932 ui::TouchEvent
touch_explore_release(
933 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
934 generator_
->Dispatch(&touch_explore_release
);
935 ui::TouchEvent
split_tap_release(
936 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
937 generator_
->Dispatch(&split_tap_release
);
938 ui::TouchEvent
third_tap_release(
939 ui::ET_TOUCH_RELEASED
, third_touch_location
, 2, Now());
940 generator_
->Dispatch(&third_tap_release
);
942 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
943 ASSERT_EQ(2U, captured_events
.size());
944 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
945 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
946 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
947 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
948 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
949 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
950 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
951 released_time
- pressed_time
);
952 EXPECT_TRUE(IsInNoFingersDownState());
955 // If the second finger is pressed soon after the first, the second
956 // finger passes through and the first does not. However, The press is
957 // released after the second finger is lifted to go into the wait state.
958 TEST_F(TouchExplorationTest
, TwoToOneFingerReleaseSecond
) {
959 gfx::Point first_touch_location
= gfx::Point(7, 7);
960 gfx::Point second_touch_location
= gfx::Point(10, 11);
961 EnterTwoToOne(first_touch_location
, second_touch_location
);
962 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
963 ASSERT_EQ(captured_events
.size(), 1u);
964 ClearCapturedEvents();
966 // Confirm events from the second finger go through as is.
967 gfx::Point second_touch_move_location
= gfx::Point(20, 21);
968 ui::TouchEvent
second_touch_move(
970 second_touch_move_location
,
973 generator_
->Dispatch(&second_touch_move
);
974 captured_events
= GetCapturedLocatedEvents();
975 ASSERT_EQ(1u, captured_events
.size());
976 ClearCapturedEvents();
978 // Events from the first finger should still not go through while the second
979 // finger is touching.
980 gfx::Point first_touch_move_location
= gfx::Point(15, 16);
981 generator_
->MoveTouchId(first_touch_move_location
, 0);
982 captured_events
= GetCapturedLocatedEvents();
983 EXPECT_EQ(0u, captured_events
.size());
984 EXPECT_TRUE(cursor_client()->IsCursorVisible());
985 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
987 // A release of the second finger should send an event, as the state
988 // changes to the wait state.
989 ui::TouchEvent
second_touch_release(
990 ui::ET_TOUCH_RELEASED
, second_touch_move_location
, 1, Now());
991 generator_
->Dispatch(&second_touch_release
);
992 EXPECT_FALSE(IsInTouchToMouseMode());
993 captured_events
= GetCapturedLocatedEvents();
994 ASSERT_EQ(captured_events
.size(), 1u);
995 ClearCapturedEvents();
997 // No events should be sent after the second finger is lifted.
999 ui::TouchEvent
unsent_move(ui::ET_TOUCH_MOVED
, gfx::Point(21, 22), 0, Now());
1000 generator_
->Dispatch(&unsent_move
);
1002 ui::TouchEvent
first_touch_release(
1003 ui::ET_TOUCH_RELEASED
, first_touch_move_location
, 0, Now());
1004 generator_
->Dispatch(&first_touch_release
);
1005 captured_events
= GetCapturedLocatedEvents();
1006 ASSERT_EQ(captured_events
.size(), 0u);
1007 EXPECT_TRUE(IsInNoFingersDownState());
1010 // The press should also be released if the first finger is lifted
1011 // in TwoToOneFinger.
1012 TEST_F(TouchExplorationTest
, TwoToOneFingerRelaseFirst
) {
1013 gfx::Point first_touch_location
= gfx::Point(11,12);
1014 gfx::Point second_touch_location
= gfx::Point(21, 22);
1015 EnterTwoToOne(first_touch_location
, second_touch_location
);
1016 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1017 ASSERT_EQ(captured_events
.size(), 1u);
1018 ClearCapturedEvents();
1020 // Actions before release have already been tested in the previous test.
1022 // A release of the first finger should send an event, as the state
1023 // changes to the wait state.
1024 ui::TouchEvent
first_touch_release(
1025 ui::ET_TOUCH_RELEASED
, first_touch_location
, 0, Now());
1026 generator_
->Dispatch(&first_touch_release
);
1027 captured_events
= GetCapturedLocatedEvents();
1028 ASSERT_EQ(captured_events
.size(), 1u);
1029 ClearCapturedEvents();
1031 // No events should be sent after the second finger is lifted.
1033 ui::TouchEvent
unsent_move(ui::ET_TOUCH_MOVED
, gfx::Point(21, 22), 1, Now());
1034 generator_
->Dispatch(&unsent_move
);
1036 ui::TouchEvent
second_touch_release(
1037 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1038 generator_
->Dispatch(&second_touch_release
);
1039 captured_events
= GetCapturedLocatedEvents();
1040 ASSERT_EQ(captured_events
.size(), 0u);
1041 EXPECT_TRUE(IsInNoFingersDownState());
1044 // Placing three fingers should start passthrough, and all fingers should
1045 // continue to be passed through until the last one is released.
1046 TEST_F(TouchExplorationTest
, Passthrough
) {
1047 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1049 gfx::Point first_touch_location
= gfx::Point(11,12);
1050 gfx::Point second_touch_location
= gfx::Point(21, 22);
1051 EnterTwoToOne(first_touch_location
, second_touch_location
);
1052 captured_events
= GetCapturedLocatedEvents();
1053 ASSERT_EQ(captured_events
.size(), 1u);
1055 gfx::Point third_touch_location
= gfx::Point(31, 32);
1056 ui::TouchEvent
third_touch_press(
1057 ui::ET_TOUCH_PRESSED
, third_touch_location
, 2, Now());
1058 generator_
->Dispatch(&third_touch_press
);
1059 captured_events
= GetCapturedLocatedEvents();
1060 // Now all fingers are registered as pressed.
1061 ASSERT_EQ(captured_events
.size(), 3u);
1062 ClearCapturedEvents();
1064 // All fingers should be passed through.
1065 first_touch_location
= gfx::Point(13, 14);
1066 second_touch_location
= gfx::Point(23, 24);
1067 third_touch_location
= gfx::Point(33, 34);
1068 ui::TouchEvent
first_touch_first_move(
1069 ui::ET_TOUCH_MOVED
, first_touch_location
, 0, Now());
1070 ui::TouchEvent
second_touch_first_move(
1071 ui::ET_TOUCH_MOVED
, second_touch_location
, 1, Now());
1072 ui::TouchEvent
third_touch_first_move(
1073 ui::ET_TOUCH_MOVED
, third_touch_location
, 2, Now());
1074 generator_
->Dispatch(&first_touch_first_move
);
1075 generator_
->Dispatch(&second_touch_first_move
);
1076 generator_
->Dispatch(&third_touch_first_move
);
1077 captured_events
= GetCapturedLocatedEvents();
1078 ASSERT_EQ(captured_events
.size(), 3u);
1079 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
1080 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1081 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[1]->type());
1082 EXPECT_EQ(second_touch_location
, captured_events
[1]->location());
1083 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[2]->type());
1084 EXPECT_EQ(third_touch_location
, captured_events
[2]->location());
1085 ClearCapturedEvents();
1087 // When we release the third finger, the other fingers should still be
1089 ui::TouchEvent
third_touch_release(
1090 ui::ET_TOUCH_RELEASED
, third_touch_location
, 2, Now());
1091 generator_
->Dispatch(&third_touch_release
);
1092 captured_events
= GetCapturedLocatedEvents();
1093 ASSERT_EQ(captured_events
.size(), 1u);
1094 ClearCapturedEvents();
1095 first_touch_location
= gfx::Point(15, 16);
1096 second_touch_location
= gfx::Point(25, 26);
1097 ui::TouchEvent
first_touch_second_move(
1098 ui::ET_TOUCH_MOVED
, first_touch_location
, 0, Now());
1099 ui::TouchEvent
second_touch_second_move(
1100 ui::ET_TOUCH_MOVED
, second_touch_location
, 1, Now());
1101 generator_
->Dispatch(&first_touch_second_move
);
1102 generator_
->Dispatch(&second_touch_second_move
);
1103 captured_events
= GetCapturedLocatedEvents();
1104 ASSERT_EQ(captured_events
.size(), 2u);
1105 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
1106 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1107 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[1]->type());
1108 EXPECT_EQ(second_touch_location
, captured_events
[1]->location());
1109 ClearCapturedEvents();
1111 // When we release the second finger, the first finger should still be
1113 ui::TouchEvent
second_touch_release(
1114 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1115 generator_
->Dispatch(&second_touch_release
);
1116 captured_events
= GetCapturedLocatedEvents();
1117 ASSERT_EQ(captured_events
.size(), 1u);
1118 ClearCapturedEvents();
1119 first_touch_location
= gfx::Point(17, 18);
1120 ui::TouchEvent
first_touch_third_move(
1121 ui::ET_TOUCH_MOVED
, first_touch_location
, 0, Now());
1122 generator_
->Dispatch(&first_touch_third_move
);
1123 captured_events
= GetCapturedLocatedEvents();
1124 ASSERT_EQ(captured_events
.size(), 1u);
1125 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
1126 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1127 ClearCapturedEvents();
1129 ui::TouchEvent
first_touch_release(
1130 ui::ET_TOUCH_RELEASED
, first_touch_location
, 0, Now());
1131 generator_
->Dispatch(&first_touch_release
);
1132 captured_events
= GetCapturedLocatedEvents();
1133 ASSERT_EQ(captured_events
.size(), 1u);
1134 EXPECT_TRUE(IsInNoFingersDownState());
1137 // Finger must have moved more than slop, faster than the minimum swipe
1138 // velocity, and before the tap timer fires in order to enter
1139 // GestureInProgress state. Otherwise, if the tap timer fires before the a
1140 // gesture is completed, enter touch exploration.
1141 TEST_F(TouchExplorationTest
, EnterGestureInProgressState
) {
1142 SwitchTouchExplorationMode(true);
1143 EXPECT_FALSE(IsInTouchToMouseMode());
1144 EXPECT_FALSE(IsInGestureInProgressState());
1146 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1147 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, gfx::Point(0, 1), 0, Now());
1148 gfx::Point
second_location(distance
/ 2, 1);
1149 gfx::Point
third_location(distance
, 1);
1151 generator_
->Dispatch(&first_press
);
1152 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1153 // Since we are not out of the touch slop yet, we should not be in gesture in
1155 generator_
->MoveTouch(second_location
);
1156 EXPECT_FALSE(IsInTouchToMouseMode());
1157 EXPECT_FALSE(IsInGestureInProgressState());
1158 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1160 // Once we are out of slop, we should be in GestureInProgress.
1161 generator_
->MoveTouch(third_location
);
1162 EXPECT_TRUE(IsInGestureInProgressState());
1163 EXPECT_FALSE(IsInTouchToMouseMode());
1164 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1165 ASSERT_EQ(0U, captured_events
.size());
1167 // Exit out of gesture mode once grace period is over and enter touch
1169 AdvanceSimulatedTimePastTapDelay();
1170 ASSERT_EQ(1U, captured_events
.size());
1171 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
1172 EXPECT_TRUE(IsInTouchToMouseMode());
1173 EXPECT_FALSE(IsInGestureInProgressState());
1176 // A swipe+direction gesture should trigger a Shift+Search+Direction
1178 TEST_F(TouchExplorationTest
, GestureSwipe
) {
1179 SwitchTouchExplorationMode(true);
1180 std::vector
<ui::KeyboardCode
> directions
;
1181 directions
.push_back(ui::VKEY_RIGHT
);
1182 directions
.push_back(ui::VKEY_LEFT
);
1183 directions
.push_back(ui::VKEY_UP
);
1184 directions
.push_back(ui::VKEY_DOWN
);
1186 for (std::vector
<ui::KeyboardCode
>::const_iterator it
= directions
.begin();
1187 it
!= directions
.end();
1191 ui::TouchEvent
origin(ui::ET_TOUCH_PRESSED
, gfx::Point(x
, y
), 0, Now());
1192 generator_
->Dispatch(&origin
);
1194 ui::KeyboardCode direction
= *it
;
1195 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1196 scoped_ptr
<gfx::Point
> swipe
;
1197 switch (direction
) {
1198 case ui::VKEY_RIGHT
:
1199 swipe
.reset(new gfx::Point(x
+ distance
, y
));
1202 swipe
.reset(new gfx::Point(x
- distance
, y
));
1205 swipe
.reset(new gfx::Point(x
, y
- distance
));
1208 swipe
.reset(new gfx::Point(x
, y
+ distance
));
1214 // A swipe is made when a fling starts
1216 distance
/ gesture_detector_config_
.maximum_fling_velocity
;
1217 simulated_clock_
->Advance(base::TimeDelta::FromSecondsD(delta_time
));
1218 generator_
->MoveTouch(*swipe
);
1219 EXPECT_TRUE(IsInGestureInProgressState());
1220 EXPECT_FALSE(IsInTouchToMouseMode());
1221 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1222 ASSERT_EQ(0U, captured_events
.size());
1223 generator_
->ReleaseTouch();
1225 // The swipe registered and sent the appropriate key events.
1226 AssertDirectionalNavigationEvents(captured_events
, direction
);
1227 EXPECT_TRUE(IsInNoFingersDownState());
1228 EXPECT_FALSE(IsInTouchToMouseMode());
1229 EXPECT_FALSE(IsInGestureInProgressState());
1230 ClearCapturedEvents();
1234 // Since there are so many permutations, this test is too slow in debug
1235 // mode, so it will only be run in release mode.
1236 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
1237 #define MAYBE_AllFingerPermutations AllFingerPermutations
1239 #define MAYBE_AllFingerPermutations DISABLED_AllFingerPermutations
1242 TEST_F(TouchExplorationTest
, MAYBE_AllFingerPermutations
) {
1243 SwitchTouchExplorationMode(true);
1244 SuppressVLOGs(true);
1245 // We will test all permutations of events from three different fingers
1246 // to ensure that we return to NO_FINGERS_DOWN when fingers have been
1248 ScopedVector
<ui::TouchEvent
> all_events
;
1249 for (int touch_id
= 0; touch_id
< 3; touch_id
++){
1250 int x
= 10*touch_id
+ 1;
1251 int y
= 10*touch_id
+ 2;
1252 all_events
.push_back(new TouchEvent(
1253 ui::ET_TOUCH_PRESSED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1254 all_events
.push_back(new TouchEvent(
1255 ui::ET_TOUCH_MOVED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1256 all_events
.push_back(new TouchEvent(
1257 ui::ET_TOUCH_RELEASED
, gfx::Point(x
, y
), touch_id
, Now()));
1260 // I'm going to explain this algorithm, and use an example in parentheses.
1261 // The example will be all permutations of a b c d.
1262 // There are four letters and 4! = 24 permutations.
1263 const int num_events
= all_events
.size();
1264 const int num_permutations
= Factorial(num_events
);
1266 for (int p
= 0; p
< num_permutations
; p
++) {
1267 std::vector
<ui::TouchEvent
*> queued_events
= all_events
.get();
1268 std::vector
<bool> fingers_pressed(3, false);
1270 int current_num_permutations
= num_permutations
;
1271 for (int events_left
= num_events
; events_left
> 0; events_left
--) {
1272 // |p| indexes to each permutation when there are num_permutations
1273 // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...)
1274 // But how do we find the index for the current number of permutations?
1275 // To find the permutation within the part of the sequence we're
1276 // currently looking at, we need a number between 0 and
1277 // |current_num_permutations| - 1.
1278 // (e.g. if we already chose the first letter, there are 3! = 6
1279 // options left, so we do p % 6. So |current_permutation| would go
1280 // from 0 to 5 and then reset to 0 again, for all combinations of
1281 // whichever three letters are remaining, as we loop through the
1283 int current_permutation
= p
% current_num_permutations
;
1285 // Since this is is the total number of permutations starting with
1286 // this event and including future events, there could be multiple
1287 // values of current_permutation that will generate the same event
1288 // in this iteration.
1289 // (e.g. If we chose 'a' but have b c d to choose from, we choose b when
1290 // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3.
1291 // Note that each letter gets two numbers, which is the next
1292 // current_num_permutations, 2! for the two letters left.)
1294 // Branching out from the first event, there are num_permutations
1295 // permutations, and each value of |p| is associated with one of these
1296 // permutations. However, once the first event is chosen, there
1297 // are now |num_events| - 1 events left, so the number of permutations
1298 // for the rest of the events changes, and will always be equal to
1299 // the factorial of the events_left.
1300 // (e.g. There are 3! = 6 permutations that start with 'a', so if we
1301 // start with 'a' there will be 6 ways to then choose from b c d.)
1302 // So we now set-up for the next iteration by setting
1303 // current_num_permutations to the factorial of the next number of
1305 current_num_permutations
/= events_left
;
1307 // To figure out what current event we want to choose, we integer
1308 // divide the current permutation by the next current_num_permutations.
1309 // (e.g. If there are 4 letters a b c d and 24 permutations, we divide
1310 // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first
1311 // 6 permutations start with 'a', and the last 6 will start with 'd'.
1312 // Note that there are 6 that start with 'a' because there are 6
1313 // permutations for the next three letters that follow 'a'.)
1314 int index
= current_permutation
/ current_num_permutations
;
1316 ui::TouchEvent
* next_dispatch
= queued_events
[index
];
1317 ASSERT_TRUE(next_dispatch
!= NULL
);
1319 // |next_dispatch| has to be put in this container so that its time
1320 // stamp can be changed to this point in the test, when it is being
1322 EventTestApi
test_dispatch(next_dispatch
);
1323 test_dispatch
.set_time_stamp(Now());
1324 generator_
->Dispatch(next_dispatch
);
1325 queued_events
.erase(queued_events
.begin() + index
);
1327 // Keep track of what fingers have been pressed, to release
1328 // only those fingers at the end, so the check for being in
1329 // no fingers down can be accurate.
1330 if (next_dispatch
->type() == ET_TOUCH_PRESSED
) {
1331 fingers_pressed
[next_dispatch
->touch_id()] = true;
1332 } else if (next_dispatch
->type() == ET_TOUCH_RELEASED
) {
1333 fingers_pressed
[next_dispatch
->touch_id()] = false;
1336 ASSERT_EQ(queued_events
.size(), 0u);
1338 // Release fingers recorded as pressed.
1339 for(int j
= 0; j
< int(fingers_pressed
.size()); j
++){
1340 if (fingers_pressed
[j
] == true) {
1341 generator_
->ReleaseTouchId(j
);
1342 fingers_pressed
[j
] = false;
1345 AdvanceSimulatedTimePastPotentialTapDelay();
1346 EXPECT_TRUE(IsInNoFingersDownState());
1347 ClearCapturedEvents();
1351 // With the simple swipe gestures, if additional fingers are added, then the
1352 // state should change to passthrough.
1353 TEST_F(TouchExplorationTest
, FromGestureToPassthrough
) {
1354 SwitchTouchExplorationMode(true);
1355 EXPECT_FALSE(IsInTouchToMouseMode());
1356 EXPECT_FALSE(IsInGestureInProgressState());
1358 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1359 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, gfx::Point(0, 1), 0, Now());
1360 generator_
->Dispatch(&first_press
);
1361 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1362 gfx::Point
second_location(distance
, 1);
1363 generator_
->MoveTouch(second_location
);
1364 EXPECT_TRUE(IsInGestureInProgressState());
1365 EXPECT_FALSE(IsInTouchToMouseMode());
1366 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1367 ASSERT_EQ(0U, captured_events
.size());
1369 // Generate a second press that should go through as is.
1370 ui::TouchEvent
second_press(
1371 ui::ET_TOUCH_PRESSED
, gfx::Point(20, 21), 1, Now());
1372 generator_
->Dispatch(&second_press
);
1373 EXPECT_FALSE(IsInGestureInProgressState());
1374 EXPECT_FALSE(IsInTouchToMouseMode());
1375 std::vector
<ui::LocatedEvent
*> captured_located_events
=
1376 GetCapturedLocatedEvents();
1377 ASSERT_EQ(1U, captured_events
.size());
1378 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_located_events
[0], &second_press
);
1379 ClearCapturedEvents();
1381 // The rest of the events should occur in passthrough.
1382 generator_
->ReleaseTouchId(0);
1383 ASSERT_EQ(1U, captured_events
.size());
1384 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[0]->type());
1385 ClearCapturedEvents();
1386 generator_
->ReleaseTouchId(1);
1387 ASSERT_EQ(0U, captured_events
.size());