Chromium Code Reviews| Index: ui/base/gestures/gesture_sequence.cc |
| diff --git a/ui/base/gestures/gesture_sequence.cc b/ui/base/gestures/gesture_sequence.cc |
| index 69af3f7516b180d31fe3e5415a5af8c07fb532ef..69538c3cf6eb71adff7c719b3a4e539f192cd341 100644 |
| --- a/ui/base/gestures/gesture_sequence.cc |
| +++ b/ui/base/gestures/gesture_sequence.cc |
| @@ -4,6 +4,8 @@ |
| #include "ui/base/gestures/gesture_sequence.h" |
| +#include <cmath> |
| + |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/time.h" |
| @@ -102,6 +104,36 @@ enum EdgeStateSignatureType { |
| GST_PINCH_SECOND_CANCELLED = |
| G(GS_PINCH, 1, TS_CANCELLED, false), |
| + |
| + 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_THREE_FINGER_SWIPE_SECOND_RELEASED = |
| + G(GS_THREE_FINGER_SWIPE, 1, TS_RELEASED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_THIRD_RELEASED = |
| + G(GS_THREE_FINGER_SWIPE, 2, TS_RELEASED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_FIRST_MOVED = |
| + G(GS_THREE_FINGER_SWIPE, 0, TS_MOVED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_SECOND_MOVED = |
| + G(GS_THREE_FINGER_SWIPE, 1, TS_MOVED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_THIRD_MOVED = |
| + G(GS_THREE_FINGER_SWIPE, 2, TS_MOVED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_FIRST_CANCELLED = |
| + G(GS_THREE_FINGER_SWIPE, 0, TS_CANCELLED, false), |
| + |
| + GST_THREE_FINGER_SWIPE_SECOND_CANCELLED = |
| + G(GS_THREE_FINGER_SWIPE, 1, 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 |
| @@ -227,6 +259,32 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
| scroll_type_ = ST_FREE; |
| set_state(GS_SCROLL); |
| break; |
| + case GST_PINCH_THIRD_PRESSED: |
| + PinchEnd(event, point, gestures.get()); |
| + ScrollEnd(event, point, gestures.get()); |
| + 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: |
| + PinchStart(event, point, gestures.get()); |
| + ScrollStart(event, point, gestures.get()); |
|
sadrul
2012/04/11 19:07:26
Do we want ScrollStart here? It might be better to
tdresser
2012/04/12 13:36:16
It's clearer what's happening if the scroll begin
sadrul
2012/04/13 11:34:20
Since PinchStart already appends scroll-start for
tdresser
2012/04/16 14:09:24
You're right, there's no reason to call pinch/scro
|
| + 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 (state_ != last_state) |
| @@ -409,6 +467,30 @@ void GestureSequence::AppendPinchGestureUpdate(const GesturePoint& p1, |
| 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_THREE_FINGER_SWIPE, |
| + center, |
| + flags_, |
| + 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, |
| const GesturePoint& point, Gestures* gestures) { |
| DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); |
| @@ -423,10 +505,12 @@ bool GestureSequence::Click(const TouchEvent& event, |
| bool GestureSequence::ScrollStart(const TouchEvent& event, |
| GesturePoint& point, Gestures* gestures) { |
| - DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK); |
| - if (point.IsInClickWindow(event) || |
| - !point.IsInScrollWindow(event) || |
| - !point.HasEnoughDataToEstablishRail()) |
| + DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK || |
| + state_ == GS_THREE_FINGER_SWIPE); |
| + if (state_ == GS_PENDING_SYNTHETIC_CLICK && |
| + (point.IsInClickWindow(event) || |
| + !point.IsInScrollWindow(event) || |
| + !point.HasEnoughDataToEstablishRail())) |
| return false; |
| AppendScrollGestureBegin(point, point.first_touch_position(), gestures); |
| if (point.IsInHorizontalRailWindow()) |
| @@ -490,7 +574,7 @@ void GestureSequence::AppendLongPressGestureEvent() { |
| bool GestureSequence::ScrollEnd(const TouchEvent& event, |
| GesturePoint& point, Gestures* gestures) { |
| - DCHECK(state_ == GS_SCROLL); |
| + DCHECK(state_ == GS_SCROLL || state_ == GS_PINCH); |
| if (point.IsInFlickWindow(event)) { |
| AppendScrollGestureEnd(point, point.last_touch_position(), gestures, |
| point.XVelocity(), point.YVelocity()); |
| @@ -504,7 +588,8 @@ bool GestureSequence::ScrollEnd(const TouchEvent& event, |
| bool GestureSequence::PinchStart(const TouchEvent& event, |
| const GesturePoint& point, Gestures* gestures) { |
| DCHECK(state_ == GS_SCROLL || |
| - state_ == GS_PENDING_SYNTHETIC_CLICK); |
| + state_ == GS_PENDING_SYNTHETIC_CLICK || |
| + state_ == GS_THREE_FINGER_SWIPE); |
| AppendTapDownGestureEvent(point, gestures); |
| const GesturePoint* point1 = GetPointByPointId(0); |
| @@ -569,4 +654,59 @@ bool GestureSequence::PinchEnd(const TouchEvent& event, |
| return true; |
| } |
| +bool GestureSequence::ThreeFingerSwipeUpdate(const TouchEvent& event, |
| + const GesturePoint& point, Gestures* gestures) { |
| + DCHECK(state_ == GS_THREE_FINGER_SWIPE); |
| + |
| + GesturePoint* point1 = GetPointByPointId(0); |
| + GesturePoint* point2 = GetPointByPointId(1); |
| + GesturePoint* point3 = GetPointByPointId(2); |
| + |
| + int min_velocity = GestureConfiguration::min_swipe_speed(); |
| + |
| + float vx1 = point1->XVelocity(); |
| + float vx2 = point2->XVelocity(); |
| + float vx3 = point3->XVelocity(); |
| + float vy1 = point1->YVelocity(); |
| + float vy2 = point2->YVelocity(); |
| + float vy3 = point3->YVelocity(); |
| + |
| + float vx = (vx1 + vx2 + vx3) / 3; |
| + float vy = (vy1 + vy2 + vy3) / 3; |
| + |
| + // Not moving fast enough |
| + if (fabs(vx) < min_velocity && fabs(vy) < min_velocity) |
| + 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 (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; |
| + return true; |
| +} |
| + |
| } // namespace ui |