Commit 93425b44 authored by tdresser@chromium.org's avatar tdresser@chromium.org

Three Finger Swipe

Implements a three finger swipe gesture event for the aura Gesture Recognizer.

BUG=122807
TEST=SystemGestureEventFilterTest.TapOutsideRootWindow, GestureRecognizerTest.GestureEventThreeFingerSwipe


Review URL: http://codereview.chromium.org/10037012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@132570 0039d316-1c4b-4281-b951-d872f2087c98
parent 1895cda7
......@@ -37,6 +37,8 @@ ui::TouchStatus SystemGestureEventFilter::PreHandleTouchEvent(
ui::GestureStatus SystemGestureEventFilter::PreHandleGestureEvent(
aura::Window* target, aura::GestureEvent* event) {
// TODO(tdresser) handle system level gesture events
if (event->type() == ui::ET_GESTURE_THREE_FINGER_SWIPE)
return ui::GESTURE_STATUS_CONSUMED;
if (target == Shell::GetRootWindow())
return ui::GESTURE_STATUS_CONSUMED;
return ui::GESTURE_STATUS_UNKNOWN;
......@@ -44,4 +46,3 @@ ui::GestureStatus SystemGestureEventFilter::PreHandleGestureEvent(
} // namespace internal
} // namespace ash
......@@ -47,4 +47,31 @@ TEST_F(SystemGestureEventFilterTest, TapOutsideRootWindow) {
EXPECT_FALSE(consumed);
}
// Ensure that a three fingered swipe is consumed by the system event handler.
TEST_F(SystemGestureEventFilterTest, ThreeFingerSwipe) {
aura::RootWindow* root_window = Shell::GetRootWindow();
const int kTouchId = 5;
// Get a target for kTouchId
aura::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(100, 100), kTouchId,
base::Time::NowFromSystemTime() - base::Time());
root_window->DispatchTouchEvent(&press);
aura::GestureEvent* event = new aura::GestureEvent(
ui::ET_GESTURE_THREE_FINGER_SWIPE, 0, 0, 0, base::Time::Now(),
0, 0, 1 << kTouchId);
bool consumed = root_window->DispatchGestureEvent(event);
EXPECT_TRUE(consumed);
// The system event filter shouldn't filter out events like tap downs.
aura::GestureEvent* event2 = new aura::GestureEvent(
ui::ET_GESTURE_TAP_DOWN, 0, 0, 0, base::Time::Now(),
0, 0, 1 << kTouchId);
consumed = root_window->DispatchGestureEvent(event2);
EXPECT_FALSE(consumed);
}
} // namespace ash
......@@ -49,6 +49,7 @@ const char* kPrefsToObserve[] = {
prefs::kLongPressTimeInSeconds,
prefs::kMaxSecondsBetweenDoubleClick,
prefs::kMaxSeparationForGestureTouchesInPixels,
prefs::kMaxSwipeDeviationRatio,
prefs::kMaxTouchDownDurationInSecondsForClick,
prefs::kMaxTouchMoveInPixelsForClick,
prefs::kMinDistanceForPinchScrollInPixels,
......@@ -56,6 +57,7 @@ const char* kPrefsToObserve[] = {
prefs::kMinPinchUpdateDistanceInPixels,
prefs::kMinRailBreakVelocity,
prefs::kMinScrollDeltaSquared,
prefs::kMinSwipeSpeed,
prefs::kMinTouchDownDurationInSecondsForClick,
prefs::kPointsBufferedForVelocity,
prefs::kRailBreakProportion,
......@@ -93,6 +95,9 @@ void GesturePrefsObserver::Update() {
GestureConfiguration::set_max_separation_for_gesture_touches_in_pixels(
prefs_->GetDouble(
prefs::kMaxSeparationForGestureTouchesInPixels));
GestureConfiguration::set_max_swipe_deviation_ratio(
prefs_->GetDouble(
prefs::kMaxSwipeDeviationRatio));
GestureConfiguration::set_max_touch_down_duration_in_seconds_for_click(
prefs_->GetDouble(
prefs::kMaxTouchDownDurationInSecondsForClick));
......@@ -114,6 +119,9 @@ void GesturePrefsObserver::Update() {
GestureConfiguration::set_min_scroll_delta_squared(
prefs_->GetDouble(
prefs::kMinScrollDeltaSquared));
GestureConfiguration::set_min_swipe_speed(
prefs_->GetDouble(
prefs::kMinSwipeSpeed));
GestureConfiguration::set_min_touch_down_duration_in_seconds_for_click(
prefs_->GetDouble(
prefs::kMinTouchDownDurationInSecondsForClick));
......@@ -160,6 +168,10 @@ void GesturePrefsObserverFactoryAura::RegisterUserPrefs(PrefService* prefs) {
prefs::kMaxSeparationForGestureTouchesInPixels,
GestureConfiguration::max_separation_for_gesture_touches_in_pixels(),
PrefService::UNSYNCABLE_PREF);
prefs->RegisterDoublePref(
prefs::kMaxSwipeDeviationRatio,
GestureConfiguration::max_swipe_deviation_ratio(),
PrefService::UNSYNCABLE_PREF);
prefs->RegisterDoublePref(
prefs::kMaxTouchDownDurationInSecondsForClick,
GestureConfiguration::max_touch_down_duration_in_seconds_for_click(),
......@@ -188,6 +200,10 @@ void GesturePrefsObserverFactoryAura::RegisterUserPrefs(PrefService* prefs) {
prefs::kMinScrollDeltaSquared,
GestureConfiguration::min_scroll_delta_squared(),
PrefService::UNSYNCABLE_PREF);
prefs->RegisterDoublePref(
prefs::kMinSwipeSpeed,
GestureConfiguration::min_swipe_speed(),
PrefService::UNSYNCABLE_PREF);
prefs->RegisterDoublePref(
prefs::kMinTouchDownDurationInSecondsForClick,
GestureConfiguration::min_touch_down_duration_in_seconds_for_click(),
......
......@@ -1814,6 +1814,8 @@ const char kMaxSecondsBetweenDoubleClick[] =
"gesture.max_seconds_between_double_click";
const char kMaxSeparationForGestureTouchesInPixels[] =
"gesture.max_separation_for_gesture_touches_in_pixels";
const char kMaxSwipeDeviationRatio[] =
"gesture.max_swipe_deviation_ratio";
const char kMaxTouchDownDurationInSecondsForClick[] =
"gesture.max_touch_down_duration_in_seconds_for_click";
const char kMaxTouchMoveInPixelsForClick[] =
......@@ -1828,6 +1830,8 @@ const char kMinRailBreakVelocity[] =
"gesture.min_rail_break_velocity";
const char kMinScrollDeltaSquared[] =
"gesture.min_scroll_delta_squared";
const char kMinSwipeSpeed[] =
"gesture.min_swipe_speed";
const char kMinTouchDownDurationInSecondsForClick[] =
"gesture.min_touch_down_duration_in_seconds_for_click";
const char kPointsBufferedForVelocity[] =
......
......@@ -677,6 +677,7 @@ extern const char kPinnedLauncherApps[];
extern const char kLongPressTimeInSeconds[];
extern const char kMaxSecondsBetweenDoubleClick[];
extern const char kMaxSeparationForGestureTouchesInPixels[];
extern const char kMaxSwipeDeviationRatio[];
extern const char kMaxTouchDownDurationInSecondsForClick[];
extern const char kMaxTouchMoveInPixelsForClick[];
extern const char kMinDistanceForPinchScrollInPixels[];
......@@ -684,6 +685,7 @@ extern const char kMinFlickSpeedSquared[];
extern const char kMinPinchUpdateDistanceInPixels[];
extern const char kMinRailBreakVelocity[];
extern const char kMinScrollDeltaSquared[];
extern const char kMinSwipeSpeed[];
extern const char kMinTouchDownDurationInSecondsForClick[];
extern const char kPointsBufferedForVelocity[];
extern const char kRailBreakProportion[];
......
......@@ -37,6 +37,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
pinch_update_(false),
pinch_end_(false),
long_press_(false),
three_finger_swipe_(false),
scroll_x_(0),
scroll_y_(0),
velocity_x_(0),
......@@ -56,6 +57,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
pinch_update_ = false;
pinch_end_ = false;
long_press_ = false;
three_finger_swipe_ = false;
scroll_begin_position_.SetPoint(0, 0);
......@@ -75,6 +77,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
bool pinch_update() const { return pinch_update_; }
bool pinch_end() const { return pinch_end_; }
bool long_press() const { return long_press_; }
bool three_finger_swipe() const { return three_finger_swipe_; }
const gfx::Point scroll_begin_position() const {
return scroll_begin_position_;
......@@ -124,6 +127,11 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
long_press_ = true;
touch_id_ = gesture->delta_x();
break;
case ui::ET_GESTURE_THREE_FINGER_SWIPE:
three_finger_swipe_ = true;
velocity_x_ = gesture->delta_x();
velocity_y_ = gesture->delta_y();
break;
default:
NOTREACHED();
}
......@@ -141,6 +149,7 @@ class GestureEventConsumeDelegate : public TestWindowDelegate {
bool pinch_update_;
bool pinch_end_;
bool long_press_;
bool three_finger_swipe_;
gfx::Point scroll_begin_position_;
......@@ -316,7 +325,6 @@ void SendScrollEvents(RootWindow* root_window,
base::TimeDelta time = time_start;
for (int i = 0; i < num_steps; i++) {
delegate->Reset();
x += dx;
y += dy;
time = time + base::TimeDelta::FromMilliseconds(time_step);
......@@ -1485,5 +1493,189 @@ TEST_F(GestureRecognizerTest, NoTapWithPreventDefaultedRelease) {
EXPECT_FALSE(delegate->tap());
}
TEST_F(GestureRecognizerTest, GestureEventThreeFingerSwipe) {
scoped_ptr<GestureEventConsumeDelegate> delegate(
new GestureEventConsumeDelegate());
const int kTouchId1 = 7;
const int kTouchId2 = 2;
const int kTouchId3 = 9;
gfx::Rect bounds(0, 0, 1000, 1000);
scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
delegate.get(), -1234, bounds, NULL));
TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId1, GetTime());
TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId2, GetTime());
TouchEvent press3(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0),
kTouchId3, GetTime());
TouchEvent release1(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0),
kTouchId1, GetTime());
TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0),
kTouchId2, GetTime());
TouchEvent release3(ui::ET_TOUCH_RELEASED, gfx::Point(0, 0),
kTouchId3, GetTime());
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Start by testing all four directions
int kBufferedPoints =
ui::GestureConfiguration::points_buffered_for_velocity();
// Swipe right
SendScrollEvents(root_window(), 1, 1, press1.time_stamp(),
100, 10, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1, press2.time_stamp(),
100, 10, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1, press3.time_stamp(),
100, 10, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_TRUE(delegate->three_finger_swipe());
EXPECT_EQ(1, delegate->velocity_x());
EXPECT_EQ(0, delegate->velocity_y());
root_window()->DispatchTouchEvent(&release1);
root_window()->DispatchTouchEvent(&release2);
root_window()->DispatchTouchEvent(&release3);
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Swipe left
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
-100, 10, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
-100, 10, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
-100, 10, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_TRUE(delegate->three_finger_swipe());
EXPECT_EQ(-1, delegate->velocity_x());
EXPECT_EQ(0, delegate->velocity_y());
root_window()->DispatchTouchEvent(&release1);
root_window()->DispatchTouchEvent(&release2);
root_window()->DispatchTouchEvent(&release3);
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Swipe down
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
10, 100, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
10, 100, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
10, 100, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_TRUE(delegate->three_finger_swipe());
EXPECT_EQ(0, delegate->velocity_x());
EXPECT_EQ(1, delegate->velocity_y());
root_window()->DispatchTouchEvent(&release1);
root_window()->DispatchTouchEvent(&release2);
root_window()->DispatchTouchEvent(&release3);
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Swipe up
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
10, -100, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
10, -100, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
10, -100, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_TRUE(delegate->three_finger_swipe());
EXPECT_EQ(0, delegate->velocity_x());
EXPECT_EQ(-1, delegate->velocity_y());
// Only one swipe can occur per press of three fingers
delegate->Reset();
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
10, -100, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
10, -100, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
10, -100, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_FALSE(delegate->three_finger_swipe());
root_window()->DispatchTouchEvent(&release1);
root_window()->DispatchTouchEvent(&release2);
root_window()->DispatchTouchEvent(&release3);
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Swiping diagonally doesn't fire an event
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
100, -100, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
100, -100, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
100, -100, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_FALSE(delegate->three_finger_swipe());
root_window()->DispatchTouchEvent(&release1);
root_window()->DispatchTouchEvent(&release2);
root_window()->DispatchTouchEvent(&release3);
root_window()->DispatchTouchEvent(&press1);
root_window()->DispatchTouchEvent(&press2);
root_window()->DispatchTouchEvent(&press3);
delegate->Reset();
// Have to swipe in a consistent direction
SendScrollEvents(root_window(), 1, 1,
press1.time_stamp(),
100, 10, kTouchId1, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press2.time_stamp(),
100, 10, kTouchId2, 1, kBufferedPoints, delegate.get());
SendScrollEvents(root_window(), 1, 1,
press3.time_stamp(),
-100, 10, kTouchId3, 1, kBufferedPoints, delegate.get());
EXPECT_FALSE(delegate->three_finger_swipe());
}
} // namespace test
} // namespace aura
......@@ -54,6 +54,7 @@ enum EventType {
ET_GESTURE_PINCH_END,
ET_GESTURE_PINCH_UPDATE,
ET_GESTURE_LONG_PRESS,
ET_GESTURE_THREE_FINGER_SWIPE,
// Scroll support.
// TODO[davemoore] we need to unify these events w/ touch and gestures.
......
......@@ -12,6 +12,7 @@ double GestureConfiguration::long_press_time_in_seconds_ = 0.5;
double GestureConfiguration::max_seconds_between_double_click_ = 0.7;
double
GestureConfiguration::max_separation_for_gesture_touches_in_pixels_ = 150;
double GestureConfiguration::max_swipe_deviation_ratio_ = 3;
double
GestureConfiguration::max_touch_down_duration_in_seconds_for_click_ = 0.8;
double GestureConfiguration::max_touch_move_in_pixels_for_click_ = 20;
......@@ -20,6 +21,7 @@ double GestureConfiguration::min_flick_speed_squared_ = 550.f * 550.f;
double GestureConfiguration::min_pinch_update_distance_in_pixels_ = 5;
double GestureConfiguration::min_rail_break_velocity_ = 200;
double GestureConfiguration::min_scroll_delta_squared_ = 5 * 5;
double GestureConfiguration::min_swipe_speed_ = 20;
double
GestureConfiguration::min_touch_down_duration_in_seconds_for_click_ = 0.01;
......
......@@ -37,6 +37,12 @@ class UI_EXPORT GestureConfiguration {
static void set_max_separation_for_gesture_touches_in_pixels(int val) {
max_separation_for_gesture_touches_in_pixels_ = val;
}
static double max_swipe_deviation_ratio() {
return max_swipe_deviation_ratio_;
}
static void set_max_swipe_deviation_ratio(double val) {
max_swipe_deviation_ratio_ = val;
}
static double max_touch_down_duration_in_seconds_for_click() {
return max_touch_down_duration_in_seconds_for_click_;
}
......@@ -79,6 +85,12 @@ class UI_EXPORT GestureConfiguration {
static void set_min_scroll_delta_squared(double val) {
min_scroll_delta_squared_ = val;
}
static double min_swipe_speed() {
return min_swipe_speed_;
}
static void set_min_swipe_speed(double val) {
min_swipe_speed_ = val;
}
static double min_touch_down_duration_in_seconds_for_click() {
return min_touch_down_duration_in_seconds_for_click_;
}
......@@ -111,6 +123,7 @@ class UI_EXPORT GestureConfiguration {
static double long_press_time_in_seconds_;
static double max_seconds_between_double_click_;
static double max_separation_for_gesture_touches_in_pixels_;
static double max_swipe_deviation_ratio_;
static double max_touch_down_duration_in_seconds_for_click_;
static double max_touch_move_in_pixels_for_click_;
static double min_distance_for_pinch_scroll_in_pixels_;
......@@ -118,6 +131,7 @@ class UI_EXPORT GestureConfiguration {
static double min_pinch_update_distance_in_pixels_;
static double min_rail_break_velocity_;
static double min_scroll_delta_squared_;
static double min_swipe_speed_;
static double min_touch_down_duration_in_seconds_for_click_;
static int points_buffered_for_velocity_;
static double rail_break_proportion_;
......
......@@ -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,28 @@ GestureSequence::Gestures* GestureSequence::ProcessTouchEventForGesture(
scroll_type_ = ST_FREE;
set_state(GS_SCROLL);
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:
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 +463,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);
......@@ -569,4 +647,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
......@@ -20,7 +20,8 @@ enum GestureState {
GS_NO_GESTURE,
GS_PENDING_SYNTHETIC_CLICK,
GS_SCROLL,
GS_PINCH
GS_PINCH,
GS_THREE_FINGER_SWIPE
};
enum ScrollType {
......@@ -99,6 +100,13 @@ class UI_EXPORT GestureSequence {
float scale,
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; }
// Various GestureTransitionFunctions for a signature.
......@@ -134,6 +142,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);
// Current state of gesture recognizer.
GestureState state_;
......@@ -148,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];
......
......@@ -29,4 +29,8 @@ GS_PENDING_SYNTHETIC_CLICK -> GS_PINCH [label= "D1"];
GS_SCROLL -> GS_PINCH [label= "D1"];
GS_PINCH -> GS_PINCH [label= "M0\n M1"];
GS_PINCH -> GS_SCROLL [label= "C0\n R0\n C1\n R1"];
GS_PINCH -> GS_PENDING_THREE_FINGER_SWIPE [label= "D2"];
GS_PENDING_THREE_FINGER_SWIPE -> GS_PINCH [label= "C0\n R0\n C1\n R1\n C2\n R2"];
GS_PENDING_THREE_FINGER_SWIPE -> GS_PENDING_THREE_FINGER_SWIPE [label= "M0\n M1\n M2"];
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment