summaryrefslogtreecommitdiffstats
path: root/ui/base/gestures
diff options
context:
space:
mode:
authorsadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-29 22:30:28 +0000
committersadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-29 22:30:28 +0000
commita379267ce19c2ae99da17e7d66c6892dbd01a2d2 (patch)
tree55095f7a3e7fb3404b6a4a926c4a0b414fe82741 /ui/base/gestures
parent60c26791b6f749a2292367e33e66922b7a049f2e (diff)
downloadchromium_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.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
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];