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.
4
5#include "ui/chromeos/touch_exploration_controller.h"
6
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"
21
22namespace ui {
23
24namespace {
25
26// Records all mouse, touch, gesture, and key events.
27class EventCapturer : public ui::EventHandler {
28 public:
29  EventCapturer() {}
30  virtual ~EventCapturer() {}
31
32  void Reset() {
33    events_.clear();
34  }
35
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;
50    }
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);
57  }
58
59  const ScopedVector<ui::Event>& captured_events() const { return events_; }
60
61 private:
62  ScopedVector<ui::Event> events_;
63
64  DISALLOW_COPY_AND_ASSIGN(EventCapturer);
65};
66
67int Factorial(int n) {
68  if (n <= 0)
69    return 0;
70  if (n == 1)
71    return 1;
72  return n * Factorial(n - 1);
73}
74
75class MockTouchExplorationControllerDelegate
76    : public ui::TouchExplorationControllerDelegate {
77 public:
78  virtual void SetOutputLevel(int volume) OVERRIDE {
79    volume_changes_.push_back(volume);
80  }
81  virtual void SilenceSpokenFeedback() OVERRIDE {
82  }
83  virtual void PlayVolumeAdjustEarcon() OVERRIDE {
84    ++num_times_adjust_sound_played_;
85  }
86  virtual void PlayPassthroughEarcon() OVERRIDE {
87    ++num_times_passthrough_played_;
88  }
89  virtual void PlayExitScreenEarcon() OVERRIDE {
90    ++num_times_exit_screen_played_;
91  }
92  virtual void PlayEnterScreenEarcon() OVERRIDE {
93    ++num_times_enter_screen_played_;
94  }
95
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_;
102  }
103
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;
109  }
110
111 private:
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;
117};
118
119}  // namespace
120
121class TouchExplorationControllerTestApi {
122 public:
123  TouchExplorationControllerTestApi(
124      TouchExplorationController* touch_exploration_controller) {
125    touch_exploration_controller_.reset(touch_exploration_controller);
126  }
127
128  void CallTapTimerNowForTesting() {
129    DCHECK(touch_exploration_controller_->tap_timer_.IsRunning());
130    touch_exploration_controller_->tap_timer_.Stop();
131    touch_exploration_controller_->OnTapTimerFired();
132  }
133
134  void CallPassthroughTimerNowForTesting() {
135    DCHECK(touch_exploration_controller_->passthrough_timer_.IsRunning());
136    touch_exploration_controller_->passthrough_timer_.Stop();
137    touch_exploration_controller_->OnPassthroughTimerFired();
138  }
139
140  void CallTapTimerNowIfRunningForTesting() {
141    if (touch_exploration_controller_->tap_timer_.IsRunning()) {
142      touch_exploration_controller_->tap_timer_.Stop();
143      touch_exploration_controller_->OnTapTimerFired();
144    }
145  }
146
147  bool IsInNoFingersDownStateForTesting() const {
148    return touch_exploration_controller_->state_ ==
149           touch_exploration_controller_->NO_FINGERS_DOWN;
150  }
151
152  bool IsInGestureInProgressStateForTesting() const {
153    return touch_exploration_controller_->state_ ==
154           touch_exploration_controller_->GESTURE_IN_PROGRESS;
155  }
156
157  bool IsInSlideGestureStateForTesting() const {
158    return touch_exploration_controller_->state_ ==
159           touch_exploration_controller_->SLIDE_GESTURE;
160  }
161
162  bool IsInTwoFingerTapStateForTesting() const {
163    return touch_exploration_controller_->state_ ==
164           touch_exploration_controller_->TWO_FINGER_TAP;
165  }
166  bool IsInCornerPassthroughStateForTesting() const {
167    return touch_exploration_controller_->state_ ==
168           touch_exploration_controller_->CORNER_PASSTHROUGH;
169  }
170
171  gfx::Rect BoundsOfRootWindowInDIPForTesting() const {
172    return touch_exploration_controller_->root_window_->GetBoundsInScreen();
173  }
174
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;
179  }
180
181  float GetMaxDistanceFromEdge() const {
182    return touch_exploration_controller_->kMaxDistanceFromEdge;
183  }
184
185  float GetSlopDistanceFromEdge() const {
186    return touch_exploration_controller_->kSlopDistanceFromEdge;
187  }
188
189  void SetTickClockForTesting(base::TickClock* simulated_clock) {
190    touch_exploration_controller_->tick_clock_ = simulated_clock;
191  }
192
193 private:
194  scoped_ptr<TouchExplorationController> touch_exploration_controller_;
195
196  DISALLOW_COPY_AND_ASSIGN(TouchExplorationControllerTestApi);
197};
198
199class TouchExplorationTest : public aura::test::AuraTestBase {
200 public:
201  TouchExplorationTest() : simulated_clock_(new base::SimpleTestTickClock()) {
202    // Tests fail if time is ever 0.
203    simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
204  }
205  virtual ~TouchExplorationTest() {}
206
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();
218  }
219
220  virtual void TearDown() OVERRIDE {
221    root_window()->RemovePreTargetHandler(&event_capturer_);
222    SwitchTouchExplorationMode(false);
223    cursor_client_.reset();
224    aura::test::AuraTestBase::TearDown();
225  }
226
227 protected:
228  aura::client::CursorClient* cursor_client() { return cursor_client_.get(); }
229
230  const ScopedVector<ui::Event>& GetCapturedEvents() {
231    return event_capturer_.captured_events();
232  }
233
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]));
242      }
243    }
244    return located_events;
245  }
246
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]);
253    }
254    return events;
255  }
256
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]);
263    }
264    return events;
265  }
266
267  void ClearCapturedEvents() {
268    event_capturer_.Reset();
269  }
270
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();
275  }
276
277  void AdvanceSimulatedTimePastPassthroughDelay() {
278    simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
279    touch_exploration_controller_->CallPassthroughTimerNowForTesting();
280  }
281
282  void AdvanceSimulatedTimePastPotentialTapDelay() {
283    simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
284    touch_exploration_controller_->CallTapTimerNowIfRunningForTesting();
285  }
286
287  void SuppressVLOGs(bool suppress) {
288    touch_exploration_controller_->SuppressVLOGsForTesting(suppress);
289  }
290
291  void SetTickClock() {
292    touch_exploration_controller_->SetTickClockForTesting(
293        static_cast<base::TickClock*>(simulated_clock_));
294  }
295
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();
305    }
306  }
307
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());
313  }
314
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());
319
320    ui::TouchEvent first_press(ui::ET_TOUCH_PRESSED, corner, 0, Now());
321    generator_->Dispatch(&first_press);
322
323    AdvanceSimulatedTimePastPassthroughDelay();
324    EXPECT_FALSE(IsInGestureInProgressState());
325    EXPECT_FALSE(IsInSlideGestureState());
326    EXPECT_FALSE(IsInTouchToMouseMode());
327    EXPECT_TRUE(IsInCornerPassthroughState());
328
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());
341
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();
349
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();
356  }
357
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();
364  }
365
366  bool IsInNoFingersDownState() {
367    return touch_exploration_controller_->IsInNoFingersDownStateForTesting();
368  }
369
370  bool IsInGestureInProgressState() {
371    return touch_exploration_controller_
372        ->IsInGestureInProgressStateForTesting();
373  }
374
375  bool IsInSlideGestureState() {
376    return touch_exploration_controller_->IsInSlideGestureStateForTesting();
377  }
378
379  bool IsInTwoFingerTapState() {
380    return touch_exploration_controller_->IsInTwoFingerTapStateForTesting();
381  }
382
383  bool IsInCornerPassthroughState() {
384    return touch_exploration_controller_
385        ->IsInCornerPassthroughStateForTesting();
386  }
387
388  gfx::Rect BoundsOfRootWindowInDIP() {
389    return touch_exploration_controller_->BoundsOfRootWindowInDIPForTesting();
390  }
391
392  float GetMaxDistanceFromEdge() const {
393    return touch_exploration_controller_->GetMaxDistanceFromEdge();
394  }
395
396  float GetSlopDistanceFromEdge() const {
397    return touch_exploration_controller_->GetSlopDistanceFromEdge();
398  }
399
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());
405  }
406
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_;
412
413 private:
414  EventCapturer event_capturer_;
415  scoped_ptr<TouchExplorationControllerTestApi>
416      touch_exploration_controller_;
417  scoped_ptr<aura::test::TestCursorClient> cursor_client_;
418
419  DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
420};
421
422// Executes a number of assertions to confirm that |e1| and |e2| are touch
423// events and are equal to each other.
424void 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());
434}
435
436// Executes a number of assertions to confirm that |e1| and |e2| are mouse
437// events and are equal to each other.
438void 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());
447}
448
449// Executes a number of assertions to confirm that |e1| and |e2| are key events
450// and are equal to each other.
451void 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());
460}
461
462#define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
463  ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
464
465#define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
466  ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
467
468#define CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(e1, e2) \
469  ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreKeyAndEqual(e1, e2))
470
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.
474
475// If a swipe has been successfully completed, then six key events will be
476// dispatched that correspond to shift+search+direction
477void 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]);
498}
499
500TEST_F(TouchExplorationTest, EntersTouchToMouseModeAfterPressAndDelay) {
501  SwitchTouchExplorationMode(true);
502  EXPECT_FALSE(IsInTouchToMouseMode());
503  generator_->PressTouch();
504  AdvanceSimulatedTimePastTapDelay();
505  EXPECT_TRUE(IsInTouchToMouseMode());
506}
507
508TEST_F(TouchExplorationTest, EntersTouchToMouseModeAfterMoveOutsideSlop) {
509  int slop = gesture_detector_config_.touch_slop;
510  int half_slop = slop / 2;
511
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());
523}
524
525TEST_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();
532
533  std::vector<ui::LocatedEvent*> events =
534      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
535  ASSERT_EQ(1U, events.size());
536
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());
541}
542
543TEST_F(TouchExplorationTest, ActualMouseMovesUnaffected) {
544  SwitchTouchExplorationMode(true);
545
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);
552
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,
557                            0,
558                            0);
559  generator_->Dispatch(&mouse_move);
560  generator_->ReleaseTouch();
561  AdvanceSimulatedTimePastTapDelay();
562
563  std::vector<ui::LocatedEvent*> events =
564      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
565  ASSERT_EQ(4U, events.size());
566
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);
570
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);
574
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);
580
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());
586}
587
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.
591TEST_F(TouchExplorationTest, TurnOnMidTouch) {
592  SwitchTouchExplorationMode(false);
593  generator_->PressTouchId(1);
594  EXPECT_TRUE(cursor_client()->IsCursorVisible());
595  ClearCapturedEvents();
596
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,
603                            gfx::Point(11, 12),
604                            1,
605                            Now());
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();
613
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)
622      break;
623  }
624  EXPECT_NE(captured_events.end(), it);
625  ClearCapturedEvents();
626
627  // The release of the first finger shouldn't be affected.
628  ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
629                               gfx::Point(11, 12),
630                               1,
631                               Now());
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();
637
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());
647}
648
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.
651TEST_F(TouchExplorationTest, TimerFiresLateDuringTouchExploration) {
652  SwitchTouchExplorationMode(true);
653
654  // Make sure the touch is not in a corner of the screen.
655  generator_->MoveTouch(gfx::Point(100, 200));
656
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);
666
667  generator_->ReleaseTouchId(2);
668  generator_->ReleaseTouchId(1);
669  AdvanceSimulatedTimePastTapDelay();
670  EXPECT_TRUE(IsInNoFingersDownState());
671}
672
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.
676TEST_F(TouchExplorationTest, TimerFiresLateAfterTap) {
677  SwitchTouchExplorationMode(true);
678
679  // Send a tap at location1.
680  gfx::Point location0(11, 12);
681  generator_->set_current_location(location0);
682  generator_->PressTouch();
683  generator_->ReleaseTouch();
684
685  // Send a tap at location2, after the double-tap timeout, but before the
686  // timer fires.
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();
693
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());
704}
705
706// Double-tapping should send a touch press and release through to the location
707// of the last successful touch exploration.
708TEST_F(TouchExplorationTest, DoubleTap) {
709  SwitchTouchExplorationMode(true);
710
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();
717
718  std::vector<ui::LocatedEvent*> events =
719      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
720  ASSERT_EQ(1U, events.size());
721
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();
726
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();
736
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());
744}
745
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.
749TEST_F(TouchExplorationTest, DoubleTapPassthrough) {
750  SwitchTouchExplorationMode(true);
751
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();
758
759  std::vector<ui::LocatedEvent*> events =
760      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
761  ASSERT_EQ(1U, events.size());
762
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();
767
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();
780
781  gfx::Vector2d passthrough_offset = second_tap_location - tap_location;
782
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());
788
789  ClearCapturedEvents();
790
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);
797
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());
806
807  ClearCapturedEvents();
808
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());
816
817  // Even with finger 3 still down, events for the first finger should still
818  // pass through.
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());
826
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());
832}
833
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.
837TEST_F(TouchExplorationTest, DoubleTapLongPress) {
838  SwitchTouchExplorationMode(true);
839  SetTickClock();
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();
846
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();
854
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();
870
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);
881}
882
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
885// elapsed.
886TEST_F(TouchExplorationTest, SingleTap) {
887  SwitchTouchExplorationMode(true);
888
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();
895
896  // Move to another location for single tap
897  gfx::Point tap_location(22, 23);
898  generator_->MoveTouch(tap_location);
899  generator_->ReleaseTouch();
900
901  // Allow time to pass within the grace period of releasing before
902  // tapping again.
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();
908
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());
917}
918
919// Double-tapping without coming from touch exploration (no previous touch
920// exploration event) should not generate any events.
921TEST_F(TouchExplorationTest, DoubleTapNoTouchExplore) {
922  SwitchTouchExplorationMode(true);
923
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());
940
941  std::vector<ui::LocatedEvent*> captured_events = GetCapturedLocatedEvents();
942  ASSERT_EQ(0U, captured_events.size());
943}
944
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.
948TEST_F(TouchExplorationTest, SplitTap) {
949  SwitchTouchExplorationMode(true);
950  gfx::Point initial_touch_location(11, 12);
951  gfx::Point second_touch_location(33, 34);
952
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());
958
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());
964
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());
986
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();
994
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());
1000}
1001
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.
1006TEST_F(TouchExplorationTest, SplitTapRelease) {
1007  SwitchTouchExplorationMode(true);
1008
1009  gfx::Point initial_touch_location(11, 12);
1010  gfx::Point second_touch_location(33, 34);
1011
1012  // Tap and hold at one location, and get a mouse move event in touch explore.
1013  EnterTouchExplorationModeAtLocation(initial_touch_location);
1014
1015  std::vector<ui::LocatedEvent*> events =
1016      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
1017  ASSERT_EQ(1U, events.size());
1018
1019  ClearCapturedEvents();
1020
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());
1035
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());
1042}
1043
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).
1048TEST_F(TouchExplorationTest, SplitTapLongPress) {
1049  SwitchTouchExplorationMode(true);
1050  gfx::Point initial_touch_location(11, 12);
1051  gfx::Point second_touch_location(33, 34);
1052
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());
1058
1059  ClearCapturedEvents();
1060
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());
1081
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);
1092}
1093
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
1099// goes through.
1100TEST_F(TouchExplorationTest, SplitTapReleaseLongPress) {
1101  SwitchTouchExplorationMode(true);
1102  gfx::Point initial_touch_location(11, 12);
1103  gfx::Point second_touch_location(33, 34);
1104
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();
1111
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());
1128
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);
1139 }
1140
1141TEST_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);
1146
1147  // Tap and hold at one location, and get a mouse move event in touch explore.
1148  EnterTouchExplorationModeAtLocation(initial_touch_location);
1149
1150  std::vector<ui::LocatedEvent*> events =
1151      GetCapturedLocatedEventsOfType(ui::ET_MOUSE_MOVED);
1152  ASSERT_EQ(1U, events.size());
1153
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();
1158
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);
1164
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);
1170
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);
1182
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());
1190}
1191
1192
1193TEST_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());
1203
1204  // Tap and hold at one location, and get a mouse move event in touch explore.
1205  EnterTouchExplorationModeAtLocation(first_touch_location);
1206  ClearCapturedEvents();
1207
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);
1212
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);
1225
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());
1233
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);
1240
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);
1253
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());
1261}
1262
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.
1267TEST_F(TouchExplorationTest, EnterGestureInProgressState) {
1268  SwitchTouchExplorationMode(true);
1269  EXPECT_FALSE(IsInTouchToMouseMode());
1270  EXPECT_FALSE(IsInGestureInProgressState());
1271
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);
1277
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
1281  // progress.
1282  generator_->MoveTouch(second_location);
1283  EXPECT_FALSE(IsInTouchToMouseMode());
1284  EXPECT_FALSE(IsInGestureInProgressState());
1285  simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
1286
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());
1293
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());
1304}
1305
1306// A swipe+direction gesture should trigger a Shift+Search+Direction
1307// keyboard event.
1308TEST_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);
1315
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;
1319
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));
1325    }
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();
1331         ++it) {
1332      int move_x = 0;
1333      int move_y = 0;
1334      ui::KeyboardCode direction = *it;
1335      switch (direction) {
1336        case ui::VKEY_RIGHT:
1337          move_x = distance;
1338          break;
1339        case ui::VKEY_LEFT:
1340          move_x = 0 - distance;
1341          break;
1342        case ui::VKEY_UP:
1343          move_y = 0 - distance;
1344          break;
1345        case ui::VKEY_DOWN:
1346          move_y = distance;
1347          break;
1348        default:
1349          return;
1350      }
1351
1352      // A swipe is made when a fling starts
1353      float delta_time =
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,
1358                                           start_points_array,
1359                                           delta_time_ms,
1360                                           kSteps,
1361                                           move_x * 2,
1362                                           move_y * 2);
1363
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);
1368      else {
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());
1376        }
1377      }
1378      EXPECT_TRUE(IsInNoFingersDownState());
1379      EXPECT_FALSE(IsInTouchToMouseMode());
1380      EXPECT_FALSE(IsInGestureInProgressState());
1381      ClearCapturedEvents();
1382    }
1383  }
1384}
1385
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.
1388
1389TEST_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
1394  // released.
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()));
1405  }
1406
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);
1412
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);
1416
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
1429      // permutations)
1430      int current_permutation = p % current_num_permutations;
1431
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.)
1440
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
1451      // events left.
1452      current_num_permutations /= events_left;
1453
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;
1462
1463      ui::TouchEvent* next_dispatch = queued_events[index];
1464      ASSERT_TRUE(next_dispatch != NULL);
1465
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
1468      // dispatched..
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);
1473
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;
1481      }
1482    }
1483    ASSERT_EQ(queued_events.size(), 0u);
1484
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;
1490      }
1491    }
1492    AdvanceSimulatedTimePastPotentialTapDelay();
1493    EXPECT_TRUE(IsInNoFingersDownState());
1494    ClearCapturedEvents();
1495  }
1496}
1497
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
1500// state.
1501TEST_F(TouchExplorationTest, GestureAddedFinger) {
1502  SwitchTouchExplorationMode(true);
1503  EXPECT_FALSE(IsInTouchToMouseMode());
1504  EXPECT_FALSE(IsInGestureInProgressState());
1505
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());
1517
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());
1527}
1528
1529TEST_F(TouchExplorationTest, EnterSlideGestureState) {
1530  SwitchTouchExplorationMode(true);
1531  EXPECT_FALSE(IsInTouchToMouseMode());
1532  EXPECT_FALSE(IsInGestureInProgressState());
1533
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);
1541
1542  generator_->Dispatch(&first_press);
1543  simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
1544
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));
1551
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());
1558
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());
1563
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
1566  // change.
1567  size_t num_adjust_sounds = delegate_.NumAdjustSounds();
1568  ASSERT_EQ(1U, num_adjust_sounds);
1569  ASSERT_EQ(1U, delegate_.VolumeChanges().size());
1570
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());
1578
1579  generator_->ReleaseTouch();
1580  ASSERT_EQ(0U, captured_events.size());
1581  EXPECT_FALSE(IsInTouchToMouseMode());
1582  EXPECT_FALSE(IsInGestureInProgressState());
1583  EXPECT_FALSE(IsInSlideGestureState());
1584}
1585
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.
1589TEST_F(TouchExplorationTest, AvoidEnteringSlideGesture) {
1590  SwitchTouchExplorationMode(true);
1591
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),
1597      0,
1598      Now());
1599  gfx::Point out_of_slop(window.right() - GetSlopDistanceFromEdge() + distance,
1600                         1);
1601  gfx::Point into_boundaries(window.right() - GetMaxDistanceFromEdge() / 2, 1);
1602
1603  generator_->Dispatch(&first_press);
1604  simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(10));
1605
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));
1611
1612  // Since we did not start moving while in the boundaries, we should not be in
1613  // slide gestures.
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());
1620
1621  generator_->ReleaseTouch();
1622}
1623
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.
1629TEST_F(TouchExplorationTest, TestingBoundaries) {
1630  SwitchTouchExplorationMode(true);
1631
1632  gfx::Rect window = BoundsOfRootWindowInDIP();
1633  gfx::Point initial_press(window.right() - GetMaxDistanceFromEdge() / 2, 1);
1634
1635  gfx::Point center_screen(window.right() / 2, window.bottom() / 2);
1636
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());
1643
1644  // Move past the touch slop to begin slide gestures.
1645  // + slop + 1 to actually leave slop.
1646  gfx::Point touch_move(
1647      initial_press.x(),
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));
1654
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());
1663
1664  // The sound is rate limiting so it only activates every 150ms.
1665  simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(200));
1666
1667  size_t num_adjust_sounds = delegate_.NumAdjustSounds();
1668  ASSERT_EQ(1U, num_adjust_sounds);
1669  ASSERT_EQ(1U, delegate_.VolumeChanges().size());
1670
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());
1677
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());
1682
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());
1689
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));
1694
1695  num_adjust_sounds = delegate_.NumAdjustSounds();
1696  ASSERT_EQ(2U, num_adjust_sounds);
1697  ASSERT_EQ(3U, delegate_.VolumeChanges().size());
1698
1699  const ScopedVector<ui::Event>& captured_events = GetCapturedEvents();
1700  ASSERT_EQ(0U, captured_events.size());
1701
1702  generator_->ReleaseTouch();
1703}
1704
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.
1707TEST_F(TouchExplorationTest, InBoundariesTouchExploration) {
1708  SwitchTouchExplorationMode(true);
1709
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,
1714      initial_press,
1715      0,
1716      Now());
1717  generator_->Dispatch(&first_press);
1718  EXPECT_FALSE(IsInGestureInProgressState());
1719  EXPECT_FALSE(IsInSlideGestureState());
1720  EXPECT_FALSE(IsInTouchToMouseMode());
1721
1722  AdvanceSimulatedTimePastTapDelay();
1723  EXPECT_FALSE(IsInGestureInProgressState());
1724  EXPECT_FALSE(IsInSlideGestureState());
1725  EXPECT_TRUE(IsInTouchToMouseMode());
1726}
1727
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.
1730TEST_F(TouchExplorationTest, TwoFingerTap) {
1731  SwitchTouchExplorationMode(true);
1732
1733  generator_->set_current_location(gfx::Point(101, 102));
1734  generator_->PressTouchId(1);
1735  EXPECT_FALSE(IsInTwoFingerTapState());
1736
1737  generator_->PressTouchId(2);
1738  EXPECT_TRUE(IsInTwoFingerTapState());
1739
1740  const ScopedVector<ui::Event>& captured_events = GetCapturedEvents();
1741  ASSERT_EQ(0U, captured_events.size());
1742
1743  generator_->ReleaseTouchId(1);
1744  EXPECT_TRUE(IsInTwoFingerTapState());
1745  generator_->ReleaseTouchId(2);
1746
1747  // Two key events should have been sent to silence the feedback.
1748  EXPECT_EQ(2U, captured_events.size());
1749}
1750
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.
1753TEST_F(TouchExplorationTest, TwoFingerTapAndHold) {
1754  SwitchTouchExplorationMode(true);
1755
1756  generator_->PressTouchId(1);
1757  EXPECT_FALSE(IsInTwoFingerTapState());
1758
1759  generator_->PressTouchId(2);
1760  EXPECT_TRUE(IsInTwoFingerTapState());
1761
1762  const ScopedVector<ui::Event>& captured_events = GetCapturedEvents();
1763  ASSERT_EQ(0U, captured_events.size());
1764
1765  AdvanceSimulatedTimePastTapDelay();
1766  // Since the tap delay has elapsed, it should no longer be in two finger tap.
1767  EXPECT_FALSE(IsInTwoFingerTapState());
1768}
1769
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.
1773TEST_F(TouchExplorationTest, TwoFingerTapAndMoveFirstFinger) {
1774  SwitchTouchExplorationMode(true);
1775
1776  // Once one of the fingers leaves slop, it should no longer be in two finger
1777  // tap.
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());
1782
1783  ui::TouchEvent slop_move_id_1(
1784      ui::ET_TOUCH_MOVED,
1785      gfx::Point(100 + gesture_detector_config_.touch_slop, 200),
1786      1,
1787      Now());
1788  ui::TouchEvent slop_move_id_2(
1789      ui::ET_TOUCH_MOVED,
1790      gfx::Point(110 + gesture_detector_config_.touch_slop, 200),
1791      2,
1792      Now());
1793
1794  ui::TouchEvent out_slop_id_1(
1795      ui::ET_TOUCH_MOVED,
1796      gfx::Point(100 + gesture_detector_config_.touch_slop + 1, 200),
1797      1,
1798      Now());
1799
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());
1805
1806  const ScopedVector<ui::Event>& captured_events = GetCapturedEvents();
1807  ASSERT_EQ(0U, captured_events.size());
1808
1809  // The presses have not moved out of slop yet so it should still be in
1810  // TwoFingerTap.
1811  generator_->Dispatch(&slop_move_id_1);
1812  EXPECT_TRUE(IsInTwoFingerTapState());
1813  generator_->Dispatch(&slop_move_id_2);
1814  EXPECT_TRUE(IsInTwoFingerTapState());
1815
1816  // Once one of the fingers moves out of slop, we are no longer in
1817  // TwoFingerTap.
1818  generator_->Dispatch(&out_slop_id_1);
1819  EXPECT_FALSE(IsInTwoFingerTapState());
1820}
1821
1822// Similar test to the previous test except the second finger placed will be the
1823// one to move out of slop.
1824TEST_F(TouchExplorationTest, TwoFingerTapAndMoveSecondFinger) {
1825  SwitchTouchExplorationMode(true);
1826
1827  // Once one of the fingers leaves slop, it should no longer be in two finger
1828  // tap.
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());
1833
1834  ui::TouchEvent out_slop_id_2(
1835      ui::ET_TOUCH_MOVED,
1836      gfx::Point(100 + gesture_detector_config_.touch_slop + 1, 200),
1837      1,
1838      Now());
1839
1840  generator_->Dispatch(&first_press_id_1);
1841  EXPECT_FALSE(IsInTwoFingerTapState());
1842
1843  generator_->Dispatch(&first_press_id_2);
1844  EXPECT_TRUE(IsInTwoFingerTapState());
1845
1846  const ScopedVector<ui::Event>& captured_events = GetCapturedEvents();
1847  ASSERT_EQ(0U, captured_events.size());
1848
1849  generator_->Dispatch(&out_slop_id_2);
1850  EXPECT_FALSE(IsInTwoFingerTapState());
1851}
1852
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
1855// the screen.
1856TEST_F(TouchExplorationTest, ActivateLeftCornerPassthrough) {
1857  SwitchTouchExplorationMode(true);
1858
1859  gfx::Rect window = BoundsOfRootWindowInDIP();
1860  gfx::Point left_corner(10, window.bottom() - GetMaxDistanceFromEdge() / 2);
1861  AssertCornerPassthroughWorking(left_corner);
1862}
1863
1864TEST_F(TouchExplorationTest, ActivateRightCornerPassthrough) {
1865  SwitchTouchExplorationMode(true);
1866
1867  gfx::Rect window = BoundsOfRootWindowInDIP();
1868  gfx::Point right_corner(window.right() - GetMaxDistanceFromEdge() / 2,
1869                          window.bottom() - GetMaxDistanceFromEdge() / 2);
1870  AssertCornerPassthroughWorking(right_corner);
1871}
1872
1873// Earcons should play if the user slides off the screen or enters the screen
1874// from the edge.
1875TEST_F(TouchExplorationTest, EnterEarconPlays) {
1876  SwitchTouchExplorationMode(true);
1877
1878  gfx::Rect window = BoundsOfRootWindowInDIP();
1879
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());
1888
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);
1898
1899  for (std::vector<gfx::Point>::const_iterator point = locations.begin();
1900       point != locations.end();
1901       ++point) {
1902    ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, *point, 1, Now());
1903
1904    generator_->Dispatch(&touch_event);
1905    ASSERT_EQ(1U, delegate_.NumEnterScreenSounds());
1906    generator_->ReleaseTouchId(1);
1907    delegate_.ResetCountersToZero();
1908  }
1909}
1910
1911TEST_F(TouchExplorationTest, ExitEarconPlays) {
1912  SwitchTouchExplorationMode(true);
1913
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();
1921
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());
1930
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);
1940
1941  for (std::vector<gfx::Point>::const_iterator point = locations.begin();
1942       point != locations.end();
1943       ++point) {
1944    generator_->PressTouch();
1945    generator_->MoveTouch(initial_press);
1946    generator_->MoveTouch(*point);
1947    generator_->ReleaseTouch();
1948    ASSERT_EQ(1U, delegate_.NumExitScreenSounds());
1949    delegate_.ResetCountersToZero();
1950  }
1951}
1952
1953}  // namespace ui
1954