Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Unified Diff: content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc

Issue 119323007: Add timestamps to synthesized events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove target variables in pinch; fix computation of total duration. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
index b2fb4bb7eb3bf82487025edf9b3e0b3e3d6bfda1..f70ba9be7b12ead8dc457f96ba24b806b338f6c4 100644
--- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
+++ b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
@@ -35,7 +35,7 @@ SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture(
SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() {}
SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents(
- const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
if (state_ == SETUP) {
gesture_source_type_ = params_.gesture_source_type;
if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
@@ -45,13 +45,14 @@ SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents(
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
state_ = STARTED;
+ start_time_ = timestamp;
}
DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
- ForwardTouchInputEvents(interval, target);
+ ForwardTouchInputEvents(timestamp, target);
else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT)
- ForwardMouseInputEvents(interval, target);
+ ForwardMouseInputEvents(timestamp, target);
else
return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
@@ -60,7 +61,8 @@ SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents(
}
void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
- const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
+ base::TimeTicks event_timestamp = timestamp;
switch (state_) {
case STARTED:
// Check for an early finish.
@@ -69,29 +71,33 @@ void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
break;
}
AddTouchSlopToDistance(target);
- PressTouchPoint(target);
+ ComputeAndSetStopScrollingTime();
+ PressTouchPoint(target, event_timestamp);
state_ = MOVING;
break;
- case MOVING:
- total_delta_ += GetPositionDelta(interval);
- MoveTouchPoint(target);
+ case MOVING: {
+ event_timestamp = ClampTimestamp(timestamp);
+ gfx::Vector2dF delta = GetPositionDeltaAtTime(event_timestamp);
+ MoveTouchPoint(target, delta, event_timestamp);
- if (HasScrolledEntireDistance()) {
+ if (HasScrolledEntireDistance(event_timestamp)) {
if (params_.prevent_fling) {
state_ = STOPPING;
} else {
- ReleaseTouchPoint(target);
+ ReleaseTouchPoint(target, event_timestamp);
state_ = DONE;
}
}
- break;
+ } break;
case STOPPING:
- total_stopping_wait_time_ += interval;
- if (total_stopping_wait_time_ >= target->PointerAssumedStoppedTime()) {
+ if (timestamp - stop_scrolling_time_ >=
+ target->PointerAssumedStoppedTime()) {
+ event_timestamp =
+ stop_scrolling_time_ + target->PointerAssumedStoppedTime();
// Send one last move event, but don't change the location. Without this
// we'd still sometimes cause a fling on Android.
- MoveTouchPoint(target);
- ReleaseTouchPoint(target);
+ ForwardTouchEvent(target, event_timestamp);
+ ReleaseTouchPoint(target, event_timestamp);
state_ = DONE;
}
break;
@@ -105,7 +111,7 @@ void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
}
void SyntheticSmoothScrollGesture::ForwardMouseInputEvents(
- const base::TimeDelta& interval, SyntheticGestureTarget* target) {
+ const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
switch (state_) {
case STARTED:
// Check for an early finish.
@@ -113,24 +119,25 @@ void SyntheticSmoothScrollGesture::ForwardMouseInputEvents(
state_ = DONE;
break;
}
+ ComputeAndSetStopScrollingTime();
state_ = MOVING;
// Fall through to forward the first event.
- case MOVING:
- {
- // Even though WebMouseWheelEvents take floating point deltas,
- // internally the scroll position is stored as an integer. We therefore
- // keep track of the discrete delta which is consistent with the
- // internal scrolling state. This ensures that when the gesture has
- // finished we've scrolled exactly the specified distance.
- total_delta_ += GetPositionDelta(interval);
- gfx::Vector2d delta_discrete =
- FloorTowardZero(total_delta_ - total_delta_discrete_);
- ForwardMouseWheelEvent(target, delta_discrete);
- total_delta_discrete_ += delta_discrete;
- }
- if (HasScrolledEntireDistance())
+ case MOVING: {
+ // Even though WebMouseWheelEvents take floating point deltas,
+ // internally the scroll position is stored as an integer. We therefore
+ // keep track of the discrete delta which is consistent with the
+ // internal scrolling state. This ensures that when the gesture has
+ // finished we've scrolled exactly the specified distance.
+ base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
+ gfx::Vector2dF total_delta = GetPositionDeltaAtTime(event_timestamp);
+ gfx::Vector2d delta_discrete =
+ FloorTowardZero(total_delta - total_delta_discrete_);
+ ForwardMouseWheelEvent(target, delta_discrete, event_timestamp);
+ total_delta_discrete_ += delta_discrete;
+
+ if (HasScrolledEntireDistance(event_timestamp))
state_ = DONE;
- break;
+ } break;
case SETUP:
NOTREACHED()
<< "State STARTED invalid for synthetic scroll using touch input.";
@@ -140,44 +147,52 @@ void SyntheticSmoothScrollGesture::ForwardMouseInputEvents(
case DONE:
NOTREACHED()
<< "State DONE invalid for synthetic scroll using touch input.";
- }
+ }
}
void SyntheticSmoothScrollGesture::ForwardTouchEvent(
- SyntheticGestureTarget* target) const {
+ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
+ touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
+
target->DispatchInputEventToPlatform(
InputEvent(touch_event_, ui::LatencyInfo(), false));
}
void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent(
- SyntheticGestureTarget* target, const gfx::Vector2dF& delta) const {
+ SyntheticGestureTarget* target,
+ const gfx::Vector2dF& delta,
+ const base::TimeTicks& timestamp) const {
blink::WebMouseWheelEvent mouse_wheel_event =
SyntheticWebMouseWheelEventBuilder::Build(delta.x(), delta.y(), 0, false);
mouse_wheel_event.x = params_.anchor.x();
mouse_wheel_event.y = params_.anchor.y();
+ mouse_wheel_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
+
target->DispatchInputEventToPlatform(
InputEvent(mouse_wheel_event, ui::LatencyInfo(), false));
}
void SyntheticSmoothScrollGesture::PressTouchPoint(
- SyntheticGestureTarget* target) {
+ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y());
- ForwardTouchEvent(target);
+ ForwardTouchEvent(target, timestamp);
}
void SyntheticSmoothScrollGesture::MoveTouchPoint(
- SyntheticGestureTarget* target) {
- gfx::PointF touch_position = params_.anchor + total_delta_;
+ SyntheticGestureTarget* target,
+ const gfx::Vector2dF& delta,
+ const base::TimeTicks& timestamp) {
+ gfx::PointF touch_position = params_.anchor + delta;
touch_event_.MovePoint(0, touch_position.x(), touch_position.y());
- ForwardTouchEvent(target);
+ ForwardTouchEvent(target, timestamp);
}
void SyntheticSmoothScrollGesture::ReleaseTouchPoint(
- SyntheticGestureTarget* target) {
+ SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
touch_event_.ReleasePoint(0);
- ForwardTouchEvent(target);
+ ForwardTouchEvent(target, timestamp);
}
void SyntheticSmoothScrollGesture::AddTouchSlopToDistance(
@@ -187,23 +202,21 @@ void SyntheticSmoothScrollGesture::AddTouchSlopToDistance(
// distance and round up to the nearest integer.
// For vertical and horizontal scrolls (the common case), both methods produce
// the same result.
- gfx::Vector2dF touch_slop_delta = ProjectLengthOntoScrollDirection(
- target->GetTouchSlopInDips());
+ gfx::Vector2dF touch_slop_delta =
+ ProjectLengthOntoScrollDirection(target->GetTouchSlopInDips());
params_.distance += CeilFromZero(touch_slop_delta);
}
-gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDelta(
- const base::TimeDelta& interval) const {
- float delta_length = params_.speed_in_pixels_s * interval.InSecondsF();
+gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDeltaAtTime(
+ const base::TimeTicks& timestamp) const {
+ // Make sure the final delta is correct. Using the computation below can lead
+ // to issues with floating point precision.
+ if (HasScrolledEntireDistance(timestamp))
+ return -params_.distance;
- // Make sure we're not scrolling too far.
- gfx::Vector2dF remaining_delta = ComputeRemainingDelta();
- if (delta_length > remaining_delta.Length())
- // In order to scroll in a certain direction we need to move the
- // touch pointer/mouse wheel in the opposite direction.
- return -remaining_delta;
- else
- return -ProjectLengthOntoScrollDirection(delta_length);
+ float delta_length =
+ params_.speed_in_pixels_s * (timestamp - start_time_).InSecondsF();
+ return -ProjectLengthOntoScrollDirection(delta_length);
}
gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection(
@@ -212,12 +225,22 @@ gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection(
return ScaleVector2d(params_.distance, delta_length / kTotalLength);
}
-gfx::Vector2dF SyntheticSmoothScrollGesture::ComputeRemainingDelta() const {
- return params_.distance + total_delta_;
+void SyntheticSmoothScrollGesture::ComputeAndSetStopScrollingTime() {
+ int64 total_duration_in_us = static_cast<int64>(
+ 1e6 * (params_.distance.Length() / params_.speed_in_pixels_s));
+ DCHECK_GT(total_duration_in_us, 0);
+ stop_scrolling_time_ =
+ start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
+}
+
+base::TimeTicks SyntheticSmoothScrollGesture::ClampTimestamp(
+ const base::TimeTicks& timestamp) const {
+ return std::min(timestamp, stop_scrolling_time_);
}
-bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance() const {
- return ComputeRemainingDelta().IsZero();
+bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance(
+ const base::TimeTicks& timestamp) const {
+ return timestamp >= stop_scrolling_time_;
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698