Chromium Code Reviews| 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..77304dc3191d2798ebd96368c3658b6f97cb51d6 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); |
| + PressTouchPoint(target, event_timestamp); |
| state_ = MOVING; |
| break; |
| - case MOVING: |
| - total_delta_ += GetPositionDelta(interval); |
| - MoveTouchPoint(target); |
| + case MOVING: { |
| + gfx::Vector2dF delta = |
| + GetPositionDeltaAndUpdateTimestamp(&event_timestamp); |
| + MoveTouchPoint(target, delta, event_timestamp); |
| - if (HasScrolledEntireDistance()) { |
| + if (HasScrolledEntireDistance(delta)) { |
| if (params_.prevent_fling) { |
| + stopping_start_time_ = event_timestamp; |
| 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 - stopping_start_time_ >= |
| + target->PointerAssumedStoppedTime()) { |
| + event_timestamp = |
| + stopping_start_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. |
| @@ -115,22 +121,23 @@ void SyntheticSmoothScrollGesture::ForwardMouseInputEvents( |
| } |
| 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 = timestamp; |
| + gfx::Vector2dF total_delta = |
| + GetPositionDeltaAndUpdateTimestamp(&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(total_delta)) |
| 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,30 @@ 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::GetPositionDeltaAndUpdateTimestamp( |
| + base::TimeTicks* timestamp) const { |
|
jdduke (slow)
2014/01/03 18:24:30
DCHECK(timestamp);
Dominik Grewe
2014/01/06 11:46:07
Done.
|
| + float delta_length = |
| + params_.speed_in_pixels_s * (*timestamp - start_time_).InSecondsF(); |
| // Make sure we're not scrolling too far. |
| - gfx::Vector2dF remaining_delta = ComputeRemainingDelta(); |
| - if (delta_length > remaining_delta.Length()) |
| + if (delta_length > params_.distance.Length()) { |
| + // Update the timestamp to match the end of the scroll. |
| + int total_duration_in_ms = |
| + (1000 * params_.distance.Length()) / params_.speed_in_pixels_s; |
|
jdduke (slow)
2014/01/03 18:24:30
Same as above, multiplying the time scale by the d
Dominik Grewe
2014/01/06 11:46:07
Done.
|
| + *timestamp = |
| + start_time_ + base::TimeDelta::FromMilliseconds(total_duration_in_ms); |
| + |
| // 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 -params_.distance; |
| + } else { |
| return -ProjectLengthOntoScrollDirection(delta_length); |
| + } |
| } |
| gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection( |
| @@ -212,12 +234,9 @@ gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection( |
| return ScaleVector2d(params_.distance, delta_length / kTotalLength); |
| } |
| -gfx::Vector2dF SyntheticSmoothScrollGesture::ComputeRemainingDelta() const { |
| - return params_.distance + total_delta_; |
| -} |
| - |
| -bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance() const { |
| - return ComputeRemainingDelta().IsZero(); |
| +bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance( |
| + const gfx::Vector2dF& delta) const { |
| + return delta == -params_.distance; |
| } |
| } // namespace content |