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 59f4af31fd891bafa6b19d6532dd1855a0f4d499..5a91d6fe90883457877de340d8f4578cd3ed71e2 100644 |
--- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc |
+++ b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc |
@@ -4,267 +4,56 @@ |
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h" |
-#include "base/logging.h" |
-#include "ui/gfx/geometry/point_f.h" |
- |
namespace content { |
-namespace { |
- |
-gfx::Vector2d FloorTowardZero(const gfx::Vector2dF& vector) { |
- int x = vector.x() > 0 ? floor(vector.x()) : ceil(vector.x()); |
- int y = vector.y() > 0 ? floor(vector.y()) : ceil(vector.y()); |
- return gfx::Vector2d(x, y); |
-} |
- |
-gfx::Vector2d CeilFromZero(const gfx::Vector2dF& vector) { |
- int x = vector.x() > 0 ? ceil(vector.x()) : floor(vector.x()); |
- int y = vector.y() > 0 ? ceil(vector.y()) : floor(vector.y()); |
- return gfx::Vector2d(x, y); |
-} |
- |
-gfx::Vector2dF ProjectScalarOntoVector( |
- float scalar, const gfx::Vector2d& vector) { |
- return gfx::ScaleVector2d(vector, scalar / vector.Length()); |
-} |
- |
-} // namespace |
SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture( |
const SyntheticSmoothScrollGestureParams& params) |
- : params_(params), |
- gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), |
- state_(SETUP) {} |
- |
-SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() {} |
- |
-SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents( |
- const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { |
- if (state_ == SETUP) { |
- gesture_source_type_ = params_.gesture_source_type; |
- if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) |
- gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); |
- |
- state_ = STARTED; |
- current_scroll_segment_ = -1; |
- current_scroll_segment_stop_time_ = timestamp; |
- } |
- |
- DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); |
- if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) |
- ForwardTouchInputEvents(timestamp, target); |
- else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) |
- ForwardMouseInputEvents(timestamp, target); |
- else |
- return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; |
- |
- return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED |
- : SyntheticGesture::GESTURE_RUNNING; |
+ : params_(params) { |
} |
-void SyntheticSmoothScrollGesture::ForwardTouchInputEvents( |
- const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { |
- base::TimeTicks event_timestamp = timestamp; |
- switch (state_) { |
- case STARTED: |
- if (ScrollIsNoOp()) { |
- state_ = DONE; |
- break; |
- } |
- AddTouchSlopToFirstDistance(target); |
- ComputeNextScrollSegment(); |
- current_scroll_segment_start_position_ = params_.anchor; |
- PressTouchPoint(target, event_timestamp); |
- state_ = MOVING; |
- break; |
- case MOVING: { |
- event_timestamp = ClampTimestamp(timestamp); |
- gfx::Vector2dF delta = GetPositionDeltaAtTime(event_timestamp); |
- MoveTouchPoint(target, delta, event_timestamp); |
- |
- if (FinishedCurrentScrollSegment(event_timestamp)) { |
- if (!IsLastScrollSegment()) { |
- current_scroll_segment_start_position_ += |
- params_.distances[current_scroll_segment_]; |
- ComputeNextScrollSegment(); |
- } else if (params_.prevent_fling) { |
- state_ = STOPPING; |
- } else { |
- ReleaseTouchPoint(target, event_timestamp); |
- state_ = DONE; |
- } |
- } |
- } break; |
- case STOPPING: |
- if (timestamp - current_scroll_segment_stop_time_ >= |
- target->PointerAssumedStoppedTime()) { |
- event_timestamp = current_scroll_segment_stop_time_ + |
- target->PointerAssumedStoppedTime(); |
- ReleaseTouchPoint(target, event_timestamp); |
- state_ = DONE; |
- } |
- break; |
- case SETUP: |
- NOTREACHED() |
- << "State STARTED invalid for synthetic scroll using touch input."; |
- case DONE: |
- NOTREACHED() |
- << "State DONE invalid for synthetic scroll using touch input."; |
- } |
+SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() { |
} |
-void SyntheticSmoothScrollGesture::ForwardMouseInputEvents( |
- const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { |
- switch (state_) { |
- case STARTED: |
- if (ScrollIsNoOp()) { |
- state_ = DONE; |
- break; |
- } |
- ComputeNextScrollSegment(); |
- 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. |
- base::TimeTicks event_timestamp = ClampTimestamp(timestamp); |
- gfx::Vector2dF current_scroll_segment_total_delta = |
- GetPositionDeltaAtTime(event_timestamp); |
- gfx::Vector2d delta_discrete = |
- FloorTowardZero(current_scroll_segment_total_delta - |
- current_scroll_segment_total_delta_discrete_); |
- ForwardMouseWheelEvent(target, delta_discrete, event_timestamp); |
- current_scroll_segment_total_delta_discrete_ += delta_discrete; |
- |
- if (FinishedCurrentScrollSegment(event_timestamp)) { |
- if (!IsLastScrollSegment()) { |
- current_scroll_segment_total_delta_discrete_ = gfx::Vector2d(); |
- ComputeNextScrollSegment(); |
- ForwardMouseInputEvents(timestamp, target); |
- } else { |
- state_ = DONE; |
- } |
- } |
- } break; |
- case SETUP: |
- NOTREACHED() |
- << "State STARTED invalid for synthetic scroll using touch input."; |
- case STOPPING: |
- NOTREACHED() |
- << "State STOPPING invalid for synthetic scroll using touch input."; |
- case DONE: |
- NOTREACHED() |
- << "State DONE invalid for synthetic scroll using touch input."; |
+SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents( |
+ const base::TimeTicks& timestamp, |
+ SyntheticGestureTarget* target) { |
+ if (!move_gesture_) { |
+ if (!InitializeMoveGesture(params_.gesture_source_type, target)) |
+ return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; |
} |
+ return move_gesture_->ForwardInputEvents(timestamp, target); |
} |
-void SyntheticSmoothScrollGesture::ForwardTouchEvent( |
- SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { |
- touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); |
- |
- target->DispatchInputEventToPlatform(touch_event_); |
-} |
- |
-void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent( |
- 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(mouse_wheel_event); |
-} |
- |
-void SyntheticSmoothScrollGesture::PressTouchPoint( |
- SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { |
- DCHECK_EQ(current_scroll_segment_, 0); |
- touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y()); |
- ForwardTouchEvent(target, timestamp); |
-} |
- |
-void SyntheticSmoothScrollGesture::MoveTouchPoint( |
- SyntheticGestureTarget* target, |
- const gfx::Vector2dF& delta, |
- const base::TimeTicks& timestamp) { |
- DCHECK_GE(current_scroll_segment_, 0); |
- DCHECK_LT(current_scroll_segment_, |
- static_cast<int>(params_.distances.size())); |
- gfx::PointF touch_position = current_scroll_segment_start_position_ + delta; |
- touch_event_.MovePoint(0, touch_position.x(), touch_position.y()); |
- ForwardTouchEvent(target, timestamp); |
-} |
- |
-void SyntheticSmoothScrollGesture::ReleaseTouchPoint( |
- SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { |
- DCHECK_EQ(current_scroll_segment_, |
- static_cast<int>(params_.distances.size()) - 1); |
- touch_event_.ReleasePoint(0); |
- ForwardTouchEvent(target, timestamp); |
+SyntheticSmoothMoveGestureParams::InputType |
+SyntheticSmoothScrollGesture::GetInputSourceType( |
+ SyntheticGestureParams::GestureSourceType gesture_source_type) { |
+ if (gesture_source_type == SyntheticGestureParams::MOUSE_INPUT) |
+ return SyntheticSmoothMoveGestureParams::MOUSE_WHEEL_INPUT; |
+ else |
+ return SyntheticSmoothMoveGestureParams::TOUCH_INPUT; |
} |
-void SyntheticSmoothScrollGesture::AddTouchSlopToFirstDistance( |
+bool SyntheticSmoothScrollGesture::InitializeMoveGesture( |
+ SyntheticGestureParams::GestureSourceType gesture_type, |
SyntheticGestureTarget* target) { |
- DCHECK_GE(params_.distances.size(), 1ul); |
- gfx::Vector2d& first_scroll_distance = params_.distances[0]; |
- DCHECK_GT(first_scroll_distance.Length(), 0); |
- first_scroll_distance += CeilFromZero(ProjectScalarOntoVector( |
- target->GetTouchSlopInDips(), first_scroll_distance)); |
-} |
- |
-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 (FinishedCurrentScrollSegment(timestamp)) |
- return params_.distances[current_scroll_segment_]; |
- |
- float delta_length = |
- params_.speed_in_pixels_s * |
- (timestamp - current_scroll_segment_start_time_).InSecondsF(); |
- return ProjectScalarOntoVector(delta_length, |
- params_.distances[current_scroll_segment_]); |
-} |
- |
-void SyntheticSmoothScrollGesture::ComputeNextScrollSegment() { |
- current_scroll_segment_++; |
- DCHECK_LT(current_scroll_segment_, |
- static_cast<int>(params_.distances.size())); |
- int64 total_duration_in_us = static_cast<int64>( |
- 1e6 * (params_.distances[current_scroll_segment_].Length() / |
- params_.speed_in_pixels_s)); |
- DCHECK_GT(total_duration_in_us, 0); |
- current_scroll_segment_start_time_ = current_scroll_segment_stop_time_; |
- current_scroll_segment_stop_time_ = |
- current_scroll_segment_start_time_ + |
- base::TimeDelta::FromMicroseconds(total_duration_in_us); |
-} |
- |
-base::TimeTicks SyntheticSmoothScrollGesture::ClampTimestamp( |
- const base::TimeTicks& timestamp) const { |
- return std::min(timestamp, current_scroll_segment_stop_time_); |
-} |
- |
-bool SyntheticSmoothScrollGesture::FinishedCurrentScrollSegment( |
- const base::TimeTicks& timestamp) const { |
- return timestamp >= current_scroll_segment_stop_time_; |
-} |
- |
-bool SyntheticSmoothScrollGesture::IsLastScrollSegment() const { |
- DCHECK_LT(current_scroll_segment_, |
- static_cast<int>(params_.distances.size())); |
- return current_scroll_segment_ == |
- static_cast<int>(params_.distances.size()) - 1; |
-} |
- |
-bool SyntheticSmoothScrollGesture::ScrollIsNoOp() const { |
- return params_.distances.size() == 0 || params_.distances[0].IsZero(); |
+ if (gesture_type == SyntheticGestureParams::DEFAULT_INPUT) |
+ gesture_type = target->GetDefaultSyntheticGestureSourceType(); |
+ |
+ if (gesture_type == SyntheticGestureParams::TOUCH_INPUT || |
+ gesture_type == SyntheticGestureParams::MOUSE_INPUT) { |
+ SyntheticSmoothMoveGestureParams move_params; |
+ move_params.start_point = params_.anchor; |
+ // TODO(ssid): Remove this when params for scroll is changed to float |
+ for (size_t i = 0; i < params_.distances.size(); i++) |
+ move_params.distances.push_back(params_.distances[i]); |
+ move_params.speed_in_pixels_s = params_.speed_in_pixels_s; |
+ move_params.prevent_fling = params_.prevent_fling; |
+ move_params.input_type = GetInputSourceType(gesture_type); |
+ move_params.add_slop = true; |
+ move_gesture_.reset(new SyntheticSmoothMoveGesture(move_params)); |
+ return true; |
+ } |
+ return false; |
} |
} // namespace content |