Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Unified Diff: ui/events/gesture_detection/gesture_detector.cc

Issue 2058723003: Slop region check for multi-finger scroll (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/events/gesture_detection/gesture_detector.h ('k') | ui/events/gesture_detection/gesture_listeners.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « ui/events/gesture_detection/gesture_detector.h ('k') | ui/events/gesture_detection/gesture_listeners.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698