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