summaryrefslogtreecommitdiffstats
path: root/ui/base
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 06:06:55 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 06:06:55 +0000
commit8181ed6224a80c643568dea0b00f0dbdd0219118 (patch)
tree3ee446154e871cd0df6ff9c4522865baadcb0d7b /ui/base
parent3b49fd028d3bb657eafe3bcd7a461cbba8c9c198 (diff)
downloadchromium_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.h5
-rw-r--r--ui/base/gestures/gesture_point.cc6
-rw-r--r--ui/base/gestures/gesture_point.h4
-rw-r--r--ui/base/gestures/gesture_sequence.cc364
-rw-r--r--ui/base/gestures/gesture_sequence.h47
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];