Index: ui/aura/gestures/gesture_sequence.cc |
diff --git a/ui/aura/gestures/gesture_sequence.cc b/ui/aura/gestures/gesture_sequence.cc |
index 554cf106a84c532e8557bffe8c673d2b6b1683bc..a31f9ef6aa7aee03e2b528c362628f3b1e561172 100644 |
--- a/ui/aura/gestures/gesture_sequence.cc |
+++ b/ui/aura/gestures/gesture_sequence.cc |
@@ -12,11 +12,6 @@ |
#include "ui/aura/gestures/gesture_configuration.h" |
#include "ui/base/events.h" |
-// TODO(sad): Pinch gestures currently always assume that the first two |
-// touch-points (i.e. at indices 0 and 1) are involved. This may not |
-// always be the case. This needs to be fixed eventually. |
-// http://crbug.com/113144 |
- |
namespace { |
// TODO(girard): Make these configurable in sync with this CL |
@@ -99,18 +94,6 @@ enum EdgeStateSignatureType { |
GST_SCROLL_FIRST_CANCELLED = |
G(GS_SCROLL, 0, TS_CANCELLED, false), |
- GST_SCROLL_FIRST_PRESSED = |
- G(GS_SCROLL, 0, TS_PRESSED, false), |
- |
- GST_SCROLL_SECOND_RELEASED = |
- G(GS_SCROLL, 1, TS_RELEASED, false), |
- |
- GST_SCROLL_SECOND_MOVED = |
- G(GS_SCROLL, 1, TS_MOVED, false), |
- |
- GST_SCROLL_SECOND_CANCELLED = |
- G(GS_SCROLL, 1, TS_CANCELLED, false), |
- |
GST_SCROLL_SECOND_PRESSED = |
G(GS_SCROLL, 1, TS_PRESSED, false), |
@@ -164,9 +147,6 @@ GestureSequence::GestureSequence(RootWindow* root_window) |
long_press_timer_(CreateTimer()), |
point_count_(0), |
root_window_(root_window) { |
- for (int i = 0; i < kMaxGesturePoints; ++i) { |
- points_[i].set_touch_id(i); |
- } |
} |
GestureSequence::~GestureSequence() { |
@@ -185,7 +165,14 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
if (event.type() == ui::ET_TOUCH_PRESSED) { |
if (point_count_ == kMaxGesturePoints) |
return NULL; |
- ++point_count_; |
+ GesturePoint* new_point = &points_[event.touch_id()]; |
+ // Eventually, we shouldn't be able to get two PRESSED events without either |
+ // a RELEASE or CANCEL. Currently if a RELEASE is preventDefaulted, |
+ // this could occur: crbug.com/116537 |
+ // TODO(tdresser): Enable this DCHECK, and remove the following condition |
+ // DCHECK(!points_[event.touch_id()].in_use()); |
+ if (!points_[event.touch_id()].in_use()) |
+ new_point->set_point_id(point_count_++); |
} |
GestureState last_state = state_; |
@@ -195,7 +182,10 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
GesturePoint& point = GesturePointForEvent(event); |
point.UpdateValues(event); |
flags_ = event.flags(); |
- switch (Signature(state_, event.touch_id(), event.type(), false)) { |
+ const int point_id = points_[event.touch_id()].point_id(); |
+ if (point_id < 0) |
+ return NULL; |
+ switch (Signature(state_, point_id, event.type(), false)) { |
case GST_NO_GESTURE_FIRST_PRESSED: |
TouchDown(event, point, gestures.get()); |
set_state(GS_PENDING_SYNTHETIC_CLICK); |
@@ -217,7 +207,6 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
NoGesture(event, point, gestures.get()); |
break; |
case GST_SCROLL_FIRST_MOVED: |
- case GST_SCROLL_SECOND_MOVED: |
if (scroll_type_ == ST_VERTICAL || |
scroll_type_ == ST_HORIZONTAL) |
BreakRailScroll(event, point, gestures.get()); |
@@ -226,12 +215,9 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
break; |
case GST_SCROLL_FIRST_RELEASED: |
case GST_SCROLL_FIRST_CANCELLED: |
- case GST_SCROLL_SECOND_RELEASED: |
- case GST_SCROLL_SECOND_CANCELLED: |
ScrollEnd(event, point, gestures.get()); |
set_state(GS_NO_GESTURE); |
break; |
- case GST_SCROLL_FIRST_PRESSED: |
case GST_SCROLL_SECOND_PRESSED: |
case GST_PENDING_SYNTHETIC_CLICK_SECOND_PRESSED: |
PinchStart(event, point, gestures.get()); |
@@ -240,8 +226,8 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
case GST_PINCH_FIRST_MOVED: |
case GST_PINCH_SECOND_MOVED: |
if (PinchUpdate(event, point, gestures.get())) { |
- points_[0].UpdateForScroll(); |
- points_[1].UpdateForScroll(); |
+ GetPointByPointId(0)->UpdateForScroll(); |
+ GetPointByPointId(1)->UpdateForScroll(); |
} |
break; |
case GST_PINCH_FIRST_RELEASED: |
@@ -265,15 +251,27 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture( |
if (last_state == GS_PENDING_SYNTHETIC_CLICK && state_ != last_state) |
long_press_timer_->Stop(); |
- if (event.type() == ui::ET_TOUCH_RELEASED) |
+ // The set of point_ids must be contiguous and include 0. |
+ // When a touch point is released, all points with ids greater than the |
+ // released point must have their ids decremented, or the set of point_ids |
+ // could end up with gaps. |
+ if (event.type() == ui::ET_TOUCH_RELEASED) { |
+ GesturePoint& old_point = points_[event.touch_id()]; |
+ for (int i = 0; i < kMaxGesturePoints; ++i) { |
+ GesturePoint& point = points_[i]; |
+ if (point.point_id() > old_point.point_id()) |
+ point.set_point_id(point.point_id() - 1); |
+ } |
+ old_point.Reset(); |
--point_count_; |
+ } |
return gestures.release(); |
} |
void GestureSequence::Reset() { |
set_state(GS_NO_GESTURE); |
- for (int i = 0; i < point_count_; ++i) |
+ for (int i = 0; i < kMaxGesturePoints; ++i) |
points_[i].Reset(); |
} |
@@ -292,6 +290,17 @@ GesturePoint& GestureSequence::GesturePointForEvent( |
return points_[event.touch_id()]; |
} |
+GesturePoint* GestureSequence::GetPointByPointId(int point_id) { |
+ DCHECK(0 <= point_id && point_id < kMaxGesturePoints); |
+ for (int i = 0; i < kMaxGesturePoints; ++i) { |
+ GesturePoint& point = points_[i]; |
+ if (point.in_use() && point.point_id() == point_id) |
+ return &point; |
+ } |
+ NOTREACHED(); |
+ return NULL; |
+} |
+ |
void GestureSequence::AppendTapDownGestureEvent(const GesturePoint& point, |
Gestures* gestures) { |
gestures->push_back(linked_ptr<GestureEvent>(new GestureEvent( |
@@ -482,16 +491,14 @@ bool GestureSequence::TouchDown(const TouchEvent& event, |
} |
void GestureSequence::AppendLongPressGestureEvent() { |
- // TODO(tdresser) - this may not always be the first point |
- const GesturePoint& point = points_[0]; |
+ const GesturePoint* point = GetPointByPointId(0); |
GestureEvent* gesture = new GestureEvent( |
ui::ET_GESTURE_LONG_PRESS, |
- point.first_touch_position().x(), |
- point.first_touch_position().y(), |
+ point->first_touch_position().x(), |
+ point->first_touch_position().y(), |
flags_, |
- base::Time::FromDoubleT(point.last_touch_time()), |
- point.touch_id(), 0.f); |
- |
+ base::Time::FromDoubleT(point->last_touch_time()), |
+ point->point_id(), 0.f); |
root_window_->DispatchGestureEvent(gesture); |
} |
@@ -514,13 +521,16 @@ bool GestureSequence::PinchStart(const TouchEvent& event, |
state_ == GS_PENDING_SYNTHETIC_CLICK); |
AppendTapDownGestureEvent(point, gestures); |
- pinch_distance_current_ = points_[0].Distance(points_[1]); |
+ const GesturePoint* point1 = GetPointByPointId(0); |
+ const GesturePoint* point2 = GetPointByPointId(1); |
+ |
+ pinch_distance_current_ = point1->Distance(*point2); |
pinch_distance_start_ = pinch_distance_current_; |
- AppendPinchGestureBegin(points_[0], points_[1], gestures); |
+ AppendPinchGestureBegin(*point1, *point2, gestures); |
if (state_ == GS_PENDING_SYNTHETIC_CLICK) { |
- gfx::Point center = points_[0].last_touch_position().Middle( |
- points_[1].last_touch_position()); |
+ gfx::Point center = point1->last_touch_position().Middle( |
+ point2->last_touch_position()); |
AppendScrollGestureBegin(point, center, gestures); |
} |
@@ -530,23 +540,27 @@ bool GestureSequence::PinchStart(const TouchEvent& event, |
bool GestureSequence::PinchUpdate(const TouchEvent& event, |
const GesturePoint& point, Gestures* gestures) { |
DCHECK(state_ == GS_PINCH); |
- float distance = points_[0].Distance(points_[1]); |
+ |
+ const GesturePoint* point1 = GetPointByPointId(0); |
+ const GesturePoint* point2 = GetPointByPointId(1); |
+ |
+ float distance = point1->Distance(*point2); |
if (abs(distance - pinch_distance_current_) < |
GestureConfiguration::minimum_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 (!points_[0].DidScroll(event, |
+ if (!point1->DidScroll(event, |
GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels()) || |
- !points_[1].DidScroll(event, |
+ !point2->DidScroll(event, |
GestureConfiguration::minimum_distance_for_pinch_scroll_in_pixels())) |
return false; |
- gfx::Point center = points_[0].last_touch_position().Middle( |
- points_[1].last_touch_position()); |
+ gfx::Point center = point1->last_touch_position().Middle( |
+ point2->last_touch_position()); |
AppendScrollGestureUpdate(point, center, gestures); |
} else { |
- AppendPinchGestureUpdate(points_[0], points_[1], |
+ AppendPinchGestureUpdate(*point1, *point2, |
distance / pinch_distance_current_, gestures); |
pinch_distance_current_ = distance; |
} |
@@ -556,8 +570,12 @@ bool GestureSequence::PinchUpdate(const TouchEvent& event, |
bool GestureSequence::PinchEnd(const TouchEvent& event, |
const GesturePoint& point, Gestures* gestures) { |
DCHECK(state_ == GS_PINCH); |
- float distance = points_[0].Distance(points_[1]); |
- AppendPinchGestureEnd(points_[0], points_[1], |
+ |
+ const GesturePoint* point1 = GetPointByPointId(0); |
+ const GesturePoint* point2 = GetPointByPointId(1); |
+ |
+ float distance = point1->Distance(*point2); |
+ AppendPinchGestureEnd(*point1, *point2, |
distance / pinch_distance_start_, gestures); |
pinch_distance_start_ = 0; |