summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-08 04:55:06 +0000
committerxiyuan@chromium.org <xiyuan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-12-08 04:55:06 +0000
commita17888c90c9bdd641f53ef8a9eea6a5361d518e4 (patch)
tree9860f67e5ddd1fb45750c68f7ecde4b0aec98c8d /ui
parent2ef9960c1302cdb0ef78ed54957fda504fe9681d (diff)
downloadchromium_src-a17888c90c9bdd641f53ef8a9eea6a5361d518e4.zip
chromium_src-a17888c90c9bdd641f53ef8a9eea6a5361d518e4.tar.gz
chromium_src-a17888c90c9bdd641f53ef8a9eea6a5361d518e4.tar.bz2
Revert 171934
> Use consistent velocity trend to start a touch scroll gesture. > > In the GestureRecognizer, we previously inititated scrolling when the finger leaves a L1-norm box surrounding the position of the touch down point. As a result, the page would seem to leap by the size of the L1-norm on the first paint after entering a scrolling gesture. > > This CL replaces the L1-norm box mechanism with a new mechanism for determining the start of a scroll: watch for the establishment of a consistent velocity trend across multiple touch moves. This permits determining that a scroll should start with a much smaller displacement than is needed with the L1-norm technique and eliminates the "leap" effect. > > BUG=141653 > > > Review URL: https://chromiumcodereview.appspot.com/11469005 TBR=rjkroege@chromium.org Review URL: https://codereview.chromium.org/11472046 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171937 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/aura/gestures/gesture_recognizer_unittest.cc34
-rw-r--r--ui/base/gestures/gesture_configuration.cc9
-rw-r--r--ui/base/gestures/gesture_configuration.h15
-rw-r--r--ui/base/gestures/gesture_point.cc31
-rw-r--r--ui/base/gestures/gesture_point.h12
-rw-r--r--ui/base/gestures/gesture_sequence.cc9
-rw-r--r--ui/base/gestures/velocity_calculator.cc25
7 files changed, 45 insertions, 90 deletions
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc
index 68a36d6..44399dc 100644
--- a/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -481,10 +481,6 @@ base::TimeDelta GetTime() {
return base::Time::NowFromSystemTime() - base::Time();
}
-base::TimeDelta AbsTime(int timeInMillis) {
- return base::TimeDelta::FromMilliseconds(timeInMillis);
-}
-
void SendScrollEvents(RootWindow* root_window,
int x_start,
int y_start,
@@ -860,6 +856,8 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
ui::ET_GESTURE_SCROLL_UPDATE);
EXPECT_EQ(29, delegate->scroll_x());
EXPECT_EQ(29, delegate->scroll_y());
+ EXPECT_EQ(0, delegate->scroll_velocity_x());
+ EXPECT_EQ(0, delegate->scroll_velocity_y());
EXPECT_EQ(gfx::Point(1, 1).ToString(),
delegate->scroll_begin_position().ToString());
@@ -887,7 +885,7 @@ TEST_F(GestureRecognizerTest, GestureEventScroll) {
base::TimeDelta::FromMilliseconds(50));
root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
EXPECT_2_EVENTS(delegate->events(),
- ui::ET_SCROLL_FLING_START,
+ ui::ET_GESTURE_SCROLL_END,
ui::ET_GESTURE_END);
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
}
@@ -1008,6 +1006,7 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailFling) {
EXPECT_EQ(20, delegate->scroll_y());
EXPECT_EQ(0, delegate->scroll_x());
EXPECT_EQ(0, delegate->scroll_velocity_x());
+ EXPECT_EQ(0, delegate->scroll_velocity_y());
// Get a high y velocity, while still staying on the rail
SendScrollEvents(root_window(), 1, 1, press.time_stamp(),
@@ -1276,6 +1275,8 @@ TEST_F(GestureRecognizerTest, GestureEventHorizontalRailScroll) {
EXPECT_EQ(5, delegate->scroll_x());
// y shouldn't change, as we're on a horizontal rail.
EXPECT_EQ(0, delegate->scroll_y());
+ EXPECT_EQ(0, delegate->scroll_velocity_x());
+ EXPECT_EQ(0, delegate->scroll_velocity_y());
// Send enough information that a velocity can be calculated for the gesture,
// and we can break the rail
@@ -1323,6 +1324,7 @@ TEST_F(GestureRecognizerTest, GestureEventVerticalRailScroll) {
// x shouldn't change, as we're on a vertical rail.
EXPECT_EQ(0, delegate->scroll_x());
EXPECT_EQ(0, delegate->scroll_velocity_x());
+ EXPECT_EQ(0, delegate->scroll_velocity_y());
// Send enough information that a velocity can be calculated for the gesture,
// and we can break the rail
@@ -1676,7 +1678,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
delegate->Reset();
ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(101, 201),
- kTouchId1, AbsTime(0));
+ kTouchId1, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
@@ -1686,7 +1688,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// should generate both SCROLL_BEGIN and SCROLL_UPDATE gestures.
delegate->Reset();
ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(130, 301),
- kTouchId1, AbsTime(10));
+ kTouchId1, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
EXPECT_3_EVENTS(delegate->events(),
ui::ET_GESTURE_TAP_CANCEL,
@@ -1697,7 +1699,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// transition to two finger tap here because the touch points are far enough.
delegate->Reset();
ui::TouchEvent press2(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10),
- kTouchId2, AbsTime(20));
+ kTouchId2, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_BEGIN,
@@ -1708,7 +1710,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// Move the first finger.
delegate->Reset();
ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(95, 201),
- kTouchId1, AbsTime(30));
+ kTouchId1, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move3);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_UPDATE,
@@ -1719,7 +1721,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// Now move the second finger.
delegate->Reset();
ui::TouchEvent move4(ui::ET_TOUCH_MOVED, gfx::Point(55, 15),
- kTouchId2, AbsTime(40));
+ kTouchId2, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move4);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_UPDATE,
@@ -1730,7 +1732,8 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// Release the first finger. This should end pinch.
delegate->Reset();
ui::TouchEvent release(ui::ET_TOUCH_RELEASED, gfx::Point(101, 201),
- kTouchId1, AbsTime(50));
+ kTouchId1, press.time_stamp() +
+ base::TimeDelta::FromMilliseconds(50));
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
EXPECT_2_EVENTS(delegate->events(),
ui::ET_GESTURE_PINCH_END,
@@ -1741,7 +1744,7 @@ TEST_F(GestureRecognizerTest, GestureEventPinchFromScroll) {
// Move the second finger. This should still generate a scroll.
delegate->Reset();
ui::TouchEvent move5(ui::ET_TOUCH_MOVED, gfx::Point(25, 10),
- kTouchId2, AbsTime(60));
+ kTouchId2, GetTime());
root->AsRootWindowHostDelegate()->OnHostTouchEvent(&move5);
EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
EXPECT_TRUE(delegate->bounding_box().IsEmpty());
@@ -2259,8 +2262,7 @@ TEST_F(GestureRecognizerTest, TwoFingerTap) {
EXPECT_FALSE(delegate->double_tap());
EXPECT_FALSE(delegate->scroll_begin());
EXPECT_FALSE(delegate->scroll_update());
- EXPECT_FALSE(delegate->scroll_end());
- EXPECT_TRUE(delegate->fling());
+ EXPECT_TRUE(delegate->scroll_end());
EXPECT_FALSE(delegate->two_finger_tap());
}
@@ -2775,9 +2777,7 @@ TEST_F(GestureRecognizerTest, GestureEventScrollTouchMovePartialConsumed) {
EXPECT_FALSE(delegate->double_tap());
EXPECT_FALSE(delegate->scroll_begin());
EXPECT_FALSE(delegate->scroll_update());
- EXPECT_FALSE(delegate->scroll_end());
- // Moves arrive without delays and hence have high velocity.
- EXPECT_TRUE(delegate->fling());
+ EXPECT_TRUE(delegate->scroll_end());
}
// Check that appropriate touch events generate double tap gesture events.
diff --git a/ui/base/gestures/gesture_configuration.cc b/ui/base/gestures/gesture_configuration.cc
index ccd7958..39847830 100644
--- a/ui/base/gestures/gesture_configuration.cc
+++ b/ui/base/gestures/gesture_configuration.cc
@@ -24,16 +24,15 @@ double GestureConfiguration::min_distance_for_pinch_scroll_in_pixels_ = 20;
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_ = 4 * 4;
-int GestureConfiguration::min_scroll_successive_velocity_events_ = 3;
-float GestureConfiguration::min_scroll_velocity_ = 30.0f;
+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;
// The number of points used in the linear regression which determines
-// touch velocity. Velocity is reported for 2 or more touch move events.
-int GestureConfiguration::points_buffered_for_velocity_ = 8;
+// touch velocity. If fewer than this number of points have been seen,
+// velocity is reported as 0.
+int GestureConfiguration::points_buffered_for_velocity_ = 3;
double GestureConfiguration::rail_break_proportion_ = 15;
double GestureConfiguration::rail_start_proportion_ = 2;
diff --git a/ui/base/gestures/gesture_configuration.h b/ui/base/gestures/gesture_configuration.h
index db46d95..2fc5470 100644
--- a/ui/base/gestures/gesture_configuration.h
+++ b/ui/base/gestures/gesture_configuration.h
@@ -113,18 +113,6 @@ class UI_EXPORT GestureConfiguration {
static void set_min_scroll_delta_squared(double val) {
min_scroll_delta_squared_ = val;
}
- static int min_scroll_successive_velocity_events() {
- return min_scroll_successive_velocity_events_;
- }
- static void set_min_scroll_successive_velocity_events(int val) {
- min_scroll_successive_velocity_events_ = val;
- }
- static float min_scroll_velocity() {
- return min_scroll_velocity_;
- }
- static void set_min_scroll_velocity(float val) {
- min_scroll_velocity_ = val;
- }
static double min_swipe_speed() {
return min_swipe_speed_;
}
@@ -199,9 +187,6 @@ class UI_EXPORT GestureConfiguration {
static double min_pinch_update_distance_in_pixels_;
static double min_rail_break_velocity_;
static double min_scroll_delta_squared_;
- // TODO(rjkroege): Expose these in chrome://gesture
- static int min_scroll_successive_velocity_events_;
- static float min_scroll_velocity_;
static double min_swipe_speed_;
static double min_touch_down_duration_in_seconds_for_click_;
static int points_buffered_for_velocity_;
diff --git a/ui/base/gestures/gesture_point.cc b/ui/base/gestures/gesture_point.cc
index 765ffd9..a95b297 100644
--- a/ui/base/gestures/gesture_point.cc
+++ b/ui/base/gestures/gesture_point.cc
@@ -30,14 +30,13 @@ GesturePoint::~GesturePoint() {}
void GesturePoint::Reset() {
first_touch_time_ = second_last_touch_time_ = last_touch_time_ = 0.0;
- ResetVelocity();
+ velocity_calculator_.ClearHistory();
point_id_ = -1;
clear_enclosing_rectangle();
}
void GesturePoint::ResetVelocity() {
velocity_calculator_.ClearHistory();
- same_direction_count_ = gfx::Vector2d();
}
gfx::Vector2d GesturePoint::ScrollDelta() {
@@ -51,24 +50,22 @@ void GesturePoint::UpdateValues(const TouchEvent& event) {
velocity_calculator_.PointSeen(event.location().x(),
event.location().y(),
event_timestamp_microseconds);
- gfx::Vector2d sd(ScrollVelocityDirection(velocity_calculator_.XVelocity()),
- ScrollVelocityDirection(velocity_calculator_.YVelocity()));
- same_direction_count_ = same_direction_count_ + sd;
}
last_touch_time_ = event.time_stamp().InSecondsF();
last_touch_position_ = event.location();
if (event.type() == ui::ET_TOUCH_PRESSED) {
- ResetVelocity();
- clear_enclosing_rectangle();
first_touch_time_ = last_touch_time_;
first_touch_position_ = event.location();
second_last_touch_position_ = last_touch_position_;
second_last_touch_time_ = last_touch_time_;
+
+ velocity_calculator_.ClearHistory();
velocity_calculator_.PointSeen(event.location().x(),
event.location().y(),
event_timestamp_microseconds);
+ clear_enclosing_rectangle();
}
UpdateEnclosingRectangle(event);
@@ -83,7 +80,6 @@ void GesturePoint::UpdateForTap() {
void GesturePoint::UpdateForScroll() {
second_last_touch_position_ = last_touch_position_;
second_last_touch_time_ = last_touch_time_;
- same_direction_count_ = gfx::Vector2d();
}
bool GesturePoint::IsInClickWindow(const TouchEvent& event) const {
@@ -105,26 +101,15 @@ bool GesturePoint::IsInFlickWindow(const TouchEvent& event) {
event.type() != ui::ET_TOUCH_CANCELLED;
}
-int GesturePoint::ScrollVelocityDirection(float v) {
- if (v < -GestureConfiguration::min_scroll_velocity())
- return -1;
- else if (v > GestureConfiguration::min_scroll_velocity())
- return 1;
- else
- return 0;
-}
-
bool GesturePoint::DidScroll(const TouchEvent& event, int dist) const {
gfx::Vector2d d = last_touch_position_ - second_last_touch_position_;
return abs(d.x()) > dist || abs(d.y()) > dist;
}
-bool GesturePoint::IsConsistentScrollingActionUnderway() {
- int me = GestureConfiguration::min_scroll_successive_velocity_events();
- if (abs(same_direction_count_.x()) >= me ||
- abs(same_direction_count_.y()) >= me)
- return true;
- return false;
+bool GesturePoint::HasEnoughDataToEstablishRail() const {
+ gfx::Vector2d d = last_touch_position_ - first_touch_position_;
+ int64 delta_squared = d.LengthSquared();
+ return delta_squared > GestureConfiguration::min_scroll_delta_squared();
}
bool GesturePoint::IsInHorizontalRailWindow() const {
diff --git a/ui/base/gestures/gesture_point.h b/ui/base/gestures/gesture_point.h
index f52fece4..0e77fd2 100644
--- a/ui/base/gestures/gesture_point.h
+++ b/ui/base/gestures/gesture_point.h
@@ -44,6 +44,7 @@ class GesturePoint {
bool IsInHorizontalRailWindow() const;
bool IsInVerticalRailWindow() const;
bool IsInsideManhattanSquare(const TouchEvent& event) const;
+ bool HasEnoughDataToEstablishRail() const;
bool BreaksHorizontalRail();
bool BreaksVerticalRail();
bool DidScroll(const TouchEvent& event, int distance) const;
@@ -78,10 +79,6 @@ class GesturePoint {
const gfx::Rect& enclosing_rectangle() const { return enclosing_rect_; }
- // Tests if the point has a consistent scroll vector across a window of touch
- // move events.
- bool IsConsistentScrollingActionUnderway();
-
private:
// Various statistical functions to manipulate gestures.
bool IsInClickTimeWindow() const;
@@ -89,10 +86,6 @@ class GesturePoint {
bool IsSecondClickInsideManhattanSquare(const TouchEvent& event) const;
bool IsOverMinFlickSpeed();
- // Returns -1, 0, 1 for |v| below the negative velocity threshold,
- // in [-threshold, threshold] or above respectively.
- int ScrollVelocityDirection(float v);
-
// The enclosing rectangle represents a rectangular touch region generated
// by a sequence of ET_TOUCH_PRESSED, ET_TOUCH_MOVED, and ET_TOUCH_RELEASED
// events forming a GESTURE_TAP event. The enclosing rectangle is updated
@@ -124,9 +117,6 @@ class GesturePoint {
// generated by a sequence of touch events
gfx::Rect enclosing_rect_;
- // Count of the number of events with same direction.
- gfx::Vector2d same_direction_count_;
-
DISALLOW_COPY_AND_ASSIGN(GesturePoint);
};
diff --git a/ui/base/gestures/gesture_sequence.cc b/ui/base/gestures/gesture_sequence.cc
index 75932ec..5029d76 100644
--- a/ui/base/gestures/gesture_sequence.cc
+++ b/ui/base/gestures/gesture_sequence.cc
@@ -846,8 +846,9 @@ bool GestureSequence::ScrollStart(const TouchEvent& event,
GesturePoint& point,
Gestures* gestures) {
DCHECK(state_ == GS_PENDING_SYNTHETIC_CLICK);
- if (!point.IsConsistentScrollingActionUnderway() &&
- !point.IsInScrollWindow(event))
+ if (point.IsInClickWindow(event) ||
+ !point.IsInScrollWindow(event) ||
+ !point.HasEnoughDataToEstablishRail())
return false;
AppendScrollGestureBegin(point, point.first_touch_position(), gestures);
if (point.IsInHorizontalRailWindow())
@@ -1066,8 +1067,8 @@ bool GestureSequence::MaybeSwipe(const TouchEvent& event,
velocity_x = points_[i].XVelocity();
velocity_y = points_[i].YVelocity();
- sign_x = velocity_x < 0.f ? -1 : 1;
- sign_y = velocity_y < 0.f ? -1 : 1;
+ sign_x = velocity_x < 0 ? -1 : 1;
+ sign_y = velocity_y < 0 ? -1 : 1;
for (++i; i < kMaxGesturePoints; ++i) {
if (!points_[i].in_use())
diff --git a/ui/base/gestures/velocity_calculator.cc b/ui/base/gestures/velocity_calculator.cc
index f4db08ac..ca862cd 100644
--- a/ui/base/gestures/velocity_calculator.cc
+++ b/ui/base/gestures/velocity_calculator.cc
@@ -50,7 +50,7 @@ float VelocityCalculator::VelocitySquared() {
void VelocityCalculator::UpdateVelocity() {
// We don't have enough data to make a good estimate of the velocity.
- if (num_valid_entries_ < 2)
+ if (num_valid_entries_ < buffer_size_)
return;
// Where A_i = A[i] - mean(A)
@@ -61,23 +61,23 @@ void VelocityCalculator::UpdateVelocity() {
float mean_y = 0;
int64 mean_time = 0;
- for (size_t i = 0; i < num_valid_entries_; ++i) {
+ for (size_t i = 0; i < buffer_size_; ++i) {
mean_x += buffer_[i].x;
mean_y += buffer_[i].y;
mean_time += buffer_[i].time;
}
// Minimize number of divides.
- const float num_valid_entries_i = 1.0f / num_valid_entries_;
+ const float buffer_size_i = 1.0f / buffer_size_;
- mean_x *= num_valid_entries_i;
- mean_y *= num_valid_entries_i;
+ mean_x *= buffer_size_i;
+ mean_y *= buffer_size_i;
// The loss in accuracy due to rounding is insignificant compared to
// the error due to the resolution of the timer.
// Use integer division to avoid the cast to double, which would cause
// VelocityCalculatorTest.IsAccurateWithLargeTimes to fail.
- mean_time /= num_valid_entries_;
+ mean_time /= buffer_size_;
float xt = 0; // sum_i(x_i * t_i)
float yt = 0; // sum_i(y_i * t_i)
@@ -85,21 +85,16 @@ void VelocityCalculator::UpdateVelocity() {
int64 t_i;
- for (size_t i = 0; i < num_valid_entries_; ++i) {
+ for (size_t i = 0; i < buffer_size_; ++i) {
t_i = (buffer_[i].time - mean_time);
xt += (buffer_[i].x - mean_x) * t_i;
yt += (buffer_[i].y - mean_y) * t_i;
tt += t_i * t_i;
}
- if (tt > 0) {
- // Convert time from microseconds to seconds.
- x_velocity_ = xt / (tt / 1000000.0f);
- y_velocity_ = yt / (tt / 1000000.0f);
- } else {
- x_velocity_ = 0.0f;
- y_velocity_ = 0.0f;
- }
+ // Convert time from microseconds to seconds.
+ x_velocity_ = xt / (tt / 1000000.0f);
+ y_velocity_ = yt / (tt / 1000000.0f);
velocities_stale_ = false;
}