| 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
|
|
|