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 |