| Index: ui/events/gesture_detection/gesture_detector.cc
|
| diff --git a/ui/events/gesture_detection/gesture_detector.cc b/ui/events/gesture_detection/gesture_detector.cc
|
| index 6fc39a8e3dd8577df51e40bca32bd4aaf5777d46..f0c3cb1c4206f0093933de764b52609c603e6489 100644
|
| --- a/ui/events/gesture_detection/gesture_detector.cc
|
| +++ b/ui/events/gesture_detection/gesture_detector.cc
|
| @@ -130,11 +130,12 @@ GestureDetector::GestureDetector(
|
| min_swipe_direction_component_ratio_(0),
|
| still_down_(false),
|
| defer_confirm_single_tap_(false),
|
| - always_in_tap_region_(false),
|
| + all_pointers_within_slop_regions_(false),
|
| always_in_bigger_tap_region_(false),
|
| two_finger_tap_allowed_for_gesture_(false),
|
| is_double_tapping_(false),
|
| is_down_candidate_for_repeated_single_tap_(false),
|
| + maximum_pointer_count_(0),
|
| current_single_tap_repeat_count_(0),
|
| single_tap_repeat_interval_(1),
|
| last_focus_x_(0),
|
| @@ -185,6 +186,14 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| down_focus_y_ = last_focus_y_ = focus_y;
|
| // Cancel long press and taps.
|
| CancelTaps();
|
| + maximum_pointer_count_ = std::max(maximum_pointer_count_,
|
| + static_cast<int>(ev.GetPointerCount()));
|
| +
|
| + // Even when two_finger_tap_allowed_for_gesture_ is false,
|
| + // second pointer down information must be stored to check
|
| + // the slop region in multi-finger scrolls.
|
| + if (ev.GetPointerCount() == 2)
|
| + secondary_pointer_down_event_ = ev.Clone();
|
|
|
| if (!two_finger_tap_allowed_for_gesture_)
|
| break;
|
| @@ -193,12 +202,9 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| const float dx = ev.GetX(action_index) - current_down_event_->GetX();
|
| const float dy = ev.GetY(action_index) - current_down_event_->GetY();
|
|
|
| - if (ev.GetPointerCount() == 2 &&
|
| - dx * dx + dy * dy < two_finger_tap_distance_square_) {
|
| - secondary_pointer_down_event_ = ev.Clone();
|
| - } else {
|
| + if (maximum_pointer_count_ > 2 ||
|
| + dx * dx + dy * dy >= two_finger_tap_distance_square_)
|
| two_finger_tap_allowed_for_gesture_ = false;
|
| - }
|
| } break;
|
|
|
| case MotionEvent::ACTION_POINTER_UP: {
|
| @@ -272,11 +278,12 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| current_down_event_ = ev.Clone();
|
|
|
| secondary_pointer_down_event_.reset();
|
| - always_in_tap_region_ = true;
|
| + all_pointers_within_slop_regions_ = true;
|
| always_in_bigger_tap_region_ = true;
|
| still_down_ = true;
|
| defer_confirm_single_tap_ = false;
|
| two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_;
|
| + maximum_pointer_count_ = 1;
|
|
|
| // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure
|
| // proper timeout ordering.
|
| @@ -295,27 +302,30 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| // Give the move events of the double-tap.
|
| DCHECK(double_tap_listener_);
|
| handled |= double_tap_listener_->OnDoubleTapEvent(ev);
|
| - } else if (always_in_tap_region_) {
|
| - const float delta_x = focus_x - down_focus_x_;
|
| - const float delta_y = focus_y - down_focus_y_;
|
| - const float distance_square = delta_x * delta_x + delta_y * delta_y;
|
| - if (distance_square > touch_slop_square_) {
|
| + } else if (all_pointers_within_slop_regions_) {
|
| + if (!IsWithinTouchSlop(ev)) {
|
| handled = listener_->OnScroll(
|
| - *current_down_event_, ev, scroll_x, scroll_y);
|
| + *current_down_event_, ev,
|
| + (ev.GetPointerCount() > 1 ? *secondary_pointer_down_event_
|
| + : ev),
|
| + scroll_x, scroll_y);
|
| last_focus_x_ = focus_x;
|
| last_focus_y_ = focus_y;
|
| - always_in_tap_region_ = false;
|
| + all_pointers_within_slop_regions_ = false;
|
| timeout_handler_->Stop();
|
| }
|
| +
|
| + const float delta_x = focus_x - down_focus_x_;
|
| + const float delta_y = focus_y - down_focus_y_;
|
| + const float distance_square = delta_x * delta_x + delta_y * delta_y;
|
| if (distance_square > double_tap_touch_slop_square_)
|
| always_in_bigger_tap_region_ = false;
|
| } else if (std::abs(scroll_x) > kScrollEpsilon ||
|
| std::abs(scroll_y) > kScrollEpsilon) {
|
| - // We should eventually apply touch slop for multi-finger
|
| - // scrolls as well as single finger scrolls. See
|
| - // crbug.com/492185 for details.
|
| - handled =
|
| - listener_->OnScroll(*current_down_event_, ev, scroll_x, scroll_y);
|
| + handled = listener_->OnScroll(
|
| + *current_down_event_, ev,
|
| + (ev.GetPointerCount() > 1 ? *secondary_pointer_down_event_ : ev),
|
| + scroll_x, scroll_y);
|
| last_focus_x_ = focus_x;
|
| last_focus_y_ = focus_y;
|
| }
|
| @@ -325,24 +335,10 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
|
|
| // Two-finger tap should be prevented if either pointer exceeds its
|
| // (independent) slop region.
|
| - const int id0 = current_down_event_->GetPointerId(0);
|
| - const int ev_idx0 = ev.GetPointerId(0) == id0 ? 0 : 1;
|
| -
|
| - // Check if the primary pointer exceeded the slop region.
|
| - float dx = current_down_event_->GetX() - ev.GetX(ev_idx0);
|
| - float dy = current_down_event_->GetY() - ev.GetY(ev_idx0);
|
| - if (dx * dx + dy * dy > touch_slop_square_) {
|
| + // If the event has had more than two pointers down at any time,
|
| + // two finger tap should be prevented.
|
| + if (maximum_pointer_count_ > 2 || !IsWithinTouchSlop(ev)) {
|
| two_finger_tap_allowed_for_gesture_ = false;
|
| - break;
|
| - }
|
| - if (ev.GetPointerCount() == 2) {
|
| - // Check if the secondary pointer exceeded the slop region.
|
| - const int ev_idx1 = ev_idx0 == 0 ? 1 : 0;
|
| - const int idx1 = secondary_pointer_down_event_->GetActionIndex();
|
| - dx = secondary_pointer_down_event_->GetX(idx1) - ev.GetX(ev_idx1);
|
| - dy = secondary_pointer_down_event_->GetY(idx1) - ev.GetY(ev_idx1);
|
| - if (dx * dx + dy * dy > touch_slop_square_)
|
| - two_finger_tap_allowed_for_gesture_ = false;
|
| }
|
| }
|
| break;
|
| @@ -354,7 +350,8 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| // Finally, give the up event of the double-tap.
|
| DCHECK(double_tap_listener_);
|
| handled |= double_tap_listener_->OnDoubleTapEvent(ev);
|
| - } else if (always_in_tap_region_) {
|
| + } else if (all_pointers_within_slop_regions_ &&
|
| + maximum_pointer_count_ == 1) {
|
| if (is_down_candidate_for_repeated_single_tap_) {
|
| current_single_tap_repeat_count_ =
|
| (1 + current_single_tap_repeat_count_) %
|
| @@ -392,6 +389,7 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
|
| timeout_handler_->StopTimeout(SHOW_PRESS);
|
| timeout_handler_->StopTimeout(LONG_PRESS);
|
| }
|
| + maximum_pointer_count_ = 0;
|
| break;
|
|
|
| case MotionEvent::ACTION_CANCEL:
|
| @@ -477,13 +475,13 @@ void GestureDetector::OnTapTimeout() {
|
| void GestureDetector::Cancel() {
|
| CancelTaps();
|
| velocity_tracker_.Clear();
|
| + all_pointers_within_slop_regions_ = false;
|
| still_down_ = false;
|
| }
|
|
|
| void GestureDetector::CancelTaps() {
|
| timeout_handler_->Stop();
|
| is_double_tapping_ = false;
|
| - always_in_tap_region_ = false;
|
| always_in_bigger_tap_region_ = false;
|
| defer_confirm_single_tap_ = false;
|
| is_down_candidate_for_repeated_single_tap_ = false;
|
| @@ -539,4 +537,32 @@ bool GestureDetector::HandleSwipeIfNeeded(const MotionEvent& up,
|
| return listener_->OnSwipe(*current_down_event_, up, vx, vy);
|
| }
|
|
|
| +bool GestureDetector::IsWithinTouchSlop(const MotionEvent& ev) {
|
| + // If there are more than two down pointers, tapping is not possible.
|
| + // Slop region check is not needed.
|
| + if (ev.GetPointerCount() > 2)
|
| + return false;
|
| +
|
| + const int id0 = current_down_event_->GetPointerId(0);
|
| + const int ev_idx0 = ev.GetPointerId(0) == id0 ? 0 : 1;
|
| +
|
| + // Check if the primary pointer exceeded the slop region.
|
| + float dx = current_down_event_->GetX() - ev.GetX(ev_idx0);
|
| + float dy = current_down_event_->GetY() - ev.GetY(ev_idx0);
|
| + if (dx * dx + dy * dy > touch_slop_square_)
|
| + return false;
|
| +
|
| + if (ev.GetPointerCount() == 2) {
|
| + // Check if the secondary pointer exceeded the slop region.
|
| + const int ev_idx1 = ev_idx0 == 0 ? 1 : 0;
|
| + const int idx1 = secondary_pointer_down_event_->GetActionIndex();
|
| + dx = secondary_pointer_down_event_->GetX(idx1) - ev.GetX(ev_idx1);
|
| + dy = secondary_pointer_down_event_->GetY(idx1) - ev.GetY(ev_idx1);
|
| + if (dx * dx + dy * dy > touch_slop_square_)
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| } // namespace ui
|
|
|