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 virtual ~EventCapturer() {}
36 virtual void OnEvent(ui::Event
* event
) OVERRIDE
{
37 if (event
->IsMouseEvent()) {
39 new ui::MouseEvent(static_cast<ui::MouseEvent
&>(*event
)));
40 } else if (event
->IsTouchEvent()) {
42 new ui::TouchEvent(static_cast<ui::TouchEvent
&>(*event
)));
43 } else if (event
->IsGestureEvent()) {
45 new ui::GestureEvent(static_cast<ui::GestureEvent
&>(*event
)));
46 } else if (event
->IsKeyEvent()) {
47 events_
.push_back(new ui::KeyEvent(static_cast<ui::KeyEvent
&>(*event
)));
51 // Stop event propagation so we don't click on random stuff that
52 // might break test assumptions.
53 event
->StopPropagation();
54 // If there is a possibility that we're in an infinite loop, we should
55 // exit early with a sensible error rather than letting the test time out.
56 ASSERT_LT(events_
.size(), 100u);
59 const ScopedVector
<ui::Event
>& captured_events() const { return events_
; }
62 ScopedVector
<ui::Event
> events_
;
64 DISALLOW_COPY_AND_ASSIGN(EventCapturer
);
67 int Factorial(int n
) {
72 return n
* Factorial(n
- 1);
75 class MockTouchExplorationControllerDelegate
76 : public ui::TouchExplorationControllerDelegate
{
78 virtual void SetOutputLevel(int volume
) OVERRIDE
{
79 volume_changes_
.push_back(volume
);
81 virtual void SilenceSpokenFeedback() OVERRIDE
{
83 virtual void PlayVolumeAdjustEarcon() OVERRIDE
{
84 ++num_times_adjust_sound_played_
;
86 virtual void PlayPassthroughEarcon() OVERRIDE
{
87 ++num_times_passthrough_played_
;
89 virtual void PlayExitScreenEarcon() OVERRIDE
{
90 ++num_times_exit_screen_played_
;
92 virtual void PlayEnterScreenEarcon() OVERRIDE
{
93 ++num_times_enter_screen_played_
;
96 const std::vector
<float> VolumeChanges() { return volume_changes_
; }
97 const size_t NumAdjustSounds() { return num_times_adjust_sound_played_
; }
98 const size_t NumPassthroughSounds() { return num_times_passthrough_played_
; }
99 const size_t NumExitScreenSounds() { return num_times_exit_screen_played_
; }
100 const size_t NumEnterScreenSounds() {
101 return num_times_enter_screen_played_
;
104 void ResetCountersToZero() {
105 num_times_adjust_sound_played_
= 0;
106 num_times_passthrough_played_
= 0;
107 num_times_exit_screen_played_
= 0;
108 num_times_enter_screen_played_
= 0;
112 std::vector
<float> volume_changes_
;
113 size_t num_times_adjust_sound_played_
= 0;
114 size_t num_times_passthrough_played_
= 0;
115 size_t num_times_exit_screen_played_
= 0;
116 size_t num_times_enter_screen_played_
= 0;
121 class TouchExplorationControllerTestApi
{
123 TouchExplorationControllerTestApi(
124 TouchExplorationController
* touch_exploration_controller
) {
125 touch_exploration_controller_
.reset(touch_exploration_controller
);
128 void CallTapTimerNowForTesting() {
129 DCHECK(touch_exploration_controller_
->tap_timer_
.IsRunning());
130 touch_exploration_controller_
->tap_timer_
.Stop();
131 touch_exploration_controller_
->OnTapTimerFired();
134 void CallPassthroughTimerNowForTesting() {
135 DCHECK(touch_exploration_controller_
->passthrough_timer_
.IsRunning());
136 touch_exploration_controller_
->passthrough_timer_
.Stop();
137 touch_exploration_controller_
->OnPassthroughTimerFired();
140 void CallTapTimerNowIfRunningForTesting() {
141 if (touch_exploration_controller_
->tap_timer_
.IsRunning()) {
142 touch_exploration_controller_
->tap_timer_
.Stop();
143 touch_exploration_controller_
->OnTapTimerFired();
147 bool IsInNoFingersDownStateForTesting() const {
148 return touch_exploration_controller_
->state_
==
149 touch_exploration_controller_
->NO_FINGERS_DOWN
;
152 bool IsInGestureInProgressStateForTesting() const {
153 return touch_exploration_controller_
->state_
==
154 touch_exploration_controller_
->GESTURE_IN_PROGRESS
;
157 bool IsInSlideGestureStateForTesting() const {
158 return touch_exploration_controller_
->state_
==
159 touch_exploration_controller_
->SLIDE_GESTURE
;
162 bool IsInTwoFingerTapStateForTesting() const {
163 return touch_exploration_controller_
->state_
==
164 touch_exploration_controller_
->TWO_FINGER_TAP
;
166 bool IsInCornerPassthroughStateForTesting() const {
167 return touch_exploration_controller_
->state_
==
168 touch_exploration_controller_
->CORNER_PASSTHROUGH
;
171 gfx::Rect
BoundsOfRootWindowInDIPForTesting() const {
172 return touch_exploration_controller_
->root_window_
->GetBoundsInScreen();
175 // VLOGs should be suppressed in tests that generate a lot of logs,
176 // for example permutations of nine touch events.
177 void SuppressVLOGsForTesting(bool suppress
) {
178 touch_exploration_controller_
->VLOG_on_
= !suppress
;
181 float GetMaxDistanceFromEdge() const {
182 return touch_exploration_controller_
->kMaxDistanceFromEdge
;
185 float GetSlopDistanceFromEdge() const {
186 return touch_exploration_controller_
->kSlopDistanceFromEdge
;
189 void SetTickClockForTesting(base::TickClock
* simulated_clock
) {
190 touch_exploration_controller_
->tick_clock_
= simulated_clock
;
194 scoped_ptr
<TouchExplorationController
> touch_exploration_controller_
;
196 DISALLOW_COPY_AND_ASSIGN(TouchExplorationControllerTestApi
);
199 class TouchExplorationTest
: public aura::test::AuraTestBase
{
201 TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) {
202 // Tests fail if time is ever 0.
203 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
205 virtual ~TouchExplorationTest() {}
207 virtual void SetUp() OVERRIDE
{
208 if (gfx::GetGLImplementation() == gfx::kGLImplementationNone
)
209 gfx::GLSurface::InitializeOneOffForTests();
210 aura::test::AuraTestBase::SetUp();
211 cursor_client_
.reset(new aura::test::TestCursorClient(root_window()));
212 root_window()->AddPreTargetHandler(&event_capturer_
);
213 generator_
.reset(new test::EventGenerator(root_window()));
214 // The generator takes ownership of the tick clock.
215 generator_
->SetTickClock(scoped_ptr
<base::TickClock
>(simulated_clock_
));
216 cursor_client()->ShowCursor();
217 cursor_client()->DisableMouseEvents();
220 virtual void TearDown() OVERRIDE
{
221 root_window()->RemovePreTargetHandler(&event_capturer_
);
222 SwitchTouchExplorationMode(false);
223 cursor_client_
.reset();
224 aura::test::AuraTestBase::TearDown();
228 aura::client::CursorClient
* cursor_client() { return cursor_client_
.get(); }
230 const ScopedVector
<ui::Event
>& GetCapturedEvents() {
231 return event_capturer_
.captured_events();
234 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEvents() {
235 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
236 std::vector
<ui::LocatedEvent
*> located_events
;
237 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
238 if (all_events
[i
]->IsMouseEvent() ||
239 all_events
[i
]->IsTouchEvent() ||
240 all_events
[i
]->IsGestureEvent()) {
241 located_events
.push_back(static_cast<ui::LocatedEvent
*>(all_events
[i
]));
244 return located_events
;
247 std::vector
<ui::Event
*> GetCapturedEventsOfType(int type
) {
248 const ScopedVector
<ui::Event
>& all_events
= GetCapturedEvents();
249 std::vector
<ui::Event
*> events
;
250 for (size_t i
= 0; i
< all_events
.size(); ++i
) {
251 if (type
== all_events
[i
]->type())
252 events
.push_back(all_events
[i
]);
257 std::vector
<ui::LocatedEvent
*> GetCapturedLocatedEventsOfType(int type
) {
258 std::vector
<ui::LocatedEvent
*> located_events
= GetCapturedLocatedEvents();
259 std::vector
<ui::LocatedEvent
*> events
;
260 for (size_t i
= 0; i
< located_events
.size(); ++i
) {
261 if (type
== located_events
[i
]->type())
262 events
.push_back(located_events
[i
]);
267 void ClearCapturedEvents() {
268 event_capturer_
.Reset();
271 void AdvanceSimulatedTimePastTapDelay() {
272 simulated_clock_
->Advance(gesture_detector_config_
.double_tap_timeout
);
273 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1));
274 touch_exploration_controller_
->CallTapTimerNowForTesting();
277 void AdvanceSimulatedTimePastPassthroughDelay() {
278 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
279 touch_exploration_controller_
->CallPassthroughTimerNowForTesting();
282 void AdvanceSimulatedTimePastPotentialTapDelay() {
283 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
284 touch_exploration_controller_
->CallTapTimerNowIfRunningForTesting();
287 void SuppressVLOGs(bool suppress
) {
288 touch_exploration_controller_
->SuppressVLOGsForTesting(suppress
);
291 void SetTickClock() {
292 touch_exploration_controller_
->SetTickClockForTesting(
293 static_cast<base::TickClock
*>(simulated_clock_
));
296 void SwitchTouchExplorationMode(bool on
) {
297 if (!on
&& touch_exploration_controller_
.get()) {
298 touch_exploration_controller_
.reset();
299 } else if (on
&& !touch_exploration_controller_
.get()) {
300 touch_exploration_controller_
.reset(
301 new ui::TouchExplorationControllerTestApi(
302 new TouchExplorationController(root_window(), &delegate_
)));
303 cursor_client()->ShowCursor();
304 cursor_client()->DisableMouseEvents();
308 void EnterTouchExplorationModeAtLocation(gfx::Point tap_location
) {
309 ui::TouchEvent
touch_press(ui::ET_TOUCH_PRESSED
, tap_location
, 0, Now());
310 generator_
->Dispatch(&touch_press
);
311 AdvanceSimulatedTimePastTapDelay();
312 EXPECT_TRUE(IsInTouchToMouseMode());
315 // Checks that Corner Passthrough is working. Assumes that corner is the
316 // bottom left corner or the bottom right corner.
317 void AssertCornerPassthroughWorking(gfx::Point corner
) {
318 ASSERT_EQ(0U, delegate_
.NumPassthroughSounds());
320 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, corner
, 0, Now());
321 generator_
->Dispatch(&first_press
);
323 AdvanceSimulatedTimePastPassthroughDelay();
324 EXPECT_FALSE(IsInGestureInProgressState());
325 EXPECT_FALSE(IsInSlideGestureState());
326 EXPECT_FALSE(IsInTouchToMouseMode());
327 EXPECT_TRUE(IsInCornerPassthroughState());
329 gfx::Rect window
= BoundsOfRootWindowInDIP();
330 // The following events should be passed through.
331 gfx::Point
passthrough(window
.right() / 2, window
.bottom() / 2);
332 ui::TouchEvent
passthrough_press(
333 ui::ET_TOUCH_PRESSED
, passthrough
, 1, Now());
334 ASSERT_EQ(1U, delegate_
.NumPassthroughSounds());
335 generator_
->Dispatch(&passthrough_press
);
336 generator_
->ReleaseTouchId(1);
337 generator_
->PressTouchId(1);
338 EXPECT_FALSE(IsInGestureInProgressState());
339 EXPECT_FALSE(IsInSlideGestureState());
340 EXPECT_TRUE(IsInCornerPassthroughState());
342 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
343 ASSERT_EQ(3U, captured_events
.size());
344 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
345 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
346 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
347 generator_
->ReleaseTouchId(1);
348 ClearCapturedEvents();
350 generator_
->ReleaseTouchId(0);
351 captured_events
= GetCapturedLocatedEvents();
352 ASSERT_EQ(0U, captured_events
.size());
353 EXPECT_FALSE(IsInTouchToMouseMode());
354 EXPECT_FALSE(IsInCornerPassthroughState());
355 ClearCapturedEvents();
358 bool IsInTouchToMouseMode() {
359 aura::client::CursorClient
* cursor_client
=
360 aura::client::GetCursorClient(root_window());
361 return cursor_client
&&
362 cursor_client
->IsMouseEventsEnabled() &&
363 !cursor_client
->IsCursorVisible();
366 bool IsInNoFingersDownState() {
367 return touch_exploration_controller_
->IsInNoFingersDownStateForTesting();
370 bool IsInGestureInProgressState() {
371 return touch_exploration_controller_
372 ->IsInGestureInProgressStateForTesting();
375 bool IsInSlideGestureState() {
376 return touch_exploration_controller_
->IsInSlideGestureStateForTesting();
379 bool IsInTwoFingerTapState() {
380 return touch_exploration_controller_
->IsInTwoFingerTapStateForTesting();
383 bool IsInCornerPassthroughState() {
384 return touch_exploration_controller_
385 ->IsInCornerPassthroughStateForTesting();
388 gfx::Rect
BoundsOfRootWindowInDIP() {
389 return touch_exploration_controller_
->BoundsOfRootWindowInDIPForTesting();
392 float GetMaxDistanceFromEdge() const {
393 return touch_exploration_controller_
->GetMaxDistanceFromEdge();
396 float GetSlopDistanceFromEdge() const {
397 return touch_exploration_controller_
->GetSlopDistanceFromEdge();
400 base::TimeDelta
Now() {
401 // This is the same as what EventTimeForNow() does, but here we do it
402 // with our simulated clock.
403 return base::TimeDelta::FromInternalValue(
404 simulated_clock_
->NowTicks().ToInternalValue());
407 scoped_ptr
<test::EventGenerator
> generator_
;
408 ui::GestureDetector::Config gesture_detector_config_
;
409 // Owned by |generator_|.
410 base::SimpleTestTickClock
* simulated_clock_
;
411 MockTouchExplorationControllerDelegate delegate_
;
414 EventCapturer event_capturer_
;
415 scoped_ptr
<TouchExplorationControllerTestApi
>
416 touch_exploration_controller_
;
417 scoped_ptr
<aura::test::TestCursorClient
> cursor_client_
;
419 DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest
);
422 // Executes a number of assertions to confirm that |e1| and |e2| are touch
423 // events and are equal to each other.
424 void ConfirmEventsAreTouchAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
425 ASSERT_TRUE(e1
->IsTouchEvent());
426 ASSERT_TRUE(e2
->IsTouchEvent());
427 ui::TouchEvent
* touch_event1
= static_cast<ui::TouchEvent
*>(e1
);
428 ui::TouchEvent
* touch_event2
= static_cast<ui::TouchEvent
*>(e2
);
429 EXPECT_EQ(touch_event1
->type(), touch_event2
->type());
430 EXPECT_EQ(touch_event1
->location(), touch_event2
->location());
431 EXPECT_EQ(touch_event1
->touch_id(), touch_event2
->touch_id());
432 EXPECT_EQ(touch_event1
->flags(), touch_event2
->flags());
433 EXPECT_EQ(touch_event1
->time_stamp(), touch_event2
->time_stamp());
436 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
437 // events and are equal to each other.
438 void ConfirmEventsAreMouseAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
439 ASSERT_TRUE(e1
->IsMouseEvent());
440 ASSERT_TRUE(e2
->IsMouseEvent());
441 ui::MouseEvent
* mouse_event1
= static_cast<ui::MouseEvent
*>(e1
);
442 ui::MouseEvent
* mouse_event2
= static_cast<ui::MouseEvent
*>(e2
);
443 EXPECT_EQ(mouse_event1
->type(), mouse_event2
->type());
444 EXPECT_EQ(mouse_event1
->location(), mouse_event2
->location());
445 EXPECT_EQ(mouse_event1
->root_location(), mouse_event2
->root_location());
446 EXPECT_EQ(mouse_event1
->flags(), mouse_event2
->flags());
449 // Executes a number of assertions to confirm that |e1| and |e2| are key events
450 // and are equal to each other.
451 void ConfirmEventsAreKeyAndEqual(ui::Event
* e1
, ui::Event
* e2
) {
452 ASSERT_TRUE(e1
->IsKeyEvent());
453 ASSERT_TRUE(e2
->IsKeyEvent());
454 ui::KeyEvent
* key_event1
= static_cast<ui::KeyEvent
*>(e1
);
455 ui::KeyEvent
* key_event2
= static_cast<ui::KeyEvent
*>(e2
);
456 EXPECT_EQ(key_event1
->type(), key_event2
->type());
457 EXPECT_EQ(key_event1
->key_code(), key_event2
->key_code());
458 EXPECT_EQ(key_event1
->code(), key_event2
->code());
459 EXPECT_EQ(key_event1
->flags(), key_event2
->flags());
462 #define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
463 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
465 #define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
466 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
468 #define CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(e1, e2) \
469 ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreKeyAndEqual(e1, e2))
471 // TODO(mfomitchev): Need to investigate why we don't get mouse enter/exit
472 // events when running these tests as part of ui_unittests. We do get them when
473 // the tests are run as part of ash unit tests.
475 // If a swipe has been successfully completed, then six key events will be
476 // dispatched that correspond to shift+search+direction
477 void AssertDirectionalNavigationEvents(const ScopedVector
<ui::Event
>& events
,
478 ui::KeyboardCode direction
) {
479 ASSERT_EQ(6U, events
.size());
480 ui::KeyEvent
shift_pressed(
481 ui::ET_KEY_PRESSED
, ui::VKEY_SHIFT
, ui::EF_SHIFT_DOWN
);
482 ui::KeyEvent
search_pressed(
483 ui::ET_KEY_PRESSED
, ui::VKEY_LWIN
, ui::EF_SHIFT_DOWN
);
484 ui::KeyEvent
direction_pressed(
485 ui::ET_KEY_PRESSED
, direction
, ui::EF_SHIFT_DOWN
);
486 ui::KeyEvent
direction_released(
487 ui::ET_KEY_RELEASED
, direction
, ui::EF_SHIFT_DOWN
);
488 ui::KeyEvent
search_released(
489 ui::ET_KEY_RELEASED
, VKEY_LWIN
, ui::EF_SHIFT_DOWN
);
490 ui::KeyEvent
shift_released(
491 ui::ET_KEY_RELEASED
, ui::VKEY_SHIFT
, ui::EF_NONE
);
492 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_pressed
, events
[0]);
493 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_pressed
, events
[1]);
494 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_pressed
, events
[2]);
495 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_released
, events
[3]);
496 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_released
, events
[4]);
497 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_released
, events
[5]);
500 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterPressAndDelay
) {
501 SwitchTouchExplorationMode(true);
502 EXPECT_FALSE(IsInTouchToMouseMode());
503 generator_
->PressTouch();
504 AdvanceSimulatedTimePastTapDelay();
505 EXPECT_TRUE(IsInTouchToMouseMode());
508 TEST_F(TouchExplorationTest
, EntersTouchToMouseModeAfterMoveOutsideSlop
) {
509 int slop
= gesture_detector_config_
.touch_slop
;
510 int half_slop
= slop
/ 2;
512 SwitchTouchExplorationMode(true);
513 EXPECT_FALSE(IsInTouchToMouseMode());
514 generator_
->set_current_location(gfx::Point(11, 12));
515 generator_
->PressTouch();
516 generator_
->MoveTouch(gfx::Point(11 + half_slop
, 12));
517 EXPECT_FALSE(IsInTouchToMouseMode());
518 generator_
->MoveTouch(gfx::Point(11, 12 + half_slop
));
519 EXPECT_FALSE(IsInTouchToMouseMode());
520 AdvanceSimulatedTimePastTapDelay();
521 generator_
->MoveTouch(gfx::Point(11 + slop
+ 1, 12));
522 EXPECT_TRUE(IsInTouchToMouseMode());
525 TEST_F(TouchExplorationTest
, OneFingerTap
) {
526 SwitchTouchExplorationMode(true);
527 gfx::Point
location(11, 12);
528 generator_
->set_current_location(location
);
529 generator_
->PressTouch();
530 generator_
->ReleaseTouch();
531 AdvanceSimulatedTimePastTapDelay();
533 std::vector
<ui::LocatedEvent
*> events
=
534 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
535 ASSERT_EQ(1U, events
.size());
537 EXPECT_EQ(location
, events
[0]->location());
538 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
539 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
540 EXPECT_TRUE(IsInNoFingersDownState());
543 TEST_F(TouchExplorationTest
, ActualMouseMovesUnaffected
) {
544 SwitchTouchExplorationMode(true);
546 gfx::Point
location_start(11, 12);
547 gfx::Point
location_end(13, 14);
548 generator_
->set_current_location(location_start
);
549 generator_
->PressTouch();
550 AdvanceSimulatedTimePastTapDelay();
551 generator_
->MoveTouch(location_end
);
553 gfx::Point
location_real_mouse_move(15, 16);
554 ui::MouseEvent
mouse_move(ui::ET_MOUSE_MOVED
,
555 location_real_mouse_move
,
556 location_real_mouse_move
,
559 generator_
->Dispatch(&mouse_move
);
560 generator_
->ReleaseTouch();
561 AdvanceSimulatedTimePastTapDelay();
563 std::vector
<ui::LocatedEvent
*> events
=
564 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
565 ASSERT_EQ(4U, events
.size());
567 EXPECT_EQ(location_start
, events
[0]->location());
568 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
569 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
571 EXPECT_EQ(location_end
, events
[1]->location());
572 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
573 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
575 // The real mouse move goes through.
576 EXPECT_EQ(location_real_mouse_move
, events
[2]->location());
577 CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(events
[2], &mouse_move
);
578 EXPECT_FALSE(events
[2]->flags() & ui::EF_IS_SYNTHESIZED
);
579 EXPECT_FALSE(events
[2]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
581 // The touch release gets written as a mouse move.
582 EXPECT_EQ(location_end
, events
[3]->location());
583 EXPECT_TRUE(events
[3]->flags() & ui::EF_IS_SYNTHESIZED
);
584 EXPECT_TRUE(events
[3]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
585 EXPECT_TRUE(IsInNoFingersDownState());
588 // Turn the touch exploration mode on in the middle of the touch gesture.
589 // Confirm that events from the finger which was touching when the mode was
590 // turned on don't get rewritten.
591 TEST_F(TouchExplorationTest
, TurnOnMidTouch
) {
592 SwitchTouchExplorationMode(false);
593 generator_
->PressTouchId(1);
594 EXPECT_TRUE(cursor_client()->IsCursorVisible());
595 ClearCapturedEvents();
597 // Enable touch exploration mode while the first finger is touching the
598 // screen. Ensure that subsequent events from that first finger are not
599 // affected by the touch exploration mode, while the touch events from another
600 // finger get rewritten.
601 SwitchTouchExplorationMode(true);
602 ui::TouchEvent
touch_move(ui::ET_TOUCH_MOVED
,
606 generator_
->Dispatch(&touch_move
);
607 EXPECT_TRUE(cursor_client()->IsCursorVisible());
608 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
609 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
610 ASSERT_EQ(1u, captured_events
.size());
611 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_move
);
612 ClearCapturedEvents();
614 // The press from the second finger should get rewritten.
615 generator_
->PressTouchId(2);
616 AdvanceSimulatedTimePastTapDelay();
617 EXPECT_TRUE(IsInTouchToMouseMode());
618 captured_events
= GetCapturedLocatedEvents();
619 std::vector
<ui::LocatedEvent
*>::const_iterator it
;
620 for (it
= captured_events
.begin(); it
!= captured_events
.end(); ++it
) {
621 if ((*it
)->type() == ui::ET_MOUSE_MOVED
)
624 EXPECT_NE(captured_events
.end(), it
);
625 ClearCapturedEvents();
627 // The release of the first finger shouldn't be affected.
628 ui::TouchEvent
touch_release(ui::ET_TOUCH_RELEASED
,
632 generator_
->Dispatch(&touch_release
);
633 captured_events
= GetCapturedLocatedEvents();
634 ASSERT_EQ(1u, captured_events
.size());
635 CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events
[0], &touch_release
);
636 ClearCapturedEvents();
638 // The move and release from the second finger should get rewritten.
639 generator_
->MoveTouchId(gfx::Point(13, 14), 2);
640 generator_
->ReleaseTouchId(2);
641 AdvanceSimulatedTimePastTapDelay();
642 captured_events
= GetCapturedLocatedEvents();
643 ASSERT_EQ(2u, captured_events
.size());
644 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
645 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
646 EXPECT_TRUE(IsInNoFingersDownState());
649 // If an event is received after the double-tap timeout has elapsed, but
650 // before the timer has fired, a mouse move should still be generated.
651 TEST_F(TouchExplorationTest
, TimerFiresLateDuringTouchExploration
) {
652 SwitchTouchExplorationMode(true);
654 // Make sure the touch is not in a corner of the screen.
655 generator_
->MoveTouch(gfx::Point(100, 200));
657 // Send a press, then add another finger after the double-tap timeout.
658 generator_
->PressTouchId(1);
659 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(1000));
660 generator_
->PressTouchId(2);
661 std::vector
<ui::LocatedEvent
*> events
=
662 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
663 ASSERT_EQ(1U, events
.size());
664 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
665 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
667 generator_
->ReleaseTouchId(2);
668 generator_
->ReleaseTouchId(1);
669 AdvanceSimulatedTimePastTapDelay();
670 EXPECT_TRUE(IsInNoFingersDownState());
673 // If a new tap is received after the double-tap timeout has elapsed from
674 // a previous tap, but before the timer has fired, a mouse move should
675 // still be generated from the old tap.
676 TEST_F(TouchExplorationTest
, TimerFiresLateAfterTap
) {
677 SwitchTouchExplorationMode(true);
679 // Send a tap at location1.
680 gfx::Point
location0(11, 12);
681 generator_
->set_current_location(location0
);
682 generator_
->PressTouch();
683 generator_
->ReleaseTouch();
685 // Send a tap at location2, after the double-tap timeout, but before the
687 gfx::Point
location1(33, 34);
688 generator_
->set_current_location(location1
);
689 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(301));
690 generator_
->PressTouch();
691 generator_
->ReleaseTouch();
692 AdvanceSimulatedTimePastTapDelay();
694 std::vector
<ui::LocatedEvent
*> events
=
695 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
696 ASSERT_EQ(2U, events
.size());
697 EXPECT_EQ(location0
, events
[0]->location());
698 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
699 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
700 EXPECT_EQ(location1
, events
[1]->location());
701 EXPECT_TRUE(events
[1]->flags() & ui::EF_IS_SYNTHESIZED
);
702 EXPECT_TRUE(events
[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
703 EXPECT_TRUE(IsInNoFingersDownState());
706 // Double-tapping should send a touch press and release through to the location
707 // of the last successful touch exploration.
708 TEST_F(TouchExplorationTest
, DoubleTap
) {
709 SwitchTouchExplorationMode(true);
711 // Tap at one location, and get a mouse move event.
712 gfx::Point
tap_location(51, 52);
713 generator_
->set_current_location(tap_location
);
714 generator_
->PressTouchId(1);
715 generator_
->ReleaseTouchId(1);
716 AdvanceSimulatedTimePastTapDelay();
718 std::vector
<ui::LocatedEvent
*> events
=
719 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
720 ASSERT_EQ(1U, events
.size());
722 EXPECT_EQ(tap_location
, events
[0]->location());
723 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
724 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
725 ClearCapturedEvents();
727 // Now double-tap at a different location. This should result in
728 // a single touch press and release at the location of the tap,
729 // not at the location of the double-tap.
730 gfx::Point
double_tap_location(33, 34);
731 generator_
->set_current_location(double_tap_location
);
732 generator_
->PressTouch();
733 generator_
->ReleaseTouch();
734 generator_
->PressTouch();
735 generator_
->ReleaseTouch();
737 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
738 ASSERT_EQ(2U, captured_events
.size());
739 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
740 EXPECT_EQ(tap_location
, captured_events
[0]->location());
741 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
742 EXPECT_EQ(tap_location
, captured_events
[1]->location());
743 EXPECT_TRUE(IsInNoFingersDownState());
746 // Double-tapping where the user holds their finger down for the second time
747 // for a longer press should send a touch press and passthrough all further
748 // events from that finger. Other finger presses should be ignored.
749 TEST_F(TouchExplorationTest
, DoubleTapPassthrough
) {
750 SwitchTouchExplorationMode(true);
752 // Tap at one location, and get a mouse move event.
753 gfx::Point
tap_location(11, 12);
754 generator_
->set_current_location(tap_location
);
755 generator_
->PressTouch();
756 generator_
->ReleaseTouch();
757 AdvanceSimulatedTimePastTapDelay();
759 std::vector
<ui::LocatedEvent
*> events
=
760 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
761 ASSERT_EQ(1U, events
.size());
763 EXPECT_EQ(tap_location
, events
[0]->location());
764 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
765 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
766 ClearCapturedEvents();
768 // Now double-tap and hold at a different location.
769 // This should result in a single touch press at the location of the tap,
770 // not at the location of the double-tap.
771 gfx::Point
first_tap_location(13, 14);
772 generator_
->set_current_location(first_tap_location
);
773 generator_
->PressTouchId(1);
774 generator_
->ReleaseTouchId(1);
775 gfx::Point
second_tap_location(15, 16);
776 generator_
->set_current_location(second_tap_location
);
777 generator_
->PressTouchId(1);
778 // Advance to the finger passing through.
779 AdvanceSimulatedTimePastTapDelay();
781 gfx::Vector2d passthrough_offset
= second_tap_location
- tap_location
;
783 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
784 ASSERT_EQ(1U, captured_events
.size());
785 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
786 EXPECT_EQ(second_tap_location
- passthrough_offset
,
787 captured_events
[0]->location());
789 ClearCapturedEvents();
791 // All events for the first finger should pass through now, displaced
792 // relative to the last touch exploration location.
793 gfx::Point
first_move_location(17, 18);
794 generator_
->MoveTouchId(first_move_location
, 1);
795 gfx::Point
second_move_location(12, 13);
796 generator_
->MoveTouchId(second_move_location
, 1);
798 captured_events
= GetCapturedLocatedEvents();
799 ASSERT_EQ(2U, captured_events
.size());
800 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
801 EXPECT_EQ(first_move_location
- passthrough_offset
,
802 captured_events
[0]->location());
803 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[1]->type());
804 EXPECT_EQ(second_move_location
- passthrough_offset
,
805 captured_events
[1]->location());
807 ClearCapturedEvents();
809 // Events for other fingers should do nothing.
810 generator_
->PressTouchId(2);
811 generator_
->PressTouchId(3);
812 generator_
->MoveTouchId(gfx::Point(34, 36), 2);
813 generator_
->ReleaseTouchId(2);
814 captured_events
= GetCapturedLocatedEvents();
815 ASSERT_EQ(0U, captured_events
.size());
817 // Even with finger 3 still down, events for the first finger should still
819 gfx::Point
third_move_location(14, 15);
820 generator_
->MoveTouchId(third_move_location
, 1);
821 captured_events
= GetCapturedLocatedEvents();
822 ASSERT_EQ(1U, captured_events
.size());
823 EXPECT_EQ(ui::ET_TOUCH_MOVED
, captured_events
[0]->type());
824 EXPECT_EQ(third_move_location
- passthrough_offset
,
825 captured_events
[0]->location());
827 // No fingers down state is only reached when every finger is lifted.
828 generator_
->ReleaseTouchId(1);
829 EXPECT_FALSE(IsInNoFingersDownState());
830 generator_
->ReleaseTouchId(3);
831 EXPECT_TRUE(IsInNoFingersDownState());
834 // Double-tapping, going into passthrough, and holding for the longpress
835 // time should send a touch press and released (right click)
836 // to the location of the last successful touch exploration.
837 TEST_F(TouchExplorationTest
, DoubleTapLongPress
) {
838 SwitchTouchExplorationMode(true);
840 // Tap at one location, and get a mouse move event.
841 gfx::Point
tap_location(11, 12);
842 generator_
->set_current_location(tap_location
);
843 generator_
->PressTouch();
844 generator_
->ReleaseTouch();
845 AdvanceSimulatedTimePastTapDelay();
847 std::vector
<ui::LocatedEvent
*> events
=
848 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
849 ASSERT_EQ(1U, events
.size());
850 EXPECT_EQ(tap_location
, events
[0]->location());
851 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
852 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
853 ClearCapturedEvents();
855 // Now double-tap and hold at a different location.
856 // This should result in a single touch long press and release
857 // at the location of the tap, not at the location of the double-tap.
858 // There should be a time delay between the touch press and release.
859 gfx::Point
first_tap_location(33, 34);
860 generator_
->set_current_location(first_tap_location
);
861 generator_
->PressTouch();
862 generator_
->ReleaseTouch();
863 gfx::Point
second_tap_location(23, 24);
864 generator_
->set_current_location(second_tap_location
);
865 generator_
->PressTouch();
866 // Advance to the finger passing through, and then to the longpress timeout.
867 AdvanceSimulatedTimePastTapDelay();
868 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
869 generator_
->ReleaseTouch();
871 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
872 ASSERT_EQ(2U, captured_events
.size());
873 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
874 EXPECT_EQ(tap_location
, captured_events
[0]->location());
875 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
876 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
877 EXPECT_EQ(tap_location
, captured_events
[1]->location());
878 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
879 EXPECT_EQ(released_time
- pressed_time
,
880 gesture_detector_config_
.longpress_timeout
);
883 // Single-tapping should send a touch press and release through to the location
884 // of the last successful touch exploration if the grace period has not
886 TEST_F(TouchExplorationTest
, SingleTap
) {
887 SwitchTouchExplorationMode(true);
889 // Tap once to simulate a mouse moved event.
890 gfx::Point
initial_location(11, 12);
891 generator_
->set_current_location(initial_location
);
892 generator_
->PressTouch();
893 AdvanceSimulatedTimePastTapDelay();
894 ClearCapturedEvents();
896 // Move to another location for single tap
897 gfx::Point
tap_location(22, 23);
898 generator_
->MoveTouch(tap_location
);
899 generator_
->ReleaseTouch();
901 // Allow time to pass within the grace period of releasing before
903 gfx::Point
final_location(33, 34);
904 generator_
->set_current_location(final_location
);
905 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(250));
906 generator_
->PressTouch();
907 generator_
->ReleaseTouch();
909 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
910 ASSERT_EQ(4U, captured_events
.size());
911 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
912 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
913 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[2]->type());
914 EXPECT_EQ(tap_location
, captured_events
[2]->location());
915 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[3]->type());
916 EXPECT_EQ(tap_location
, captured_events
[3]->location());
919 // Double-tapping without coming from touch exploration (no previous touch
920 // exploration event) should not generate any events.
921 TEST_F(TouchExplorationTest
, DoubleTapNoTouchExplore
) {
922 SwitchTouchExplorationMode(true);
924 // Double-tap without any previous touch.
925 // Touch exploration mode has not been entered, so there is no previous
926 // touch exploration event. The double-tap should be discarded, and no events
927 // should be generated at all.
928 gfx::Point
double_tap_location(33, 34);
929 generator_
->set_current_location(double_tap_location
);
930 generator_
->PressTouch();
931 generator_
->ReleaseTouch();
932 generator_
->PressTouch();
933 // Since the state stays in single_tap_released, we need to make sure the
934 // tap timer doesn't fire and set the state to no fingers down (since there
935 // is still a finger down).
936 AdvanceSimulatedTimePastPotentialTapDelay();
937 EXPECT_FALSE(IsInNoFingersDownState());
938 generator_
->ReleaseTouch();
939 EXPECT_TRUE(IsInNoFingersDownState());
941 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
942 ASSERT_EQ(0U, captured_events
.size());
945 // Tapping and releasing with a second finger when in touch exploration mode
946 // should send a touch press and released to the location of the last
947 // successful touch exploration and return to touch explore.
948 TEST_F(TouchExplorationTest
, SplitTap
) {
949 SwitchTouchExplorationMode(true);
950 gfx::Point
initial_touch_location(11, 12);
951 gfx::Point
second_touch_location(33, 34);
953 // Tap and hold at one location, and get a mouse move event in touch explore.
954 EnterTouchExplorationModeAtLocation(initial_touch_location
);
955 std::vector
<ui::LocatedEvent
*> events
=
956 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
957 ASSERT_EQ(1U, events
.size());
959 EXPECT_EQ(initial_touch_location
, events
[0]->location());
960 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
961 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
962 ClearCapturedEvents();
963 EXPECT_TRUE(IsInTouchToMouseMode());
965 // Now tap and release at a different location. This should result in a
966 // single touch and release at the location of the first (held) tap,
967 // not at the location of the second tap and release.
968 // After the release, there is still a finger in touch explore mode.
969 ui::TouchEvent
split_tap_press(
970 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
971 generator_
->Dispatch(&split_tap_press
);
972 // To simulate the behavior of the real device, we manually disable
973 // mouse events. To not rely on manually setting the state, this is also
974 // tested in touch_exploration_controller_browsertest.
975 cursor_client()->DisableMouseEvents();
976 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
977 EXPECT_FALSE(cursor_client()->IsCursorVisible());
978 EXPECT_FALSE(IsInGestureInProgressState());
979 ui::TouchEvent
split_tap_release(
980 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
981 generator_
->Dispatch(&split_tap_release
);
982 // Releasing the second finger should re-enable mouse events putting us
983 // back into the touch exploration mode.
984 EXPECT_TRUE(IsInTouchToMouseMode());
985 EXPECT_FALSE(IsInNoFingersDownState());
987 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
988 ASSERT_EQ(2U, captured_events
.size());
989 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
990 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
991 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
992 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
993 ClearCapturedEvents();
995 ui::TouchEvent
touch_explore_release(
996 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
997 generator_
->Dispatch(&touch_explore_release
);
998 AdvanceSimulatedTimePastTapDelay();
999 EXPECT_TRUE(IsInNoFingersDownState());
1002 // If split tap is started but the touch explore finger is released first,
1003 // there should still be a touch press and release sent to the location of
1004 // the last successful touch exploration.
1005 // Both fingers should be released after the click goes through.
1006 TEST_F(TouchExplorationTest
, SplitTapRelease
) {
1007 SwitchTouchExplorationMode(true);
1009 gfx::Point
initial_touch_location(11, 12);
1010 gfx::Point
second_touch_location(33, 34);
1012 // Tap and hold at one location, and get a mouse move event in touch explore.
1013 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1015 std::vector
<ui::LocatedEvent
*> events
=
1016 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1017 ASSERT_EQ(1U, events
.size());
1019 ClearCapturedEvents();
1021 // Now tap at a different location. Release at the first location,
1022 // then release at the second. This should result in a
1023 // single touch and release at the location of the first (held) tap,
1024 // not at the location of the second tap and release.
1025 ui::TouchEvent
split_tap_press(
1026 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1027 generator_
->Dispatch(&split_tap_press
);
1028 ui::TouchEvent
touch_explore_release(
1029 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1030 generator_
->Dispatch(&touch_explore_release
);
1031 ui::TouchEvent
split_tap_release(
1032 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1033 generator_
->Dispatch(&split_tap_release
);
1034 EXPECT_TRUE(IsInNoFingersDownState());
1036 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1037 ASSERT_EQ(2U, captured_events
.size());
1038 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1039 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1040 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1041 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1044 // When in touch exploration mode, making a long press with a second finger
1045 // should send a touch press and released to the location of the last
1046 // successful touch exploration. There should be a delay between the
1047 // touch and release events (right click).
1048 TEST_F(TouchExplorationTest
, SplitTapLongPress
) {
1049 SwitchTouchExplorationMode(true);
1050 gfx::Point
initial_touch_location(11, 12);
1051 gfx::Point
second_touch_location(33, 34);
1053 // Tap and hold at one location, and get a mouse move event in touch explore.
1054 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1055 std::vector
<ui::LocatedEvent
*> events
=
1056 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1057 ASSERT_EQ(1U, events
.size());
1059 ClearCapturedEvents();
1061 // Now tap, hold, and release at a different location. This should result
1062 // in a single touch and release (long press) at the location of the first
1063 // (held) tap, not at the location of the second tap and release.
1064 ui::TouchEvent
split_tap_press(
1065 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1066 generator_
->Dispatch(&split_tap_press
);
1067 // To simulate the behavior of the real device, we manually disable
1068 // mouse events, like in the SplitTap test.
1069 cursor_client()->DisableMouseEvents();
1070 EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
1071 EXPECT_FALSE(cursor_client()->IsCursorVisible());
1072 EXPECT_FALSE(IsInGestureInProgressState());
1073 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1074 // After the release, there is still a finger in touch exploration, and
1075 // mouse events should be enabled again.
1076 ui::TouchEvent
split_tap_release(
1077 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1078 generator_
->Dispatch(&split_tap_release
);
1079 EXPECT_FALSE(IsInNoFingersDownState());
1080 EXPECT_TRUE(IsInTouchToMouseMode());
1082 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1083 ASSERT_EQ(2U, captured_events
.size());
1084 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1085 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1086 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
1087 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1088 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1089 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
1090 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
1091 released_time
- pressed_time
);
1094 // If split tap is started but the touch explore finger is released first,
1095 // there should still be a touch press and release sent to the location of
1096 // the last successful touch exploration. If the remaining finger is held
1097 // as a longpress, there should be a delay between the sent touch and release
1098 // events (right click).All fingers should be released after the click
1100 TEST_F(TouchExplorationTest
, SplitTapReleaseLongPress
) {
1101 SwitchTouchExplorationMode(true);
1102 gfx::Point
initial_touch_location(11, 12);
1103 gfx::Point
second_touch_location(33, 34);
1105 // Tap and hold at one location, and get a mouse move event in touch explore.
1106 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1107 std::vector
<ui::LocatedEvent
*> events
=
1108 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1109 ASSERT_EQ(1U, events
.size());
1110 ClearCapturedEvents();
1112 // Now tap at a different location. Release at the first location,
1113 // then release at the second. This should result in a
1114 // single touch and release at the location of the first (held) tap,
1115 // not at the location of the second tap and release.
1116 // After the release, TouchToMouseMode should still be on.
1117 ui::TouchEvent
split_tap_press(
1118 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1119 generator_
->Dispatch(&split_tap_press
);
1120 ui::TouchEvent
touch_explore_release(
1121 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1122 generator_
->Dispatch(&touch_explore_release
);
1123 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1124 ui::TouchEvent
split_tap_release(
1125 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1126 generator_
->Dispatch(&split_tap_release
);
1127 EXPECT_TRUE(IsInTouchToMouseMode());
1129 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1130 ASSERT_EQ(2U, captured_events
.size());
1131 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1132 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1133 base::TimeDelta pressed_time
= captured_events
[0]->time_stamp();
1134 EXPECT_EQ(ui::ET_TOUCH_RELEASED
, captured_events
[1]->type());
1135 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1136 base::TimeDelta released_time
= captured_events
[1]->time_stamp();
1137 EXPECT_EQ(gesture_detector_config_
.longpress_timeout
,
1138 released_time
- pressed_time
);
1141 TEST_F(TouchExplorationTest
, SplitTapMultiFinger
) {
1142 SwitchTouchExplorationMode(true);
1143 gfx::Point
initial_touch_location(11, 12);
1144 gfx::Point
second_touch_location(33, 34);
1145 gfx::Point
third_touch_location(16, 17);
1147 // Tap and hold at one location, and get a mouse move event in touch explore.
1148 EnterTouchExplorationModeAtLocation(initial_touch_location
);
1150 std::vector
<ui::LocatedEvent
*> events
=
1151 GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED
);
1152 ASSERT_EQ(1U, events
.size());
1154 EXPECT_EQ(initial_touch_location
, events
[0]->location());
1155 EXPECT_TRUE(events
[0]->flags() & ui::EF_IS_SYNTHESIZED
);
1156 EXPECT_TRUE(events
[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY
);
1157 ClearCapturedEvents();
1159 // Now tap at a different location and hold for long press.
1160 ui::TouchEvent
split_tap_press(
1161 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1162 generator_
->Dispatch(&split_tap_press
);
1163 simulated_clock_
->Advance(gesture_detector_config_
.longpress_timeout
);
1165 // Placing a third finger on the screen should cancel the initial press and
1166 // enter the wait state.
1167 ui::TouchEvent
third_press(
1168 ui::ET_TOUCH_PRESSED
, third_touch_location
, 2, Now());
1169 generator_
->Dispatch(&third_press
);
1171 // When all three fingers are released, the only events captured should be a
1172 // press and touch cancel. All fingers should then be up.
1173 ui::TouchEvent
touch_explore_release(
1174 ui::ET_TOUCH_RELEASED
, initial_touch_location
, 0, Now());
1175 generator_
->Dispatch(&touch_explore_release
);
1176 ui::TouchEvent
split_tap_release(
1177 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1178 generator_
->Dispatch(&split_tap_release
);
1179 ui::TouchEvent
third_tap_release(
1180 ui::ET_TOUCH_RELEASED
, third_touch_location
, 2, Now());
1181 generator_
->Dispatch(&third_tap_release
);
1183 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1184 ASSERT_EQ(2U, captured_events
.size());
1185 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1186 EXPECT_EQ(initial_touch_location
, captured_events
[0]->location());
1187 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1188 EXPECT_EQ(initial_touch_location
, captured_events
[1]->location());
1189 EXPECT_TRUE(IsInNoFingersDownState());
1193 TEST_F(TouchExplorationTest
, SplitTapLeaveSlop
) {
1194 SwitchTouchExplorationMode(true);
1195 gfx::Point
first_touch_location(11, 12);
1196 gfx::Point
second_touch_location(33, 34);
1197 gfx::Point
first_move_location(
1198 first_touch_location
.x() + gesture_detector_config_
.touch_slop
* 3 + 1,
1199 first_touch_location
.y());
1200 gfx::Point
second_move_location(
1201 second_touch_location
.x() + gesture_detector_config_
.touch_slop
* 3 + 1,
1202 second_touch_location
.y());
1204 // Tap and hold at one location, and get a mouse move event in touch explore.
1205 EnterTouchExplorationModeAtLocation(first_touch_location
);
1206 ClearCapturedEvents();
1208 // Now tap at a different location for split tap.
1209 ui::TouchEvent
split_tap_press(
1210 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1211 generator_
->Dispatch(&split_tap_press
);
1213 // Move the first finger out of slop and release both fingers. The split
1214 // tap should have been cancelled, so a touch press and touch cancel event
1215 // should go through at the last touch exploration location (the first press).
1216 ui::TouchEvent
first_touch_move(
1217 ui::ET_TOUCH_MOVED
, first_move_location
, 0, Now());
1218 generator_
->Dispatch(&first_touch_move
);
1219 ui::TouchEvent
first_touch_release(
1220 ui::ET_TOUCH_RELEASED
, first_move_location
, 0, Now());
1221 generator_
->Dispatch(&first_touch_release
);
1222 ui::TouchEvent
second_touch_release(
1223 ui::ET_TOUCH_RELEASED
, second_touch_location
, 1, Now());
1224 generator_
->Dispatch(&second_touch_release
);
1226 std::vector
<ui::LocatedEvent
*> captured_events
= GetCapturedLocatedEvents();
1227 ASSERT_EQ(2U, captured_events
.size());
1228 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1229 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1230 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1231 EXPECT_EQ(first_touch_location
, captured_events
[1]->location());
1232 EXPECT_TRUE(IsInNoFingersDownState());
1234 // Now do the same, but moving the split tap finger out of slop
1235 EnterTouchExplorationModeAtLocation(first_touch_location
);
1236 ClearCapturedEvents();
1237 ui::TouchEvent
split_tap_press2(
1238 ui::ET_TOUCH_PRESSED
, second_touch_location
, 1, Now());
1239 generator_
->Dispatch(&split_tap_press2
);
1241 // Move the second finger out of slop and release both fingers. The split
1242 // tap should have been cancelled, so a touch press and touch cancel event
1243 // should go through at the last touch exploration location (the first press).
1244 ui::TouchEvent
second_touch_move2(
1245 ui::ET_TOUCH_MOVED
, second_move_location
, 1, Now());
1246 generator_
->Dispatch(&second_touch_move2
);
1247 ui::TouchEvent
first_touch_release2(
1248 ui::ET_TOUCH_RELEASED
, first_touch_location
, 0, Now());
1249 generator_
->Dispatch(&first_touch_release2
);
1250 ui::TouchEvent
second_touch_release2(
1251 ui::ET_TOUCH_RELEASED
, second_move_location
, 1, Now());
1252 generator_
->Dispatch(&second_touch_release2
);
1254 captured_events
= GetCapturedLocatedEvents();
1255 ASSERT_EQ(2U, captured_events
.size());
1256 EXPECT_EQ(ui::ET_TOUCH_PRESSED
, captured_events
[0]->type());
1257 EXPECT_EQ(first_touch_location
, captured_events
[0]->location());
1258 EXPECT_EQ(ui::ET_TOUCH_CANCELLED
, captured_events
[1]->type());
1259 EXPECT_EQ(first_touch_location
, captured_events
[1]->location());
1260 EXPECT_TRUE(IsInNoFingersDownState());
1263 // Finger must have moved more than slop, faster than the minimum swipe
1264 // velocity, and before the tap timer fires in order to enter
1265 // GestureInProgress state. Otherwise, if the tap timer fires before the a
1266 // gesture is completed, enter touch exploration.
1267 TEST_F(TouchExplorationTest
, EnterGestureInProgressState
) {
1268 SwitchTouchExplorationMode(true);
1269 EXPECT_FALSE(IsInTouchToMouseMode());
1270 EXPECT_FALSE(IsInGestureInProgressState());
1272 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1273 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, gfx::Point(0, 1), 0, Now());
1274 gfx::Point
second_location(distance
/ 2, 1);
1275 gfx::Point
third_location(distance
, 1);
1276 gfx::Point
touch_exploration_location(20, 21);
1278 generator_
->Dispatch(&first_press
);
1279 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1280 // Since we are not out of the touch slop yet, we should not be in gesture in
1282 generator_
->MoveTouch(second_location
);
1283 EXPECT_FALSE(IsInTouchToMouseMode());
1284 EXPECT_FALSE(IsInGestureInProgressState());
1285 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1287 // Once we are out of slop, we should be in GestureInProgress.
1288 generator_
->MoveTouch(third_location
);
1289 EXPECT_TRUE(IsInGestureInProgressState());
1290 EXPECT_FALSE(IsInTouchToMouseMode());
1291 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1292 ASSERT_EQ(0U, captured_events
.size());
1294 // Exit out of gesture mode once grace period is over and enter touch
1295 // exploration. There should be a move when entering touch exploration and
1296 // also for the touch move.
1297 AdvanceSimulatedTimePastTapDelay();
1298 generator_
->MoveTouch(touch_exploration_location
);
1299 ASSERT_EQ(2U, captured_events
.size());
1300 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[0]->type());
1301 EXPECT_EQ(ui::ET_MOUSE_MOVED
, captured_events
[1]->type());
1302 EXPECT_TRUE(IsInTouchToMouseMode());
1303 EXPECT_FALSE(IsInGestureInProgressState());
1306 // A swipe+direction gesture should trigger a Shift+Search+Direction
1308 TEST_F(TouchExplorationTest
, GestureSwipe
) {
1309 SwitchTouchExplorationMode(true);
1310 std::vector
<ui::KeyboardCode
> directions
;
1311 directions
.push_back(ui::VKEY_RIGHT
);
1312 directions
.push_back(ui::VKEY_LEFT
);
1313 directions
.push_back(ui::VKEY_UP
);
1314 directions
.push_back(ui::VKEY_DOWN
);
1316 // This value was taken from gesture_recognizer_unittest.cc in a swipe
1317 // detector test, since it seems to be about the right amount to get a swipe.
1318 const int kSteps
= 15;
1320 // There are gestures supported with up to four fingers.
1321 for (int num_fingers
= 1; num_fingers
<= 4; num_fingers
++) {
1322 std::vector
<gfx::Point
> start_points
;
1323 for (int j
= 0; j
< num_fingers
; j
++) {
1324 start_points
.push_back(gfx::Point(j
* 10 + 100, j
* 10 + 200));
1326 gfx::Point
* start_points_array
= &start_points
[0];
1327 const float distance
= gesture_detector_config_
.touch_slop
+ 1;
1328 // Iterate through each swipe direction for this number of fingers.
1329 for (std::vector
<ui::KeyboardCode
>::const_iterator it
= directions
.begin();
1330 it
!= directions
.end();
1334 ui::KeyboardCode direction
= *it
;
1335 switch (direction
) {
1336 case ui::VKEY_RIGHT
:
1340 move_x
= 0 - distance
;
1343 move_y
= 0 - distance
;
1352 // A swipe is made when a fling starts
1354 distance
/ gesture_detector_config_
.maximum_fling_velocity
;
1355 // delta_time is in seconds, so we convert to ms.
1356 int delta_time_ms
= floor(delta_time
* 1000);
1357 generator_
->GestureMultiFingerScroll(num_fingers
,
1364 // The swipe registered and sent the appropriate key events.
1365 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1366 if (num_fingers
== 1)
1367 AssertDirectionalNavigationEvents(captured_events
, direction
);
1369 // Most of the time this is 2 right now, but two of the two finger
1370 // swipes are mapped to chromevox commands which dispatch 6 key events,
1371 // and these will probably be remapped a lot as we're developing.
1372 ASSERT_GE(captured_events
.size(), 2U);
1373 std::vector
<ui::Event
>::size_type i
;
1374 for (i
= 0; i
!= captured_events
.size(); i
++) {
1375 EXPECT_TRUE(captured_events
[i
]->IsKeyEvent());
1378 EXPECT_TRUE(IsInNoFingersDownState());
1379 EXPECT_FALSE(IsInTouchToMouseMode());
1380 EXPECT_FALSE(IsInGestureInProgressState());
1381 ClearCapturedEvents();
1386 // Since there are so many permutations, this test is fairly slow. Therefore, it
1387 // is disabled and will be turned on to check during development.
1389 TEST_F(TouchExplorationTest
, DISABLED_AllFingerPermutations
) {
1390 SwitchTouchExplorationMode(true);
1391 SuppressVLOGs(true);
1392 // We will test all permutations of events from three different fingers
1393 // to ensure that we return to NO_FINGERS_DOWN when fingers have been
1395 ScopedVector
<ui::TouchEvent
> all_events
;
1396 for (int touch_id
= 0; touch_id
< 3; touch_id
++){
1397 int x
= 10*touch_id
+ 1;
1398 int y
= 10*touch_id
+ 2;
1399 all_events
.push_back(new TouchEvent(
1400 ui::ET_TOUCH_PRESSED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1401 all_events
.push_back(new TouchEvent(
1402 ui::ET_TOUCH_MOVED
, gfx::Point(x
++, y
++), touch_id
, Now()));
1403 all_events
.push_back(new TouchEvent(
1404 ui::ET_TOUCH_RELEASED
, gfx::Point(x
, y
), touch_id
, Now()));
1407 // I'm going to explain this algorithm, and use an example in parentheses.
1408 // The example will be all permutations of a b c d.
1409 // There are four letters and 4! = 24 permutations.
1410 const int num_events
= all_events
.size();
1411 const int num_permutations
= Factorial(num_events
);
1413 for (int p
= 0; p
< num_permutations
; p
++) {
1414 std::vector
<ui::TouchEvent
*> queued_events
= all_events
.get();
1415 std::vector
<bool> fingers_pressed(3, false);
1417 int current_num_permutations
= num_permutations
;
1418 for (int events_left
= num_events
; events_left
> 0; events_left
--) {
1419 // |p| indexes to each permutation when there are num_permutations
1420 // permutations. (e.g. 0 is abcd, 1 is abdc, 2 is acbd, 3 is acdb...)
1421 // But how do we find the index for the current number of permutations?
1422 // To find the permutation within the part of the sequence we're
1423 // currently looking at, we need a number between 0 and
1424 // |current_num_permutations| - 1.
1425 // (e.g. if we already chose the first letter, there are 3! = 6
1426 // options left, so we do p % 6. So |current_permutation| would go
1427 // from 0 to 5 and then reset to 0 again, for all combinations of
1428 // whichever three letters are remaining, as we loop through the
1430 int current_permutation
= p
% current_num_permutations
;
1432 // Since this is is the total number of permutations starting with
1433 // this event and including future events, there could be multiple
1434 // values of current_permutation that will generate the same event
1435 // in this iteration.
1436 // (e.g. If we chose 'a' but have b c d to choose from, we choose b when
1437 // |current_permutation| = 0, 1 and c when |current_permutation| = 2, 3.
1438 // Note that each letter gets two numbers, which is the next
1439 // current_num_permutations, 2! for the two letters left.)
1441 // Branching out from the first event, there are num_permutations
1442 // permutations, and each value of |p| is associated with one of these
1443 // permutations. However, once the first event is chosen, there
1444 // are now |num_events| - 1 events left, so the number of permutations
1445 // for the rest of the events changes, and will always be equal to
1446 // the factorial of the events_left.
1447 // (e.g. There are 3! = 6 permutations that start with 'a', so if we
1448 // start with 'a' there will be 6 ways to then choose from b c d.)
1449 // So we now set-up for the next iteration by setting
1450 // current_num_permutations to the factorial of the next number of
1452 current_num_permutations
/= events_left
;
1454 // To figure out what current event we want to choose, we integer
1455 // divide the current permutation by the next current_num_permutations.
1456 // (e.g. If there are 4 letters a b c d and 24 permutations, we divide
1457 // by 24/4 = 6. Values 0 to 5 when divided by 6 equals 0, so the first
1458 // 6 permutations start with 'a', and the last 6 will start with 'd'.
1459 // Note that there are 6 that start with 'a' because there are 6
1460 // permutations for the next three letters that follow 'a'.)
1461 int index
= current_permutation
/ current_num_permutations
;
1463 ui::TouchEvent
* next_dispatch
= queued_events
[index
];
1464 ASSERT_TRUE(next_dispatch
!= NULL
);
1466 // |next_dispatch| has to be put in this container so that its time
1467 // stamp can be changed to this point in the test, when it is being
1469 EventTestApi
test_dispatch(next_dispatch
);
1470 test_dispatch
.set_time_stamp(Now());
1471 generator_
->Dispatch(next_dispatch
);
1472 queued_events
.erase(queued_events
.begin() + index
);
1474 // Keep track of what fingers have been pressed, to release
1475 // only those fingers at the end, so the check for being in
1476 // no fingers down can be accurate.
1477 if (next_dispatch
->type() == ET_TOUCH_PRESSED
) {
1478 fingers_pressed
[next_dispatch
->touch_id()] = true;
1479 } else if (next_dispatch
->type() == ET_TOUCH_RELEASED
) {
1480 fingers_pressed
[next_dispatch
->touch_id()] = false;
1483 ASSERT_EQ(queued_events
.size(), 0u);
1485 // Release fingers recorded as pressed.
1486 for(int j
= 0; j
< int(fingers_pressed
.size()); j
++){
1487 if (fingers_pressed
[j
] == true) {
1488 generator_
->ReleaseTouchId(j
);
1489 fingers_pressed
[j
] = false;
1492 AdvanceSimulatedTimePastPotentialTapDelay();
1493 EXPECT_TRUE(IsInNoFingersDownState());
1494 ClearCapturedEvents();
1498 // With the simple swipe gestures, if additional fingers are added and the tap
1499 // timer times out, then the state should change to the wait for one finger
1501 TEST_F(TouchExplorationTest
, GestureAddedFinger
) {
1502 SwitchTouchExplorationMode(true);
1503 EXPECT_FALSE(IsInTouchToMouseMode());
1504 EXPECT_FALSE(IsInGestureInProgressState());
1506 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1507 ui::TouchEvent
first_press(
1508 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 0, Now());
1509 generator_
->Dispatch(&first_press
);
1510 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1511 gfx::Point
second_location(100 + distance
, 200);
1512 generator_
->MoveTouch(second_location
);
1513 EXPECT_TRUE(IsInGestureInProgressState());
1514 EXPECT_FALSE(IsInTouchToMouseMode());
1515 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1516 ASSERT_EQ(0U, captured_events
.size());
1518 // Generate a second press, but time out past the gesture period so that
1519 // gestures are prevented from continuing to go through.
1520 ui::TouchEvent
second_press(
1521 ui::ET_TOUCH_PRESSED
, gfx::Point(20, 21), 1, Now());
1522 generator_
->Dispatch(&second_press
);
1523 AdvanceSimulatedTimePastTapDelay();
1524 EXPECT_FALSE(IsInGestureInProgressState());
1525 EXPECT_FALSE(IsInTouchToMouseMode());
1526 ASSERT_EQ(0U, captured_events
.size());
1529 TEST_F(TouchExplorationTest
, EnterSlideGestureState
) {
1530 SwitchTouchExplorationMode(true);
1531 EXPECT_FALSE(IsInTouchToMouseMode());
1532 EXPECT_FALSE(IsInGestureInProgressState());
1534 int window_right
= BoundsOfRootWindowInDIP().right();
1535 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1536 ui::TouchEvent
first_press(
1537 ui::ET_TOUCH_PRESSED
, gfx::Point(window_right
, 1), 0, Now());
1538 gfx::Point
second_location(window_right
, 1 + distance
/ 2);
1539 gfx::Point
third_location(window_right
, 1 + distance
);
1540 gfx::Point
fourth_location(window_right
, 35);
1542 generator_
->Dispatch(&first_press
);
1543 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1545 // Since we haven't moved past slop yet, we should not be in slide gesture.
1546 generator_
->MoveTouch(second_location
);
1547 EXPECT_FALSE(IsInTouchToMouseMode());
1548 EXPECT_FALSE(IsInGestureInProgressState());
1549 EXPECT_FALSE(IsInSlideGestureState());
1550 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1552 // Once we are out of slop, we should be in slide gesture since we are along
1553 // the edge of the screen.
1554 generator_
->MoveTouch(third_location
);
1555 EXPECT_FALSE(IsInGestureInProgressState());
1556 EXPECT_TRUE(IsInSlideGestureState());
1557 EXPECT_FALSE(IsInTouchToMouseMode());
1559 // Now that we are in slide gesture, we can adjust the volume.
1560 generator_
->MoveTouch(fourth_location
);
1561 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1562 ASSERT_EQ(0U, captured_events
.size());
1564 // Since we are at the right edge of the screen, but the sound timer has not
1565 // elapsed, there should have been a sound that fired and a volume
1567 size_t num_adjust_sounds
= delegate_
.NumAdjustSounds();
1568 ASSERT_EQ(1U, num_adjust_sounds
);
1569 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1571 // Exit out of slide gesture once touch is lifted, but not before even if the
1572 // grace period is over.
1573 AdvanceSimulatedTimePastPotentialTapDelay();
1574 ASSERT_EQ(0U, captured_events
.size());
1575 EXPECT_FALSE(IsInTouchToMouseMode());
1576 EXPECT_FALSE(IsInGestureInProgressState());
1577 EXPECT_TRUE(IsInSlideGestureState());
1579 generator_
->ReleaseTouch();
1580 ASSERT_EQ(0U, captured_events
.size());
1581 EXPECT_FALSE(IsInTouchToMouseMode());
1582 EXPECT_FALSE(IsInGestureInProgressState());
1583 EXPECT_FALSE(IsInSlideGestureState());
1586 // If a press + move occurred outside the boundaries, but within the slop
1587 // boundaries and then moved into the boundaries of an edge, there still should
1588 // not be a slide gesture.
1589 TEST_F(TouchExplorationTest
, AvoidEnteringSlideGesture
) {
1590 SwitchTouchExplorationMode(true);
1592 gfx::Rect window
= BoundsOfRootWindowInDIP();
1593 float distance
= gesture_detector_config_
.touch_slop
+ 1;
1594 ui::TouchEvent
first_press(
1595 ui::ET_TOUCH_PRESSED
,
1596 gfx::Point(window
.right() - GetSlopDistanceFromEdge(), 1),
1599 gfx::Point
out_of_slop(window
.right() - GetSlopDistanceFromEdge() + distance
,
1601 gfx::Point
into_boundaries(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1603 generator_
->Dispatch(&first_press
);
1604 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1606 generator_
->MoveTouch(out_of_slop
);
1607 EXPECT_FALSE(IsInTouchToMouseMode());
1608 EXPECT_TRUE(IsInGestureInProgressState());
1609 EXPECT_FALSE(IsInSlideGestureState());
1610 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1612 // Since we did not start moving while in the boundaries, we should not be in
1614 generator_
->MoveTouch(into_boundaries
);
1615 EXPECT_TRUE(IsInGestureInProgressState());
1616 EXPECT_FALSE(IsInSlideGestureState());
1617 EXPECT_FALSE(IsInTouchToMouseMode());
1618 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1619 ASSERT_EQ(0U, captured_events
.size());
1621 generator_
->ReleaseTouch();
1624 // If the slide gesture begins within the boundaries and then moves
1625 // SlopDistanceFromEdge there should still be a sound change. If the finger
1626 // moves into the center screen, there should no longer be a sound change but it
1627 // should still be in slide gesture. If the finger moves back into the edges
1628 // without lifting, it should start changing sound again.
1629 TEST_F(TouchExplorationTest
, TestingBoundaries
) {
1630 SwitchTouchExplorationMode(true);
1632 gfx::Rect window
= BoundsOfRootWindowInDIP();
1633 gfx::Point
initial_press(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1635 gfx::Point
center_screen(window
.right() / 2, window
.bottom() / 2);
1637 ui::TouchEvent
first_press(ui::ET_TOUCH_PRESSED
, initial_press
, 0, Now());
1638 generator_
->Dispatch(&first_press
);
1639 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1640 EXPECT_FALSE(IsInGestureInProgressState());
1641 EXPECT_FALSE(IsInSlideGestureState());
1642 EXPECT_FALSE(IsInTouchToMouseMode());
1644 // Move past the touch slop to begin slide gestures.
1645 // + slop + 1 to actually leave slop.
1646 gfx::Point
touch_move(
1648 initial_press
.y() + gesture_detector_config_
.touch_slop
+ 1);
1649 generator_
->MoveTouch(touch_move
);
1650 EXPECT_FALSE(IsInGestureInProgressState());
1651 EXPECT_TRUE(IsInSlideGestureState());
1652 EXPECT_FALSE(IsInTouchToMouseMode());
1653 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(10));
1655 // Move the touch into slop boundaries. It should still be in slide gestures
1656 // and adjust the volume.
1657 gfx::Point
into_slop_boundaries(
1658 window
.right() - GetSlopDistanceFromEdge() / 2, 1);
1659 generator_
->MoveTouch(into_slop_boundaries
);
1660 EXPECT_FALSE(IsInGestureInProgressState());
1661 EXPECT_TRUE(IsInSlideGestureState());
1662 EXPECT_FALSE(IsInTouchToMouseMode());
1664 // The sound is rate limiting so it only activates every 150ms.
1665 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1667 size_t num_adjust_sounds
= delegate_
.NumAdjustSounds();
1668 ASSERT_EQ(1U, num_adjust_sounds
);
1669 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1671 // Move the touch into the center of the window. It should still be in slide
1672 // gestures, but there should not be anymore volume adjustments.
1673 generator_
->MoveTouch(center_screen
);
1674 EXPECT_FALSE(IsInGestureInProgressState());
1675 EXPECT_TRUE(IsInSlideGestureState());
1676 EXPECT_FALSE(IsInTouchToMouseMode());
1678 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1679 num_adjust_sounds
= delegate_
.NumAdjustSounds();
1680 ASSERT_EQ(1U, num_adjust_sounds
);
1681 ASSERT_EQ(1U, delegate_
.VolumeChanges().size());
1683 // Move the touch back into slop edge distance and volume should be changing
1684 // again, one volume change for each new move.
1685 generator_
->MoveTouch(into_slop_boundaries
);
1686 EXPECT_FALSE(IsInGestureInProgressState());
1687 EXPECT_TRUE(IsInSlideGestureState());
1688 EXPECT_FALSE(IsInTouchToMouseMode());
1690 generator_
->MoveTouch(
1691 gfx::Point(into_slop_boundaries
.x() + gesture_detector_config_
.touch_slop
,
1692 into_slop_boundaries
.y()));
1693 simulated_clock_
->Advance(base::TimeDelta::FromMilliseconds(200));
1695 num_adjust_sounds
= delegate_
.NumAdjustSounds();
1696 ASSERT_EQ(2U, num_adjust_sounds
);
1697 ASSERT_EQ(3U, delegate_
.VolumeChanges().size());
1699 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1700 ASSERT_EQ(0U, captured_events
.size());
1702 generator_
->ReleaseTouch();
1705 // Even if the gesture starts within bounds, if it has not moved past slop
1706 // within the grace period, it should go to touch exploration.
1707 TEST_F(TouchExplorationTest
, InBoundariesTouchExploration
) {
1708 SwitchTouchExplorationMode(true);
1710 gfx::Rect window
= BoundsOfRootWindowInDIP();
1711 gfx::Point
initial_press(window
.right() - GetMaxDistanceFromEdge() / 2, 1);
1712 ui::TouchEvent
first_press(
1713 ui::ET_TOUCH_PRESSED
,
1717 generator_
->Dispatch(&first_press
);
1718 EXPECT_FALSE(IsInGestureInProgressState());
1719 EXPECT_FALSE(IsInSlideGestureState());
1720 EXPECT_FALSE(IsInTouchToMouseMode());
1722 AdvanceSimulatedTimePastTapDelay();
1723 EXPECT_FALSE(IsInGestureInProgressState());
1724 EXPECT_FALSE(IsInSlideGestureState());
1725 EXPECT_TRUE(IsInTouchToMouseMode());
1728 // If two fingers tap the screen at the same time and release before the tap
1729 // timer runs out, a control key event should be sent to silence chromevox.
1730 TEST_F(TouchExplorationTest
, TwoFingerTap
) {
1731 SwitchTouchExplorationMode(true);
1733 generator_
->set_current_location(gfx::Point(101, 102));
1734 generator_
->PressTouchId(1);
1735 EXPECT_FALSE(IsInTwoFingerTapState());
1737 generator_
->PressTouchId(2);
1738 EXPECT_TRUE(IsInTwoFingerTapState());
1740 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1741 ASSERT_EQ(0U, captured_events
.size());
1743 generator_
->ReleaseTouchId(1);
1744 EXPECT_TRUE(IsInTwoFingerTapState());
1745 generator_
->ReleaseTouchId(2);
1747 // Two key events should have been sent to silence the feedback.
1748 EXPECT_EQ(2U, captured_events
.size());
1751 // If the fingers are not released before the tap timer runs out, a control
1752 // keyevent is not sent and the state will no longer be in two finger tap.
1753 TEST_F(TouchExplorationTest
, TwoFingerTapAndHold
) {
1754 SwitchTouchExplorationMode(true);
1756 generator_
->PressTouchId(1);
1757 EXPECT_FALSE(IsInTwoFingerTapState());
1759 generator_
->PressTouchId(2);
1760 EXPECT_TRUE(IsInTwoFingerTapState());
1762 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1763 ASSERT_EQ(0U, captured_events
.size());
1765 AdvanceSimulatedTimePastTapDelay();
1766 // Since the tap delay has elapsed, it should no longer be in two finger tap.
1767 EXPECT_FALSE(IsInTwoFingerTapState());
1770 // The next two tests set up two finger swipes to happen. If one of the fingers
1771 // moves out of slop before the tap timer fires, a two finger tap is not made.
1772 // In this first test, the first finger placed will move out of slop.
1773 TEST_F(TouchExplorationTest
, TwoFingerTapAndMoveFirstFinger
) {
1774 SwitchTouchExplorationMode(true);
1776 // Once one of the fingers leaves slop, it should no longer be in two finger
1778 ui::TouchEvent
first_press_id_1(
1779 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 1, Now());
1780 ui::TouchEvent
first_press_id_2(
1781 ui::ET_TOUCH_PRESSED
, gfx::Point(110, 200), 2, Now());
1783 ui::TouchEvent
slop_move_id_1(
1785 gfx::Point(100 + gesture_detector_config_
.touch_slop
, 200),
1788 ui::TouchEvent
slop_move_id_2(
1790 gfx::Point(110 + gesture_detector_config_
.touch_slop
, 200),
1794 ui::TouchEvent
out_slop_id_1(
1796 gfx::Point(100 + gesture_detector_config_
.touch_slop
+ 1, 200),
1800 // Dispatch the inital presses.
1801 generator_
->Dispatch(&first_press_id_1
);
1802 EXPECT_FALSE(IsInTwoFingerTapState());
1803 generator_
->Dispatch(&first_press_id_2
);
1804 EXPECT_TRUE(IsInTwoFingerTapState());
1806 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1807 ASSERT_EQ(0U, captured_events
.size());
1809 // The presses have not moved out of slop yet so it should still be in
1811 generator_
->Dispatch(&slop_move_id_1
);
1812 EXPECT_TRUE(IsInTwoFingerTapState());
1813 generator_
->Dispatch(&slop_move_id_2
);
1814 EXPECT_TRUE(IsInTwoFingerTapState());
1816 // Once one of the fingers moves out of slop, we are no longer in
1818 generator_
->Dispatch(&out_slop_id_1
);
1819 EXPECT_FALSE(IsInTwoFingerTapState());
1822 // Similar test to the previous test except the second finger placed will be the
1823 // one to move out of slop.
1824 TEST_F(TouchExplorationTest
, TwoFingerTapAndMoveSecondFinger
) {
1825 SwitchTouchExplorationMode(true);
1827 // Once one of the fingers leaves slop, it should no longer be in two finger
1829 ui::TouchEvent
first_press_id_1(
1830 ui::ET_TOUCH_PRESSED
, gfx::Point(100, 200), 1, Now());
1831 ui::TouchEvent
first_press_id_2(
1832 ui::ET_TOUCH_PRESSED
, gfx::Point(110, 200), 2, Now());
1834 ui::TouchEvent
out_slop_id_2(
1836 gfx::Point(100 + gesture_detector_config_
.touch_slop
+ 1, 200),
1840 generator_
->Dispatch(&first_press_id_1
);
1841 EXPECT_FALSE(IsInTwoFingerTapState());
1843 generator_
->Dispatch(&first_press_id_2
);
1844 EXPECT_TRUE(IsInTwoFingerTapState());
1846 const ScopedVector
<ui::Event
>& captured_events
= GetCapturedEvents();
1847 ASSERT_EQ(0U, captured_events
.size());
1849 generator_
->Dispatch(&out_slop_id_2
);
1850 EXPECT_FALSE(IsInTwoFingerTapState());
1853 // Corner passthrough should turn on if the user first holds down on either the
1854 // right or left corner past a delay and then places a finger anywhere else on
1856 TEST_F(TouchExplorationTest
, ActivateLeftCornerPassthrough
) {
1857 SwitchTouchExplorationMode(true);
1859 gfx::Rect window
= BoundsOfRootWindowInDIP();
1860 gfx::Point
left_corner(10, window
.bottom() - GetMaxDistanceFromEdge() / 2);
1861 AssertCornerPassthroughWorking(left_corner
);
1864 TEST_F(TouchExplorationTest
, ActivateRightCornerPassthrough
) {
1865 SwitchTouchExplorationMode(true);
1867 gfx::Rect window
= BoundsOfRootWindowInDIP();
1868 gfx::Point
right_corner(window
.right() - GetMaxDistanceFromEdge() / 2,
1869 window
.bottom() - GetMaxDistanceFromEdge() / 2);
1870 AssertCornerPassthroughWorking(right_corner
);
1873 // Earcons should play if the user slides off the screen or enters the screen
1875 TEST_F(TouchExplorationTest
, EnterEarconPlays
) {
1876 SwitchTouchExplorationMode(true);
1878 gfx::Rect window
= BoundsOfRootWindowInDIP();
1880 gfx::Point
upper_left_corner(0, 0);
1881 gfx::Point
upper_right_corner(window
.right(), 0);
1882 gfx::Point
lower_left_corner(0, window
.bottom());
1883 gfx::Point
lower_right_corner(window
.right(), window
.bottom());
1884 gfx::Point
left_edge(0, 30);
1885 gfx::Point
right_edge(window
.right(), 30);
1886 gfx::Point
top_edge(30, 0);
1887 gfx::Point
bottom_edge(30, window
.bottom());
1889 std::vector
<gfx::Point
> locations
;
1890 locations
.push_back(upper_left_corner
);
1891 locations
.push_back(upper_right_corner
);
1892 locations
.push_back(lower_left_corner
);
1893 locations
.push_back(lower_right_corner
);
1894 locations
.push_back(left_edge
);
1895 locations
.push_back(right_edge
);
1896 locations
.push_back(top_edge
);
1897 locations
.push_back(bottom_edge
);
1899 for (std::vector
<gfx::Point
>::const_iterator point
= locations
.begin();
1900 point
!= locations
.end();
1902 ui::TouchEvent
touch_event(ui::ET_TOUCH_PRESSED
, *point
, 1, Now());
1904 generator_
->Dispatch(&touch_event
);
1905 ASSERT_EQ(1U, delegate_
.NumEnterScreenSounds());
1906 generator_
->ReleaseTouchId(1);
1907 delegate_
.ResetCountersToZero();
1911 TEST_F(TouchExplorationTest
, ExitEarconPlays
) {
1912 SwitchTouchExplorationMode(true);
1914 // On the device, it cannot actually tell if the finger has left the screen or
1915 // not. If the finger has left the screen, it reads it as a release that
1916 // occurred very close to the edge of the screen even if the finger is still
1917 // technically touching the moniter. To simulate this, a release that occurs
1918 // close to the edge is dispatched.
1919 gfx::Point
initial_press(100, 200);
1920 gfx::Rect window
= BoundsOfRootWindowInDIP();
1922 gfx::Point
upper_left_corner(0, 0);
1923 gfx::Point
upper_right_corner(window
.right(), 0);
1924 gfx::Point
lower_left_corner(0, window
.bottom());
1925 gfx::Point
lower_right_corner(window
.right(), window
.bottom());
1926 gfx::Point
left_edge(0, 30);
1927 gfx::Point
right_edge(window
.right(), 30);
1928 gfx::Point
top_edge(30, 0);
1929 gfx::Point
bottom_edge(30, window
.bottom());
1931 std::vector
<gfx::Point
> locations
;
1932 locations
.push_back(upper_left_corner
);
1933 locations
.push_back(upper_right_corner
);
1934 locations
.push_back(lower_left_corner
);
1935 locations
.push_back(lower_right_corner
);
1936 locations
.push_back(left_edge
);
1937 locations
.push_back(right_edge
);
1938 locations
.push_back(top_edge
);
1939 locations
.push_back(bottom_edge
);
1941 for (std::vector
<gfx::Point
>::const_iterator point
= locations
.begin();
1942 point
!= locations
.end();
1944 generator_
->PressTouch();
1945 generator_
->MoveTouch(initial_press
);
1946 generator_
->MoveTouch(*point
);
1947 generator_
->ReleaseTouch();
1948 ASSERT_EQ(1U, delegate_
.NumExitScreenSounds());
1949 delegate_
.ResetCountersToZero();