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/test_cursor_client.h"
12 #include "ui/aura/window.h"
13 #include "ui/events/event.h"
14 #include "ui/events/event_utils.h"
15 #include "ui/events/gestures/gesture_provider_aura.h"
16 #include "ui/events/test/event_generator.h"
17 #include "ui/events/test/events_test_utils.h"
18 #include "ui/gfx/geometry/point.h"
19 #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 ~EventCapturer() override
{}
36 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);
75 class MockTouchExplorationControllerDelegate
76 : public ui::TouchExplorationControllerDelegate
{
78 void SetOutputLevel(int volume
) override
{
79 volume_changes_
.push_back(volume
);
81 void SilenceSpokenFeedback() override
{}
82 void PlayVolumeAdjustEarcon() override
{ ++num_times_adjust_sound_played_
; }
83 void PlayPassthroughEarcon() override
{ ++num_times_passthrough_played_
; }
84 void PlayExitScreenEarcon() override
{ ++num_times_exit_screen_played_
; }
85 void PlayEnterScreenEarcon() override
{ ++num_times_enter_screen_played_
; }
87 const std::vector
<float> VolumeChanges() { return volume_changes_
; }
88 size_t NumAdjustSounds() { return num_times_adjust_sound_played_
; }
89 size_t NumPassthroughSounds() { return num_times_passthrough_played_
; }
90 size_t NumExitScreenSounds() { return num_times_exit_screen_played_
; }
91 size_t NumEnterScreenSounds() {
92 return num_times_enter_screen_played_
;
95 void ResetCountersToZero() {
96 num_times_adjust_sound_played_
= 0;
97 num_times_passthrough_played_
= 0;
98 num_times_exit_screen_played_
= 0;
99 num_times_enter_screen_played_
= 0;
103 std::vector
<float> volume_changes_
;
104 size_t num_times_adjust_sound_played_
= 0;
105 size_t num_times_passthrough_played_
= 0;
106 size_t num_times_exit_screen_played_
= 0;
107 size_t num_times_enter_screen_played_
= 0;
112 class TouchExplorationControllerTestApi
{
114 TouchExplorationControllerTestApi(
115 TouchExplorationController
* touch_exploration_controller
) {
116 touch_exploration_controller_
.reset(touch_exploration_controller
);
119 void CallTapTimerNowForTesting() {
120 DCHECK(touch_exploration_controller_
->tap_timer_
.IsRunning());
121 touch_exploration_controller_
->tap_timer_
.Stop();
122 touch_exploration_controller_
->OnTapTimerFired();
125 void CallPassthroughTimerNowForTesting() {
126 DCHECK(touch_exploration_controller_
->passthrough_timer_
.IsRunning());
127 touch_exploration_controller_
->passthrough_timer_
.Stop();
128 touch_exploration_controller_
->OnPassthroughTimerFired();
131 void CallTapTimerNowIfRunningForTesting() {
132 if (touch_exploration_controller_
->tap_timer_
.IsRunning()) {
133 touch_exploration_controller_
->tap_timer_
.Stop();
134 touch_exploration_controller_
->OnTapTimerFired();
138 bool IsInNoFingersDownStateForTesting() const {
139 return touch_exploration_controller_
->state_
==
140 touch_exploration_controller_
->NO_FINGERS_DOWN
;
143 bool IsInGestureInProgressStateForTesting() const {
144 return touch_exploration_controller_
->state_
==
145 touch_exploration_controller_
->GESTURE_IN_PROGRESS
;
148 bool IsInSlideGestureStateForTesting() const {
149 return touch_exploration_controller_
->state_
==
150 touch_exploration_controller_
->SLIDE_GESTURE
;
153 bool IsInTwoFingerTapStateForTesting() const {
154 return touch_exploration_controller_
->state_
==
155 touch_exploration_controller_
->TWO_FINGER_TAP
;
157 bool IsInCornerPassthroughStateForTesting() const {
158 return touch_exploration_controller_
->state_
==
159 touch_exploration_controller_
->CORNER_PASSTHROUGH
;
162 gfx::Rect
BoundsOfRootWindowInDIPForTesting() const {
163 return touch_exploration_controller_
->root_window_
->GetBoundsInScreen();
166 // VLOGs should be suppressed in tests that generate a lot of logs,
167 // for example permutations of nine touch events.
168 void SuppressVLOGsForTesting(bool suppress
) {
169 touch_exploration_controller_
->VLOG_on_
= !suppress
;
172 float GetMaxDistanceFromEdge() const {
173 return touch_exploration_controller_
->kMaxDistanceFromEdge
;
176 float GetSlopDistanceFromEdge() const {
177 return touch_exploration_controller_
->kSlopDistanceFromEdge
;
180 void SetTickClockForTesting(base::TickClock
* simulated_clock
) {
181 touch_exploration_controller_
->tick_clock_
= simulated_clock
;
185 scoped_ptr
<TouchExplorationController
> touch_exploration_controller_
;
187 DISALLOW_COPY_AND_ASSIGN(TouchExplorationControllerTestApi
);
190 class TouchExplorationTest
: public aura::test::AuraTestBase
{
192 TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) {
193 // Tests fail if time is ever 0.
194 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
196 ~TouchExplorationTest() override
{}
198 void SetUp() override
{
199 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone
)
200 gfx::GLSurface::InitializeOneOffForTests();
201 aura::test::AuraTestBase::SetUp();
202 cursor_client_
.reset(new aura::test::TestCursorClient(root_window()));
203 root_window()->AddPreTargetHandler(&event_capturer_
);
204 generator_
.reset(new test::EventGenerator(root_window()));
205 // The generator takes ownership of the tick clock.
206 generator_
->SetTickClock(scoped_ptr
<base::TickClock
>(simulated_clock_
));
207 cursor_client()->ShowCursor();
208 cursor_client()->DisableMouseEvents();
211 void TearDown() override
{
212 root_window()->RemovePreTargetHandler(&event_capturer_
);
213 SwitchTouchExplorationMode(false);
214 cursor_client_
.reset();
215 aura::test::AuraTestBase::TearDown();
219 aura::client::CursorClient
* cursor_client() { return cursor_client_
.get(); }
221 const ScopedVector
<ui::Event
>& GetCapturedEvents() {
222 return event_capturer_
.captured_events();
225 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEvents() {
226 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
227 std::vector
<ui::LocatedEvent
*> located_events
;
228 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
229 if (all_events
[i
]->IsMouseEvent() ||
230 all_events
[i
]->IsTouchEvent() ||
231 all_events
[i
]->IsGestureEvent()) {
232 located_events
.push_back(static_cast<ui::LocatedEvent
*>(all_events
[i
]));
235 return located_events
;
238 std::vector
<ui::Event
*> GetCapturedEventsOfType(int type
) {
239 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
240 std::vector
<ui::Event
*> events
;
241 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
242 if (type
== all_events
[i
]->type())
243 events
.push_back(all_events
[i
]);
248 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEventsOfType(int type
) {
249 std::vector
<ui::LocatedEvent
*> located_events
= GetCapturedLocatedEvents();
250 std::vector
<ui::LocatedEvent
*> events
;
251 for (size_t i
= 0; i
< located_events
.size(); ++i
) {
252 if (type
== located_events
[i
]->type())
253 events
.push_back(located_events
[i
]);
258 void ClearCapturedEvents() {
259 event_capturer_
.Reset();
262 void AdvanceSimulatedTimePastTapDelay() {
263 simulated_clock_
->Advance(gesture_detector_config_
.double_tap_timeout
);
264 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1));
265 touch_exploration_controller_
->CallTapTimerNowForTesting();
268 void AdvanceSimulatedTimePastPassthroughDelay() {
269 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
270 touch_exploration_controller_
->CallPassthroughTimerNowForTesting();
273 void AdvanceSimulatedTimePastPotentialTapDelay() {
274 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
275 touch_exploration_controller_
->CallTapTimerNowIfRunningForTesting();
278 void SuppressVLOGs(bool suppress
) {
279 touch_exploration_controller_
->SuppressVLOGsForTesting(suppress
);
282 void SetTickClock() {
283 touch_exploration_controller_
->SetTickClockForTesting(
284 static_cast<base::TickClock
*>(simulated_clock_
));
287 void SwitchTouchExplorationMode(bool on
) {
288 if (!on
&& touch_exploration_controller_
.get()) {
289 touch_exploration_controller_
.reset();
290 } else if (on
&& !touch_exploration_controller_
.get()) {
291 touch_exploration_controller_
.reset(
292 new ui::TouchExplorationControllerTestApi(
293 new TouchExplorationController(root_window(), &delegate_
)));
294 cursor_client()->ShowCursor();
295 cursor_client()->DisableMouseEvents();
299 void EnterTouchExplorationModeAtLocation(gfx::Point tap_location
) {
300 ui::TouchEvent
touch_press(ui::ET_TOUCH_PRESSED
, tap_location
, 0, Now());
301 generator_
->Dispatch(&touch_press
);
302 AdvanceSimulatedTimePastTapDelay();
303 EXPECT_TRUE(IsInTouchToMouseMode());
306 // Checks that Corner Passthrough is working. Assumes that corner is the
307 // bottom left corner or the bottom right corner.
308 void AssertCornerPassthroughWorking(gfx::Point corner
) {
309 ASSERT_EQ(0U, delegate_
.NumPassthroughSounds());
311 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, corner
, 0, Now());
312 generator_
->Dispatch(&first_press
);
314 AdvanceSimulatedTimePastPassthroughDelay();
315 EXPECT_FALSE(IsInGestureInProgressState());
316 EXPECT_FALSE(IsInSlideGestureState());
317 EXPECT_FALSE(IsInTouchToMouseMode());
318 EXPECT_TRUE(IsInCornerPassthroughState());
320 gfx::Rect window
= BoundsOfRootWindowInDIP();
321 // The following events should be passed through.
322 gfx::Point
passthrough(window
.right() / 2, window
.bottom() / 2);
323 ui::TouchEvent
passthrough_press(
324 ui::ET_TOUCH_PRESSED
, passthrough
, 1, Now());
325 ASSERT_EQ(1U, delegate_
.NumPassthroughSounds());
326 generator_
->Dispatch(&passthrough_press
);
327 generator_
->ReleaseTouchId(1);
328 generator_
->PressTouchId(1);
329 EXPECT_FALSE(IsInGestureInProgressState());
330 EXPECT_FALSE(IsInSlideGestureState());
331 EXPECT_TRUE(IsInCornerPassthroughState());
333 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
334 ASSERT_EQ(3U, captured_events
.size());
335 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
336 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
337 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
338 generator_
->ReleaseTouchId(1);
339 ClearCapturedEvents();
341 generator_
->ReleaseTouchId(0);
342 captured_events
= GetCapturedLocatedEvents();
343 ASSERT_EQ(0U, captured_events
.size());
344 EXPECT_FALSE(IsInTouchToMouseMode());
345 EXPECT_FALSE(IsInCornerPassthroughState());
346 ClearCapturedEvents();
349 bool IsInTouchToMouseMode() {
350 aura::client::CursorClient
* cursor_client
=
351 aura::client::GetCursorClient(root_window());
352 return cursor_client
&&
353 cursor_client
->IsMouseEventsEnabled() &&
354 !cursor_client
->IsCursorVisible();
357 bool IsInNoFingersDownState() {
358 return touch_exploration_controller_
->IsInNoFingersDownStateForTesting();
361 bool IsInGestureInProgressState() {
362 return touch_exploration_controller_
363 ->IsInGestureInProgressStateForTesting();
366 bool IsInSlideGestureState() {
367 return touch_exploration_controller_
->IsInSlideGestureStateForTesting();
370 bool IsInTwoFingerTapState() {
371 return touch_exploration_controller_
->IsInTwoFingerTapStateForTesting();
374 bool IsInCornerPassthroughState() {
375 return touch_exploration_controller_
376 ->IsInCornerPassthroughStateForTesting();
379 gfx::Rect
BoundsOfRootWindowInDIP() {
380 return touch_exploration_controller_
->BoundsOfRootWindowInDIPForTesting();
383 float GetMaxDistanceFromEdge() const {
384 return touch_exploration_controller_
->GetMaxDistanceFromEdge();
387 float GetSlopDistanceFromEdge() const {
388 return touch_exploration_controller_
->GetSlopDistanceFromEdge();
391 base::TimeDelta
Now() {
392 // This is the same as what EventTimeForNow() does, but here we do it
393 // with our simulated clock.
394 return base::TimeDelta::FromInternalValue(
395 simulated_clock_
->NowTicks().ToInternalValue());
398 scoped_ptr
<test::EventGenerator
> generator_
;
399 ui::GestureDetector::Config gesture_detector_config_
;
400 // Owned by |generator_|.
401 base::SimpleTestTickClock
* simulated_clock_
;
402 MockTouchExplorationControllerDelegate delegate_
;
405 EventCapturer event_capturer_
;
406 scoped_ptr
<TouchExplorationControllerTestApi
>
407 touch_exploration_controller_
;
408 scoped_ptr
<aura::test::TestCursorClient
> cursor_client_
;
410 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest
);
413 // Executes a number of assertions to confirm that |e1| and |e2| are touch
414 // events and are equal to each other.
415 void ConfirmEventsAreTouchAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
416 ASSERT_TRUE(e1
->IsTouchEvent());
417 ASSERT_TRUE(e2
->IsTouchEvent());
418 ui::TouchEvent
* touch_event1
= static_cast<ui::TouchEvent
*>(e1
);
419 ui::TouchEvent
* touch_event2
= static_cast<ui::TouchEvent
*>(e2
);
420 EXPECT_EQ(touch_event1
->type(), touch_event2
->type());
421 EXPECT_EQ(touch_event1
->location(), touch_event2
->location());
422 EXPECT_EQ(touch_event1
->touch_id(), touch_event2
->touch_id());
423 EXPECT_EQ(touch_event1
->flags(), touch_event2
->flags());
424 EXPECT_EQ(touch_event1
->time_stamp(), touch_event2
->time_stamp());
427 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
428 // events and are equal to each other.
429 void ConfirmEventsAreMouseAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
430 ASSERT_TRUE(e1
->IsMouseEvent());
431 ASSERT_TRUE(e2
->IsMouseEvent());
432 ui::MouseEvent
* mouse_event1
= static_cast<ui::MouseEvent
*>(e1
);
433 ui::MouseEvent
* mouse_event2
= static_cast<ui::MouseEvent
*>(e2
);
434 EXPECT_EQ(mouse_event1
->type(), mouse_event2
->type());
435 EXPECT_EQ(mouse_event1
->location(), mouse_event2
->location());
436 EXPECT_EQ(mouse_event1
->root_location(), mouse_event2
->root_location());
437 EXPECT_EQ(mouse_event1
->flags(), mouse_event2
->flags());
440 // Executes a number of assertions to confirm that |e1| and |e2| are key events
441 // and are equal to each other.
442 void ConfirmEventsAreKeyAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
443 ASSERT_TRUE(e1
->IsKeyEvent());
444 ASSERT_TRUE(e2
->IsKeyEvent());
445 ui::KeyEvent
* key_event1
= static_cast<ui::KeyEvent
*>(e1
);
446 ui::KeyEvent
* key_event2
= static_cast<ui::KeyEvent
*>(e2
);
447 EXPECT_EQ(key_event1
->type(), key_event2
->type());
448 EXPECT_EQ(key_event1
->key_code(), key_event2
->key_code());
449 EXPECT_EQ(key_event1
->code(), key_event2
->code());
450 EXPECT_EQ(key_event1
->flags(), key_event2
->flags());
453 #define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
454 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
456 #define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
457 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
459 #define CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(e1, e2) \
460 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreKeyAndEqual(e1, e2))
462 // TODO(mfomitchev): Need to investigate why we don't get mouse enter/exit
463 // events when running these tests as part of ui_base_unittests. We do get them
464 // when the tests are run as part of ash unit tests.
466 // If a swipe has been successfully completed, then six key events will be
467 // dispatched that correspond to shift+search+direction
468 void AssertDirectionalNavigationEvents(const ScopedVector
<ui::Event
>& events
,
469 ui::KeyboardCode direction
) {
470 ASSERT_EQ(6U, events
.size());
471 ui::KeyEvent
shift_pressed(
472 ui::ET_KEY_PRESSED
, ui::VKEY_SHIFT
, ui::EF_SHIFT_DOWN
);
473 ui::KeyEvent
search_pressed(
474 ui::ET_KEY_PRESSED
, ui::VKEY_LWIN
, ui::EF_SHIFT_DOWN
);
475 ui::KeyEvent
direction_pressed(
476 ui::ET_KEY_PRESSED
, direction
, ui::EF_SHIFT_DOWN
);
477 ui::KeyEvent
direction_released(
478 ui::ET_KEY_RELEASED
, direction
, ui::EF_SHIFT_DOWN
);
479 ui::KeyEvent
search_released(
480 ui::ET_KEY_RELEASED
, VKEY_LWIN
, ui::EF_SHIFT_DOWN
);
481 ui::KeyEvent
shift_released(
482 ui::ET_KEY_RELEASED
, ui::VKEY_SHIFT
, ui::EF_NONE
);
483 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_pressed
, events
[0]);
484 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_pressed
, events
[1]);
485 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_pressed
, events
[2]);
486 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_released
, events
[3]);
487 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_released
, events
[4]);
488 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_released
, events
[5]);
491 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterPressAndDelay
) {
492 SwitchTouchExplorationMode(true);
493 EXPECT_FALSE(IsInTouchToMouseMode());
494 generator_
->PressTouch();
495 AdvanceSimulatedTimePastTapDelay();
496 EXPECT_TRUE(IsInTouchToMouseMode());
499 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterMoveOutsideSlop
) {
500 int slop
= gesture_detector_config_
.touch_slop
;
501 int half_slop
= slop
/ 2;
503 SwitchTouchExplorationMode(true);
504 EXPECT_FALSE(IsInTouchToMouseMode());
505 generator_
->set_current_location(gfx::Point(11, 12));
506 generator_
->PressTouch();
507 generator_
->MoveTouch(gfx::Point(11 + half_slop
, 12));
508 EXPECT_FALSE(IsInTouchToMouseMode());
509 generator_
->MoveTouch(gfx::Point(11, 12 + half_slop
));
510 EXPECT_FALSE(IsInTouchToMouseMode());
511 AdvanceSimulatedTimePastTapDelay();
512 generator_
->MoveTouch(gfx::Point(11 + slop
+ 1, 12));
513 EXPECT_TRUE(IsInTouchToMouseMode());
516 TEST_F(TouchExplorationTest
, OneFingerTap
) {
517 SwitchTouchExplorationMode(true);
518 gfx::Point
location(11, 12);
519 generator_
->set_current_location(location
);
520 generator_
->PressTouch();
521 generator_
->ReleaseTouch();
522 AdvanceSimulatedTimePastTapDelay();
524 std::vector
<ui::LocatedEvent
*> events
=
525 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
526 ASSERT_EQ(1U, events
.size());
528 EXPECT_EQ(location
, events
[0]->location());
529 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
530 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
531 EXPECT_TRUE(IsInNoFingersDownState());
534 TEST_F(TouchExplorationTest
, ActualMouseMovesUnaffected
) {
535 SwitchTouchExplorationMode(true);
537 gfx::Point
location_start(11, 12);
538 gfx::Point
location_end(13, 14);
539 generator_
->set_current_location(location_start
);
540 generator_
->PressTouch();
541 AdvanceSimulatedTimePastTapDelay();
542 generator_
->MoveTouch(location_end
);
544 gfx::Point
location_real_mouse_move(15, 16);
545 ui::MouseEvent
mouse_move(ui::ET_MOUSE_MOVED
, location_real_mouse_move
,
546 location_real_mouse_move
, ui::EventTimeForNow(), 0,
548 generator_
->Dispatch(&mouse_move
);
549 generator_
->ReleaseTouch();
550 AdvanceSimulatedTimePastTapDelay();
552 std::vector
<ui::LocatedEvent
*> events
=
553 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
554 ASSERT_EQ(4U, events
.size());
556 EXPECT_EQ(location_start
, events
[0]->location());
557 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
558 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
560 EXPECT_EQ(location_end
, events
[1]->location());
561 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
562 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
564 // The real mouse move goes through.
565 EXPECT_EQ(location_real_mouse_move
, events
[2]->location());
566 CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(events
[2], &mouse_move
);
567 EXPECT_FALSE(events
[2]->flags() & ui::EF_IS_SYNTHESIZED
);
568 EXPECT_FALSE(events
[2]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
570 // The touch release gets written as a mouse move.
571 EXPECT_EQ(location_end
, events
[3]->location());
572 EXPECT_TRUE(events
[3]->flags() & ui::EF_IS_SYNTHESIZED
);
573 EXPECT_TRUE(events
[3]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
574 EXPECT_TRUE(IsInNoFingersDownState());
577 // Turn the touch exploration mode on in the middle of the touch gesture.
578 // Confirm that events from the finger which was touching when the mode was
579 // turned on don't get rewritten.
580 TEST_F(TouchExplorationTest
, TurnOnMidTouch
) {
581 SwitchTouchExplorationMode(false);
582 generator_
->PressTouchId(1);
583 EXPECT_TRUE(cursor_client()->IsCursorVisible());
584 ClearCapturedEvents();
586 // Enable touch exploration mode while the first finger is touching the
587 // screen. Ensure that subsequent events from that first finger are not
588 // affected by the touch exploration mode, while the touch events from another
589 // finger get rewritten.
590 SwitchTouchExplorationMode(true);
591 ui::TouchEvent
touch_move(ui::ET_TOUCH_MOVED
,
595 generator_
->Dispatch(&touch_move
);
596 EXPECT_TRUE(cursor_client()->IsCursorVisible());
597 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
598 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
599 ASSERT_EQ(1u, captured_events
.size());
600 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_move
);
601 ClearCapturedEvents();
603 // The press from the second finger should get rewritten.
604 generator_
->PressTouchId(2);
605 AdvanceSimulatedTimePastTapDelay();
606 EXPECT_TRUE(IsInTouchToMouseMode());
607 captured_events
= GetCapturedLocatedEvents();
608 std::vector
<ui::LocatedEvent
*>::const_iterator it
;
609 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
610 if ((*it
)->type() == ui::ET_MOUSE_MOVED
)
613 EXPECT_NE(captured_events
.end(), it
);
614 ClearCapturedEvents();
616 // The release of the first finger shouldn't be affected.
617 ui::TouchEvent
touch_release(ui::ET_TOUCH_RELEASED
,
621 generator_
->Dispatch(&touch_release
);
622 captured_events
= GetCapturedLocatedEvents();
623 ASSERT_EQ(1u, captured_events
.size());
624 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_release
);
625 ClearCapturedEvents();
627 // The move and release from the second finger should get rewritten.
628 generator_
->MoveTouchId(gfx::Point(13, 14), 2);
629 generator_
->ReleaseTouchId(2);
630 AdvanceSimulatedTimePastTapDelay();
631 captured_events
= GetCapturedLocatedEvents();
632 ASSERT_EQ(2u, captured_events
.size());
633 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
634 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
635 EXPECT_TRUE(IsInNoFingersDownState());
638 // If an event is received after the double-tap timeout has elapsed, but
639 // before the timer has fired, a mouse move should still be generated.
640 TEST_F(TouchExplorationTest
, TimerFiresLateDuringTouchExploration
) {
641 SwitchTouchExplorationMode(true);
643 // Make sure the touch is not in a corner of the screen.
644 generator_
->MoveTouch(gfx::Point(100, 200));
646 // Send a press, then add another finger after the double-tap timeout.
647 generator_
->PressTouchId(1);
648 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
649 generator_
->PressTouchId(2);
650 std::vector
<ui::LocatedEvent
*> events
=
651 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
652 ASSERT_EQ(1U, events
.size());
653 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
654 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
656 generator_
->ReleaseTouchId(2);
657 generator_
->ReleaseTouchId(1);
658 AdvanceSimulatedTimePastTapDelay();
659 EXPECT_TRUE(IsInNoFingersDownState());
662 // If a new tap is received after the double-tap timeout has elapsed from
663 // a previous tap, but before the timer has fired, a mouse move should
664 // still be generated from the old tap.
665 TEST_F(TouchExplorationTest
, TimerFiresLateAfterTap
) {
666 SwitchTouchExplorationMode(true);
668 // Send a tap at location1.
669 gfx::Point
location0(11, 12);
670 generator_
->set_current_location(location0
);
671 generator_
->PressTouch();
672 generator_
->ReleaseTouch();
674 // Send a tap at location2, after the double-tap timeout, but before the
676 gfx::Point
location1(33, 34);
677 generator_
->set_current_location(location1
);
678 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(301));
679 generator_
->PressTouch();
680 generator_
->ReleaseTouch();
681 AdvanceSimulatedTimePastTapDelay();
683 std::vector
<ui::LocatedEvent
*> events
=
684 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
685 ASSERT_EQ(2U, events
.size());
686 EXPECT_EQ(location0
, events
[0]->location());
687 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
688 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
689 EXPECT_EQ(location1
, events
[1]->location());
690 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
691 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
692 EXPECT_TRUE(IsInNoFingersDownState());
695 // Double-tapping should send a touch press and release through to the location
696 // of the last successful touch exploration.
697 TEST_F(TouchExplorationTest
, DoubleTap
) {
698 SwitchTouchExplorationMode(true);
700 // Tap at one location, and get a mouse move event.
701 gfx::Point
tap_location(51, 52);
702 generator_
->set_current_location(tap_location
);
703 generator_
->PressTouchId(1);
704 generator_
->ReleaseTouchId(1);
705 AdvanceSimulatedTimePastTapDelay();
707 std::vector
<ui::LocatedEvent
*> events
=
708 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
709 ASSERT_EQ(1U, events
.size());
711 EXPECT_EQ(tap_location
, events
[0]->location());
712 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
713 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
714 ClearCapturedEvents();
716 // Now double-tap at a different location. This should result in
717 // a single touch press and release at the location of the tap,
718 // not at the location of the double-tap.
719 gfx::Point
double_tap_location(33, 34);
720 generator_
->set_current_location(double_tap_location
);
721 generator_
->PressTouch();
722 generator_
->ReleaseTouch();
723 generator_
->PressTouch();
724 generator_
->ReleaseTouch();
726 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
727 ASSERT_EQ(2U, captured_events
.size());
728 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
729 EXPECT_EQ(tap_location
, captured_events
[0]->location());
730 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
731 EXPECT_EQ(tap_location
, captured_events
[1]->location());
732 EXPECT_TRUE(IsInNoFingersDownState());
735 // Double-tapping where the user holds their finger down for the second time
736 // for a longer press should send a touch press and passthrough all further
737 // events from that finger. Other finger presses should be ignored.
738 TEST_F(TouchExplorationTest
, DoubleTapPassthrough
) {
739 SwitchTouchExplorationMode(true);
741 // Tap at one location, and get a mouse move event.
742 gfx::Point
tap_location(11, 12);
743 generator_
->set_current_location(tap_location
);
744 generator_
->PressTouch();
745 generator_
->ReleaseTouch();
746 AdvanceSimulatedTimePastTapDelay();
748 std::vector
<ui::LocatedEvent
*> events
=
749 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
750 ASSERT_EQ(1U, events
.size());
752 EXPECT_EQ(tap_location
, events
[0]->location());
753 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
754 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
755 ClearCapturedEvents();
757 // Now double-tap and hold at a different location.
758 // This should result in a single touch press at the location of the tap,
759 // not at the location of the double-tap.
760 gfx::Point
first_tap_location(13, 14);
761 generator_
->set_current_location(first_tap_location
);
762 generator_
->PressTouchId(1);
763 generator_
->ReleaseTouchId(1);
764 gfx::Point
second_tap_location(15, 16);
765 generator_
->set_current_location(second_tap_location
);
766 generator_
->PressTouchId(1);
767 // Advance to the finger passing through.
768 AdvanceSimulatedTimePastTapDelay();
770 gfx::Vector2d passthrough_offset
= second_tap_location
- tap_location
;
772 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
773 ASSERT_EQ(1U, captured_events
.size());
774 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
775 EXPECT_EQ(second_tap_location
- passthrough_offset
,
776 captured_events
[0]->location());
778 ClearCapturedEvents();
780 // All events for the first finger should pass through now, displaced
781 // relative to the last touch exploration location.
782 gfx::Point
first_move_location(17, 18);
783 generator_
->MoveTouchId(first_move_location
, 1);
784 gfx::Point
second_move_location(12, 13);
785 generator_
->MoveTouchId(second_move_location
, 1);
787 captured_events
= GetCapturedLocatedEvents();
788 ASSERT_EQ(2U, captured_events
.size());
789 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
790 EXPECT_EQ(first_move_location
- passthrough_offset
,
791 captured_events
[0]->location());
792 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[1]->type());
793 EXPECT_EQ(second_move_location
- passthrough_offset
,
794 captured_events
[1]->location());
796 ClearCapturedEvents();
798 // Events for other fingers should do nothing.
799 generator_
->PressTouchId(2);
800 generator_
->PressTouchId(3);
801 generator_
->MoveTouchId(gfx::Point(34, 36), 2);
802 generator_
->ReleaseTouchId(2);
803 captured_events
= GetCapturedLocatedEvents();
804 ASSERT_EQ(0U, captured_events
.size());
806 // Even with finger 3 still down, events for the first finger should still
808 gfx::Point
third_move_location(14, 15);
809 generator_
->MoveTouchId(third_move_location
, 1);
810 captured_events
= GetCapturedLocatedEvents();
811 ASSERT_EQ(1U, captured_events
.size());
812 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
813 EXPECT_EQ(third_move_location
- passthrough_offset
,
814 captured_events
[0]->location());
816 // No fingers down state is only reached when every finger is lifted.
817 generator_
->ReleaseTouchId(1);
818 EXPECT_FALSE(IsInNoFingersDownState());
819 generator_
->ReleaseTouchId(3);
820 EXPECT_TRUE(IsInNoFingersDownState());
823 // Double-tapping, going into passthrough, and holding for the longpress
824 // time should send a touch press and released (right click)
825 // to the location of the last successful touch exploration.
826 TEST_F(TouchExplorationTest
, DoubleTapLongPress
) {
827 SwitchTouchExplorationMode(true);
829 // Tap at one location, and get a mouse move event.
830 gfx::Point
tap_location(11, 12);
831 generator_
->set_current_location(tap_location
);
832 generator_
->PressTouch();
833 generator_
->ReleaseTouch();
834 AdvanceSimulatedTimePastTapDelay();
836 std::vector
<ui::LocatedEvent
*> events
=
837 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
838 ASSERT_EQ(1U, events
.size());
839 EXPECT_EQ(tap_location
, events
[0]->location());
840 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
841 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
842 ClearCapturedEvents();
844 // Now double-tap and hold at a different location.
845 // This should result in a single touch long press and release
846 // at the location of the tap, not at the location of the double-tap.
847 // There should be a time delay between the touch press and release.
848 gfx::Point
first_tap_location(33, 34);
849 generator_
->set_current_location(first_tap_location
);
850 generator_
->PressTouch();
851 generator_
->ReleaseTouch();
852 gfx::Point
second_tap_location(23, 24);
853 generator_
->set_current_location(second_tap_location
);
854 generator_
->PressTouch();
855 // Advance to the finger passing through, and then to the longpress timeout.
856 AdvanceSimulatedTimePastTapDelay();
857 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
858 generator_
->ReleaseTouch();
860 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
861 ASSERT_EQ(2U, captured_events
.size());
862 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
863 EXPECT_EQ(tap_location
, captured_events
[0]->location());
864 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
865 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
866 EXPECT_EQ(tap_location
, captured_events
[1]->location());
867 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
868 EXPECT_EQ(released_time
- pressed_time
,
869 gesture_detector_config_
.longpress_timeout
);
872 // Single-tapping should send a touch press and release through to the location
873 // of the last successful touch exploration if the grace period has not
875 TEST_F(TouchExplorationTest
, SingleTap
) {
876 SwitchTouchExplorationMode(true);
878 // Tap once to simulate a mouse moved event.
879 gfx::Point
initial_location(11, 12);
880 generator_
->set_current_location(initial_location
);
881 generator_
->PressTouch();
882 AdvanceSimulatedTimePastTapDelay();
883 ClearCapturedEvents();
885 // Move to another location for single tap
886 gfx::Point
tap_location(22, 23);
887 generator_
->MoveTouch(tap_location
);
888 generator_
->ReleaseTouch();
890 // Allow time to pass within the grace period of releasing before
892 gfx::Point
final_location(33, 34);
893 generator_
->set_current_location(final_location
);
894 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(250));
895 generator_
->PressTouch();
896 generator_
->ReleaseTouch();
898 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
899 ASSERT_EQ(4U, captured_events
.size());
900 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
901 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
902 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
903 EXPECT_EQ(tap_location
, captured_events
[2]->location());
904 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[3]->type());
905 EXPECT_EQ(tap_location
, captured_events
[3]->location());
908 // Double-tapping without coming from touch exploration (no previous touch
909 // exploration event) should not generate any events.
910 TEST_F(TouchExplorationTest
, DoubleTapNoTouchExplore
) {
911 SwitchTouchExplorationMode(true);
913 // Double-tap without any previous touch.
914 // Touch exploration mode has not been entered, so there is no previous
915 // touch exploration event. The double-tap should be discarded, and no events
916 // should be generated at all.
917 gfx::Point
double_tap_location(33, 34);
918 generator_
->set_current_location(double_tap_location
);
919 generator_
->PressTouch();
920 generator_
->ReleaseTouch();
921 generator_
->PressTouch();
922 // Since the state stays in single_tap_released, we need to make sure the
923 // tap timer doesn't fire and set the state to no fingers down (since there
924 // is still a finger down).
925 AdvanceSimulatedTimePastPotentialTapDelay();
926 EXPECT_FALSE(IsInNoFingersDownState());
927 generator_
->ReleaseTouch();
928 EXPECT_TRUE(IsInNoFingersDownState());
930 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
931 ASSERT_EQ(0U, captured_events
.size());
934 // Tapping and releasing with a second finger when in touch exploration mode
935 // should send a touch press and released to the location of the last
936 // successful touch exploration and return to touch explore.
937 TEST_F(TouchExplorationTest
, SplitTap
) {
938 SwitchTouchExplorationMode(true);
939 gfx::Point
initial_touch_location(11, 12);
940 gfx::Point
second_touch_location(33, 34);
942 // Tap and hold at one location, and get a mouse move event in touch explore.
943 EnterTouchExplorationModeAtLocation(initial_touch_location
);
944 std::vector
<ui::LocatedEvent
*> events
=
945 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
946 ASSERT_EQ(1U, events
.size());
948 EXPECT_EQ(initial_touch_location
, events
[0]->location());
949 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
950 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
951 ClearCapturedEvents();
952 EXPECT_TRUE(IsInTouchToMouseMode());
954 // Now tap and release at a different location. This should result in a
955 // single touch and release at the location of the first (held) tap,
956 // not at the location of the second tap and release.
957 // After the release, there is still a finger in touch explore mode.
958 ui::TouchEvent
split_tap_press(
959 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
960 generator_
->Dispatch(&split_tap_press
);
961 // To simulate the behavior of the real device, we manually disable
962 // mouse events. To not rely on manually setting the state, this is also
963 // tested in touch_exploration_controller_browsertest.
964 cursor_client()->DisableMouseEvents();
965 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
966 EXPECT_FALSE(cursor_client()->IsCursorVisible());
967 EXPECT_FALSE(IsInGestureInProgressState());
968 ui::TouchEvent
split_tap_release(
969 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
970 generator_
->Dispatch(&split_tap_release
);
971 // Releasing the second finger should re-enable mouse events putting us
972 // back into the touch exploration mode.
973 EXPECT_TRUE(IsInTouchToMouseMode());
974 EXPECT_FALSE(IsInNoFingersDownState());
976 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
977 ASSERT_EQ(2U, captured_events
.size());
978 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
979 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
980 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
981 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
982 ClearCapturedEvents();
984 ui::TouchEvent
touch_explore_release(
985 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
986 generator_
->Dispatch(&touch_explore_release
);
987 AdvanceSimulatedTimePastTapDelay();
988 EXPECT_TRUE(IsInNoFingersDownState());
991 // If split tap is started but the touch explore finger is released first,
992 // there should still be a touch press and release sent to the location of
993 // the last successful touch exploration.
994 // Both fingers should be released after the click goes through.
995 TEST_F(TouchExplorationTest
, SplitTapRelease
) {
996 SwitchTouchExplorationMode(true);
998 gfx::Point
initial_touch_location(11, 12);
999 gfx::Point
second_touch_location(33, 34);
1001 // Tap and hold at one location, and get a mouse move event in touch explore.
1002 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1004 std::vector
<ui::LocatedEvent
*> events
=
1005 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1006 ASSERT_EQ(1U, events
.size());
1008 ClearCapturedEvents();
1010 // Now tap at a different location. Release at the first location,
1011 // then release at the second. This should result in a
1012 // single touch and release at the location of the first (held) tap,
1013 // not at the location of the second tap and release.
1014 ui::TouchEvent
split_tap_press(
1015 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1016 generator_
->Dispatch(&split_tap_press
);
1017 ui::TouchEvent
touch_explore_release(
1018 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1019 generator_
->Dispatch(&touch_explore_release
);
1020 ui::TouchEvent
split_tap_release(
1021 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1022 generator_
->Dispatch(&split_tap_release
);
1023 EXPECT_TRUE(IsInNoFingersDownState());
1025 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1026 ASSERT_EQ(2U, captured_events
.size());
1027 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1028 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1029 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1030 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1033 // When in touch exploration mode, making a long press with a second finger
1034 // should send a touch press and released to the location of the last
1035 // successful touch exploration. There should be a delay between the
1036 // touch and release events (right click).
1037 TEST_F(TouchExplorationTest
, SplitTapLongPress
) {
1038 SwitchTouchExplorationMode(true);
1039 gfx::Point
initial_touch_location(11, 12);
1040 gfx::Point
second_touch_location(33, 34);
1042 // Tap and hold at one location, and get a mouse move event in touch explore.
1043 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1044 std::vector
<ui::LocatedEvent
*> events
=
1045 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1046 ASSERT_EQ(1U, events
.size());
1048 ClearCapturedEvents();
1050 // Now tap, hold, and release at a different location. This should result
1051 // in a single touch and release (long press) at the location of the first
1052 // (held) tap, not at the location of the second tap and release.
1053 ui::TouchEvent
split_tap_press(
1054 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1055 generator_
->Dispatch(&split_tap_press
);
1056 // To simulate the behavior of the real device, we manually disable
1057 // mouse events, like in the SplitTap test.
1058 cursor_client()->DisableMouseEvents();
1059 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
1060 EXPECT_FALSE(cursor_client()->IsCursorVisible());
1061 EXPECT_FALSE(IsInGestureInProgressState());
1062 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1063 // After the release, there is still a finger in touch exploration, and
1064 // mouse events should be enabled again.
1065 ui::TouchEvent
split_tap_release(
1066 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1067 generator_
->Dispatch(&split_tap_release
);
1068 EXPECT_FALSE(IsInNoFingersDownState());
1069 EXPECT_TRUE(IsInTouchToMouseMode());
1071 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1072 ASSERT_EQ(2U, captured_events
.size());
1073 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1074 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1075 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
1076 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1077 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1078 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
1079 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
1080 released_time
- pressed_time
);
1083 // If split tap is started but the touch explore finger is released first,
1084 // there should still be a touch press and release sent to the location of
1085 // the last successful touch exploration. If the remaining finger is held
1086 // as a longpress, there should be a delay between the sent touch and release
1087 // events (right click).All fingers should be released after the click
1089 TEST_F(TouchExplorationTest
, SplitTapReleaseLongPress
) {
1090 SwitchTouchExplorationMode(true);
1091 gfx::Point
initial_touch_location(11, 12);
1092 gfx::Point
second_touch_location(33, 34);
1094 // Tap and hold at one location, and get a mouse move event in touch explore.
1095 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1096 std::vector
<ui::LocatedEvent
*> events
=
1097 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1098 ASSERT_EQ(1U, events
.size());
1099 ClearCapturedEvents();
1101 // Now tap at a different location. Release at the first location,
1102 // then release at the second. This should result in a
1103 // single touch and release at the location of the first (held) tap,
1104 // not at the location of the second tap and release.
1105 // After the release, TouchToMouseMode should still be on.
1106 ui::TouchEvent
split_tap_press(
1107 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1108 generator_
->Dispatch(&split_tap_press
);
1109 ui::TouchEvent
touch_explore_release(
1110 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1111 generator_
->Dispatch(&touch_explore_release
);
1112 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1113 ui::TouchEvent
split_tap_release(
1114 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1115 generator_
->Dispatch(&split_tap_release
);
1116 EXPECT_TRUE(IsInTouchToMouseMode());
1118 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1119 ASSERT_EQ(2U, captured_events
.size());
1120 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1121 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1122 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
1123 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1124 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1125 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
1126 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
1127 released_time
- pressed_time
);
1130 TEST_F(TouchExplorationTest
, SplitTapMultiFinger
) {
1131 SwitchTouchExplorationMode(true);
1132 gfx::Point
initial_touch_location(11, 12);
1133 gfx::Point
second_touch_location(33, 34);
1134 gfx::Point
third_touch_location(16, 17);
1136 // Tap and hold at one location, and get a mouse move event in touch explore.
1137 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1139 std::vector
<ui::LocatedEvent
*> events
=
1140 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1141 ASSERT_EQ(1U, events
.size());
1143 EXPECT_EQ(initial_touch_location
, events
[0]->location());
1144 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
1145 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
1146 ClearCapturedEvents();
1148 // Now tap at a different location and hold for long press.
1149 ui::TouchEvent
split_tap_press(
1150 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1151 generator_
->Dispatch(&split_tap_press
);
1152 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1154 // Placing a third finger on the screen should cancel the initial press and
1155 // enter the wait state.
1156 ui::TouchEvent
third_press(
1157 ui::ET_TOUCH_PRESSED
, third_touch_location
, 2, Now());
1158 generator_
->Dispatch(&third_press
);
1160 // When all three fingers are released, the only events captured should be a
1161 // press and touch cancel. All fingers should then be up.
1162 ui::TouchEvent
touch_explore_release(
1163 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1164 generator_
->Dispatch(&touch_explore_release
);
1165 ui::TouchEvent
split_tap_release(
1166 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1167 generator_
->Dispatch(&split_tap_release
);
1168 ui::TouchEvent
third_tap_release(
1169 ui::ET_TOUCH_RELEASED
, third_touch_location
, 2, Now());
1170 generator_
->Dispatch(&third_tap_release
);
1172 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1173 ASSERT_EQ(2U, captured_events
.size());
1174 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1175 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1176 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1177 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1178 EXPECT_TRUE(IsInNoFingersDownState());
1182 TEST_F(TouchExplorationTest
, SplitTapLeaveSlop
) {
1183 SwitchTouchExplorationMode(true);
1184 gfx::Point
first_touch_location(11, 12);
1185 gfx::Point
second_touch_location(33, 34);
1186 gfx::Point
first_move_location(
1187 first_touch_location
.x() + gesture_detector_config_
.touch_slop
* 3 + 1,
1188 first_touch_location
.y());
1189 gfx::Point
second_move_location(
1190 second_touch_location
.x() + gesture_detector_config_
.touch_slop
* 3 + 1,
1191 second_touch_location
.y());
1193 // Tap and hold at one location, and get a mouse move event in touch explore.
1194 EnterTouchExplorationModeAtLocation(first_touch_location
);
1195 ClearCapturedEvents();
1197 // Now tap at a different location for split tap.
1198 ui::TouchEvent
split_tap_press(
1199 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1200 generator_
->Dispatch(&split_tap_press
);
1202 // Move the first finger out of slop and release both fingers. The split
1203 // tap should have been cancelled, so a touch press and touch cancel event
1204 // should go through at the last touch exploration location (the first press).
1205 ui::TouchEvent
first_touch_move(
1206 ui::ET_TOUCH_MOVED
, first_move_location
, 0, Now());
1207 generator_
->Dispatch(&first_touch_move
);
1208 ui::TouchEvent
first_touch_release(
1209 ui::ET_TOUCH_RELEASED
, first_move_location
, 0, Now());
1210 generator_
->Dispatch(&first_touch_release
);
1211 ui::TouchEvent
second_touch_release(
1212 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1213 generator_
->Dispatch(&second_touch_release
);
1215 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1216 ASSERT_EQ(2U, captured_events
.size());
1217 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1218 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1219 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1220 EXPECT_EQ(first_touch_location
, captured_events
[1]->location());
1221 EXPECT_TRUE(IsInNoFingersDownState());
1223 // Now do the same, but moving the split tap finger out of slop
1224 EnterTouchExplorationModeAtLocation(first_touch_location
);
1225 ClearCapturedEvents();
1226 ui::TouchEvent
split_tap_press2(
1227 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1228 generator_
->Dispatch(&split_tap_press2
);
1230 // Move the second finger out of slop and release both fingers. The split
1231 // tap should have been cancelled, so a touch press and touch cancel event
1232 // should go through at the last touch exploration location (the first press).
1233 ui::TouchEvent
second_touch_move2(
1234 ui::ET_TOUCH_MOVED
, second_move_location
, 1, Now());
1235 generator_
->Dispatch(&second_touch_move2
);
1236 ui::TouchEvent
first_touch_release2(
1237 ui::ET_TOUCH_RELEASED
, first_touch_location
, 0, Now());
1238 generator_
->Dispatch(&first_touch_release2
);
1239 ui::TouchEvent
second_touch_release2(
1240 ui::ET_TOUCH_RELEASED
, second_move_location
, 1, Now());
1241 generator_
->Dispatch(&second_touch_release2
);
1243 captured_events
= GetCapturedLocatedEvents();
1244 ASSERT_EQ(2U, captured_events
.size());
1245 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1246 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1247 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1248 EXPECT_EQ(first_touch_location
, captured_events
[1]->location());
1249 EXPECT_TRUE(IsInNoFingersDownState());
1252 // Finger must have moved more than slop, faster than the minimum swipe
1253 // velocity, and before the tap timer fires in order to enter
1254 // GestureInProgress state. Otherwise, if the tap timer fires before the a
1255 // gesture is completed, enter touch exploration.
1256 TEST_F(TouchExplorationTest
, EnterGestureInProgressState
) {
1257 SwitchTouchExplorationMode(true);
1258 EXPECT_FALSE(IsInTouchToMouseMode());
1259 EXPECT_FALSE(IsInGestureInProgressState());
1261 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1262 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, gfx::Point(0, 1), 0, Now());
1263 gfx::Point
second_location(distance
/ 2, 1);
1264 gfx::Point
third_location(distance
, 1);
1265 gfx::Point
touch_exploration_location(20, 21);
1267 generator_
->Dispatch(&first_press
);
1268 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1269 // Since we are not out of the touch slop yet, we should not be in gesture in
1271 generator_
->MoveTouch(second_location
);
1272 EXPECT_FALSE(IsInTouchToMouseMode());
1273 EXPECT_FALSE(IsInGestureInProgressState());
1274 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1276 // Once we are out of slop, we should be in GestureInProgress.
1277 generator_
->MoveTouch(third_location
);
1278 EXPECT_TRUE(IsInGestureInProgressState());
1279 EXPECT_FALSE(IsInTouchToMouseMode());
1280 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1281 ASSERT_EQ(0U, captured_events
.size());
1283 // Exit out of gesture mode once grace period is over and enter touch
1284 // exploration. There should be a move when entering touch exploration and
1285 // also for the touch move.
1286 AdvanceSimulatedTimePastTapDelay();
1287 generator_
->MoveTouch(touch_exploration_location
);
1288 ASSERT_EQ(2U, captured_events
.size());
1289 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
1290 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
1291 EXPECT_TRUE(IsInTouchToMouseMode());
1292 EXPECT_FALSE(IsInGestureInProgressState());
1295 // A swipe+direction gesture should trigger a Shift+Search+Direction
1297 TEST_F(TouchExplorationTest
, GestureSwipe
) {
1298 SwitchTouchExplorationMode(true);
1299 std::vector
<ui::KeyboardCode
> directions
;
1300 directions
.push_back(ui::VKEY_RIGHT
);
1301 directions
.push_back(ui::VKEY_LEFT
);
1302 directions
.push_back(ui::VKEY_UP
);
1303 directions
.push_back(ui::VKEY_DOWN
);
1305 // This value was taken from gesture_recognizer_unittest.cc in a swipe
1306 // detector test, since it seems to be about the right amount to get a swipe.
1307 const int kSteps
= 15;
1309 // There are gestures supported with up to four fingers.
1310 for (int num_fingers
= 1; num_fingers
<= 4; num_fingers
++) {
1311 std::vector
<gfx::Point
> start_points
;
1312 for (int j
= 0; j
< num_fingers
; j
++) {
1313 start_points
.push_back(gfx::Point(j
* 10 + 100, j
* 10 + 200));
1315 gfx::Point
* start_points_array
= &start_points
[0];
1316 const float distance
= gesture_detector_config_
.touch_slop
+ 1;
1317 // Iterate through each swipe direction for this number of fingers.
1318 for (std::vector
<ui::KeyboardCode
>::const_iterator it
= directions
.begin();
1319 it
!= directions
.end();
1323 ui::KeyboardCode direction
= *it
;
1324 switch (direction
) {
1325 case ui::VKEY_RIGHT
:
1329 move_x
= 0 - distance
;
1332 move_y
= 0 - distance
;
1341 // A swipe is made when a fling starts
1343 distance
/ gesture_detector_config_
.maximum_fling_velocity
;
1344 // delta_time is in seconds, so we convert to ms.
1345 int delta_time_ms
= floor(delta_time
* 1000);
1346 generator_
->GestureMultiFingerScroll(num_fingers
,
1353 // The swipe registered and sent the appropriate key events.
1354 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1355 if (num_fingers
== 1)
1356 AssertDirectionalNavigationEvents(captured_events
, direction
);
1358 // Most of the time this is 2 right now, but two of the two finger
1359 // swipes are mapped to chromevox commands which dispatch 6 key events,
1360 // and these will probably be remapped a lot as we're developing.
1361 ASSERT_GE(captured_events
.size(), 2U);
1362 std::vector
<ui::Event
>::size_type i
;
1363 for (i
= 0; i
!= captured_events
.size(); i
++) {
1364 EXPECT_TRUE(captured_events
[i
]->IsKeyEvent());
1367 EXPECT_TRUE(IsInNoFingersDownState());
1368 EXPECT_FALSE(IsInTouchToMouseMode());
1369 EXPECT_FALSE(IsInGestureInProgressState());
1370 ClearCapturedEvents();
1375 // Since there are so many permutations, this test is fairly slow. Therefore, it
1376 // is disabled and will be turned on to check during development.
1378 TEST_F(TouchExplorationTest
, DISABLED_AllFingerPermutations
) {
1379 SwitchTouchExplorationMode(true);
1380 SuppressVLOGs(true);
1381 // We will test all permutations of events from three different fingers
1382 // to ensure that we return to NO_FINGERS_DOWN when fingers have been
1384 ScopedVector
<ui::TouchEvent
> all_events
;
1385 for (int touch_id
= 0; touch_id
< 3; touch_id
++){
1386 int x
= 10*touch_id
+ 1;
1387 int y
= 10*touch_id
+ 2;
1388 all_events
.push_back(new TouchEvent(
1389 ui::ET_TOUCH_PRESSED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1390 all_events
.push_back(new TouchEvent(
1391 ui::ET_TOUCH_MOVED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1392 all_events
.push_back(new TouchEvent(
1393 ui::ET_TOUCH_RELEASED
, gfx::Point(x
, y
), touch_id
, Now()));
1396 // I'm going to explain this algorithm, and use an example in parentheses.
1397 // The example will be all permutations of a b c d.
1398 // There are four letters and 4! = 24 permutations.
1399 const int num_events
= all_events
.size();
1400 const int num_permutations
= Factorial(num_events
);
1402 for (int p
= 0; p
< num_permutations
; p
++) {
1403 std::vector
<ui::TouchEvent
*> queued_events
= all_events
.get();
1404 std::vector
<bool> fingers_pressed(3, false);
1406 int current_num_permutations
= num_permutations
;
1407 for (int events_left
= num_events
; events_left
> 0; events_left
--) {
1408 // |p| indexes to each permutation when there are num_permutations
1409 // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...)
1410 // But how do we find the index for the current number of permutations?
1411 // To find the permutation within the part of the sequence we're
1412 // currently looking at, we need a number between 0 and
1413 // |current_num_permutations| - 1.
1414 // (e.g. if we already chose the first letter, there are 3! = 6
1415 // options left, so we do p % 6. So |current_permutation| would go
1416 // from 0 to 5 and then reset to 0 again, for all combinations of
1417 // whichever three letters are remaining, as we loop through the
1419 int current_permutation
= p
% current_num_permutations
;
1421 // Since this is is the total number of permutations starting with
1422 // this event and including future events, there could be multiple
1423 // values of current_permutation that will generate the same event
1424 // in this iteration.
1425 // (e.g. If we chose 'a' but have b c d to choose from, we choose b when
1426 // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3.
1427 // Note that each letter gets two numbers, which is the next
1428 // current_num_permutations, 2! for the two letters left.)
1430 // Branching out from the first event, there are num_permutations
1431 // permutations, and each value of |p| is associated with one of these
1432 // permutations. However, once the first event is chosen, there
1433 // are now |num_events| - 1 events left, so the number of permutations
1434 // for the rest of the events changes, and will always be equal to
1435 // the factorial of the events_left.
1436 // (e.g. There are 3! = 6 permutations that start with 'a', so if we
1437 // start with 'a' there will be 6 ways to then choose from b c d.)
1438 // So we now set-up for the next iteration by setting
1439 // current_num_permutations to the factorial of the next number of
1441 current_num_permutations
/= events_left
;
1443 // To figure out what current event we want to choose, we integer
1444 // divide the current permutation by the next current_num_permutations.
1445 // (e.g. If there are 4 letters a b c d and 24 permutations, we divide
1446 // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first
1447 // 6 permutations start with 'a', and the last 6 will start with 'd'.
1448 // Note that there are 6 that start with 'a' because there are 6
1449 // permutations for the next three letters that follow 'a'.)
1450 int index
= current_permutation
/ current_num_permutations
;
1452 ui::TouchEvent
* next_dispatch
= queued_events
[index
];
1453 ASSERT_TRUE(next_dispatch
!= NULL
);
1455 // |next_dispatch| has to be put in this container so that its time
1456 // stamp can be changed to this point in the test, when it is being
1458 EventTestApi
test_dispatch(next_dispatch
);
1459 test_dispatch
.set_time_stamp(Now());
1460 generator_
->Dispatch(next_dispatch
);
1461 queued_events
.erase(queued_events
.begin() + index
);
1463 // Keep track of what fingers have been pressed, to release
1464 // only those fingers at the end, so the check for being in
1465 // no fingers down can be accurate.
1466 if (next_dispatch
->type() == ET_TOUCH_PRESSED
) {
1467 fingers_pressed
[next_dispatch
->touch_id()] = true;
1468 } else if (next_dispatch
->type() == ET_TOUCH_RELEASED
) {
1469 fingers_pressed
[next_dispatch
->touch_id()] = false;
1472 ASSERT_EQ(queued_events
.size(), 0u);
1474 // Release fingers recorded as pressed.
1475 for(int j
= 0; j
< int(fingers_pressed
.size()); j
++){
1476 if (fingers_pressed
[j
] == true) {
1477 generator_
->ReleaseTouchId(j
);
1478 fingers_pressed
[j
] = false;
1481 AdvanceSimulatedTimePastPotentialTapDelay();
1482 EXPECT_TRUE(IsInNoFingersDownState());
1483 ClearCapturedEvents();
1487 // With the simple swipe gestures, if additional fingers are added and the tap
1488 // timer times out, then the state should change to the wait for one finger
1490 TEST_F(TouchExplorationTest
, GestureAddedFinger
) {
1491 SwitchTouchExplorationMode(true);
1492 EXPECT_FALSE(IsInTouchToMouseMode());
1493 EXPECT_FALSE(IsInGestureInProgressState());
1495 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1496 ui::TouchEvent
first_press(
1497 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 0, Now());
1498 generator_
->Dispatch(&first_press
);
1499 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1500 gfx::Point
second_location(100 + distance
, 200);
1501 generator_
->MoveTouch(second_location
);
1502 EXPECT_TRUE(IsInGestureInProgressState());
1503 EXPECT_FALSE(IsInTouchToMouseMode());
1504 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1505 ASSERT_EQ(0U, captured_events
.size());
1507 // Generate a second press, but time out past the gesture period so that
1508 // gestures are prevented from continuing to go through.
1509 ui::TouchEvent
second_press(
1510 ui::ET_TOUCH_PRESSED
, gfx::Point(20, 21), 1, Now());
1511 generator_
->Dispatch(&second_press
);
1512 AdvanceSimulatedTimePastTapDelay();
1513 EXPECT_FALSE(IsInGestureInProgressState());
1514 EXPECT_FALSE(IsInTouchToMouseMode());
1515 ASSERT_EQ(0U, captured_events
.size());
1518 TEST_F(TouchExplorationTest
, EnterSlideGestureState
) {
1519 SwitchTouchExplorationMode(true);
1520 EXPECT_FALSE(IsInTouchToMouseMode());
1521 EXPECT_FALSE(IsInGestureInProgressState());
1523 int window_right
= BoundsOfRootWindowInDIP().right();
1524 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1525 ui::TouchEvent
first_press(
1526 ui::ET_TOUCH_PRESSED
, gfx::Point(window_right
, 1), 0, Now());
1527 gfx::Point
second_location(window_right
, 1 + distance
/ 2);
1528 gfx::Point
third_location(window_right
, 1 + distance
);
1529 gfx::Point
fourth_location(window_right
, 35);
1531 generator_
->Dispatch(&first_press
);
1532 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1534 // Since we haven't moved past slop yet, we should not be in slide gesture.
1535 generator_
->MoveTouch(second_location
);
1536 EXPECT_FALSE(IsInTouchToMouseMode());
1537 EXPECT_FALSE(IsInGestureInProgressState());
1538 EXPECT_FALSE(IsInSlideGestureState());
1539 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1541 // Once we are out of slop, we should be in slide gesture since we are along
1542 // the edge of the screen.
1543 generator_
->MoveTouch(third_location
);
1544 EXPECT_FALSE(IsInGestureInProgressState());
1545 EXPECT_TRUE(IsInSlideGestureState());
1546 EXPECT_FALSE(IsInTouchToMouseMode());
1548 // Now that we are in slide gesture, we can adjust the volume.
1549 generator_
->MoveTouch(fourth_location
);
1550 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1551 ASSERT_EQ(0U, captured_events
.size());
1553 // Since we are at the right edge of the screen, but the sound timer has not
1554 // elapsed, there should have been a sound that fired and a volume
1556 size_t num_adjust_sounds
= delegate_
.NumAdjustSounds();
1557 ASSERT_EQ(1U, num_adjust_sounds
);
1558 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1560 // Exit out of slide gesture once touch is lifted, but not before even if the
1561 // grace period is over.
1562 AdvanceSimulatedTimePastPotentialTapDelay();
1563 ASSERT_EQ(0U, captured_events
.size());
1564 EXPECT_FALSE(IsInTouchToMouseMode());
1565 EXPECT_FALSE(IsInGestureInProgressState());
1566 EXPECT_TRUE(IsInSlideGestureState());
1568 generator_
->ReleaseTouch();
1569 ASSERT_EQ(0U, captured_events
.size());
1570 EXPECT_FALSE(IsInTouchToMouseMode());
1571 EXPECT_FALSE(IsInGestureInProgressState());
1572 EXPECT_FALSE(IsInSlideGestureState());
1575 // If a press + move occurred outside the boundaries, but within the slop
1576 // boundaries and then moved into the boundaries of an edge, there still should
1577 // not be a slide gesture.
1578 TEST_F(TouchExplorationTest
, AvoidEnteringSlideGesture
) {
1579 SwitchTouchExplorationMode(true);
1581 gfx::Rect window
= BoundsOfRootWindowInDIP();
1582 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1583 ui::TouchEvent
first_press(
1584 ui::ET_TOUCH_PRESSED
,
1585 gfx::Point(window
.right() - GetSlopDistanceFromEdge(), 1),
1588 gfx::Point
out_of_slop(window
.right() - GetSlopDistanceFromEdge() + distance
,
1590 gfx::Point
into_boundaries(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1592 generator_
->Dispatch(&first_press
);
1593 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1595 generator_
->MoveTouch(out_of_slop
);
1596 EXPECT_FALSE(IsInTouchToMouseMode());
1597 EXPECT_TRUE(IsInGestureInProgressState());
1598 EXPECT_FALSE(IsInSlideGestureState());
1599 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1601 // Since we did not start moving while in the boundaries, we should not be in
1603 generator_
->MoveTouch(into_boundaries
);
1604 EXPECT_TRUE(IsInGestureInProgressState());
1605 EXPECT_FALSE(IsInSlideGestureState());
1606 EXPECT_FALSE(IsInTouchToMouseMode());
1607 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1608 ASSERT_EQ(0U, captured_events
.size());
1610 generator_
->ReleaseTouch();
1613 // If the slide gesture begins within the boundaries and then moves
1614 // SlopDistanceFromEdge there should still be a sound change. If the finger
1615 // moves into the center screen, there should no longer be a sound change but it
1616 // should still be in slide gesture. If the finger moves back into the edges
1617 // without lifting, it should start changing sound again.
1618 TEST_F(TouchExplorationTest
, TestingBoundaries
) {
1619 SwitchTouchExplorationMode(true);
1621 gfx::Rect window
= BoundsOfRootWindowInDIP();
1622 gfx::Point
initial_press(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1624 gfx::Point
center_screen(window
.right() / 2, window
.bottom() / 2);
1626 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, initial_press
, 0, Now());
1627 generator_
->Dispatch(&first_press
);
1628 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1629 EXPECT_FALSE(IsInGestureInProgressState());
1630 EXPECT_FALSE(IsInSlideGestureState());
1631 EXPECT_FALSE(IsInTouchToMouseMode());
1633 // Move past the touch slop to begin slide gestures.
1634 // + slop + 1 to actually leave slop.
1635 gfx::Point
touch_move(
1637 initial_press
.y() + gesture_detector_config_
.touch_slop
+ 1);
1638 generator_
->MoveTouch(touch_move
);
1639 EXPECT_FALSE(IsInGestureInProgressState());
1640 EXPECT_TRUE(IsInSlideGestureState());
1641 EXPECT_FALSE(IsInTouchToMouseMode());
1642 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1644 // Move the touch into slop boundaries. It should still be in slide gestures
1645 // and adjust the volume.
1646 gfx::Point
into_slop_boundaries(
1647 window
.right() - GetSlopDistanceFromEdge() / 2, 1);
1648 generator_
->MoveTouch(into_slop_boundaries
);
1649 EXPECT_FALSE(IsInGestureInProgressState());
1650 EXPECT_TRUE(IsInSlideGestureState());
1651 EXPECT_FALSE(IsInTouchToMouseMode());
1653 // The sound is rate limiting so it only activates every 150ms.
1654 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1656 size_t num_adjust_sounds
= delegate_
.NumAdjustSounds();
1657 ASSERT_EQ(1U, num_adjust_sounds
);
1658 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1660 // Move the touch into the center of the window. It should still be in slide
1661 // gestures, but there should not be anymore volume adjustments.
1662 generator_
->MoveTouch(center_screen
);
1663 EXPECT_FALSE(IsInGestureInProgressState());
1664 EXPECT_TRUE(IsInSlideGestureState());
1665 EXPECT_FALSE(IsInTouchToMouseMode());
1667 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1668 num_adjust_sounds
= delegate_
.NumAdjustSounds();
1669 ASSERT_EQ(1U, num_adjust_sounds
);
1670 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1672 // Move the touch back into slop edge distance and volume should be changing
1673 // again, one volume change for each new move.
1674 generator_
->MoveTouch(into_slop_boundaries
);
1675 EXPECT_FALSE(IsInGestureInProgressState());
1676 EXPECT_TRUE(IsInSlideGestureState());
1677 EXPECT_FALSE(IsInTouchToMouseMode());
1679 generator_
->MoveTouch(
1680 gfx::Point(into_slop_boundaries
.x() + gesture_detector_config_
.touch_slop
,
1681 into_slop_boundaries
.y()));
1682 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1684 num_adjust_sounds
= delegate_
.NumAdjustSounds();
1685 ASSERT_EQ(2U, num_adjust_sounds
);
1686 ASSERT_EQ(3U, delegate_
.VolumeChanges().size());
1688 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1689 ASSERT_EQ(0U, captured_events
.size());
1691 generator_
->ReleaseTouch();
1694 // Even if the gesture starts within bounds, if it has not moved past slop
1695 // within the grace period, it should go to touch exploration.
1696 TEST_F(TouchExplorationTest
, InBoundariesTouchExploration
) {
1697 SwitchTouchExplorationMode(true);
1699 gfx::Rect window
= BoundsOfRootWindowInDIP();
1700 gfx::Point
initial_press(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1701 ui::TouchEvent
first_press(
1702 ui::ET_TOUCH_PRESSED
,
1706 generator_
->Dispatch(&first_press
);
1707 EXPECT_FALSE(IsInGestureInProgressState());
1708 EXPECT_FALSE(IsInSlideGestureState());
1709 EXPECT_FALSE(IsInTouchToMouseMode());
1711 AdvanceSimulatedTimePastTapDelay();
1712 EXPECT_FALSE(IsInGestureInProgressState());
1713 EXPECT_FALSE(IsInSlideGestureState());
1714 EXPECT_TRUE(IsInTouchToMouseMode());
1717 // If two fingers tap the screen at the same time and release before the tap
1718 // timer runs out, a control key event should be sent to silence chromevox.
1719 TEST_F(TouchExplorationTest
, TwoFingerTap
) {
1720 SwitchTouchExplorationMode(true);
1722 generator_
->set_current_location(gfx::Point(101, 102));
1723 generator_
->PressTouchId(1);
1724 EXPECT_FALSE(IsInTwoFingerTapState());
1726 generator_
->PressTouchId(2);
1727 EXPECT_TRUE(IsInTwoFingerTapState());
1729 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1730 ASSERT_EQ(0U, captured_events
.size());
1732 generator_
->ReleaseTouchId(1);
1733 EXPECT_TRUE(IsInTwoFingerTapState());
1734 generator_
->ReleaseTouchId(2);
1736 // Two key events should have been sent to silence the feedback.
1737 EXPECT_EQ(2U, captured_events
.size());
1740 // If the fingers are not released before the tap timer runs out, a control
1741 // keyevent is not sent and the state will no longer be in two finger tap.
1742 TEST_F(TouchExplorationTest
, TwoFingerTapAndHold
) {
1743 SwitchTouchExplorationMode(true);
1745 generator_
->PressTouchId(1);
1746 EXPECT_FALSE(IsInTwoFingerTapState());
1748 generator_
->PressTouchId(2);
1749 EXPECT_TRUE(IsInTwoFingerTapState());
1751 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1752 ASSERT_EQ(0U, captured_events
.size());
1754 AdvanceSimulatedTimePastTapDelay();
1755 // Since the tap delay has elapsed, it should no longer be in two finger tap.
1756 EXPECT_FALSE(IsInTwoFingerTapState());
1759 // The next two tests set up two finger swipes to happen. If one of the fingers
1760 // moves out of slop before the tap timer fires, a two finger tap is not made.
1761 // In this first test, the first finger placed will move out of slop.
1762 TEST_F(TouchExplorationTest
, TwoFingerTapAndMoveFirstFinger
) {
1763 SwitchTouchExplorationMode(true);
1765 // Once one of the fingers leaves slop, it should no longer be in two finger
1767 ui::TouchEvent
first_press_id_1(
1768 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 1, Now());
1769 ui::TouchEvent
first_press_id_2(
1770 ui::ET_TOUCH_PRESSED
, gfx::Point(110, 200), 2, Now());
1772 ui::TouchEvent
slop_move_id_1(
1774 gfx::Point(100 + gesture_detector_config_
.touch_slop
, 200),
1777 ui::TouchEvent
slop_move_id_2(
1779 gfx::Point(110 + gesture_detector_config_
.touch_slop
, 200),
1783 ui::TouchEvent
out_slop_id_1(
1785 gfx::Point(100 + gesture_detector_config_
.touch_slop
+ 1, 200),
1789 // Dispatch the inital presses.
1790 generator_
->Dispatch(&first_press_id_1
);
1791 EXPECT_FALSE(IsInTwoFingerTapState());
1792 generator_
->Dispatch(&first_press_id_2
);
1793 EXPECT_TRUE(IsInTwoFingerTapState());
1795 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1796 ASSERT_EQ(0U, captured_events
.size());
1798 // The presses have not moved out of slop yet so it should still be in
1800 generator_
->Dispatch(&slop_move_id_1
);
1801 EXPECT_TRUE(IsInTwoFingerTapState());
1802 generator_
->Dispatch(&slop_move_id_2
);
1803 EXPECT_TRUE(IsInTwoFingerTapState());
1805 // Once one of the fingers moves out of slop, we are no longer in
1807 generator_
->Dispatch(&out_slop_id_1
);
1808 EXPECT_FALSE(IsInTwoFingerTapState());
1811 // Similar test to the previous test except the second finger placed will be the
1812 // one to move out of slop.
1813 TEST_F(TouchExplorationTest
, TwoFingerTapAndMoveSecondFinger
) {
1814 SwitchTouchExplorationMode(true);
1816 // Once one of the fingers leaves slop, it should no longer be in two finger
1818 ui::TouchEvent
first_press_id_1(
1819 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 1, Now());
1820 ui::TouchEvent
first_press_id_2(
1821 ui::ET_TOUCH_PRESSED
, gfx::Point(110, 200), 2, Now());
1823 ui::TouchEvent
out_slop_id_2(
1825 gfx::Point(100 + gesture_detector_config_
.touch_slop
+ 1, 200),
1829 generator_
->Dispatch(&first_press_id_1
);
1830 EXPECT_FALSE(IsInTwoFingerTapState());
1832 generator_
->Dispatch(&first_press_id_2
);
1833 EXPECT_TRUE(IsInTwoFingerTapState());
1835 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1836 ASSERT_EQ(0U, captured_events
.size());
1838 generator_
->Dispatch(&out_slop_id_2
);
1839 EXPECT_FALSE(IsInTwoFingerTapState());
1842 // Corner passthrough should turn on if the user first holds down on either the
1843 // right or left corner past a delay and then places a finger anywhere else on
1845 TEST_F(TouchExplorationTest
, ActivateLeftCornerPassthrough
) {
1846 SwitchTouchExplorationMode(true);
1848 gfx::Rect window
= BoundsOfRootWindowInDIP();
1849 gfx::Point
left_corner(10, window
.bottom() - GetMaxDistanceFromEdge() / 2);
1850 AssertCornerPassthroughWorking(left_corner
);
1853 TEST_F(TouchExplorationTest
, ActivateRightCornerPassthrough
) {
1854 SwitchTouchExplorationMode(true);
1856 gfx::Rect window
= BoundsOfRootWindowInDIP();
1857 gfx::Point
right_corner(window
.right() - GetMaxDistanceFromEdge() / 2,
1858 window
.bottom() - GetMaxDistanceFromEdge() / 2);
1859 AssertCornerPassthroughWorking(right_corner
);
1862 // Earcons should play if the user slides off the screen or enters the screen
1864 TEST_F(TouchExplorationTest
, EnterEarconPlays
) {
1865 SwitchTouchExplorationMode(true);
1867 gfx::Rect window
= BoundsOfRootWindowInDIP();
1869 gfx::Point
upper_left_corner(0, 0);
1870 gfx::Point
upper_right_corner(window
.right(), 0);
1871 gfx::Point
lower_left_corner(0, window
.bottom());
1872 gfx::Point
lower_right_corner(window
.right(), window
.bottom());
1873 gfx::Point
left_edge(0, 30);
1874 gfx::Point
right_edge(window
.right(), 30);
1875 gfx::Point
top_edge(30, 0);
1876 gfx::Point
bottom_edge(30, window
.bottom());
1878 std::vector
<gfx::Point
> locations
;
1879 locations
.push_back(upper_left_corner
);
1880 locations
.push_back(upper_right_corner
);
1881 locations
.push_back(lower_left_corner
);
1882 locations
.push_back(lower_right_corner
);
1883 locations
.push_back(left_edge
);
1884 locations
.push_back(right_edge
);
1885 locations
.push_back(top_edge
);
1886 locations
.push_back(bottom_edge
);
1888 for (std::vector
<gfx::Point
>::const_iterator point
= locations
.begin();
1889 point
!= locations
.end();
1891 ui::TouchEvent
touch_event(ui::ET_TOUCH_PRESSED
, *point
, 1, Now());
1893 generator_
->Dispatch(&touch_event
);
1894 ASSERT_EQ(1U, delegate_
.NumEnterScreenSounds());
1895 generator_
->ReleaseTouchId(1);
1896 delegate_
.ResetCountersToZero();
1900 TEST_F(TouchExplorationTest
, ExitEarconPlays
) {
1901 SwitchTouchExplorationMode(true);
1903 // On the device, it cannot actually tell if the finger has left the screen or
1904 // not. If the finger has left the screen, it reads it as a release that
1905 // occurred very close to the edge of the screen even if the finger is still
1906 // technically touching the moniter. To simulate this, a release that occurs
1907 // close to the edge is dispatched.
1908 gfx::Point
initial_press(100, 200);
1909 gfx::Rect window
= BoundsOfRootWindowInDIP();
1911 gfx::Point
upper_left_corner(0, 0);
1912 gfx::Point
upper_right_corner(window
.right(), 0);
1913 gfx::Point
lower_left_corner(0, window
.bottom());
1914 gfx::Point
lower_right_corner(window
.right(), window
.bottom());
1915 gfx::Point
left_edge(0, 30);
1916 gfx::Point
right_edge(window
.right(), 30);
1917 gfx::Point
top_edge(30, 0);
1918 gfx::Point
bottom_edge(30, window
.bottom());
1920 std::vector
<gfx::Point
> locations
;
1921 locations
.push_back(upper_left_corner
);
1922 locations
.push_back(upper_right_corner
);
1923 locations
.push_back(lower_left_corner
);
1924 locations
.push_back(lower_right_corner
);
1925 locations
.push_back(left_edge
);
1926 locations
.push_back(right_edge
);
1927 locations
.push_back(top_edge
);
1928 locations
.push_back(bottom_edge
);
1930 for (std::vector
<gfx::Point
>::const_iterator point
= locations
.begin();
1931 point
!= locations
.end();
1933 generator_
->PressTouch();
1934 generator_
->MoveTouch(initial_press
);
1935 generator_
->MoveTouch(*point
);
1936 generator_
->ReleaseTouch();
1937 ASSERT_EQ(1U, delegate_
.NumExitScreenSounds());
1938 delegate_
.ResetCountersToZero();