| Index: content/browser/renderer_host/input/synthetic_pinch_gesture.cc
|
| diff --git a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc b/content/browser/renderer_host/input/synthetic_pinch_gesture.cc
|
| index dfe5cf474e7a72957ed5f4f7ac1c258440ecc8d5..d49024b09a196efd49a4afe085dcbda5a6a5d5c7 100644
|
| --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc
|
| +++ b/content/browser/renderer_host/input/synthetic_pinch_gesture.cc
|
| @@ -15,10 +15,8 @@ namespace content {
|
| SyntheticPinchGesture::SyntheticPinchGesture(
|
| const SyntheticPinchGestureParams& params)
|
| : params_(params),
|
| - current_y_0_(0.0f),
|
| - current_y_1_(0.0f),
|
| - target_y_0_(0.0f),
|
| - target_y_1_(0.0f),
|
| + start_y_0_(0.0f),
|
| + start_y_1_(0.0f),
|
| gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
|
| state_(SETUP) {
|
| DCHECK_GE(params_.total_num_pixels_covered, 0);
|
| @@ -27,7 +25,7 @@ SyntheticPinchGesture::SyntheticPinchGesture(
|
| SyntheticPinchGesture::~SyntheticPinchGesture() {}
|
|
|
| SyntheticGesture::Result SyntheticPinchGesture::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)
|
| @@ -37,11 +35,12 @@ SyntheticGesture::Result SyntheticPinchGesture::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
|
| return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
|
|
|
| @@ -50,7 +49,7 @@ SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents(
|
| }
|
|
|
| void SyntheticPinchGesture::ForwardTouchInputEvents(
|
| - const base::TimeDelta& interval, SyntheticGestureTarget* target) {
|
| + const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
|
| switch (state_) {
|
| case STARTED:
|
| // Check for an early finish.
|
| @@ -58,18 +57,19 @@ void SyntheticPinchGesture::ForwardTouchInputEvents(
|
| state_ = DONE;
|
| break;
|
| }
|
| - SetupCoordinates(target);
|
| - PressTouchPoints(target);
|
| + SetupCoordinatesAndStopTime(target);
|
| + PressTouchPoints(target, timestamp);
|
| state_ = MOVING;
|
| break;
|
| - case MOVING:
|
| - UpdateTouchPoints(interval);
|
| - MoveTouchPoints(target);
|
| - if (HasReachedTarget()) {
|
| - ReleaseTouchPoints(target);
|
| + case MOVING: {
|
| + base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
|
| + float delta = GetDeltaForPointer0AtTime(event_timestamp);
|
| + MoveTouchPoints(target, delta, event_timestamp);
|
| + if (HasReachedTarget(event_timestamp)) {
|
| + ReleaseTouchPoints(target, event_timestamp);
|
| state_ = DONE;
|
| }
|
| - break;
|
| + } break;
|
| case SETUP:
|
| NOTREACHED() << "State SETUP invalid for synthetic pinch.";
|
| case DONE:
|
| @@ -77,90 +77,94 @@ void SyntheticPinchGesture::ForwardTouchInputEvents(
|
| }
|
| }
|
|
|
| -void SyntheticPinchGesture::UpdateTouchPoints(base::TimeDelta interval) {
|
| - // Compute the delta for the first pointer. The other one moves exactly
|
| - // the same but in the opposite direction.
|
| - float delta = GetDeltaForPointer0(interval);
|
| - current_y_0_ += delta;
|
| - current_y_1_ -= delta;
|
| +void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target,
|
| + const base::TimeTicks& timestamp) {
|
| + touch_event_.PressPoint(params_.anchor.x(), start_y_0_);
|
| + touch_event_.PressPoint(params_.anchor.x(), start_y_1_);
|
| + ForwardTouchEvent(target, timestamp);
|
| }
|
|
|
| -void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target) {
|
| - touch_event_.PressPoint(params_.anchor.x(), current_y_0_);
|
| - touch_event_.PressPoint(params_.anchor.x(), current_y_1_);
|
| - ForwardTouchEvent(target);
|
| -}
|
| +void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target,
|
| + float delta,
|
| + const base::TimeTicks& timestamp) {
|
| + // The two pointers move in opposite directions.
|
| + float current_y_0 = start_y_0_ + delta;
|
| + float current_y_1 = start_y_1_ - delta;
|
|
|
| -void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target) {
|
| // The current pointer positions are stored as float but the pointer
|
| // coordinates of the input event are integers. Floor both positions so that
|
| // in case of an odd distance one of the pointers (the one whose position goes
|
| // down) moves one pixel further than the other. The explicit flooring is only
|
| // needed for negative values.
|
| - touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0_));
|
| - touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1_));
|
| - ForwardTouchEvent(target);
|
| + touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0));
|
| + touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1));
|
| + ForwardTouchEvent(target, timestamp);
|
| }
|
|
|
| -void SyntheticPinchGesture::ReleaseTouchPoints(SyntheticGestureTarget* target) {
|
| +void SyntheticPinchGesture::ReleaseTouchPoints(
|
| + SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
|
| touch_event_.ReleasePoint(0);
|
| touch_event_.ReleasePoint(1);
|
| - ForwardTouchEvent(target);
|
| + ForwardTouchEvent(target, timestamp);
|
| }
|
|
|
| -
|
| -void SyntheticPinchGesture::ForwardTouchEvent(SyntheticGestureTarget* target)
|
| - const {
|
| +void SyntheticPinchGesture::ForwardTouchEvent(
|
| + SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
|
| + touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
|
| target->DispatchInputEventToPlatform(
|
| InputEvent(touch_event_, ui::LatencyInfo(), false));
|
| }
|
|
|
| -void SyntheticPinchGesture::SetupCoordinates(SyntheticGestureTarget* target) {
|
| - const float kTouchSlopInDips = target->GetTouchSlopInDips();
|
| +void SyntheticPinchGesture::SetupCoordinatesAndStopTime(
|
| + SyntheticGestureTarget* target) {
|
| + const int kTouchSlopInDips = target->GetTouchSlopInDips();
|
| + params_.total_num_pixels_covered += 2 * kTouchSlopInDips;
|
| float inner_distance_to_anchor = 2 * kTouchSlopInDips;
|
| - float outer_distance_to_anchor = inner_distance_to_anchor +
|
| - params_.total_num_pixels_covered / 2.0f +
|
| - kTouchSlopInDips;
|
| + float outer_distance_to_anchor =
|
| + inner_distance_to_anchor + params_.total_num_pixels_covered / 2.0f;
|
|
|
| // Move pointers away from each other to zoom in
|
| // or towards each other to zoom out.
|
| if (params_.zoom_in) {
|
| - current_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
|
| - current_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
|
| - target_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
|
| - target_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
|
| + start_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
|
| + start_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
|
| } else {
|
| - current_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
|
| - current_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
|
| - target_y_0_ = params_.anchor.y() - inner_distance_to_anchor;
|
| - target_y_1_ = params_.anchor.y() + inner_distance_to_anchor;
|
| + start_y_0_ = params_.anchor.y() - outer_distance_to_anchor;
|
| + start_y_1_ = params_.anchor.y() + outer_distance_to_anchor;
|
| }
|
| +
|
| + int64 total_duration_in_us = static_cast<int64>(
|
| + 1e6 * (static_cast<double>(params_.total_num_pixels_covered) /
|
| + params_.relative_pointer_speed_in_pixels_s));
|
| + DCHECK_GT(total_duration_in_us, 0);
|
| + stop_time_ =
|
| + start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us);
|
| }
|
|
|
| -float SyntheticPinchGesture::GetDeltaForPointer0(
|
| - const base::TimeDelta& interval) const {
|
| - float total_abs_delta =
|
| - params_.relative_pointer_speed_in_pixels_s * interval.InSecondsF();
|
| +float SyntheticPinchGesture::GetDeltaForPointer0AtTime(
|
| + const base::TimeTicks& timestamp) const {
|
| + float total_abs_delta;
|
|
|
| - // Make sure we're not moving too far in the final step.
|
| - total_abs_delta =
|
| - std::min(total_abs_delta, ComputeAbsoluteRemainingDistance());
|
| + // Make sure the final delta is correct. Using the computation below can lead
|
| + // to issues with floating point precision.
|
| + if (HasReachedTarget(timestamp))
|
| + total_abs_delta = params_.total_num_pixels_covered;
|
| + else
|
| + total_abs_delta = params_.relative_pointer_speed_in_pixels_s *
|
| + (timestamp - start_time_).InSecondsF();
|
|
|
| - float abs_delta_pointer_0 = total_abs_delta / 2;
|
| + float abs_delta_pointer_0 = total_abs_delta / 2.0f;
|
| return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0;
|
| }
|
|
|
| -float SyntheticPinchGesture::ComputeAbsoluteRemainingDistance() const {
|
| - float distance_0 = params_.zoom_in ? (current_y_0_ - target_y_0_)
|
| - : (target_y_0_ - current_y_0_);
|
| - DCHECK_GE(distance_0, 0);
|
| -
|
| - // Both pointers move the same overall distance at the same speed.
|
| - return 2 * distance_0;
|
| +base::TimeTicks SyntheticPinchGesture::ClampTimestamp(
|
| + const base::TimeTicks& timestamp) const {
|
| + return std::min(timestamp, stop_time_);
|
| }
|
|
|
| -bool SyntheticPinchGesture::HasReachedTarget() const {
|
| - return ComputeAbsoluteRemainingDistance() == 0;
|
| +bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp)
|
| + const {
|
| + return timestamp >= stop_time_;
|
| }
|
|
|
| } // namespace content
|
|
|