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/gfx/geometry/point.h"
17 #include "ui/gl/gl_implementation.h"
18 #include "ui/gl/gl_surface.h"
23 // Records all mouse and touch events.
24 class EventCapturer
: public ui::EventHandler
{
27 virtual ~EventCapturer() {}
33 virtual void OnEvent(ui::Event
* event
) OVERRIDE
{
34 if (event
->IsMouseEvent()) {
36 new ui::MouseEvent(static_cast<ui::MouseEvent
&>(*event
)));
37 } else if (event
->IsTouchEvent()) {
39 new ui::TouchEvent(static_cast<ui::TouchEvent
&>(*event
)));
43 // Stop event propagation so we don't click on random stuff that
44 // might break test assumptions.
45 event
->StopPropagation();
46 // If there is a possibility that we're in an infinite loop, we should
47 // exit early with a sensible error rather than letting the test time out.
48 ASSERT_LT(events_
.size(), 100u);
50 const ScopedVector
<ui::LocatedEvent
>& captured_events() const {
55 ScopedVector
<ui::LocatedEvent
> events_
;
57 DISALLOW_COPY_AND_ASSIGN(EventCapturer
);
62 class TouchExplorationTest
: public aura::test::AuraTestBase
{
64 TouchExplorationTest()
65 : simulated_clock_(new base::SimpleTestTickClock()) {}
66 virtual ~TouchExplorationTest() {}
68 virtual void SetUp() OVERRIDE
{
69 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone
)
70 gfx::GLSurface::InitializeOneOffForTests();
71 aura::test::AuraTestBase::SetUp();
72 cursor_client_
.reset(new aura::test::TestCursorClient(root_window()));
73 root_window()->AddPreTargetHandler(&event_capturer_
);
74 generator_
.reset(new aura::test::EventGenerator(root_window()));
75 // The generator takes ownership of the clock.
76 generator_
->SetTickClock(scoped_ptr
<base::TickClock
>(simulated_clock_
));
77 cursor_client()->ShowCursor();
78 cursor_client()->DisableMouseEvents();
81 virtual void TearDown() OVERRIDE
{
82 root_window()->RemovePreTargetHandler(&event_capturer_
);
83 SwitchTouchExplorationMode(false);
84 cursor_client_
.reset();
85 aura::test::AuraTestBase::TearDown();
89 aura::client::CursorClient
* cursor_client() { return cursor_client_
.get(); }
91 const ScopedVector
<ui::LocatedEvent
>& GetCapturedEvents() {
92 return event_capturer_
.captured_events();
95 std::vector
<ui::LocatedEvent
*> GetCapturedEventsOfType(int type
) {
96 const ScopedVector
<ui::LocatedEvent
>& all_events
= GetCapturedEvents();
97 std::vector
<ui::LocatedEvent
*> events
;
98 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
99 if (type
== all_events
[i
]->type())
100 events
.push_back(all_events
[i
]);
105 void ClearCapturedEvents() {
106 event_capturer_
.Reset();
109 void AdvanceSimulatedTimePastTapDelay() {
110 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
111 touch_exploration_controller_
->CallTapTimerNowForTesting();
114 void SwitchTouchExplorationMode(bool on
) {
115 if (!on
&& touch_exploration_controller_
.get()) {
116 touch_exploration_controller_
.reset();
117 } else if (on
&& !touch_exploration_controller_
.get()) {
118 touch_exploration_controller_
.reset(
119 new ui::TouchExplorationController(root_window()));
120 touch_exploration_controller_
->SetEventHandlerForTesting(
122 cursor_client()->ShowCursor();
123 cursor_client()->DisableMouseEvents();
127 void EnterTouchExplorationModeAtLocation(gfx::Point tap_location
) {
128 ui::TouchEvent
touch_press(ui::ET_TOUCH_PRESSED
, tap_location
, 0, Now());
129 generator_
->Dispatch(&touch_press
);
130 AdvanceSimulatedTimePastTapDelay();
131 EXPECT_TRUE(IsInTouchToMouseMode());
134 bool IsInTouchToMouseMode() {
135 aura::client::CursorClient
* cursor_client
=
136 aura::client::GetCursorClient(root_window());
137 return cursor_client
&&
138 cursor_client
->IsMouseEventsEnabled() &&
139 !cursor_client
->IsCursorVisible();
142 bool IsInNoFingersDownState() {
143 return touch_exploration_controller_
->IsInNoFingersDownStateForTesting();
146 base::TimeDelta
Now() {
147 // This is the same as what EventTimeForNow() does, but here we do it
148 // with our simulated clock.
149 return base::TimeDelta::FromInternalValue(
150 simulated_clock_
->NowTicks().ToInternalValue());
153 scoped_ptr
<aura::test::EventGenerator
> generator_
;
154 ui::GestureDetector::Config gesture_detector_config_
;
155 // Owned by |generator_|.
156 base::SimpleTestTickClock
* simulated_clock_
;
159 EventCapturer event_capturer_
;
160 scoped_ptr
<ui::TouchExplorationController
> touch_exploration_controller_
;
161 scoped_ptr
<aura::test::TestCursorClient
> cursor_client_
;
163 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest
);
166 // Executes a number of assertions to confirm that |e1| and |e2| are touch
167 // events and are equal to each other.
168 void ConfirmEventsAreTouchAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
169 ASSERT_TRUE(e1
->IsTouchEvent());
170 ASSERT_TRUE(e2
->IsTouchEvent());
171 ui::TouchEvent
* touch_event1
= static_cast<ui::TouchEvent
*>(e1
);
172 ui::TouchEvent
* touch_event2
= static_cast<ui::TouchEvent
*>(e2
);
173 EXPECT_EQ(touch_event1
->type(), touch_event2
->type());
174 EXPECT_EQ(touch_event1
->location(), touch_event2
->location());
175 EXPECT_EQ(touch_event1
->touch_id(), touch_event2
->touch_id());
176 EXPECT_EQ(touch_event1
->flags(), touch_event2
->flags());
177 EXPECT_EQ(touch_event1
->time_stamp(), touch_event2
->time_stamp());
180 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
181 // events and are equal to each other.
182 void ConfirmEventsAreMouseAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
183 ASSERT_TRUE(e1
->IsMouseEvent());
184 ASSERT_TRUE(e2
->IsMouseEvent());
185 ui::MouseEvent
* mouse_event1
= static_cast<ui::MouseEvent
*>(e1
);
186 ui::MouseEvent
* mouse_event2
= static_cast<ui::MouseEvent
*>(e2
);
187 EXPECT_EQ(mouse_event1
->type(), mouse_event2
->type());
188 EXPECT_EQ(mouse_event1
->location(), mouse_event2
->location());
189 EXPECT_EQ(mouse_event1
->root_location(), mouse_event2
->root_location());
190 EXPECT_EQ(mouse_event1
->flags(), mouse_event2
->flags());
193 #define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
194 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
196 #define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
197 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
199 // TODO(mfomitchev): Need to investigate why we don't get mouse enter/exit
200 // events when running these tests as part of ui_unittests. We do get them when
201 // the tests are run as part of ash unit tests.
203 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterPressAndDelay
) {
204 SwitchTouchExplorationMode(true);
205 EXPECT_FALSE(IsInTouchToMouseMode());
206 generator_
->PressTouch();
207 AdvanceSimulatedTimePastTapDelay();
208 EXPECT_TRUE(IsInTouchToMouseMode());
211 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterMoveOutsideSlop
) {
212 int slop
= gesture_detector_config_
.touch_slop
;
213 int half_slop
= slop
/ 2;
215 SwitchTouchExplorationMode(true);
216 EXPECT_FALSE(IsInTouchToMouseMode());
217 generator_
->set_current_location(gfx::Point(11, 12));
218 generator_
->PressTouch();
219 generator_
->MoveTouch(gfx::Point(11 + half_slop
, 12));
220 EXPECT_FALSE(IsInTouchToMouseMode());
221 generator_
->MoveTouch(gfx::Point(11, 12 + half_slop
));
222 EXPECT_FALSE(IsInTouchToMouseMode());
223 generator_
->MoveTouch(gfx::Point(11 + slop
+ 1, 12));
224 EXPECT_TRUE(IsInTouchToMouseMode());
227 TEST_F(TouchExplorationTest
, OneFingerTap
) {
228 SwitchTouchExplorationMode(true);
229 gfx::Point
location(11, 12);
230 generator_
->set_current_location(location
);
231 generator_
->PressTouch();
232 generator_
->ReleaseTouch();
233 AdvanceSimulatedTimePastTapDelay();
235 std::vector
<ui::LocatedEvent
*> events
=
236 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
237 ASSERT_EQ(1U, events
.size());
239 EXPECT_EQ(location
, events
[0]->location());
240 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
241 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
242 EXPECT_TRUE(IsInNoFingersDownState());
245 TEST_F(TouchExplorationTest
, ActualMouseMovesUnaffected
) {
246 SwitchTouchExplorationMode(true);
248 gfx::Point
location_start(11, 12);
249 gfx::Point
location_end(13, 14);
250 generator_
->set_current_location(location_start
);
251 generator_
->PressTouch();
252 AdvanceSimulatedTimePastTapDelay();
253 generator_
->MoveTouch(location_end
);
255 gfx::Point
location_real_mouse_move(15, 16);
256 ui::MouseEvent
mouse_move(ui::ET_MOUSE_MOVED
,
257 location_real_mouse_move
,
258 location_real_mouse_move
,
261 generator_
->Dispatch(&mouse_move
);
262 generator_
->ReleaseTouch();
263 AdvanceSimulatedTimePastTapDelay();
265 std::vector
<ui::LocatedEvent
*> events
=
266 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
267 ASSERT_EQ(4U, events
.size());
269 EXPECT_EQ(location_start
, events
[0]->location());
270 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
271 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
273 EXPECT_EQ(location_end
, events
[1]->location());
274 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
275 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
277 // The real mouse move goes through.
278 EXPECT_EQ(location_real_mouse_move
, events
[2]->location());
279 CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(events
[2], &mouse_move
);
280 EXPECT_FALSE(events
[2]->flags() & ui::EF_IS_SYNTHESIZED
);
281 EXPECT_FALSE(events
[2]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
283 // The touch release gets written as a mouse move.
284 EXPECT_EQ(location_end
, events
[3]->location());
285 EXPECT_TRUE(events
[3]->flags() & ui::EF_IS_SYNTHESIZED
);
286 EXPECT_TRUE(events
[3]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
287 EXPECT_TRUE(IsInNoFingersDownState());
290 // Turn the touch exploration mode on in the middle of the touch gesture.
291 // Confirm that events from the finger which was touching when the mode was
292 // turned on don't get rewritten.
293 TEST_F(TouchExplorationTest
, TurnOnMidTouch
) {
294 SwitchTouchExplorationMode(false);
295 generator_
->PressTouchId(1);
296 EXPECT_TRUE(cursor_client()->IsCursorVisible());
297 ClearCapturedEvents();
299 // Enable touch exploration mode while the first finger is touching the
300 // screen. Ensure that subsequent events from that first finger are not
301 // affected by the touch exploration mode, while the touch events from another
302 // finger get rewritten.
303 SwitchTouchExplorationMode(true);
304 ui::TouchEvent
touch_move(ui::ET_TOUCH_MOVED
,
308 generator_
->Dispatch(&touch_move
);
309 EXPECT_TRUE(cursor_client()->IsCursorVisible());
310 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
311 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
312 ASSERT_EQ(1u, captured_events
.size());
313 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_move
);
314 ClearCapturedEvents();
316 // The press from the second finger should get rewritten.
317 generator_
->PressTouchId(2);
318 AdvanceSimulatedTimePastTapDelay();
319 EXPECT_TRUE(IsInTouchToMouseMode());
320 ScopedVector
<ui::LocatedEvent
>::const_iterator it
;
321 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
322 if ((*it
)->type() == ui::ET_MOUSE_MOVED
)
325 EXPECT_NE(captured_events
.end(), it
);
326 ClearCapturedEvents();
328 // The release of the first finger shouldn't be affected.
329 ui::TouchEvent
touch_release(ui::ET_TOUCH_RELEASED
,
333 generator_
->Dispatch(&touch_release
);
334 ASSERT_EQ(1u, captured_events
.size());
335 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_release
);
336 ClearCapturedEvents();
338 // The move and release from the second finger should get rewritten.
339 generator_
->MoveTouchId(gfx::Point(13, 14), 2);
340 generator_
->ReleaseTouchId(2);
341 AdvanceSimulatedTimePastTapDelay();
343 ASSERT_EQ(2u, captured_events
.size());
344 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
345 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
346 EXPECT_TRUE(IsInNoFingersDownState());
349 TEST_F(TouchExplorationTest
, TwoFingerTouch
) {
350 SwitchTouchExplorationMode(true);
351 generator_
->PressTouchId(1);
352 ClearCapturedEvents();
354 // Confirm events from the second finger go through as is.
355 ui::TouchEvent
touch_press(
356 ui::ET_TOUCH_PRESSED
,
360 generator_
->Dispatch(&touch_press
);
361 EXPECT_TRUE(cursor_client()->IsCursorVisible());
362 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
363 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
364 // TODO(mfomitchev): mouse enter/exit events
365 // There will be a ET_MOUSE_EXITED event synthesized when the mouse cursor is
366 // hidden - ignore it.
367 ScopedVector
<ui::LocatedEvent
>::const_iterator it
;
368 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
369 if ((*it
)->type() == ui::ET_TOUCH_PRESSED
) {
370 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(*it
, &touch_press
);
374 EXPECT_NE(captured_events
.end(), it
);
375 ClearCapturedEvents();
376 ui::TouchEvent
touch_move(
381 generator_
->Dispatch(&touch_move
);
382 ASSERT_EQ(1u, captured_events
.size());
383 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_move
);
384 ClearCapturedEvents();
386 // Confirm mouse moves go through unaffected.
387 ui::MouseEvent
mouse_move(ui::ET_MOUSE_MOVED
,
392 generator_
->Dispatch(&mouse_move
);
393 // TODO(mfomitchev): mouse enter/exit events
394 // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
395 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
396 if ((*it
)->type() == ui::ET_MOUSE_MOVED
) {
397 CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(*it
, &mouse_move
);
401 EXPECT_NE(captured_events
.end(), it
);
402 ClearCapturedEvents();
404 // Events from the first finger should not go through while the second finger
406 gfx::Point touch1_location
= gfx::Point(15, 16);
407 generator_
->MoveTouchId(touch1_location
, 1);
408 EXPECT_EQ(0u, GetCapturedEvents().size());
410 EXPECT_TRUE(cursor_client()->IsCursorVisible());
411 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
413 // A release of the second finger should be rewritten as a mouse move
414 // of that finger to the |touch1_location| and we stay in passthrough
416 ui::TouchEvent
touch_release(
417 ui::ET_TOUCH_RELEASED
,
421 generator_
->Dispatch(&touch_release
);
422 EXPECT_FALSE(IsInTouchToMouseMode());
423 ASSERT_EQ(captured_events
.size(), 1u);
424 EXPECT_EQ(touch1_location
, captured_events
[0]->location());
427 TEST_F(TouchExplorationTest
, MultiFingerTouch
) {
428 SwitchTouchExplorationMode(true);
429 generator_
->PressTouchId(1);
430 generator_
->PressTouchId(2);
431 ClearCapturedEvents();
433 // Confirm events from other fingers go through as is.
434 ui::TouchEvent
touch3_press(ui::ET_TOUCH_PRESSED
,
438 ui::TouchEvent
touch3_move1(ui::ET_TOUCH_MOVED
,
442 ui::TouchEvent
touch4_press(ui::ET_TOUCH_PRESSED
,
446 ui::TouchEvent
touch3_move2(ui::ET_TOUCH_MOVED
,
450 ui::TouchEvent
touch4_move(ui::ET_TOUCH_MOVED
,
454 ui::TouchEvent
touch3_release(ui::ET_TOUCH_RELEASED
,
458 ui::TouchEvent
touch4_release(ui::ET_TOUCH_RELEASED
,
462 generator_
->Dispatch(&touch3_press
);
463 generator_
->Dispatch(&touch3_move1
);
464 generator_
->Dispatch(&touch4_press
);
465 generator_
->Dispatch(&touch3_move2
);
466 generator_
->Dispatch(&touch4_move
);
467 generator_
->Dispatch(&touch3_release
);
468 generator_
->Dispatch(&touch4_release
);
470 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
471 ASSERT_EQ(7u, captured_events
.size());
472 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch3_press
);
473 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[1], &touch3_move1
);
474 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[2], &touch4_press
);
475 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[3], &touch3_move2
);
476 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[4], &touch4_move
);
478 // The release of finger 3 is rewritten as a move to the former location
480 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[5]->type());
481 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[6], &touch4_release
);
484 // Test the case when there are multiple fingers on the screen and the first
485 // finger is released. This should be ignored, but then the second finger
486 // release should be passed through.
487 TEST_F(TouchExplorationTest
, FirstFingerLifted
) {
488 SwitchTouchExplorationMode(true);
489 generator_
->PressTouchId(1);
490 generator_
->PressTouchId(2);
491 gfx::Point
touch2_location(10, 11);
492 generator_
->MoveTouchId(touch2_location
, 2);
493 generator_
->PressTouchId(3);
494 gfx::Point
touch3_location(20, 21);
495 generator_
->MoveTouchId(touch3_location
, 3);
496 ClearCapturedEvents();
498 // Release of finger 1 should be ignored.
499 generator_
->ReleaseTouchId(1);
500 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
501 ASSERT_EQ(0u, captured_events
.size());
503 // Move of finger 2 should be passed through.
504 gfx::Point
touch2_new_location(20, 11);
505 generator_
->MoveTouchId(touch2_new_location
, 2);
506 ASSERT_EQ(1u, captured_events
.size());
507 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
508 EXPECT_EQ(touch2_new_location
, captured_events
[0]->location());
509 ClearCapturedEvents();
511 // Release of finger 2 should be passed through.
512 ui::TouchEvent
touch2_release(
513 ui::ET_TOUCH_RELEASED
,
517 generator_
->Dispatch(&touch2_release
);
518 ASSERT_EQ(1u, captured_events
.size());
519 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch2_release
);
522 // Test the case when there are multiple fingers on the screen and the
523 // second finger is released. This should be rewritten as a move to the
524 // location of the first finger.
525 TEST_F(TouchExplorationTest
, SecondFingerLifted
) {
526 SwitchTouchExplorationMode(true);
527 gfx::Point
touch1_location(0, 11);
528 generator_
->set_current_location(touch1_location
);
529 generator_
->PressTouchId(1);
530 generator_
->PressTouchId(2);
531 gfx::Point
touch2_location(10, 11);
532 generator_
->MoveTouchId(touch2_location
, 2);
533 generator_
->PressTouchId(3);
534 gfx::Point
touch3_location(20, 21);
535 generator_
->MoveTouchId(touch3_location
, 3);
536 ClearCapturedEvents();
538 // Release of finger 2 should be rewritten as a move to the location
539 // of the first finger.
540 generator_
->ReleaseTouchId(2);
541 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
542 ASSERT_EQ(1u, captured_events
.size());
543 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
544 EXPECT_EQ(2, static_cast<ui::TouchEvent
*>(captured_events
[0])->touch_id());
545 EXPECT_EQ(touch1_location
, captured_events
[0]->location());
546 ClearCapturedEvents();
548 // Move of finger 1 should be rewritten as a move of finger 2.
549 gfx::Point
touch1_new_location(0, 41);
550 generator_
->MoveTouchId(touch1_new_location
, 1);
551 ASSERT_EQ(1u, captured_events
.size());
552 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
553 EXPECT_EQ(2, static_cast<ui::TouchEvent
*>(captured_events
[0])->touch_id());
554 EXPECT_EQ(touch1_new_location
, captured_events
[0]->location());
555 ClearCapturedEvents();
557 // Release of finger 1 should be rewritten as release of finger 2.
558 gfx::Point
touch1_final_location(0, 41);
559 ui::TouchEvent
touch1_release(
560 ui::ET_TOUCH_RELEASED
,
561 touch1_final_location
,
564 generator_
->Dispatch(&touch1_release
);
565 ASSERT_EQ(1u, captured_events
.size());
566 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[0]->type());
567 EXPECT_EQ(2, static_cast<ui::TouchEvent
*>(captured_events
[0])->touch_id());
568 EXPECT_EQ(touch1_final_location
, captured_events
[0]->location());
571 // If an event is received after the double-tap timeout has elapsed, but
572 // before the timer has fired, a mouse move should still be generated.
573 TEST_F(TouchExplorationTest
, TimerFiresLateDuringTouchExploration
) {
574 SwitchTouchExplorationMode(true);
576 // Send a press, then add another finger after the double-tap timeout.
577 generator_
->PressTouchId(1);
578 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
579 generator_
->PressTouchId(2);
580 std::vector
<ui::LocatedEvent
*> events
=
581 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
582 ASSERT_EQ(1U, events
.size());
583 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
584 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
586 generator_
->ReleaseTouchId(2);
587 generator_
->ReleaseTouchId(1);
588 AdvanceSimulatedTimePastTapDelay();
589 EXPECT_TRUE(IsInNoFingersDownState());
592 // If a new tap is received after the double-tap timeout has elapsed from
593 // a previous tap, but before the timer has fired, a mouse move should
594 // still be generated from the old tap.
595 TEST_F(TouchExplorationTest
, TimerFiresLateAfterTap
) {
596 SwitchTouchExplorationMode(true);
598 // Send a tap at location1.
599 gfx::Point
location0(11, 12);
600 generator_
->set_current_location(location0
);
601 generator_
->PressTouch();
602 generator_
->ReleaseTouch();
604 // Send a tap at location2, after the double-tap timeout, but before the
606 gfx::Point
location1(33, 34);
607 generator_
->set_current_location(location1
);
608 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(301));
609 generator_
->PressTouch();
610 generator_
->ReleaseTouch();
611 AdvanceSimulatedTimePastTapDelay();
613 std::vector
<ui::LocatedEvent
*> events
=
614 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
615 ASSERT_EQ(2U, events
.size());
616 EXPECT_EQ(location0
, events
[0]->location());
617 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
618 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
619 EXPECT_EQ(location1
, events
[1]->location());
620 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
621 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
622 EXPECT_TRUE(IsInNoFingersDownState());
625 // Double-tapping should send a touch press and release through to the location
626 // of the last successful touch exploration.
627 TEST_F(TouchExplorationTest
, DoubleTap
) {
628 SwitchTouchExplorationMode(true);
630 // Tap at one location, and get a mouse move event.
631 gfx::Point
tap_location(11, 12);
632 generator_
->set_current_location(tap_location
);
633 generator_
->PressTouch();
634 generator_
->ReleaseTouch();
635 AdvanceSimulatedTimePastTapDelay();
637 std::vector
<ui::LocatedEvent
*> events
=
638 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
639 ASSERT_EQ(1U, events
.size());
641 EXPECT_EQ(tap_location
, events
[0]->location());
642 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
643 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
644 ClearCapturedEvents();
646 // Now double-tap at a different location. This should result in
647 // a single touch press and release at the location of the tap,
648 // not at the location of the double-tap.
649 gfx::Point
double_tap_location(33, 34);
650 generator_
->set_current_location(double_tap_location
);
651 generator_
->PressTouch();
652 generator_
->ReleaseTouch();
653 generator_
->PressTouch();
654 generator_
->ReleaseTouch();
656 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
657 ASSERT_EQ(2U, captured_events
.size());
658 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
659 EXPECT_EQ(tap_location
, captured_events
[0]->location());
660 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
661 EXPECT_EQ(tap_location
, captured_events
[1]->location());
662 EXPECT_TRUE(IsInNoFingersDownState());
665 // Double-tapping where the user holds their finger down for the second time
666 // for a longer press should send a touch press and released (right click)
667 // to the location of the last successful touch exploration.
668 TEST_F(TouchExplorationTest
, DoubleTapLongPress
) {
669 SwitchTouchExplorationMode(true);
671 // Tap at one location, and get a mouse move event.
672 gfx::Point
tap_location(11, 12);
673 generator_
->set_current_location(tap_location
);
674 generator_
->PressTouch();
675 generator_
->ReleaseTouch();
676 AdvanceSimulatedTimePastTapDelay();
678 std::vector
<ui::LocatedEvent
*> events
=
679 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
680 ASSERT_EQ(1U, events
.size());
682 EXPECT_EQ(tap_location
, events
[0]->location());
683 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
684 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
685 ClearCapturedEvents();
687 // Now double-tap and hold at a different location.
688 // This should result in a single touch long press and release
689 // at the location of the tap, not at the location of the double-tap.
690 // There should be a time delay between the touch press and release.
691 gfx::Point
first_tap_location(33, 34);
692 generator_
->set_current_location(first_tap_location
);
693 generator_
->PressTouch();
694 generator_
->ReleaseTouch();
695 gfx::Point
second_tap_location(23, 24);
696 generator_
->set_current_location(second_tap_location
);
697 generator_
->PressTouch();
698 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
699 generator_
->ReleaseTouch();
701 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
702 ASSERT_EQ(2U, captured_events
.size());
703 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
704 EXPECT_EQ(tap_location
, captured_events
[0]->location());
705 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
706 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
707 EXPECT_EQ(tap_location
, captured_events
[1]->location());
708 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
709 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
710 released_time
- pressed_time
);
713 // Single-tapping should send a touch press and release through to the location
714 // of the last successful touch exploration if the grace period has not
716 TEST_F(TouchExplorationTest
, SingleTap
) {
717 SwitchTouchExplorationMode(true);
719 // Tap once to simulate a mouse moved event.
720 gfx::Point
initial_location(11, 12);
721 generator_
->set_current_location(initial_location
);
722 generator_
->PressTouch();
724 // Move to another location for single tap
725 gfx::Point
tap_location(22, 23);
726 generator_
->MoveTouch(tap_location
);
727 generator_
->ReleaseTouch();
729 // Allow time to pass within the grace period of releasing before
731 gfx::Point
final_location(33, 34);
732 generator_
->set_current_location(final_location
);
733 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(250));
734 generator_
->PressTouch();
735 generator_
->ReleaseTouch();
737 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
738 ASSERT_EQ(4U, captured_events
.size());
739 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
740 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
741 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
742 EXPECT_EQ(tap_location
, captured_events
[2]->location());
743 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[3]->type());
744 EXPECT_EQ(tap_location
, captured_events
[3]->location());
747 // Double-tapping without coming from touch exploration (no previous touch
748 // exploration event) should not generate any events.
749 TEST_F(TouchExplorationTest
, DoubleTapNoTouchExplore
) {
750 SwitchTouchExplorationMode(true);
752 // Double-tap without any previous touch.
753 // Touch exploration mode has not been entered, so there is no previous
754 // touch exploration event. The double-tap should be discarded, and no events
755 // should be generated at all.
756 gfx::Point
double_tap_location(33, 34);
757 generator_
->set_current_location(double_tap_location
);
758 generator_
->PressTouch();
759 generator_
->ReleaseTouch();
760 generator_
->PressTouch();
761 generator_
->ReleaseTouch();
763 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
764 ASSERT_EQ(0U, captured_events
.size());
767 // Tapping and releasing with a second finger when in touch exploration mode
768 // should send a touch press and released to the location of the last
769 // successful touch exploration and return to touch explore.
770 TEST_F(TouchExplorationTest
, SplitTap
) {
771 SwitchTouchExplorationMode(true);
772 gfx::Point
initial_touch_location(11, 12);
773 gfx::Point
second_touch_location(33, 34);
775 // Tap and hold at one location, and get a mouse move event in touch explore.
776 EnterTouchExplorationModeAtLocation(initial_touch_location
);
777 std::vector
<ui::LocatedEvent
*> events
=
778 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
779 ASSERT_EQ(1U, events
.size());
781 EXPECT_EQ(initial_touch_location
, events
[0]->location());
782 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
783 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
784 ClearCapturedEvents();
786 // Now tap and release at a different location. This should result in a
787 // single touch and release at the location of the first (held) tap,
788 // not at the location of the second tap and release.
789 // After the release, there is still a finger in touch explore mode.
790 ui::TouchEvent
split_tap_press(
791 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
792 generator_
->Dispatch(&split_tap_press
);
793 ui::TouchEvent
split_tap_release(
794 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
795 generator_
->Dispatch(&split_tap_release
);
796 EXPECT_FALSE(IsInNoFingersDownState());
798 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
799 ASSERT_EQ(2U, captured_events
.size());
800 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
801 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
802 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
803 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
806 // If split tap is started but the touch explore finger is released first,
807 // there should still be a touch press and release sent to the location of
808 // the last successful touch exploration.
809 // Both fingers should be released after the click goes through.
810 TEST_F(TouchExplorationTest
, SplitTapRelease
) {
811 SwitchTouchExplorationMode(true);
813 gfx::Point
initial_touch_location(11, 12);
814 gfx::Point
second_touch_location(33, 34);
816 // Tap and hold at one location, and get a mouse move event in touch explore.
817 EnterTouchExplorationModeAtLocation(initial_touch_location
);
819 std::vector
<ui::LocatedEvent
*> events
=
820 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
821 ASSERT_EQ(1U, events
.size());
823 ClearCapturedEvents();
825 // Now tap at a different location. Release at the first location,
826 // then release at the second. This should result in a
827 // single touch and release at the location of the first (held) tap,
828 // not at the location of the second tap and release.
829 ui::TouchEvent
split_tap_press(
830 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
831 generator_
->Dispatch(&split_tap_press
);
832 ui::TouchEvent
touch_explore_release(
833 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
834 generator_
->Dispatch(&touch_explore_release
);
835 ui::TouchEvent
split_tap_release(
836 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
837 generator_
->Dispatch(&split_tap_release
);
838 EXPECT_TRUE(IsInNoFingersDownState());
840 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
841 ASSERT_EQ(2U, captured_events
.size());
842 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
843 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
844 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
845 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
848 // When in touch exploration mode, making a long press with a second finger
849 // should send a touch press and released to the location of the last
850 // successful touch exploration. There should be a delay between the
851 // touch and release events (right click).
852 TEST_F(TouchExplorationTest
, SplitTapLongPress
) {
853 SwitchTouchExplorationMode(true);
854 gfx::Point
initial_touch_location(11, 12);
855 gfx::Point
second_touch_location(33, 34);
857 // Tap and hold at one location, and get a mouse move event in touch explore.
858 EnterTouchExplorationModeAtLocation(initial_touch_location
);
859 std::vector
<ui::LocatedEvent
*> events
=
860 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
861 ASSERT_EQ(1U, events
.size());
863 ClearCapturedEvents();
865 // Now tap and release at a different location. This should result in a
866 // single touch and release at the location of the first (held) tap,
867 // not at the location of the second tap and release.
868 // After the release, there is still a finger in touch explore mode.
869 ui::TouchEvent
split_tap_press(
870 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
871 generator_
->Dispatch(&split_tap_press
);
872 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
873 ui::TouchEvent
split_tap_release(
874 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
875 generator_
->Dispatch(&split_tap_release
);
876 EXPECT_FALSE(IsInNoFingersDownState());
878 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
879 ASSERT_EQ(2U, captured_events
.size());
880 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
881 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
882 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
883 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
884 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
885 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
886 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
887 released_time
- pressed_time
);
890 // If split tap is started but the touch explore finger is released first,
891 // there should still be a touch press and release sent to the location of
892 // the last successful touch exploration. If the remaining finger is held
893 // as a longpress, there should be a delay between the sent touch and release
894 // events (right click).All fingers should be released after the click
896 TEST_F(TouchExplorationTest
, SplitTapReleaseLongPress
) {
897 SwitchTouchExplorationMode(true);
898 gfx::Point
initial_touch_location(11, 12);
899 gfx::Point
second_touch_location(33, 34);
901 // Tap and hold at one location, and get a mouse move event in touch explore.
902 EnterTouchExplorationModeAtLocation(initial_touch_location
);
903 std::vector
<ui::LocatedEvent
*> events
=
904 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
905 ASSERT_EQ(1U, events
.size());
906 ClearCapturedEvents();
908 // Now tap at a different location. Release at the first location,
909 // then release at the second. This should result in a
910 // single touch and release at the location of the first (held) tap,
911 // not at the location of the second tap and release.
912 // After the release, TouchToMouseMode should still be on.
913 ui::TouchEvent
split_tap_press(
914 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
915 generator_
->Dispatch(&split_tap_press
);
916 ui::TouchEvent
touch_explore_release(
917 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
918 generator_
->Dispatch(&touch_explore_release
);
919 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
920 ui::TouchEvent
split_tap_release(
921 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
922 generator_
->Dispatch(&split_tap_release
);
923 EXPECT_TRUE(IsInTouchToMouseMode());
925 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
926 ASSERT_EQ(2U, captured_events
.size());
927 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
928 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
929 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
930 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
931 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
932 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
933 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
934 released_time
- pressed_time
);
937 TEST_F(TouchExplorationTest
, SplitTapLongPressMultiFinger
) {
938 SwitchTouchExplorationMode(true);
939 gfx::Point
initial_touch_location(11, 12);
940 gfx::Point
second_touch_location(33, 34);
941 gfx::Point
third_touch_location(16, 17);
943 // Tap and hold at one location, and get a mouse move event in touch explore.
944 EnterTouchExplorationModeAtLocation(initial_touch_location
);
946 std::vector
<ui::LocatedEvent
*> events
=
947 GetCapturedEventsOfType(ui::ET_MOUSE_MOVED
);
948 ASSERT_EQ(1U, events
.size());
950 EXPECT_EQ(initial_touch_location
, events
[0]->location());
951 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
952 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
953 ClearCapturedEvents();
955 // Now tap at a different location and hold for long press.
956 ui::TouchEvent
split_tap_press(
957 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
958 generator_
->Dispatch(&split_tap_press
);
959 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
961 // Placing a third finger on the screen should be discarded and not affect
962 // the events passed through.
963 ui::TouchEvent
third_press(
964 ui::ET_TOUCH_PRESSED
, third_touch_location
, 2, Now());
965 generator_
->Dispatch(&third_press
);
967 // When all three fingers are released, there should be only two captured
968 // events: touch press and touch release. All fingers should then be up.
969 ui::TouchEvent
touch_explore_release(
970 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
971 generator_
->Dispatch(&touch_explore_release
);
972 ui::TouchEvent
split_tap_release(
973 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
974 generator_
->Dispatch(&split_tap_release
);
975 ui::TouchEvent
third_tap_release(
976 ui::ET_TOUCH_RELEASED
, third_touch_location
, 2, Now());
977 generator_
->Dispatch(&third_tap_release
);
979 const ScopedVector
<ui::LocatedEvent
>& captured_events
= GetCapturedEvents();
980 ASSERT_EQ(2U, captured_events
.size());
981 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
982 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
983 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
984 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
985 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
986 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
987 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
988 released_time
- pressed_time
);
989 EXPECT_TRUE(IsInNoFingersDownState());