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 22 namespace ui { 23 24 namespace { 25 26 // Records all mouse, touch, gesture, and key events. 27 class 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 67 int Factorial(int n) { 68 if (n <= 0) 69 return 0; 70 if (n == 1) 71 return 1; 72 return n * Factorial(n - 1); 73 } 74 75 class 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 121 class 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 199 class 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. 424 void ConfirmEventsAreTouchAndEqual(ui::Event* e1, ui::Event* e2) { 425 ASSERT_TRUE(e1->IsTouchEvent()); 426 ASSERT_TRUE(e2->IsTouchEvent()); 427 ui::TouchEvent* touch_event1 = static_cast<ui::TouchEvent*>(e1); 428 ui::TouchEvent* touch_event2 = static_cast<ui::TouchEvent*>(e2); 429 EXPECT_EQ(touch_event1->type(), touch_event2->type()); 430 EXPECT_EQ(touch_event1->location(), touch_event2->location()); 431 EXPECT_EQ(touch_event1->touch_id(), touch_event2->touch_id()); 432 EXPECT_EQ(touch_event1->flags(), touch_event2->flags()); 433 EXPECT_EQ(touch_event1->time_stamp(), touch_event2->time_stamp()); 434 } 435 436 // Executes a number of assertions to confirm that |e1| and |e2| are mouse 437 // events and are equal to each other. 438 void ConfirmEventsAreMouseAndEqual(ui::Event* e1, ui::Event* e2) { 439 ASSERT_TRUE(e1->IsMouseEvent()); 440 ASSERT_TRUE(e2->IsMouseEvent()); 441 ui::MouseEvent* mouse_event1 = static_cast<ui::MouseEvent*>(e1); 442 ui::MouseEvent* mouse_event2 = static_cast<ui::MouseEvent*>(e2); 443 EXPECT_EQ(mouse_event1->type(), mouse_event2->type()); 444 EXPECT_EQ(mouse_event1->location(), mouse_event2->location()); 445 EXPECT_EQ(mouse_event1->root_location(), mouse_event2->root_location()); 446 EXPECT_EQ(mouse_event1->flags(), mouse_event2->flags()); 447 } 448 449 // Executes a number of assertions to confirm that |e1| and |e2| are key events 450 // and are equal to each other. 451 void ConfirmEventsAreKeyAndEqual(ui::Event* e1, ui::Event* e2) { 452 ASSERT_TRUE(e1->IsKeyEvent()); 453 ASSERT_TRUE(e2->IsKeyEvent()); 454 ui::KeyEvent* key_event1 = static_cast<ui::KeyEvent*>(e1); 455 ui::KeyEvent* key_event2 = static_cast<ui::KeyEvent*>(e2); 456 EXPECT_EQ(key_event1->type(), key_event2->type()); 457 EXPECT_EQ(key_event1->key_code(), key_event2->key_code()); 458 EXPECT_EQ(key_event1->code(), key_event2->code()); 459 EXPECT_EQ(key_event1->flags(), key_event2->flags()); 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 477 void AssertDirectionalNavigationEvents(const ScopedVector<ui::Event>& events, 478 ui::KeyboardCode direction) { 479 ASSERT_EQ(6U, events.size()); 480 ui::KeyEvent shift_pressed( 481 ui::ET_KEY_PRESSED, ui::VKEY_SHIFT, ui::EF_SHIFT_DOWN); 482 ui::KeyEvent search_pressed( 483 ui::ET_KEY_PRESSED, ui::VKEY_LWIN, ui::EF_SHIFT_DOWN); 484 ui::KeyEvent direction_pressed( 485 ui::ET_KEY_PRESSED, direction, ui::EF_SHIFT_DOWN); 486 ui::KeyEvent direction_released( 487 ui::ET_KEY_RELEASED, direction, ui::EF_SHIFT_DOWN); 488 ui::KeyEvent search_released( 489 ui::ET_KEY_RELEASED, VKEY_LWIN, ui::EF_SHIFT_DOWN); 490 ui::KeyEvent shift_released( 491 ui::ET_KEY_RELEASED, ui::VKEY_SHIFT, ui::EF_NONE); 492 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_pressed, events[0]); 493 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_pressed, events[1]); 494 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_pressed, events[2]); 495 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&direction_released, events[3]); 496 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&search_released, events[4]); 497 CONFIRM_EVENTS_ARE_KEY_AND_EQUAL(&shift_released, events[5]); 498 } 499 500 TEST_F(TouchExplorationTest, EntersTouchToMouseModeAfterPressAndDelay) { 501 SwitchTouchExplorationMode(true); 502 EXPECT_FALSE(IsInTouchToMouseMode()); 503 generator_->PressTouch(); 504 AdvanceSimulatedTimePastTapDelay(); 505 EXPECT_TRUE(IsInTouchToMouseMode()); 506 } 507 508 TEST_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 525 TEST_F(TouchExplorationTest, OneFingerTap) { 526 SwitchTouchExplorationMode(true); 527 gfx::Point location(11, 12); 528 generator_->set_current_location(location); 529 generator_->PressTouch(); 530 generator_->ReleaseTouch(); 531 AdvanceSimulatedTimePastTapDelay(); 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 543 TEST_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. 591 TEST_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. 651 TEST_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. 676 TEST_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. 708 TEST_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. 749 TEST_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. 837 TEST_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. 886 TEST_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. 921 TEST_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. 948 TEST_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. 1006 TEST_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). 1048 TEST_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. 1100 TEST_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 1141 TEST_F(TouchExplorationTest, SplitTapMultiFinger) { 1142 SwitchTouchExplorationMode(true); 1143 gfx::Point initial_touch_location(11, 12); 1144 gfx::Point second_touch_location(33, 34); 1145 gfx::Point third_touch_location(16, 17); 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 1193 TEST_F(TouchExplorationTest, SplitTapLeaveSlop) { 1194 SwitchTouchExplorationMode(true); 1195 gfx::Point first_touch_location(11, 12); 1196 gfx::Point second_touch_location(33, 34); 1197 gfx::Point first_move_location( 1198 first_touch_location.x() + gesture_detector_config_.touch_slop * 3 + 1, 1199 first_touch_location.y()); 1200 gfx::Point second_move_location( 1201 second_touch_location.x() + gesture_detector_config_.touch_slop * 3 + 1, 1202 second_touch_location.y()); 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. 1267 TEST_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. 1308 TEST_F(TouchExplorationTest, GestureSwipe) { 1309 SwitchTouchExplorationMode(true); 1310 std::vector<ui::KeyboardCode> directions; 1311 directions.push_back(ui::VKEY_RIGHT); 1312 directions.push_back(ui::VKEY_LEFT); 1313 directions.push_back(ui::VKEY_UP); 1314 directions.push_back(ui::VKEY_DOWN); 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 1389 TEST_F(TouchExplorationTest, DISABLED_AllFingerPermutations) { 1390 SwitchTouchExplorationMode(true); 1391 SuppressVLOGs(true); 1392 // We will test all permutations of events from three different fingers 1393 // to ensure that we return to NO_FINGERS_DOWN when fingers have been 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. 1501 TEST_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 1529 TEST_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. 1589 TEST_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. 1629 TEST_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. 1707 TEST_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. 1730 TEST_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. 1753 TEST_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. 1773 TEST_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. 1824 TEST_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. 1856 TEST_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 1864 TEST_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. 1875 TEST_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 1911 TEST_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