diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-29 22:30:28 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-29 22:30:28 +0000 |
commit | a379267ce19c2ae99da17e7d66c6892dbd01a2d2 (patch) | |
tree | 55095f7a3e7fb3404b6a4a926c4a0b414fe82741 /ui/base/gestures | |
parent | 60c26791b6f749a2292367e33e66922b7a049f2e (diff) | |
download | chromium_src-a379267ce19c2ae99da17e7d66c6892dbd01a2d2.zip chromium_src-a379267ce19c2ae99da17e7d66c6892dbd01a2d2.tar.gz chromium_src-a379267ce19c2ae99da17e7d66c6892dbd01a2d2.tar.bz2 |
gesture recognizer: Allow multi-finger pinch/scroll gestures.
Instead of having specific X-finger gestures (e.g. three-finger swipe,
two-finger pinch), add support for gestures with a variable number of fingers
(e.g. two-finger pinch and three-finger pinch etc.)
BUG=121140
TEST=none
Review URL: https://chromiumcodereview.appspot.com/10137010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139398 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base/gestures')
-rw-r--r-- | ui/base/gestures/gesture_point.cc | 6 | ||||
-rw-r--r-- | ui/base/gestures/gesture_point.h | 4 | ||||
-rw-r--r-- | ui/base/gestures/gesture_sequence.cc | 364 | ||||
-rw-r--r-- | ui/base/gestures/gesture_sequence.h | 47 |
4 files changed, 242 insertions, 179 deletions
diff --git a/ui/base/gestures/gesture_point.cc b/ui/base/gestures/gesture_point.cc index 6b7dbf1..d75250a 100644 --- a/ui/base/gestures/gesture_point.cc +++ b/ui/base/gestures/gesture_point.cc @@ -99,12 +99,6 @@ bool GesturePoint::DidScroll(const TouchEvent& event, int dist) const { abs(last_touch_position_.y() - first_touch_position_.y()) > dist; } -float GesturePoint::Distance(const GesturePoint& point) const { - float x_diff = point.last_touch_position_.x() - last_touch_position_.x(); - float y_diff = point.last_touch_position_.y() - last_touch_position_.y(); - return sqrt(x_diff * x_diff + y_diff * y_diff); -} - bool GesturePoint::HasEnoughDataToEstablishRail() const { int dx = x_delta(); int dy = y_delta(); diff --git a/ui/base/gestures/gesture_point.h b/ui/base/gestures/gesture_point.h index 871427b..19a8a3c 100644 --- a/ui/base/gestures/gesture_point.h +++ b/ui/base/gestures/gesture_point.h @@ -55,6 +55,8 @@ class GesturePoint { double last_touch_time() const { return last_touch_time_; } const gfx::Point& last_touch_position() const { return last_touch_position_; } + int x() const { return last_touch_position_.x(); } + int y() const { return last_touch_position_.y(); } // point_id_ is used to drive GestureSequence::ProcessTouchEventForGesture. // point_ids are maintained such that the set of point_ids is always @@ -81,8 +83,6 @@ class GesturePoint { float XVelocity() { return velocity_calculator_.XVelocity(); } float YVelocity() { return velocity_calculator_.YVelocity(); } - float Distance(const GesturePoint& point) const; - const gfx::Rect& enclosing_rectangle() const { return enclosing_rect_; } private: diff --git a/ui/base/gestures/gesture_sequence.cc b/ui/base/gestures/gesture_sequence.cc index 02d4b4e..5e74aff 100644 --- a/ui/base/gestures/gesture_sequence.cc +++ b/ui/base/gestures/gesture_sequence.cc @@ -109,32 +109,38 @@ enum EdgeStateSignatureType { GST_PINCH_THIRD_PRESSED = G(GS_PINCH, 2, TS_PRESSED, false), - GST_THREE_FINGER_SWIPE_FIRST_RELEASED = - G(GS_THREE_FINGER_SWIPE, 0, TS_RELEASED, false), + GST_PINCH_THIRD_MOVED = + G(GS_PINCH, 2, TS_MOVED, false), - GST_THREE_FINGER_SWIPE_SECOND_RELEASED = - G(GS_THREE_FINGER_SWIPE, 1, TS_RELEASED, false), + GST_PINCH_THIRD_RELEASED = + G(GS_PINCH, 2, TS_RELEASED, false), - GST_THREE_FINGER_SWIPE_THIRD_RELEASED = - G(GS_THREE_FINGER_SWIPE, 2, TS_RELEASED, false), + GST_PINCH_THIRD_CANCELLED = + G(GS_PINCH, 2, TS_CANCELLED, false), - GST_THREE_FINGER_SWIPE_FIRST_MOVED = - G(GS_THREE_FINGER_SWIPE, 0, TS_MOVED, false), + GST_PINCH_FOURTH_PRESSED = + G(GS_PINCH, 3, TS_PRESSED, false), - GST_THREE_FINGER_SWIPE_SECOND_MOVED = - G(GS_THREE_FINGER_SWIPE, 1, TS_MOVED, false), + GST_PINCH_FOURTH_MOVED = + G(GS_PINCH, 3, TS_MOVED, false), - GST_THREE_FINGER_SWIPE_THIRD_MOVED = - G(GS_THREE_FINGER_SWIPE, 2, TS_MOVED, false), + GST_PINCH_FOURTH_RELEASED = + G(GS_PINCH, 3, TS_RELEASED, false), - GST_THREE_FINGER_SWIPE_FIRST_CANCELLED = - G(GS_THREE_FINGER_SWIPE, 0, TS_CANCELLED, false), + GST_PINCH_FOURTH_CANCELLED = + G(GS_PINCH, 3, TS_CANCELLED, false), - GST_THREE_FINGER_SWIPE_SECOND_CANCELLED = - G(GS_THREE_FINGER_SWIPE, 1, TS_CANCELLED, false), + GST_PINCH_FIFTH_PRESSED = + G(GS_PINCH, 4, TS_PRESSED, false), - GST_THREE_FINGER_SWIPE_THIRD_CANCELLED = - G(GS_THREE_FINGER_SWIPE, 2, TS_CANCELLED, false), + GST_PINCH_FIFTH_MOVED = + G(GS_PINCH, 4, TS_MOVED, false), + + GST_PINCH_FIFTH_RELEASED = + G(GS_PINCH, 4, TS_RELEASED, false), + + GST_PINCH_FIFTH_CANCELLED = + G(GS_PINCH, 4, TS_CANCELLED, false), }; // Builds a signature. Signatures are assembled by joining together @@ -155,6 +161,21 @@ EdgeStateSignatureType Signature(GestureState gesture_state, } #undef G +float BoundingBoxDiagonal(const gfx::Rect& rect) { + float width = rect.width() * rect.width(); + float height = rect.height() * rect.height(); + return sqrt(width + height); +} + +unsigned int ComputeTouchBitmask(const GesturePoint* points) { + unsigned int touch_bitmask = 0; + for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) { + if (points[i].in_use()) + touch_bitmask |= 1 << points[i].touch_id(); + } + return touch_bitmask; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -166,7 +187,6 @@ GestureSequence::GestureSequence(GestureEventHelper* helper) pinch_distance_start_(0.f), pinch_distance_current_(0.f), scroll_type_(ST_FREE), - three_finger_swipe_has_fired_(false), long_press_timer_(CreateTimer()), point_count_(0), helper_(helper) { @@ -202,6 +222,7 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( scoped_ptr<Gestures> gestures(new Gestures()); GesturePoint& point = GesturePointForEvent(event); point.UpdateValues(event); + RecreateBoundingBox(); flags_ = event.GetEventFlags(); const int point_id = points_[event.GetTouchId()].point_id(); if (point_id < 0) @@ -241,54 +262,62 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( break; case GST_SCROLL_SECOND_PRESSED: case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: + // Once pinch starts, we immediately break rail scroll. + scroll_type_ = ST_FREE; PinchStart(event, point, gestures.get()); set_state(GS_PINCH); break; case GST_PINCH_FIRST_MOVED: case GST_PINCH_SECOND_MOVED: + case GST_PINCH_THIRD_MOVED: + case GST_PINCH_FOURTH_MOVED: + case GST_PINCH_FIFTH_MOVED: if (PinchUpdate(event, point, gestures.get())) { - GetPointByPointId(0)->UpdateForScroll(); - GetPointByPointId(1)->UpdateForScroll(); + for (int i = 0; i < point_count_; ++i) + GetPointByPointId(i)->UpdateForScroll(); } break; case GST_PINCH_FIRST_RELEASED: case GST_PINCH_SECOND_RELEASED: + case GST_PINCH_THIRD_RELEASED: + case GST_PINCH_FOURTH_RELEASED: + case GST_PINCH_FIFTH_RELEASED: case GST_PINCH_FIRST_CANCELLED: case GST_PINCH_SECOND_CANCELLED: - PinchEnd(event, point, gestures.get()); - - // Once pinch ends, it should still be possible to scroll with the - // remaining finger on the screen. - scroll_type_ = ST_FREE; - set_state(GS_SCROLL); + case GST_PINCH_THIRD_CANCELLED: + case GST_PINCH_FOURTH_CANCELLED: + case GST_PINCH_FIFTH_CANCELLED: + if (point_count_ == 2) { + PinchEnd(event, point, gestures.get()); + + // Once pinch ends, it should still be possible to scroll with the + // remaining finger on the screen. + set_state(GS_SCROLL); + } else { + // Was it a swipe? i.e. were all the fingers moving in the same + // direction? + MaybeSwipe(event, point, gestures.get()); + + // Nothing else to do if we have more than 2 fingers active, since after + // the release/cancel, there are still enough fingers to do pinch. + // pinch_distance_current_ and pinch_distance_start_ will be updated + // when the bounding-box is updated. + } + ResetVelocities(); break; case GST_PINCH_THIRD_PRESSED: - three_finger_swipe_has_fired_ = false; - set_state(GS_THREE_FINGER_SWIPE); - break; - case GST_THREE_FINGER_SWIPE_FIRST_RELEASED: - case GST_THREE_FINGER_SWIPE_SECOND_RELEASED: - case GST_THREE_FINGER_SWIPE_THIRD_RELEASED: - case GST_THREE_FINGER_SWIPE_FIRST_CANCELLED: - case GST_THREE_FINGER_SWIPE_SECOND_CANCELLED: - case GST_THREE_FINGER_SWIPE_THIRD_CANCELLED: - GetPointByPointId(0)->ResetVelocity(); - GetPointByPointId(1)->ResetVelocity(); - GetPointByPointId(2)->ResetVelocity(); - set_state(GS_PINCH); - break; - case GST_THREE_FINGER_SWIPE_FIRST_MOVED: - case GST_THREE_FINGER_SWIPE_SECOND_MOVED: - case GST_THREE_FINGER_SWIPE_THIRD_MOVED: - if (!three_finger_swipe_has_fired_) { - ThreeFingerSwipeUpdate(event, point, gestures.get()); - GetPointByPointId(0)->UpdateForScroll(); - GetPointByPointId(1)->UpdateForScroll(); - GetPointByPointId(2)->UpdateForScroll(); - } + case GST_PINCH_FOURTH_PRESSED: + case GST_PINCH_FIFTH_PRESSED: + AppendTapDownGestureEvent(point, gestures.get()); + pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); + pinch_distance_start_ = pinch_distance_current_; break; } + if (event.GetEventType() == ui::ET_TOUCH_RELEASED || + event.GetEventType() == ui::ET_TOUCH_CANCELLED) + AppendTapUpGestureEvent(point, gestures.get()); + if (state_ != last_state) DVLOG(4) << "Gesture Sequence" << " State: " << state_ @@ -309,10 +338,16 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( if (point.point_id() > old_point.point_id()) point.set_point_id(point.point_id() - 1); } + if (old_point.in_use()) { old_point.Reset(); --point_count_; DCHECK_GE(point_count_, 0); + RecreateBoundingBox(); + if (state_ == GS_PINCH) { + pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); + pinch_distance_start_ = pinch_distance_current_; + } } } @@ -326,6 +361,33 @@ void GestureSequence::Reset() { point_count_ = 0; } +void GestureSequence::RecreateBoundingBox() { + // TODO(sad): Recreating the bounding box at every touch-event is not very + // efficient. This should be made better. + int left = INT_MAX, top = INT_MAX, right = INT_MIN, bottom = INT_MIN; + for (int i = 0; i < kMaxGesturePoints; ++i) { + if (!points_[i].in_use()) + continue; + if (left > points_[i].x()) + left = points_[i].x(); + if (right < points_[i].x()) + right = points_[i].x(); + if (top > points_[i].y()) + top = points_[i].y(); + if (bottom < points_[i].y()) + bottom = points_[i].y(); + } + bounding_box_last_center_ = bounding_box_.CenterPoint(); + bounding_box_.SetRect(left, top, right - left, bottom - top); +} + +void GestureSequence::ResetVelocities() { + for (int i = 0; i < kMaxGesturePoints; ++i) { + if (points_[i].in_use()) + points_[i].ResetVelocity(); + } +} + //////////////////////////////////////////////////////////////////////////////// // GestureSequence Protected: @@ -359,7 +421,17 @@ void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, point.first_touch_position(), flags_, base::Time::FromDoubleT(point.last_touch_time()), - 0.f, 0.f, 1 << point.touch_id())); + point_count_, 0.f, 1 << point.touch_id())); +} + +void GestureSequence::AppendTapUpGestureEvent(const GesturePoint& point, + Gestures* gestures) { + gestures->push_back(helper_->CreateGestureEvent( + ui::ET_GESTURE_TAP_UP, + point.first_touch_position(), + flags_, + base::Time::FromDoubleT(point.last_touch_time()), + point_count_, 0.f, 1 << point.touch_id())); } void GestureSequence::AppendClickGestureEvent(const GesturePoint& point, @@ -436,9 +508,10 @@ void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point, void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, const gfx::Point& location, Gestures* gestures) { - int dx = point.x_delta(); - int dy = point.y_delta(); - + int dx = location.x() - bounding_box_last_center_.x(); + int dy = location.y() - bounding_box_last_center_.y(); + if (dx == 0 && dy == 0) + return; if (scroll_type_ == ST_HORIZONTAL) dy = 0; else if (scroll_type_ == ST_VERTICAL) @@ -449,13 +522,13 @@ void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, location, flags_, base::Time::FromDoubleT(point.last_touch_time()), - dx, dy, 1 << point.touch_id())); + dx, dy, ComputeTouchBitmask(points_))); } void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1, const GesturePoint& p2, Gestures* gestures) { - gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); + gfx::Point center = bounding_box_.CenterPoint(); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_BEGIN, center, @@ -468,52 +541,40 @@ void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1, const GesturePoint& p2, float scale, Gestures* gestures) { - gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); + gfx::Point center = bounding_box_.CenterPoint(); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_END, center, flags_, base::Time::FromDoubleT(p1.last_touch_time()), - scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); + 0.f, 0.f, + 1 << p1.touch_id() | 1 << p2.touch_id())); } -void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& p1, - const GesturePoint& p2, +void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, float scale, Gestures* gestures) { // TODO(sad): Compute rotation and include it in delta_y. // http://crbug.com/113145 - gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_UPDATE, - center, + bounding_box_.CenterPoint(), flags_, - base::Time::FromDoubleT(p1.last_touch_time()), - scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); -} - -void GestureSequence::AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, - const GesturePoint& p2, - const GesturePoint& p3, - float x_velocity, - float y_velocity, - Gestures* gestures) { - int x = ( - p1.last_touch_position().x() + - p2.last_touch_position().x() + - p3.last_touch_position().x()) / 3; - int y = ( - p1.last_touch_position().y() + - p2.last_touch_position().y() + - p3.last_touch_position().y()) / 3; - gfx::Point center(x, y); + base::Time::FromDoubleT(point.last_touch_time()), + scale, 0.f, + ComputeTouchBitmask(points_))); +} + +void GestureSequence::AppendSwipeGesture(const GesturePoint& point, + int swipe_x, + int swipe_y, + Gestures* gestures) { gestures->push_back(helper_->CreateGestureEvent( - ui::ET_GESTURE_THREE_FINGER_SWIPE, - center, + ui::ET_GESTURE_MULTIFINGER_SWIPE, + bounding_box_.CenterPoint(), flags_, - base::Time::FromDoubleT(p1.last_touch_time()), - x_velocity, y_velocity, - 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); + base::Time::FromDoubleT(point.last_touch_time()), + swipe_x, swipe_y, ComputeTouchBitmask(points_))); } bool GestureSequence::Click(const TouchEvent& event, @@ -617,13 +678,12 @@ bool GestureSequence::PinchStart(const TouchEvent& event, const GesturePoint* point1 = GetPointByPointId(0); const GesturePoint* point2 = GetPointByPointId(1); - pinch_distance_current_ = point1->Distance(*point2); + pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); pinch_distance_start_ = pinch_distance_current_; AppendPinchGestureBegin(*point1, *point2, gestures); if (state_ == GS_PENDING_SYNTHETIC_CLICK) { - gfx::Point center = point1->last_touch_position().Middle( - point2->last_touch_position()); + gfx::Point center = bounding_box_.CenterPoint(); AppendScrollGestureBegin(point, center, gestures); } @@ -634,29 +694,18 @@ bool GestureSequence::PinchUpdate(const TouchEvent& event, const GesturePoint& point, Gestures* gestures) { DCHECK(state_ == GS_PINCH); - const GesturePoint* point1 = GetPointByPointId(0); - const GesturePoint* point2 = GetPointByPointId(1); + float distance = BoundingBoxDiagonal(bounding_box_); - float distance = point1->Distance(*point2); - if (abs(distance - pinch_distance_current_) < + if (abs(distance - pinch_distance_current_) >= GestureConfiguration::min_pinch_update_distance_in_pixels()) { - // The fingers didn't move towards each other, or away from each other, - // enough to constitute a pinch. But perhaps they moved enough in the same - // direction to do a two-finger scroll. - if (!point1->DidScroll(event, - GestureConfiguration::min_distance_for_pinch_scroll_in_pixels()) || - !point2->DidScroll(event, - GestureConfiguration::min_distance_for_pinch_scroll_in_pixels())) - return false; - - gfx::Point center = point1->last_touch_position().Middle( - point2->last_touch_position()); - AppendScrollGestureUpdate(point, center, gestures); - } else { - AppendPinchGestureUpdate(*point1, *point2, + AppendPinchGestureUpdate(point, distance / pinch_distance_current_, gestures); pinch_distance_current_ = distance; + } else { + gfx::Point center = bounding_box_.CenterPoint(); + AppendScrollGestureUpdate(point, center, gestures); } + return true; } @@ -667,70 +716,79 @@ bool GestureSequence::PinchEnd(const TouchEvent& event, GesturePoint* point1 = GetPointByPointId(0); GesturePoint* point2 = GetPointByPointId(1); - float distance = point1->Distance(*point2); + float distance = BoundingBoxDiagonal(bounding_box_); AppendPinchGestureEnd(*point1, *point2, distance / pinch_distance_start_, gestures); - point1->ResetVelocity(); - point2->ResetVelocity(); - pinch_distance_start_ = 0; pinch_distance_current_ = 0; return true; } -bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, - const GesturePoint& point, Gestures* gestures) { - DCHECK(state_ == GS_THREE_FINGER_SWIPE); +bool GestureSequence::MaybeSwipe(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures) { + DCHECK(state_ == GS_PINCH); + float velocity_x = 0.f, velocity_y = 0.f; + bool swipe_x = true, swipe_y = true; + int sign_x = 0, sign_y = 0; + int i = 0; - GesturePoint* point1 = GetPointByPointId(0); - GesturePoint* point2 = GetPointByPointId(1); - GesturePoint* point3 = GetPointByPointId(2); + for (i = 0; i < kMaxGesturePoints; ++i) { + if (points_[i].in_use()) + break; + } + DCHECK(i < kMaxGesturePoints); + + velocity_x = points_[i].XVelocity(); + velocity_y = points_[i].YVelocity(); + sign_x = velocity_x < 0 ? -1 : 1; + sign_y = velocity_y < 0 ? -1 : 1; - int min_velocity = GestureConfiguration::min_swipe_speed(); + for (++i; i < kMaxGesturePoints; ++i) { + if (!points_[i].in_use()) + continue; - float vx1 = point1->XVelocity(); - float vx2 = point2->XVelocity(); - float vx3 = point3->XVelocity(); - float vy1 = point1->YVelocity(); - float vy2 = point2->YVelocity(); - float vy3 = point3->YVelocity(); + if (sign_x * points_[i].XVelocity() < 0) + swipe_x = false; - float vx = (vx1 + vx2 + vx3) / 3; - float vy = (vy1 + vy2 + vy3) / 3; + if (sign_y * points_[i].YVelocity() < 0) + swipe_y = false; + + velocity_x += points_[i].XVelocity(); + velocity_y += points_[i].YVelocity(); + } - // Not moving fast enough - if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) + float min_velocity = GestureConfiguration::min_swipe_speed(); + min_velocity *= min_velocity; + + velocity_x = fabs(velocity_x / point_count_); + velocity_y = fabs(velocity_y / point_count_); + if (velocity_x < min_velocity) + swipe_x = false; + if (velocity_y < min_velocity) + swipe_y = false; + + if (!swipe_x && !swipe_y) return false; - // Diagonal swipe, no event fired - // TODO(tdresser|sadrul): consider adding diagonal swipes - float ratio = fabs(vx) > fabs(vy) ? fabs(vx / vy) : fabs(vy / vx); + if (!swipe_x) + velocity_x = 0.001f; + if (!swipe_y) + velocity_y = 0.001f; + + float ratio = velocity_x > velocity_y ? velocity_x / velocity_y : + velocity_y / velocity_x; if (ratio < GestureConfiguration::max_swipe_deviation_ratio()) return false; - if (fabs(vx) > fabs(vy)) { - int sign = vx > 0 ? 1 : -1; - // ensure all touches are moving in the same direction, and are - // all moving faster than min_velocity. - if (vx1 * sign < min_velocity || - vx2 * sign < min_velocity || - vx3 * sign < min_velocity) - return false; - AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, - sign, 0, gestures); - } else { - int sign = vy > 0 ? 1 : -1; - // ensure all touches are moving in the same direction, and are - // all moving faster than min_velocity. - if (vy1 * sign < min_velocity || - vy2 * sign < min_velocity || - vy3 * sign < min_velocity) - return false; - AppendThreeFingerSwipeGestureEvent(*point1, *point2, *point3, - 0, sign, gestures); - } - three_finger_swipe_has_fired_ = true; + if (velocity_x > velocity_y) + sign_y = 0; + else + sign_x = 0; + + AppendSwipeGesture(point, sign_x, sign_y, gestures); + return true; } diff --git a/ui/base/gestures/gesture_sequence.h b/ui/base/gestures/gesture_sequence.h index e8d7aab..b8a9a02 100644 --- a/ui/base/gestures/gesture_sequence.h +++ b/ui/base/gestures/gesture_sequence.h @@ -10,6 +10,7 @@ #include "ui/base/events.h" #include "ui/base/gestures/gesture_point.h" #include "ui/base/gestures/gesture_recognizer.h" +#include "ui/gfx/rect.h" namespace ui { class TouchEvent; @@ -21,7 +22,6 @@ enum GestureState { GS_PENDING_SYNTHETIC_CLICK, GS_SCROLL, GS_PINCH, - GS_THREE_FINGER_SWIPE }; enum ScrollType { @@ -59,6 +59,12 @@ class UI_EXPORT GestureSequence { private: void Reset(); + // Recreates the axis-aligned bounding box that contains all the touch-points + // at their most recent position. + void RecreateBoundingBox(); + + void ResetVelocities(); + GesturePoint& GesturePointForEvent(const TouchEvent& event); // Do a linear scan through points_ to find the GesturePoint @@ -69,6 +75,7 @@ class UI_EXPORT GestureSequence { // Tap gestures. void AppendTapDownGestureEvent(const GesturePoint& point, Gestures* gestures); + void AppendTapUpGestureEvent(const GesturePoint& point, Gestures* gestures); void AppendClickGestureEvent(const GesturePoint& point, Gestures* gestures); void AppendDoubleClickGestureEvent(const GesturePoint& point, Gestures* gestures); @@ -95,17 +102,13 @@ class UI_EXPORT GestureSequence { const GesturePoint& p2, float scale, Gestures* gestures); - void AppendPinchGestureUpdate(const GesturePoint& p1, - const GesturePoint& p2, + void AppendPinchGestureUpdate(const GesturePoint& point, float scale, Gestures* gestures); - - void AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, - const GesturePoint& p2, - const GesturePoint& p3, - float x_velocity, - float y_velocity, - Gestures* gestures); + void AppendSwipeGesture(const GesturePoint& point, + int swipe_x, + int swipe_y, + Gestures* gestures); void set_state(const GestureState state ) { state_ = state; } @@ -116,11 +119,11 @@ class UI_EXPORT GestureSequence { const GesturePoint& point, Gestures* gestures); bool ScrollStart(const TouchEvent& event, - GesturePoint& point, - Gestures* gestures); + GesturePoint& point, + Gestures* gestures); void BreakRailScroll(const TouchEvent& event, - GesturePoint& point, - Gestures* gestures); + GesturePoint& point, + Gestures* gestures); bool ScrollUpdate(const TouchEvent& event, const GesturePoint& point, Gestures* gestures); @@ -142,9 +145,9 @@ class UI_EXPORT GestureSequence { bool PinchEnd(const TouchEvent& event, const GesturePoint& point, Gestures* gestures); - bool ThreeFingerSwipeUpdate(const TouchEvent& event, - const GesturePoint& point, - Gestures* gestures); + bool MaybeSwipe(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures); // Current state of gesture recognizer. GestureState state_; @@ -152,6 +155,15 @@ class UI_EXPORT GestureSequence { // ui::EventFlags. int flags_; + // We maintain the smallest axis-aligned rectangle that contains all the + // current touch-points. The 'distance' represents the diagonal distance. + // This box is updated after every touch-event. + gfx::Rect bounding_box_; + gfx::Point bounding_box_last_center_; + + // For pinch, the 'distance' represents the diagonal distance of + // |bounding_box_|. + // The distance between the two points at PINCH_START. float pinch_distance_start_; @@ -159,7 +171,6 @@ class UI_EXPORT GestureSequence { float pinch_distance_current_; ScrollType scroll_type_; - bool three_finger_swipe_has_fired_; scoped_ptr<base::OneShotTimer<GestureSequence> > long_press_timer_; GesturePoint points_[kMaxGesturePoints]; |