| Index: content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc
|
| diff --git a/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc b/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..0bf75acb6a6e92896094e654d610e9fb1baf8e53
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc
|
| @@ -0,0 +1,150 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h"
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +float Lerp(float start, float end, float progress) {
|
| + return start + progress * (end - start);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +SyntheticTouchpadPinchGesture::SyntheticTouchpadPinchGesture(
|
| + const SyntheticPinchGestureParams& params)
|
| + : params_(params),
|
| + gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
|
| + state_(SETUP),
|
| + current_scale_(1.0f) {
|
| + DCHECK_GT(params_.scale_factor, 0.0f);
|
| +}
|
| +
|
| +SyntheticTouchpadPinchGesture::~SyntheticTouchpadPinchGesture() {}
|
| +
|
| +SyntheticGesture::Result SyntheticTouchpadPinchGesture::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;
|
| + start_time_ = timestamp;
|
| + }
|
| +
|
| + DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
|
| + if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) {
|
| + ForwardGestureEvents(timestamp, target);
|
| + } else {
|
| + // Touch input should be using SyntheticTouchscreenPinchGesture.
|
| + return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
|
| + }
|
| +
|
| + return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
|
| + : SyntheticGesture::GESTURE_RUNNING;
|
| +}
|
| +
|
| +void SyntheticTouchpadPinchGesture::ForwardGestureEvents(
|
| + const base::TimeTicks& timestamp,
|
| + SyntheticGestureTarget* target) {
|
| + switch (state_) {
|
| + case STARTED:
|
| + // Check for an early finish.
|
| + if (params_.scale_factor == 1.0f) {
|
| + state_ = DONE;
|
| + break;
|
| + }
|
| +
|
| + CalculateEndTime(target);
|
| +
|
| + // Send the start event.
|
| + target->DispatchInputEventToPlatform(
|
| + SyntheticWebGestureEventBuilder::Build(
|
| + blink::WebGestureEvent::GesturePinchBegin,
|
| + blink::WebGestureDeviceTouchpad));
|
| + state_ = IN_PROGRESS;
|
| + break;
|
| + case IN_PROGRESS: {
|
| + base::TimeTicks event_timestamp = ClampTimestamp(timestamp);
|
| +
|
| + float target_scale = CalculateTargetScale(event_timestamp);
|
| + float incremental_scale = target_scale / current_scale_;
|
| + current_scale_ = target_scale;
|
| +
|
| + // Send the incremental scale event.
|
| + target->DispatchInputEventToPlatform(
|
| + SyntheticWebGestureEventBuilder::BuildPinchUpdate(
|
| + incremental_scale, params_.anchor.x(), params_.anchor.y(),
|
| + 0 /* modifierFlags */, blink::WebGestureDeviceTouchpad));
|
| +
|
| + if (HasReachedTarget(event_timestamp)) {
|
| + target->DispatchInputEventToPlatform(
|
| + SyntheticWebGestureEventBuilder::Build(
|
| + blink::WebGestureEvent::GesturePinchEnd,
|
| + blink::WebGestureDeviceTouchpad));
|
| + state_ = DONE;
|
| + }
|
| + break;
|
| + }
|
| + case SETUP:
|
| + NOTREACHED() << "State SETUP invalid for synthetic pinch.";
|
| + case DONE:
|
| + NOTREACHED() << "State DONE invalid for synthetic pinch.";
|
| + }
|
| +}
|
| +
|
| +float SyntheticTouchpadPinchGesture::CalculateTargetScale(
|
| + 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 (HasReachedTarget(timestamp))
|
| + return params_.scale_factor;
|
| +
|
| + float progress = (timestamp - start_time_).InSecondsF() /
|
| + (stop_time_ - start_time_).InSecondsF();
|
| + return Lerp(1.0f, params_.scale_factor, progress);
|
| +}
|
| +
|
| +// Calculate an end time based on the amount of scaling to be done and the
|
| +// |relative_pointer_speed_in_pixels_s|. Because we don't have an actual pixel
|
| +// delta, we assume that a pinch of 200 pixels is needed to double the screen
|
| +// size and generate a stop time based on that.
|
| +// TODO(ericrk): We should not calculate duration from
|
| +// |relative_pointer_speed_in_pixels_s|, but should instead get a duration from
|
| +// a SyntheticTouchpadPinchGestureParams type. crbug.com/534976
|
| +void SyntheticTouchpadPinchGesture::CalculateEndTime(
|
| + SyntheticGestureTarget* target) {
|
| + const int kPixelsNeededToDoubleOrHalve = 200;
|
| +
|
| + float scale_factor = params_.scale_factor;
|
| + if (scale_factor < 1.0f) {
|
| + // If we are scaling down, calculate the time based on the inverse so that
|
| + // halving or doubling the scale takes the same amount of time.
|
| + scale_factor = 1.0f / scale_factor;
|
| + }
|
| + float scale_factor_delta =
|
| + (scale_factor - 1.0f) * kPixelsNeededToDoubleOrHalve;
|
| +
|
| + int64 total_duration_in_us =
|
| + static_cast<int64>(1e6 * (static_cast<double>(scale_factor_delta) /
|
| + 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);
|
| +}
|
| +
|
| +base::TimeTicks SyntheticTouchpadPinchGesture::ClampTimestamp(
|
| + const base::TimeTicks& timestamp) const {
|
| + return std::min(timestamp, stop_time_);
|
| +}
|
| +
|
| +bool SyntheticTouchpadPinchGesture::HasReachedTarget(
|
| + const base::TimeTicks& timestamp) const {
|
| + return timestamp >= stop_time_;
|
| +}
|
| +
|
| +} // namespace content
|
|
|