• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/event_generator.h"
12 #include "ui/aura/test/test_cursor_client.h"
13 #include "ui/aura/window.h"
14 #include "ui/events/event.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/gfx/geometry/point.h"
17 #include "ui/gl/gl_implementation.h"
18 #include "ui/gl/gl_surface.h"
19 
20 namespace ui {
21 
22 namespace {
23 // Records all mouse and touch events.
24 class EventCapturer : public ui::EventHandler {
25  public:
EventCapturer()26   EventCapturer() {}
~EventCapturer()27   virtual ~EventCapturer() {}
28 
Reset()29   void Reset() {
30     events_.clear();
31   }
32 
OnEvent(ui::Event * event)33   virtual void OnEvent(ui::Event* event) OVERRIDE {
34     if (event->IsMouseEvent()) {
35       events_.push_back(
36           new ui::MouseEvent(static_cast<ui::MouseEvent&>(*event)));
37     } else if (event->IsTouchEvent()) {
38       events_.push_back(
39           new ui::TouchEvent(static_cast<ui::TouchEvent&>(*event)));
40     } else {
41       return;
42     }
43     // Stop event propagation so we don't click on random stuff that
44     // might break test assumptions.
45     event->StopPropagation();
46     // If there is a possibility that we're in an infinite loop, we should
47     // exit early with a sensible error rather than letting the test time out.
48     ASSERT_LT(events_.size(), 100u);
49   }
captured_events() const50   const ScopedVector<ui::LocatedEvent>& captured_events() const {
51     return events_;
52   }
53 
54  private:
55   ScopedVector<ui::LocatedEvent> events_;
56 
57   DISALLOW_COPY_AND_ASSIGN(EventCapturer);
58 };
59 
60 }  // namespace
61 
62 class TouchExplorationTest : public aura::test::AuraTestBase {
63  public:
TouchExplorationTest()64   TouchExplorationTest()
65       : simulated_clock_(new base::SimpleTestTickClock()) {}
~TouchExplorationTest()66   virtual ~TouchExplorationTest() {}
67 
SetUp()68   virtual void SetUp() OVERRIDE {
69     if (gfx::GetGLImplementation() == gfx::kGLImplementationNone)
70       gfx::GLSurface::InitializeOneOffForTests();
71     aura::test::AuraTestBase::SetUp();
72     cursor_client_.reset(new aura::test::TestCursorClient(root_window()));
73     root_window()->AddPreTargetHandler(&event_capturer_);
74     generator_.reset(new aura::test::EventGenerator(root_window()));
75     // The generator takes ownership of the clock.
76     generator_->SetTickClock(scoped_ptr<base::TickClock>(simulated_clock_));
77     cursor_client()->ShowCursor();
78     cursor_client()->DisableMouseEvents();
79   }
80 
TearDown()81   virtual void TearDown() OVERRIDE {
82     root_window()->RemovePreTargetHandler(&event_capturer_);
83     SwitchTouchExplorationMode(false);
84     cursor_client_.reset();
85     aura::test::AuraTestBase::TearDown();
86   }
87 
88  protected:
cursor_client()89   aura::client::CursorClient* cursor_client() { return cursor_client_.get(); }
90 
GetCapturedEvents()91   const ScopedVector<ui::LocatedEvent>& GetCapturedEvents() {
92     return event_capturer_.captured_events();
93   }
94 
GetCapturedEventsOfType(int type)95   std::vector<ui::LocatedEvent*> GetCapturedEventsOfType(int type) {
96     const ScopedVector<ui::LocatedEvent>& all_events = GetCapturedEvents();
97     std::vector<ui::LocatedEvent*> events;
98     for (size_t i = 0; i < all_events.size(); ++i) {
99       if (type == all_events[i]->type())
100         events.push_back(all_events[i]);
101     }
102     return events;
103   }
104 
ClearCapturedEvents()105   void ClearCapturedEvents() {
106     event_capturer_.Reset();
107   }
108 
AdvanceSimulatedTimePastTapDelay()109   void AdvanceSimulatedTimePastTapDelay() {
110     simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
111     touch_exploration_controller_->CallTapTimerNowForTesting();
112   }
113 
SwitchTouchExplorationMode(bool on)114   void SwitchTouchExplorationMode(bool on) {
115     if (!on && touch_exploration_controller_.get()) {
116       touch_exploration_controller_.reset();
117     } else if (on && !touch_exploration_controller_.get()) {
118       touch_exploration_controller_.reset(
119           new ui::TouchExplorationController(root_window()));
120       touch_exploration_controller_->SetEventHandlerForTesting(
121           &event_capturer_);
122       cursor_client()->ShowCursor();
123       cursor_client()->DisableMouseEvents();
124     }
125   }
126 
EnterTouchExplorationModeAtLocation(gfx::Point tap_location)127   void EnterTouchExplorationModeAtLocation(gfx::Point tap_location) {
128     ui::TouchEvent touch_press(ui::ET_TOUCH_PRESSED, tap_location, 0, Now());
129     generator_->Dispatch(&touch_press);
130     AdvanceSimulatedTimePastTapDelay();
131     EXPECT_TRUE(IsInTouchToMouseMode());
132   }
133 
IsInTouchToMouseMode()134   bool IsInTouchToMouseMode() {
135     aura::client::CursorClient* cursor_client =
136         aura::client::GetCursorClient(root_window());
137     return cursor_client &&
138            cursor_client->IsMouseEventsEnabled() &&
139            !cursor_client->IsCursorVisible();
140   }
141 
IsInNoFingersDownState()142   bool IsInNoFingersDownState() {
143     return touch_exploration_controller_->IsInNoFingersDownStateForTesting();
144   }
145 
Now()146   base::TimeDelta Now() {
147     // This is the same as what EventTimeForNow() does, but here we do it
148     // with our simulated clock.
149     return base::TimeDelta::FromInternalValue(
150         simulated_clock_->NowTicks().ToInternalValue());
151   }
152 
153   scoped_ptr<aura::test::EventGenerator> generator_;
154   ui::GestureDetector::Config gesture_detector_config_;
155   // Owned by |generator_|.
156   base::SimpleTestTickClock* simulated_clock_;
157 
158  private:
159   EventCapturer event_capturer_;
160   scoped_ptr<ui::TouchExplorationController> touch_exploration_controller_;
161   scoped_ptr<aura::test::TestCursorClient> cursor_client_;
162 
163   DISALLOW_COPY_AND_ASSIGN(TouchExplorationTest);
164 };
165 
166 // Executes a number of assertions to confirm that |e1| and |e2| are touch
167 // events and are equal to each other.
ConfirmEventsAreTouchAndEqual(ui::Event * e1,ui::Event * e2)168 void ConfirmEventsAreTouchAndEqual(ui::Event* e1, ui::Event* e2) {
169   ASSERT_TRUE(e1->IsTouchEvent());
170   ASSERT_TRUE(e2->IsTouchEvent());
171   ui::TouchEvent* touch_event1 = static_cast<ui::TouchEvent*>(e1);
172   ui::TouchEvent* touch_event2 = static_cast<ui::TouchEvent*>(e2);
173   EXPECT_EQ(touch_event1->type(), touch_event2->type());
174   EXPECT_EQ(touch_event1->location(), touch_event2->location());
175   EXPECT_EQ(touch_event1->touch_id(), touch_event2->touch_id());
176   EXPECT_EQ(touch_event1->flags(), touch_event2->flags());
177   EXPECT_EQ(touch_event1->time_stamp(), touch_event2->time_stamp());
178 }
179 
180 // Executes a number of assertions to confirm that |e1| and |e2| are mouse
181 // events and are equal to each other.
ConfirmEventsAreMouseAndEqual(ui::Event * e1,ui::Event * e2)182 void ConfirmEventsAreMouseAndEqual(ui::Event* e1, ui::Event* e2) {
183   ASSERT_TRUE(e1->IsMouseEvent());
184   ASSERT_TRUE(e2->IsMouseEvent());
185   ui::MouseEvent* mouse_event1 = static_cast<ui::MouseEvent*>(e1);
186   ui::MouseEvent* mouse_event2 = static_cast<ui::MouseEvent*>(e2);
187   EXPECT_EQ(mouse_event1->type(), mouse_event2->type());
188   EXPECT_EQ(mouse_event1->location(), mouse_event2->location());
189   EXPECT_EQ(mouse_event1->root_location(), mouse_event2->root_location());
190   EXPECT_EQ(mouse_event1->flags(), mouse_event2->flags());
191 }
192 
193 #define CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(e1, e2) \
194   ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreTouchAndEqual(e1, e2))
195 
196 #define CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(e1, e2) \
197   ASSERT_NO_FATAL_FAILURE(ConfirmEventsAreMouseAndEqual(e1, e2))
198 
199 // TODO(mfomitchev): Need to investigate why we don't get mouse enter/exit
200 // events when running these tests as part of ui_unittests. We do get them when
201 // the tests are run as part of ash unit tests.
202 
TEST_F(TouchExplorationTest,EntersTouchToMouseModeAfterPressAndDelay)203 TEST_F(TouchExplorationTest, EntersTouchToMouseModeAfterPressAndDelay) {
204   SwitchTouchExplorationMode(true);
205   EXPECT_FALSE(IsInTouchToMouseMode());
206   generator_->PressTouch();
207   AdvanceSimulatedTimePastTapDelay();
208   EXPECT_TRUE(IsInTouchToMouseMode());
209 }
210 
TEST_F(TouchExplorationTest,EntersTouchToMouseModeAfterMoveOutsideSlop)211 TEST_F(TouchExplorationTest, EntersTouchToMouseModeAfterMoveOutsideSlop) {
212   int slop = gesture_detector_config_.touch_slop;
213   int half_slop = slop / 2;
214 
215   SwitchTouchExplorationMode(true);
216   EXPECT_FALSE(IsInTouchToMouseMode());
217   generator_->set_current_location(gfx::Point(11, 12));
218   generator_->PressTouch();
219   generator_->MoveTouch(gfx::Point(11 + half_slop, 12));
220   EXPECT_FALSE(IsInTouchToMouseMode());
221   generator_->MoveTouch(gfx::Point(11, 12 + half_slop));
222   EXPECT_FALSE(IsInTouchToMouseMode());
223   generator_->MoveTouch(gfx::Point(11 + slop + 1, 12));
224   EXPECT_TRUE(IsInTouchToMouseMode());
225 }
226 
TEST_F(TouchExplorationTest,OneFingerTap)227 TEST_F(TouchExplorationTest, OneFingerTap) {
228   SwitchTouchExplorationMode(true);
229   gfx::Point location(11, 12);
230   generator_->set_current_location(location);
231   generator_->PressTouch();
232   generator_->ReleaseTouch();
233   AdvanceSimulatedTimePastTapDelay();
234 
235   std::vector<ui::LocatedEvent*> events =
236       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
237   ASSERT_EQ(1U, events.size());
238 
239   EXPECT_EQ(location, events[0]->location());
240   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
241   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
242   EXPECT_TRUE(IsInNoFingersDownState());
243 }
244 
TEST_F(TouchExplorationTest,ActualMouseMovesUnaffected)245 TEST_F(TouchExplorationTest, ActualMouseMovesUnaffected) {
246   SwitchTouchExplorationMode(true);
247 
248   gfx::Point location_start(11, 12);
249   gfx::Point location_end(13, 14);
250   generator_->set_current_location(location_start);
251   generator_->PressTouch();
252   AdvanceSimulatedTimePastTapDelay();
253   generator_->MoveTouch(location_end);
254 
255   gfx::Point location_real_mouse_move(15, 16);
256   ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
257                             location_real_mouse_move,
258                             location_real_mouse_move,
259                             0,
260                             0);
261   generator_->Dispatch(&mouse_move);
262   generator_->ReleaseTouch();
263 
264   std::vector<ui::LocatedEvent*> events =
265       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
266   ASSERT_EQ(4U, events.size());
267 
268   EXPECT_EQ(location_start, events[0]->location());
269   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
270   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
271 
272   EXPECT_EQ(location_end, events[1]->location());
273   EXPECT_TRUE(events[1]->flags() & ui::EF_IS_SYNTHESIZED);
274   EXPECT_TRUE(events[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
275 
276   // The real mouse move goes through.
277   EXPECT_EQ(location_real_mouse_move, events[2]->location());
278   CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(events[2], &mouse_move);
279   EXPECT_FALSE(events[2]->flags() & ui::EF_IS_SYNTHESIZED);
280   EXPECT_FALSE(events[2]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
281 
282   // The touch release gets written as a mouse move.
283   EXPECT_EQ(location_end, events[3]->location());
284   EXPECT_TRUE(events[3]->flags() & ui::EF_IS_SYNTHESIZED);
285   EXPECT_TRUE(events[3]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
286   EXPECT_TRUE(IsInNoFingersDownState());
287 }
288 
289 // Turn the touch exploration mode on in the middle of the touch gesture.
290 // Confirm that events from the finger which was touching when the mode was
291 // turned on don't get rewritten.
TEST_F(TouchExplorationTest,TurnOnMidTouch)292 TEST_F(TouchExplorationTest, TurnOnMidTouch) {
293   SwitchTouchExplorationMode(false);
294   generator_->PressTouchId(1);
295   EXPECT_TRUE(cursor_client()->IsCursorVisible());
296   ClearCapturedEvents();
297 
298   // Enable touch exploration mode while the first finger is touching the
299   // screen. Ensure that subsequent events from that first finger are not
300   // affected by the touch exploration mode, while the touch events from another
301   // finger get rewritten.
302   SwitchTouchExplorationMode(true);
303   ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED,
304                             gfx::Point(11, 12),
305                             1,
306                             Now());
307   generator_->Dispatch(&touch_move);
308   EXPECT_TRUE(cursor_client()->IsCursorVisible());
309   EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
310   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
311   ASSERT_EQ(1u, captured_events.size());
312   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[0], &touch_move);
313   ClearCapturedEvents();
314 
315   // The press from the second finger should get rewritten.
316   generator_->PressTouchId(2);
317   AdvanceSimulatedTimePastTapDelay();
318   EXPECT_TRUE(IsInTouchToMouseMode());
319   ScopedVector<ui::LocatedEvent>::const_iterator it;
320   for (it = captured_events.begin(); it != captured_events.end(); ++it) {
321     if ((*it)->type() == ui::ET_MOUSE_MOVED)
322       break;
323   }
324   EXPECT_NE(captured_events.end(), it);
325   ClearCapturedEvents();
326 
327   // The release of the first finger shouldn't be affected.
328   ui::TouchEvent touch_release(ui::ET_TOUCH_RELEASED,
329                                gfx::Point(11, 12),
330                                1,
331                                Now());
332   generator_->Dispatch(&touch_release);
333   ASSERT_EQ(1u, captured_events.size());
334   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[0], &touch_release);
335   ClearCapturedEvents();
336 
337   // The move and release from the second finger should get rewritten.
338   generator_->MoveTouchId(gfx::Point(13, 14), 2);
339   generator_->ReleaseTouchId(2);
340   ASSERT_EQ(2u, captured_events.size());
341   EXPECT_EQ(ui::ET_MOUSE_MOVED, captured_events[0]->type());
342   EXPECT_EQ(ui::ET_MOUSE_MOVED, captured_events[1]->type());
343   EXPECT_TRUE(IsInNoFingersDownState());
344 }
345 
TEST_F(TouchExplorationTest,TwoFingerTouch)346 TEST_F(TouchExplorationTest, TwoFingerTouch) {
347   SwitchTouchExplorationMode(true);
348   generator_->PressTouchId(1);
349   ClearCapturedEvents();
350 
351   // Confirm events from the second finger go through as is.
352   ui::TouchEvent touch_press(
353       ui::ET_TOUCH_PRESSED,
354       gfx::Point(10, 11),
355       2,
356       Now());
357   generator_->Dispatch(&touch_press);
358   EXPECT_TRUE(cursor_client()->IsCursorVisible());
359   EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
360   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
361   // TODO(mfomitchev): mouse enter/exit events
362   // There will be a ET_MOUSE_EXITED event synthesized when the mouse cursor is
363   // hidden - ignore it.
364   ScopedVector<ui::LocatedEvent>::const_iterator it;
365   for (it = captured_events.begin(); it != captured_events.end(); ++it) {
366     if ((*it)->type() == ui::ET_TOUCH_PRESSED) {
367       CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(*it, &touch_press);
368       break;
369     }
370   }
371   EXPECT_NE(captured_events.end(), it);
372   ClearCapturedEvents();
373   ui::TouchEvent touch_move(
374       ui::ET_TOUCH_MOVED,
375       gfx::Point(20, 21),
376       2,
377       Now());
378   generator_->Dispatch(&touch_move);
379   ASSERT_EQ(1u, captured_events.size());
380   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[0], &touch_move);
381   ClearCapturedEvents();
382 
383   // Confirm mouse moves go through unaffected.
384   ui::MouseEvent mouse_move(ui::ET_MOUSE_MOVED,
385                             gfx::Point(13, 14),
386                             gfx::Point(13, 14),
387                             0,
388                             0);
389   generator_->Dispatch(&mouse_move);
390   // TODO(mfomitchev): mouse enter/exit events
391   // Ignore synthesized ET_MOUSE_ENTERED/ET_MOUSE_EXITED
392   for (it = captured_events.begin(); it != captured_events.end(); ++it) {
393     if ((*it)->type() == ui::ET_MOUSE_MOVED) {
394       CONFIRM_EVENTS_ARE_MOUSE_AND_EQUAL(*it, &mouse_move);
395       break;
396     }
397   }
398   EXPECT_NE(captured_events.end(), it);
399   ClearCapturedEvents();
400 
401   // Events from the first finger should not go through while the second finger
402   // is touching.
403   gfx::Point touch1_location = gfx::Point(15, 16);
404   generator_->MoveTouchId(touch1_location, 1);
405   EXPECT_EQ(0u, GetCapturedEvents().size());
406 
407   EXPECT_TRUE(cursor_client()->IsCursorVisible());
408   EXPECT_FALSE(cursor_client()->IsMouseEventsEnabled());
409 
410   // A release of the second finger should be rewritten as a mouse move
411   // of that finger to the |touch1_location| and we stay in passthrough
412   // mode.
413   ui::TouchEvent touch_release(
414       ui::ET_TOUCH_RELEASED,
415       gfx::Point(25, 26),
416       2,
417       Now());
418   generator_->Dispatch(&touch_release);
419   EXPECT_FALSE(IsInTouchToMouseMode());
420   ASSERT_EQ(captured_events.size(), 1u);
421   EXPECT_EQ(touch1_location, captured_events[0]->location());
422 }
423 
TEST_F(TouchExplorationTest,MultiFingerTouch)424 TEST_F(TouchExplorationTest, MultiFingerTouch) {
425   SwitchTouchExplorationMode(true);
426   generator_->PressTouchId(1);
427   generator_->PressTouchId(2);
428   ClearCapturedEvents();
429 
430   // Confirm events from other fingers go through as is.
431   ui::TouchEvent touch3_press(ui::ET_TOUCH_PRESSED,
432                               gfx::Point(10, 11),
433                               3,
434                               Now());
435   ui::TouchEvent touch3_move1(ui::ET_TOUCH_MOVED,
436                               gfx::Point(12, 13),
437                               3,
438                               Now());
439   ui::TouchEvent touch4_press(ui::ET_TOUCH_PRESSED,
440                               gfx::Point(20, 21),
441                               4,
442                               Now());
443   ui::TouchEvent touch3_move2(ui::ET_TOUCH_MOVED,
444                               gfx::Point(14, 15),
445                               3,
446                               Now());
447   ui::TouchEvent touch4_move(ui::ET_TOUCH_MOVED,
448                              gfx::Point(22, 23),
449                              4,
450                              Now());
451   ui::TouchEvent touch3_release(ui::ET_TOUCH_RELEASED,
452                                 gfx::Point(14, 15),
453                                 3,
454                                 Now());
455   ui::TouchEvent touch4_release(ui::ET_TOUCH_RELEASED,
456                                 gfx::Point(22, 23),
457                                 4,
458                                 Now());
459   generator_->Dispatch(&touch3_press);
460   generator_->Dispatch(&touch3_move1);
461   generator_->Dispatch(&touch4_press);
462   generator_->Dispatch(&touch3_move2);
463   generator_->Dispatch(&touch4_move);
464   generator_->Dispatch(&touch3_release);
465   generator_->Dispatch(&touch4_release);
466 
467   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
468   ASSERT_EQ(7u, captured_events.size());
469   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[0], &touch3_press);
470   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[1], &touch3_move1);
471   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[2], &touch4_press);
472   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[3], &touch3_move2);
473   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[4], &touch4_move);
474 
475   // The release of finger 3 is rewritten as a move to the former location
476   // of finger 1.
477   EXPECT_EQ(ui::ET_TOUCH_MOVED, captured_events[5]->type());
478   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[6], &touch4_release);
479 }
480 
481 // Test the case when there are multiple fingers on the screen and the first
482 // finger is released. This should be ignored, but then the second finger
483 // release should be passed through.
TEST_F(TouchExplorationTest,FirstFingerLifted)484 TEST_F(TouchExplorationTest, FirstFingerLifted) {
485   SwitchTouchExplorationMode(true);
486   generator_->PressTouchId(1);
487   generator_->PressTouchId(2);
488   gfx::Point touch2_location(10, 11);
489   generator_->MoveTouchId(touch2_location, 2);
490   generator_->PressTouchId(3);
491   gfx::Point touch3_location(20, 21);
492   generator_->MoveTouchId(touch3_location, 3);
493   ClearCapturedEvents();
494 
495   // Release of finger 1 should be ignored.
496   generator_->ReleaseTouchId(1);
497   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
498   ASSERT_EQ(0u, captured_events.size());
499 
500   // Move of finger 2 should be passed through.
501   gfx::Point touch2_new_location(20, 11);
502   generator_->MoveTouchId(touch2_new_location, 2);
503   ASSERT_EQ(1u, captured_events.size());
504   EXPECT_EQ(ui::ET_TOUCH_MOVED, captured_events[0]->type());
505   EXPECT_EQ(touch2_new_location, captured_events[0]->location());
506   ClearCapturedEvents();
507 
508   // Release of finger 2 should be passed through.
509   ui::TouchEvent touch2_release(
510       ui::ET_TOUCH_RELEASED,
511       gfx::Point(14, 15),
512       2,
513       Now());
514   generator_->Dispatch(&touch2_release);
515   ASSERT_EQ(1u, captured_events.size());
516   CONFIRM_EVENTS_ARE_TOUCH_AND_EQUAL(captured_events[0], &touch2_release);
517 }
518 
519 // Test the case when there are multiple fingers on the screen and the
520 // second finger is released. This should be rewritten as a move to the
521 // location of the first finger.
TEST_F(TouchExplorationTest,SecondFingerLifted)522 TEST_F(TouchExplorationTest, SecondFingerLifted) {
523   SwitchTouchExplorationMode(true);
524   gfx::Point touch1_location(0, 11);
525   generator_->set_current_location(touch1_location);
526   generator_->PressTouchId(1);
527   generator_->PressTouchId(2);
528   gfx::Point touch2_location(10, 11);
529   generator_->MoveTouchId(touch2_location, 2);
530   generator_->PressTouchId(3);
531   gfx::Point touch3_location(20, 21);
532   generator_->MoveTouchId(touch3_location, 3);
533   ClearCapturedEvents();
534 
535   // Release of finger 2 should be rewritten as a move to the location
536   // of the first finger.
537   generator_->ReleaseTouchId(2);
538   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
539   ASSERT_EQ(1u, captured_events.size());
540   EXPECT_EQ(ui::ET_TOUCH_MOVED, captured_events[0]->type());
541   EXPECT_EQ(2, static_cast<ui::TouchEvent*>(captured_events[0])->touch_id());
542   EXPECT_EQ(touch1_location, captured_events[0]->location());
543   ClearCapturedEvents();
544 
545   // Move of finger 1 should be rewritten as a move of finger 2.
546   gfx::Point touch1_new_location(0, 41);
547   generator_->MoveTouchId(touch1_new_location, 1);
548   ASSERT_EQ(1u, captured_events.size());
549   EXPECT_EQ(ui::ET_TOUCH_MOVED, captured_events[0]->type());
550   EXPECT_EQ(2, static_cast<ui::TouchEvent*>(captured_events[0])->touch_id());
551   EXPECT_EQ(touch1_new_location, captured_events[0]->location());
552   ClearCapturedEvents();
553 
554   // Release of finger 1 should be rewritten as release of finger 2.
555   gfx::Point touch1_final_location(0, 41);
556   ui::TouchEvent touch1_release(
557       ui::ET_TOUCH_RELEASED,
558       touch1_final_location,
559       1,
560       Now());
561   generator_->Dispatch(&touch1_release);
562   ASSERT_EQ(1u, captured_events.size());
563   EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[0]->type());
564   EXPECT_EQ(2, static_cast<ui::TouchEvent*>(captured_events[0])->touch_id());
565   EXPECT_EQ(touch1_final_location, captured_events[0]->location());
566 }
567 
568 // If an event is received after the double-tap timeout has elapsed, but
569 // before the timer has fired, a mouse move should still be generated.
TEST_F(TouchExplorationTest,TimerFiresLateDuringTouchExploration)570 TEST_F(TouchExplorationTest, TimerFiresLateDuringTouchExploration) {
571   SwitchTouchExplorationMode(true);
572 
573   // Send a press, then add another finger after the double-tap timeout.
574   generator_->PressTouchId(1);
575   simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(1000));
576   generator_->PressTouchId(2);
577   std::vector<ui::LocatedEvent*> events =
578       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
579   ASSERT_EQ(1U, events.size());
580   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
581   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
582 
583   generator_->ReleaseTouchId(2);
584   generator_->ReleaseTouchId(1);
585   EXPECT_TRUE(IsInNoFingersDownState());
586 }
587 
588 // If a new tap is received after the double-tap timeout has elapsed from
589 // a previous tap, but before the timer has fired, a mouse move should
590 // still be generated from the old tap.
TEST_F(TouchExplorationTest,TimerFiresLateAfterTap)591 TEST_F(TouchExplorationTest, TimerFiresLateAfterTap) {
592   SwitchTouchExplorationMode(true);
593 
594   // Send a tap at location1.
595   gfx::Point location0(11, 12);
596   generator_->set_current_location(location0);
597   generator_->PressTouch();
598   generator_->ReleaseTouch();
599 
600   // Send a tap at location2, after the double-tap timeout, but before the
601   // timer fires.
602   gfx::Point location1(33, 34);
603   generator_->set_current_location(location1);
604   simulated_clock_->Advance(base::TimeDelta::FromMilliseconds(301));
605   generator_->PressTouch();
606   generator_->ReleaseTouch();
607   AdvanceSimulatedTimePastTapDelay();
608 
609   std::vector<ui::LocatedEvent*> events =
610       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
611   ASSERT_EQ(2U, events.size());
612   EXPECT_EQ(location0, events[0]->location());
613   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
614   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
615   EXPECT_EQ(location1, events[1]->location());
616   EXPECT_TRUE(events[1]->flags() & ui::EF_IS_SYNTHESIZED);
617   EXPECT_TRUE(events[1]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
618   EXPECT_TRUE(IsInNoFingersDownState());
619 }
620 
621 // Double-tapping should send a touch press and release through to the location
622 // of the last successful touch exploration.
TEST_F(TouchExplorationTest,DoubleTap)623 TEST_F(TouchExplorationTest, DoubleTap) {
624   SwitchTouchExplorationMode(true);
625 
626   // Tap at one location, and get a mouse move event.
627   gfx::Point tap_location(11, 12);
628   generator_->set_current_location(tap_location);
629   generator_->PressTouch();
630   generator_->ReleaseTouch();
631   AdvanceSimulatedTimePastTapDelay();
632 
633   std::vector<ui::LocatedEvent*> events =
634       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
635   ASSERT_EQ(1U, events.size());
636 
637   EXPECT_EQ(tap_location, events[0]->location());
638   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
639   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
640   ClearCapturedEvents();
641 
642   // Now double-tap at a different location. This should result in
643   // a single touch press and release at the location of the tap,
644   // not at the location of the double-tap.
645   gfx::Point double_tap_location(33, 34);
646   generator_->set_current_location(double_tap_location);
647   generator_->PressTouch();
648   generator_->ReleaseTouch();
649   generator_->PressTouch();
650   generator_->ReleaseTouch();
651 
652   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
653   ASSERT_EQ(2U, captured_events.size());
654   EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
655   EXPECT_EQ(tap_location, captured_events[0]->location());
656   EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
657   EXPECT_EQ(tap_location, captured_events[1]->location());
658   EXPECT_TRUE(IsInNoFingersDownState());
659 }
660 
661 
662 // Double-tapping where the user holds their finger down for the second time
663 // for a longer press should send a touch press and released (right click)
664 // to the location of the last successful touch exploration.
TEST_F(TouchExplorationTest,DoubleTapLongPress)665 TEST_F(TouchExplorationTest, DoubleTapLongPress) {
666   SwitchTouchExplorationMode(true);
667 
668   // Tap at one location, and get a mouse move event.
669   gfx::Point tap_location(11, 12);
670   generator_->set_current_location(tap_location);
671   generator_->PressTouch();
672   generator_->ReleaseTouch();
673   AdvanceSimulatedTimePastTapDelay();
674 
675   std::vector<ui::LocatedEvent*> events =
676       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
677   ASSERT_EQ(1U, events.size());
678 
679   EXPECT_EQ(tap_location, events[0]->location());
680   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
681   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
682   ClearCapturedEvents();
683 
684   // Now double-tap and hold at a different location.
685   // This should result in a single touch long press and release
686   // at the location of the tap, not at the location of the double-tap.
687   // There should be a time delay between the touch press and release.
688   gfx::Point first_tap_location(33, 34);
689   generator_->set_current_location(first_tap_location);
690   generator_->PressTouch();
691   generator_->ReleaseTouch();
692   gfx::Point second_tap_location(23, 24);
693   generator_->set_current_location(second_tap_location);
694   generator_->PressTouch();
695   simulated_clock_->Advance(gesture_detector_config_.longpress_timeout);
696   generator_->ReleaseTouch();
697 
698   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
699   ASSERT_EQ(2U, captured_events.size());
700   EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
701   EXPECT_EQ(tap_location, captured_events[0]->location());
702   base::TimeDelta pressed_time = captured_events[0]->time_stamp();
703   EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
704   EXPECT_EQ(tap_location, captured_events[1]->location());
705   base::TimeDelta released_time = captured_events[1]->time_stamp();
706   EXPECT_EQ(gesture_detector_config_.longpress_timeout,
707             released_time - pressed_time);
708 }
709 
710 // Double-tapping without coming from touch exploration (no previous touch
711 // exploration event) should not generate any events.
TEST_F(TouchExplorationTest,DoubleTapNoTouchExplore)712 TEST_F(TouchExplorationTest, DoubleTapNoTouchExplore) {
713   SwitchTouchExplorationMode(true);
714 
715   // Double-tap without any previous touch.
716   // Touch exploration mode has not been entered, so there is no previous
717   // touch exploration event. The double-tap should be discarded, and no events
718   // should be generated at all.
719   gfx::Point double_tap_location(33, 34);
720   generator_->set_current_location(double_tap_location);
721   generator_->PressTouch();
722   generator_->ReleaseTouch();
723   generator_->PressTouch();
724   generator_->ReleaseTouch();
725 
726   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
727   ASSERT_EQ(0U, captured_events.size());
728 }
729 
730 // Tapping and releasing with a second finger when in touch exploration mode
731 // should send a touch press and released to the location of the last
732 // successful touch exploration and return to touch explore.
TEST_F(TouchExplorationTest,SplitTap)733 TEST_F(TouchExplorationTest, SplitTap) {
734   SwitchTouchExplorationMode(true);
735   gfx::Point initial_touch_location(11, 12);
736   gfx::Point second_touch_location(33, 34);
737 
738   // Tap and hold at one location, and get a mouse move event in touch explore.
739   EnterTouchExplorationModeAtLocation(initial_touch_location);
740   std::vector<ui::LocatedEvent*> events =
741       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
742   ASSERT_EQ(1U, events.size());
743 
744   EXPECT_EQ(initial_touch_location, events[0]->location());
745   EXPECT_TRUE(events[0]->flags() & ui::EF_IS_SYNTHESIZED);
746   EXPECT_TRUE(events[0]->flags() & ui::EF_TOUCH_ACCESSIBILITY);
747   ClearCapturedEvents();
748 
749   // Now tap and release at a different location. This should result in a
750   // single touch and release at the location of the first (held) tap,
751   // not at the location of the second tap and release.
752   // After the release, there is still a finger in touch explore mode.
753   ui::TouchEvent split_tap_press(
754       ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
755   generator_->Dispatch(&split_tap_press);
756   ui::TouchEvent split_tap_release(
757       ui::ET_TOUCH_RELEASED, second_touch_location, 1, Now());
758   generator_->Dispatch(&split_tap_release);
759   EXPECT_FALSE(IsInNoFingersDownState());
760 
761   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
762   ASSERT_EQ(2U, captured_events.size());
763   EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
764   EXPECT_EQ(initial_touch_location, captured_events[0]->location());
765   EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
766   EXPECT_EQ(initial_touch_location, captured_events[1]->location());
767 }
768 
769 // If split tap is started but the touch explore finger is released first,
770 // there should still be a touch press and release sent to the location of
771 // the last successful touch exploration.
772 // Both fingers should be released after the click goes through.
TEST_F(TouchExplorationTest,SplitTapRelease)773 TEST_F(TouchExplorationTest, SplitTapRelease) {
774   SwitchTouchExplorationMode(true);
775 
776   gfx::Point initial_touch_location(11, 12);
777   gfx::Point second_touch_location(33, 34);
778 
779   // Tap and hold at one location, and get a mouse move event in touch explore.
780   EnterTouchExplorationModeAtLocation(initial_touch_location);
781 
782   std::vector<ui::LocatedEvent*> events =
783       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
784   ASSERT_EQ(1U, events.size());
785 
786   ClearCapturedEvents();
787 
788   // Now tap at a different location. Release at the first location,
789   // then release at the second. This should result in a
790   // single touch and release at the location of the first (held) tap,
791   // not at the location of the second tap and release.
792   ui::TouchEvent split_tap_press(
793       ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
794   generator_->Dispatch(&split_tap_press);
795   ui::TouchEvent touch_explore_release(
796       ui::ET_TOUCH_RELEASED, initial_touch_location, 0, Now());
797   generator_->Dispatch(&touch_explore_release);
798   ui::TouchEvent split_tap_release(
799       ui::ET_TOUCH_RELEASED, second_touch_location , 1, Now());
800   generator_->Dispatch(&split_tap_release);
801   EXPECT_TRUE(IsInNoFingersDownState());
802 
803   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
804   ASSERT_EQ(2U, captured_events.size());
805   EXPECT_EQ(ui::ET_TOUCH_PRESSED, captured_events[0]->type());
806   EXPECT_EQ(initial_touch_location, captured_events[0]->location());
807   EXPECT_EQ(ui::ET_TOUCH_RELEASED, captured_events[1]->type());
808   EXPECT_EQ(initial_touch_location, captured_events[1]->location());
809 }
810 
811 // When in touch exploration mode, making a long press with a second finger
812 // should send a touch press and released to the location of the last
813 // successful touch exploration. There should be a delay between the
814 // touch and release events (right click).
TEST_F(TouchExplorationTest,SplitTapLongPress)815 TEST_F(TouchExplorationTest, SplitTapLongPress) {
816   SwitchTouchExplorationMode(true);
817   gfx::Point initial_touch_location(11, 12);
818   gfx::Point second_touch_location(33, 34);
819 
820   // Tap and hold at one location, and get a mouse move event in touch explore.
821   EnterTouchExplorationModeAtLocation(initial_touch_location);
822   std::vector<ui::LocatedEvent*> events =
823       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
824   ASSERT_EQ(1U, events.size());
825 
826   ClearCapturedEvents();
827 
828   // Now tap and release at a different location. This should result in a
829   // single touch and release at the location of the first (held) tap,
830   // not at the location of the second tap and release.
831   // After the release, there is still a finger in touch explore mode.
832   ui::TouchEvent split_tap_press(
833       ui::ET_TOUCH_PRESSED, second_touch_location, 1, Now());
834   generator_->Dispatch(&split_tap_press);
835   simulated_clock_->Advance(gesture_detector_config_.longpress_timeout);
836   ui::TouchEvent split_tap_release(
837       ui::ET_TOUCH_RELEASED, second_touch_location, 1, Now());
838   generator_->Dispatch(&split_tap_release);
839   EXPECT_FALSE(IsInNoFingersDownState());
840 
841   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
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);
851 }
852 
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.
TEST_F(TouchExplorationTest,SplitTapReleaseLongPress)859 TEST_F(TouchExplorationTest, SplitTapReleaseLongPress) {
860   SwitchTouchExplorationMode(true);
861   gfx::Point initial_touch_location(11, 12);
862   gfx::Point second_touch_location(33, 34);
863 
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       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
868   ASSERT_EQ(1U, events.size());
869   ClearCapturedEvents();
870 
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());
887 
888   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
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);
898  }
899 
TEST_F(TouchExplorationTest,SplitTapLongPressMultiFinger)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);
905 
906   // Tap and hold at one location, and get a mouse move event in touch explore.
907   EnterTouchExplorationModeAtLocation(initial_touch_location);
908 
909   std::vector<ui::LocatedEvent*> events =
910       GetCapturedEventsOfType(ui::ET_MOUSE_MOVED);
911   ASSERT_EQ(1U, events.size());
912 
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();
917 
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);
923 
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);
929 
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);
941 
942   const ScopedVector<ui::LocatedEvent>& captured_events = GetCapturedEvents();
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());
953 }
954 
955 }  // namespace ui
956