diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 06:06:55 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-30 06:06:55 +0000 |
commit | 8181ed6224a80c643568dea0b00f0dbdd0219118 (patch) | |
tree | 3ee446154e871cd0df6ff9c4522865baadcb0d7b /ui/base | |
parent | 3b49fd028d3bb657eafe3bcd7a461cbba8c9c198 (diff) | |
download | chromium_src-8181ed6224a80c643568dea0b00f0dbdd0219118.zip chromium_src-8181ed6224a80c643568dea0b00f0dbdd0219118.tar.gz chromium_src-8181ed6224a80c643568dea0b00f0dbdd0219118.tar.bz2 |
Revert 139398 - 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
TBR=sadrul@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10449065
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139473 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/events.h | 5 | ||||
-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 |
5 files changed, 180 insertions, 246 deletions
diff --git a/ui/base/events.h b/ui/base/events.h index 6c9f271..e779dbf 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -53,15 +53,12 @@ enum EventType { ET_GESTURE_SCROLL_UPDATE, ET_GESTURE_TAP, ET_GESTURE_TAP_DOWN, - ET_GESTURE_TAP_UP, ET_GESTURE_DOUBLE_TAP, ET_GESTURE_PINCH_BEGIN, ET_GESTURE_PINCH_END, ET_GESTURE_PINCH_UPDATE, ET_GESTURE_LONG_PRESS, - // A SWIPE gesture can happen at the end of a TAP_UP gesture if the - // finger(s) were moving quickly before they are released. - ET_GESTURE_MULTIFINGER_SWIPE, + ET_GESTURE_THREE_FINGER_SWIPE, // Scroll support. // TODO[davemoore] we need to unify these events w/ touch and gestures. diff --git a/ui/base/gestures/gesture_point.cc b/ui/base/gestures/gesture_point.cc index d75250a..6b7dbf1 100644 --- a/ui/base/gestures/gesture_point.cc +++ b/ui/base/gestures/gesture_point.cc @@ -99,6 +99,12 @@ 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 19a8a3c..871427b 100644 --- a/ui/base/gestures/gesture_point.h +++ b/ui/base/gestures/gesture_point.h @@ -55,8 +55,6 @@ 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 @@ -83,6 +81,8 @@ 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 5e74aff..02d4b4e 100644 --- a/ui/base/gestures/gesture_sequence.cc +++ b/ui/base/gestures/gesture_sequence.cc @@ -109,38 +109,32 @@ enum EdgeStateSignatureType { GST_PINCH_THIRD_PRESSED = G(GS_PINCH, 2, TS_PRESSED, false), - GST_PINCH_THIRD_MOVED = - G(GS_PINCH, 2, TS_MOVED, false), + GST_THREE_FINGER_SWIPE_FIRST_RELEASED = + G(GS_THREE_FINGER_SWIPE, 0, TS_RELEASED, false), - GST_PINCH_THIRD_RELEASED = - G(GS_PINCH, 2, TS_RELEASED, false), + GST_THREE_FINGER_SWIPE_SECOND_RELEASED = + G(GS_THREE_FINGER_SWIPE, 1, TS_RELEASED, false), - GST_PINCH_THIRD_CANCELLED = - G(GS_PINCH, 2, TS_CANCELLED, false), + GST_THREE_FINGER_SWIPE_THIRD_RELEASED = + G(GS_THREE_FINGER_SWIPE, 2, TS_RELEASED, false), - GST_PINCH_FOURTH_PRESSED = - G(GS_PINCH, 3, TS_PRESSED, false), + GST_THREE_FINGER_SWIPE_FIRST_MOVED = + G(GS_THREE_FINGER_SWIPE, 0, TS_MOVED, false), - GST_PINCH_FOURTH_MOVED = - G(GS_PINCH, 3, TS_MOVED, false), + GST_THREE_FINGER_SWIPE_SECOND_MOVED = + G(GS_THREE_FINGER_SWIPE, 1, TS_MOVED, false), - GST_PINCH_FOURTH_RELEASED = - G(GS_PINCH, 3, TS_RELEASED, false), + GST_THREE_FINGER_SWIPE_THIRD_MOVED = + G(GS_THREE_FINGER_SWIPE, 2, TS_MOVED, false), - GST_PINCH_FOURTH_CANCELLED = - G(GS_PINCH, 3, TS_CANCELLED, false), + GST_THREE_FINGER_SWIPE_FIRST_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 0, TS_CANCELLED, false), - GST_PINCH_FIFTH_PRESSED = - G(GS_PINCH, 4, TS_PRESSED, false), + GST_THREE_FINGER_SWIPE_SECOND_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 1, 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), + GST_THREE_FINGER_SWIPE_THIRD_CANCELLED = + G(GS_THREE_FINGER_SWIPE, 2, TS_CANCELLED, false), }; // Builds a signature. Signatures are assembled by joining together @@ -161,21 +155,6 @@ 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 //////////////////////////////////////////////////////////////////////////////// @@ -187,6 +166,7 @@ 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) { @@ -222,7 +202,6 @@ 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) @@ -262,62 +241,54 @@ 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())) { - for (int i = 0; i < point_count_; ++i) - GetPointByPointId(i)->UpdateForScroll(); + GetPointByPointId(0)->UpdateForScroll(); + GetPointByPointId(1)->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: - 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(); + 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); break; case GST_PINCH_THIRD_PRESSED: - 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_; + 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(); + } 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_ @@ -338,16 +309,10 @@ 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_; - } } } @@ -361,33 +326,6 @@ 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: @@ -421,17 +359,7 @@ void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, point.first_touch_position(), flags_, base::Time::FromDoubleT(point.last_touch_time()), - 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())); + 0.f, 0.f, 1 << point.touch_id())); } void GestureSequence::AppendClickGestureEvent(const GesturePoint& point, @@ -508,10 +436,9 @@ void GestureSequence::AppendScrollGestureEnd(const GesturePoint& point, void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, const gfx::Point& location, Gestures* gestures) { - int dx = location.x() - bounding_box_last_center_.x(); - int dy = location.y() - bounding_box_last_center_.y(); - if (dx == 0 && dy == 0) - return; + int dx = point.x_delta(); + int dy = point.y_delta(); + if (scroll_type_ == ST_HORIZONTAL) dy = 0; else if (scroll_type_ == ST_VERTICAL) @@ -522,13 +449,13 @@ void GestureSequence::AppendScrollGestureUpdate(const GesturePoint& point, location, flags_, base::Time::FromDoubleT(point.last_touch_time()), - dx, dy, ComputeTouchBitmask(points_))); + dx, dy, 1 << point.touch_id())); } void GestureSequence::AppendPinchGestureBegin(const GesturePoint& p1, const GesturePoint& p2, Gestures* gestures) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_BEGIN, center, @@ -541,40 +468,52 @@ void GestureSequence::AppendPinchGestureEnd(const GesturePoint& p1, const GesturePoint& p2, float scale, Gestures* gestures) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = p1.last_touch_position().Middle(p2.last_touch_position()); gestures->push_back(helper_->CreateGestureEvent( ui::ET_GESTURE_PINCH_END, center, flags_, base::Time::FromDoubleT(p1.last_touch_time()), - 0.f, 0.f, - 1 << p1.touch_id() | 1 << p2.touch_id())); + scale, 0.f, 1 << p1.touch_id() | 1 << p2.touch_id())); } -void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& point, +void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& p1, + const GesturePoint& p2, 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, - bounding_box_.CenterPoint(), + center, flags_, - 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) { + 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); gestures->push_back(helper_->CreateGestureEvent( - ui::ET_GESTURE_MULTIFINGER_SWIPE, - bounding_box_.CenterPoint(), + ui::ET_GESTURE_THREE_FINGER_SWIPE, + center, flags_, - base::Time::FromDoubleT(point.last_touch_time()), - swipe_x, swipe_y, ComputeTouchBitmask(points_))); + base::Time::FromDoubleT(p1.last_touch_time()), + x_velocity, y_velocity, + 1 << p1.touch_id() | 1 << p2.touch_id() | 1 << p3.touch_id())); } bool GestureSequence::Click(const TouchEvent& event, @@ -678,12 +617,13 @@ bool GestureSequence::PinchStart(const TouchEvent& event, const GesturePoint* point1 = GetPointByPointId(0); const GesturePoint* point2 = GetPointByPointId(1); - pinch_distance_current_ = BoundingBoxDiagonal(bounding_box_); + pinch_distance_current_ = point1->Distance(*point2); pinch_distance_start_ = pinch_distance_current_; AppendPinchGestureBegin(*point1, *point2, gestures); if (state_ == GS_PENDING_SYNTHETIC_CLICK) { - gfx::Point center = bounding_box_.CenterPoint(); + gfx::Point center = point1->last_touch_position().Middle( + point2->last_touch_position()); AppendScrollGestureBegin(point, center, gestures); } @@ -694,18 +634,29 @@ bool GestureSequence::PinchUpdate(const TouchEvent& event, const GesturePoint& point, Gestures* gestures) { DCHECK(state_ == GS_PINCH); - float distance = BoundingBoxDiagonal(bounding_box_); + const GesturePoint* point1 = GetPointByPointId(0); + const GesturePoint* point2 = GetPointByPointId(1); - if (abs(distance - pinch_distance_current_) >= + float distance = point1->Distance(*point2); + if (abs(distance - pinch_distance_current_) < GestureConfiguration::min_pinch_update_distance_in_pixels()) { - AppendPinchGestureUpdate(point, + // 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, distance / pinch_distance_current_, gestures); pinch_distance_current_ = distance; - } else { - gfx::Point center = bounding_box_.CenterPoint(); - AppendScrollGestureUpdate(point, center, gestures); } - return true; } @@ -716,79 +667,70 @@ bool GestureSequence::PinchEnd(const TouchEvent& event, GesturePoint* point1 = GetPointByPointId(0); GesturePoint* point2 = GetPointByPointId(1); - float distance = BoundingBoxDiagonal(bounding_box_); + float distance = point1->Distance(*point2); AppendPinchGestureEnd(*point1, *point2, distance / pinch_distance_start_, gestures); + point1->ResetVelocity(); + point2->ResetVelocity(); + pinch_distance_start_ = 0; pinch_distance_current_ = 0; return true; } -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; - - 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; - - for (++i; i < kMaxGesturePoints; ++i) { - if (!points_[i].in_use()) - continue; - - if (sign_x * points_[i].XVelocity() < 0) - swipe_x = false; +bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, + const GesturePoint& point, Gestures* gestures) { + DCHECK(state_ == GS_THREE_FINGER_SWIPE); - if (sign_y * points_[i].YVelocity() < 0) - swipe_y = false; + GesturePoint* point1 = GetPointByPointId(0); + GesturePoint* point2 = GetPointByPointId(1); + GesturePoint* point3 = GetPointByPointId(2); - velocity_x += points_[i].XVelocity(); - velocity_y += points_[i].YVelocity(); - } + int min_velocity = GestureConfiguration::min_swipe_speed(); - float min_velocity = GestureConfiguration::min_swipe_speed(); - min_velocity *= min_velocity; + float vx1 = point1->XVelocity(); + float vx2 = point2->XVelocity(); + float vx3 = point3->XVelocity(); + float vy1 = point1->YVelocity(); + float vy2 = point2->YVelocity(); + float vy3 = point3->YVelocity(); - 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; + float vx = (vx1 + vx2 + vx3) / 3; + float vy = (vy1 + vy2 + vy3) / 3; - if (!swipe_x && !swipe_y) + // Not moving fast enough + if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) return false; - 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; + // 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 (ratio < GestureConfiguration::max_swipe_deviation_ratio()) return false; - if (velocity_x > velocity_y) - sign_y = 0; - else - sign_x = 0; - - AppendSwipeGesture(point, sign_x, sign_y, gestures); - + 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; return true; } diff --git a/ui/base/gestures/gesture_sequence.h b/ui/base/gestures/gesture_sequence.h index b8a9a02..e8d7aab 100644 --- a/ui/base/gestures/gesture_sequence.h +++ b/ui/base/gestures/gesture_sequence.h @@ -10,7 +10,6 @@ #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; @@ -22,6 +21,7 @@ enum GestureState { GS_PENDING_SYNTHETIC_CLICK, GS_SCROLL, GS_PINCH, + GS_THREE_FINGER_SWIPE }; enum ScrollType { @@ -59,12 +59,6 @@ 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 @@ -75,7 +69,6 @@ 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); @@ -102,13 +95,17 @@ class UI_EXPORT GestureSequence { const GesturePoint& p2, float scale, Gestures* gestures); - void AppendPinchGestureUpdate(const GesturePoint& point, + void AppendPinchGestureUpdate(const GesturePoint& p1, + const GesturePoint& p2, float scale, Gestures* gestures); - void AppendSwipeGesture(const GesturePoint& point, - int swipe_x, - int swipe_y, - Gestures* gestures); + + void AppendThreeFingerSwipeGestureEvent(const GesturePoint& p1, + const GesturePoint& p2, + const GesturePoint& p3, + float x_velocity, + float y_velocity, + Gestures* gestures); void set_state(const GestureState state ) { state_ = state; } @@ -119,11 +116,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); @@ -145,9 +142,9 @@ class UI_EXPORT GestureSequence { bool PinchEnd(const TouchEvent& event, const GesturePoint& point, Gestures* gestures); - bool MaybeSwipe(const TouchEvent& event, - const GesturePoint& point, - Gestures* gestures); + bool ThreeFingerSwipeUpdate(const TouchEvent& event, + const GesturePoint& point, + Gestures* gestures); // Current state of gesture recognizer. GestureState state_; @@ -155,15 +152,6 @@ 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_; @@ -171,6 +159,7 @@ 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]; |