| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/chromeos/touch_exploration_controller.h" | 5 #include "ui/chromeos/touch_exploration_controller.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 root_window_->GetHost()->ConvertDIPToScreenInPixels(&native_point); | 65 root_window_->GetHost()->ConvertDIPToScreenInPixels(&native_point); |
| 66 | 66 |
| 67 anchor_point_ = gfx::PointF(native_point.x(), native_point.y()); | 67 anchor_point_ = gfx::PointF(native_point.x(), native_point.y()); |
| 68 anchor_point_state_ = ANCHOR_POINT_EXPLICITLY_SET; | 68 anchor_point_state_ = ANCHOR_POINT_EXPLICITLY_SET; |
| 69 } | 69 } |
| 70 | 70 |
| 71 void TouchExplorationController::SetExcludeBounds(const gfx::Rect& bounds) { | 71 void TouchExplorationController::SetExcludeBounds(const gfx::Rect& bounds) { |
| 72 exclude_bounds_ = bounds; | 72 exclude_bounds_ = bounds; |
| 73 } | 73 } |
| 74 | 74 |
| 75 void TouchExplorationController::SetLiftActivationBounds( |
| 76 const gfx::Rect& bounds) { |
| 77 lift_activation_bounds_ = bounds; |
| 78 } |
| 79 |
| 75 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( | 80 ui::EventRewriteStatus TouchExplorationController::RewriteEvent( |
| 76 const ui::Event& event, | 81 const ui::Event& event, |
| 77 std::unique_ptr<ui::Event>* rewritten_event) { | 82 std::unique_ptr<ui::Event>* rewritten_event) { |
| 78 if (!event.IsTouchEvent()) { | 83 if (!event.IsTouchEvent()) { |
| 79 if (event.IsKeyEvent()) { | 84 if (event.IsKeyEvent()) { |
| 80 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); | 85 const ui::KeyEvent& key_event = static_cast<const ui::KeyEvent&>(event); |
| 81 VLOG(1) << "\nKeyboard event: " << key_event.GetName() | 86 VLOG(1) << "\nKeyboard event: " << key_event.GetName() |
| 82 << "\n Key code: " << key_event.key_code() | 87 << "\n Key code: " << key_event.key_code() |
| 83 << ", Flags: " << key_event.flags() | 88 << ", Flags: " << key_event.flags() |
| 84 << ", Is char: " << key_event.is_char(); | 89 << ", Is char: " << key_event.is_char(); |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 | 321 |
| 317 if (type == ui::ET_TOUCH_PRESSED) { | 322 if (type == ui::ET_TOUCH_PRESSED) { |
| 318 initial_presses_[event.pointer_details().id] = event.location(); | 323 initial_presses_[event.pointer_details().id] = event.location(); |
| 319 SET_STATE(TWO_FINGER_TAP); | 324 SET_STATE(TWO_FINGER_TAP); |
| 320 return EVENT_REWRITE_DISCARD; | 325 return EVENT_REWRITE_DISCARD; |
| 321 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 326 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 322 if (passthrough_timer_.IsRunning()) | 327 if (passthrough_timer_.IsRunning()) |
| 323 passthrough_timer_.Stop(); | 328 passthrough_timer_.Stop(); |
| 324 if (current_touch_ids_.size() == 0 && | 329 if (current_touch_ids_.size() == 0 && |
| 325 event.pointer_details().id == initial_press_->pointer_details().id) { | 330 event.pointer_details().id == initial_press_->pointer_details().id) { |
| 331 MaybeSendSimulatedTapInLiftActivationBounds(event); |
| 326 SET_STATE(SINGLE_TAP_RELEASED); | 332 SET_STATE(SINGLE_TAP_RELEASED); |
| 327 } else if (current_touch_ids_.size() == 0) { | 333 } else if (current_touch_ids_.size() == 0) { |
| 328 SET_STATE(NO_FINGERS_DOWN); | 334 SET_STATE(NO_FINGERS_DOWN); |
| 329 } | 335 } |
| 330 return EVENT_REWRITE_DISCARD; | 336 return EVENT_REWRITE_DISCARD; |
| 331 } else if (type == ui::ET_TOUCH_MOVED) { | 337 } else if (type == ui::ET_TOUCH_MOVED) { |
| 332 float distance = (event.location() - initial_press_->location()).Length(); | 338 float distance = (event.location() - initial_press_->location()).Length(); |
| 333 // If the user does not move far enough from the original position, then the | 339 // If the user does not move far enough from the original position, then the |
| 334 // resulting movement should not be considered to be a deliberate gesture or | 340 // resulting movement should not be considered to be a deliberate gesture or |
| 335 // touch exploration. | 341 // touch exploration. |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 426 float delta = (event.location() - initial_press_->location()).Length(); | 432 float delta = (event.location() - initial_press_->location()).Length(); |
| 427 if (delta > gesture_detector_config_.touch_slop) { | 433 if (delta > gesture_detector_config_.touch_slop) { |
| 428 tap_timer_.Stop(); | 434 tap_timer_.Stop(); |
| 429 OnTapTimerFired(); | 435 OnTapTimerFired(); |
| 430 } | 436 } |
| 431 return EVENT_REWRITE_DISCARD; | 437 return EVENT_REWRITE_DISCARD; |
| 432 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 438 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 433 if (current_touch_ids_.size() != 0) | 439 if (current_touch_ids_.size() != 0) |
| 434 return EVENT_REWRITE_DISCARD; | 440 return EVENT_REWRITE_DISCARD; |
| 435 | 441 |
| 436 SendSimulatedClick(); | 442 SendSimulatedClickOrTap(); |
| 437 | 443 |
| 438 SET_STATE(NO_FINGERS_DOWN); | 444 SET_STATE(NO_FINGERS_DOWN); |
| 439 return ui::EVENT_REWRITE_DISCARD; | 445 return ui::EVENT_REWRITE_DISCARD; |
| 440 } | 446 } |
| 441 NOTREACHED(); | 447 NOTREACHED(); |
| 442 return ui::EVENT_REWRITE_CONTINUE; | 448 return ui::EVENT_REWRITE_CONTINUE; |
| 443 } | 449 } |
| 444 | 450 |
| 445 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( | 451 ui::EventRewriteStatus TouchExplorationController::InTouchReleasePending( |
| 446 const ui::TouchEvent& event, | 452 const ui::TouchEvent& event, |
| 447 std::unique_ptr<ui::Event>* rewritten_event) { | 453 std::unique_ptr<ui::Event>* rewritten_event) { |
| 448 const ui::EventType type = event.type(); | 454 const ui::EventType type = event.type(); |
| 449 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { | 455 if (type == ui::ET_TOUCH_PRESSED || type == ui::ET_TOUCH_MOVED) { |
| 450 return ui::EVENT_REWRITE_DISCARD; | 456 return ui::EVENT_REWRITE_DISCARD; |
| 451 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 457 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 452 if (current_touch_ids_.size() != 0) | 458 if (current_touch_ids_.size() != 0) |
| 453 return EVENT_REWRITE_DISCARD; | 459 return EVENT_REWRITE_DISCARD; |
| 454 | 460 |
| 455 SendSimulatedClick(); | 461 SendSimulatedClickOrTap(); |
| 456 SET_STATE(NO_FINGERS_DOWN); | 462 SET_STATE(NO_FINGERS_DOWN); |
| 457 return ui::EVENT_REWRITE_DISCARD; | 463 return ui::EVENT_REWRITE_DISCARD; |
| 458 } | 464 } |
| 459 NOTREACHED(); | 465 NOTREACHED(); |
| 460 return ui::EVENT_REWRITE_CONTINUE; | 466 return ui::EVENT_REWRITE_CONTINUE; |
| 461 } | 467 } |
| 462 | 468 |
| 463 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( | 469 ui::EventRewriteStatus TouchExplorationController::InTouchExploration( |
| 464 const ui::TouchEvent& event, | 470 const ui::TouchEvent& event, |
| 465 std::unique_ptr<ui::Event>* rewritten_event) { | 471 std::unique_ptr<ui::Event>* rewritten_event) { |
| 466 const ui::EventType type = event.type(); | 472 const ui::EventType type = event.type(); |
| 467 if (type == ui::ET_TOUCH_PRESSED) { | 473 if (type == ui::ET_TOUCH_PRESSED) { |
| 468 // Enter split-tap mode. | 474 // Enter split-tap mode. |
| 469 initial_press_.reset(new TouchEvent(event)); | 475 initial_press_.reset(new TouchEvent(event)); |
| 470 tap_timer_.Stop(); | 476 tap_timer_.Stop(); |
| 471 SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); | 477 SET_STATE(TOUCH_EXPLORE_SECOND_PRESS); |
| 472 return ui::EVENT_REWRITE_DISCARD; | 478 return ui::EVENT_REWRITE_DISCARD; |
| 473 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { | 479 } else if (type == ui::ET_TOUCH_RELEASED || type == ui::ET_TOUCH_CANCELLED) { |
| 474 initial_press_.reset(new TouchEvent(event)); | 480 initial_press_.reset(new TouchEvent(event)); |
| 475 StartTapTimer(); | 481 StartTapTimer(); |
| 482 MaybeSendSimulatedTapInLiftActivationBounds(event); |
| 476 SET_STATE(TOUCH_EXPLORE_RELEASED); | 483 SET_STATE(TOUCH_EXPLORE_RELEASED); |
| 477 } else if (type != ui::ET_TOUCH_MOVED) { | 484 } else if (type != ui::ET_TOUCH_MOVED) { |
| 478 NOTREACHED(); | 485 NOTREACHED(); |
| 479 return ui::EVENT_REWRITE_CONTINUE; | 486 return ui::EVENT_REWRITE_CONTINUE; |
| 480 } | 487 } |
| 481 | 488 |
| 482 // Rewrite as a mouse-move event. | 489 // Rewrite as a mouse-move event. |
| 483 *rewritten_event = CreateMouseMoveEvent(event.location_f(), event.flags()); | 490 *rewritten_event = CreateMouseMoveEvent(event.location_f(), event.flags()); |
| 484 last_touch_exploration_.reset(new TouchEvent(event)); | 491 last_touch_exploration_.reset(new TouchEvent(event)); |
| 485 if (anchor_point_state_ != ANCHOR_POINT_EXPLICITLY_SET) | 492 if (anchor_point_state_ != ANCHOR_POINT_EXPLICITLY_SET) |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 607 last_touch_exploration_->pointer_details().id) { | 614 last_touch_exploration_->pointer_details().id) { |
| 608 SET_STATE(TOUCH_RELEASE_PENDING); | 615 SET_STATE(TOUCH_RELEASE_PENDING); |
| 609 return EVENT_REWRITE_DISCARD; | 616 return EVENT_REWRITE_DISCARD; |
| 610 } | 617 } |
| 611 | 618 |
| 612 // Continue to release the touch only if the touch explore finger is the | 619 // Continue to release the touch only if the touch explore finger is the |
| 613 // only finger remaining. | 620 // only finger remaining. |
| 614 if (current_touch_ids_.size() != 1) | 621 if (current_touch_ids_.size() != 1) |
| 615 return EVENT_REWRITE_DISCARD; | 622 return EVENT_REWRITE_DISCARD; |
| 616 | 623 |
| 617 SendSimulatedClick(); | 624 SendSimulatedClickOrTap(); |
| 618 | 625 |
| 619 SET_STATE(TOUCH_EXPLORATION); | 626 SET_STATE(TOUCH_EXPLORATION); |
| 620 EnterTouchToMouseMode(); | 627 EnterTouchToMouseMode(); |
| 621 return ui::EVENT_REWRITE_DISCARD; | 628 return ui::EVENT_REWRITE_DISCARD; |
| 622 } | 629 } |
| 623 NOTREACHED(); | 630 NOTREACHED(); |
| 624 return ui::EVENT_REWRITE_CONTINUE; | 631 return ui::EVENT_REWRITE_CONTINUE; |
| 625 } | 632 } |
| 626 | 633 |
| 627 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( | 634 ui::EventRewriteStatus TouchExplorationController::InWaitForNoFingers( |
| 628 const ui::TouchEvent& event, | 635 const ui::TouchEvent& event, |
| 629 std::unique_ptr<ui::Event>* rewritten_event) { | 636 std::unique_ptr<ui::Event>* rewritten_event) { |
| 630 if (current_touch_ids_.size() == 0) | 637 if (current_touch_ids_.size() == 0) |
| 631 SET_STATE(NO_FINGERS_DOWN); | 638 SET_STATE(NO_FINGERS_DOWN); |
| 632 return EVENT_REWRITE_DISCARD; | 639 return EVENT_REWRITE_DISCARD; |
| 633 } | 640 } |
| 634 | 641 |
| 635 void TouchExplorationController::PlaySoundForTimer() { | 642 void TouchExplorationController::PlaySoundForTimer() { |
| 636 delegate_->PlayVolumeAdjustEarcon(); | 643 delegate_->PlayVolumeAdjustEarcon(); |
| 637 } | 644 } |
| 638 | 645 |
| 639 void TouchExplorationController::SendSimulatedClick() { | 646 void TouchExplorationController::SendSimulatedClickOrTap() { |
| 640 // If we got an anchor point from ChromeVox, send a double-tap gesture | 647 // If we got an anchor point from ChromeVox, send a double-tap gesture |
| 641 // and let ChromeVox handle the click. | 648 // and let ChromeVox handle the click. |
| 642 if (anchor_point_state_ == ANCHOR_POINT_EXPLICITLY_SET) { | 649 if (anchor_point_state_ == ANCHOR_POINT_EXPLICITLY_SET) { |
| 643 delegate_->HandleAccessibilityGesture(ui::AX_GESTURE_CLICK); | 650 delegate_->HandleAccessibilityGesture(ui::AX_GESTURE_CLICK); |
| 644 return; | 651 return; |
| 645 } | 652 } |
| 653 SendSimulatedTap(); |
| 654 } |
| 646 | 655 |
| 647 // If we don't have an anchor point, we can't send a simulated click. | 656 void TouchExplorationController::SendSimulatedTap() { |
| 648 if (anchor_point_state_ == ANCHOR_POINT_NONE) | |
| 649 return; | |
| 650 | |
| 651 // Otherwise send a simulated press/release at the anchor point. | |
| 652 std::unique_ptr<ui::TouchEvent> touch_press; | 657 std::unique_ptr<ui::TouchEvent> touch_press; |
| 653 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), | 658 touch_press.reset(new ui::TouchEvent(ui::ET_TOUCH_PRESSED, gfx::Point(), |
| 654 Now(), | 659 Now(), |
| 655 initial_press_->pointer_details())); | 660 initial_press_->pointer_details())); |
| 656 touch_press->set_location_f(anchor_point_); | 661 touch_press->set_location_f(anchor_point_); |
| 657 touch_press->set_root_location_f(anchor_point_); | 662 touch_press->set_root_location_f(anchor_point_); |
| 658 DispatchEvent(touch_press.get()); | 663 DispatchEvent(touch_press.get()); |
| 659 | 664 |
| 660 std::unique_ptr<ui::TouchEvent> touch_release; | 665 std::unique_ptr<ui::TouchEvent> touch_release; |
| 661 touch_release.reset(new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), | 666 touch_release.reset(new ui::TouchEvent(ui::ET_TOUCH_RELEASED, gfx::Point(), |
| 662 Now(), | 667 Now(), |
| 663 initial_press_->pointer_details())); | 668 initial_press_->pointer_details())); |
| 664 touch_release->set_location_f(anchor_point_); | 669 touch_release->set_location_f(anchor_point_); |
| 665 touch_release->set_root_location_f(anchor_point_); | 670 touch_release->set_root_location_f(anchor_point_); |
| 666 DispatchEvent(touch_release.get()); | 671 DispatchEvent(touch_release.get()); |
| 667 } | 672 } |
| 668 | 673 |
| 674 void TouchExplorationController::MaybeSendSimulatedTapInLiftActivationBounds( |
| 675 const ui::TouchEvent& event) { |
| 676 gfx::Point location = event.location(); |
| 677 root_window_->GetHost()->ConvertScreenInPixelsToDIP(&location); |
| 678 if (lift_activation_bounds_.Contains(anchor_point_.x(), anchor_point_.y()) && |
| 679 lift_activation_bounds_.Contains(location)) { |
| 680 SendSimulatedTap(); |
| 681 } |
| 682 } |
| 683 |
| 669 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( | 684 ui::EventRewriteStatus TouchExplorationController::InSlideGesture( |
| 670 const ui::TouchEvent& event, | 685 const ui::TouchEvent& event, |
| 671 std::unique_ptr<ui::Event>* rewritten_event) { | 686 std::unique_ptr<ui::Event>* rewritten_event) { |
| 672 // The timer should not fire when sliding. | 687 // The timer should not fire when sliding. |
| 673 tap_timer_.Stop(); | 688 tap_timer_.Stop(); |
| 674 | 689 |
| 675 ui::EventType type = event.type(); | 690 ui::EventType type = event.type(); |
| 676 // If additional fingers are added before a swipe gesture has been registered, | 691 // If additional fingers are added before a swipe gesture has been registered, |
| 677 // then wait until all fingers have been lifted. | 692 // then wait until all fingers have been lifted. |
| 678 if (type == ui::ET_TOUCH_PRESSED || | 693 if (type == ui::ET_TOUCH_PRESSED || |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 return "TWO_FINGER_TAP"; | 1207 return "TWO_FINGER_TAP"; |
| 1193 } | 1208 } |
| 1194 return "Not a state"; | 1209 return "Not a state"; |
| 1195 } | 1210 } |
| 1196 | 1211 |
| 1197 float TouchExplorationController::GetSplitTapTouchSlop() { | 1212 float TouchExplorationController::GetSplitTapTouchSlop() { |
| 1198 return gesture_detector_config_.touch_slop * 3; | 1213 return gesture_detector_config_.touch_slop * 3; |
| 1199 } | 1214 } |
| 1200 | 1215 |
| 1201 } // namespace ui | 1216 } // namespace ui |
| OLD | NEW |