Chromium Code Reviews| 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..b65533ed4e45a246aa835d1e7f8dc5ac90b82e21 100644 |
| --- a/content/browser/renderer_host/input/synthetic_pinch_gesture.cc |
| +++ b/content/browser/renderer_host/input/synthetic_pinch_gesture.cc |
| @@ -15,8 +15,8 @@ namespace content { |
| SyntheticPinchGesture::SyntheticPinchGesture( |
| const SyntheticPinchGestureParams& params) |
| : params_(params), |
| - current_y_0_(0.0f), |
| - current_y_1_(0.0f), |
| + start_y_0_(0.0f), |
| + start_y_1_(0.0f), |
| target_y_0_(0.0f), |
| target_y_1_(0.0f), |
| gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), |
| @@ -27,7 +27,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 +37,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 +51,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 +59,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 +79,97 @@ 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; |
| + 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; |
| + start_y_0_ = params_.anchor.y() - inner_distance_to_anchor; |
| + start_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; |
| } else { |
| - current_y_0_ = params_.anchor.y() - outer_distance_to_anchor; |
| - current_y_1_ = params_.anchor.y() + outer_distance_to_anchor; |
| + start_y_0_ = params_.anchor.y() - outer_distance_to_anchor; |
| + start_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; |
| } |
| + |
| + int64 total_duration_in_us = static_cast<int64>( |
| + 1e6 * (params_.total_num_pixels_covered / |
| + params_.relative_pointer_speed_in_pixels_s)); |
| + 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 (timestamp == stop_time_) |
|
jdduke (slow)
2014/01/06 21:41:14
if (HasReachedTarget(distance))
|
| + 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_; |
|
jdduke (slow)
2014/01/06 21:41:14
Same as with scroll, let's generalize this by:
re
|
| } |
| } // namespace content |