Chromium Code Reviews| 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..8b03d941bc8778ffbb8d966d3833d3a4f4086797 |
| --- /dev/null |
| +++ b/content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc |
| @@ -0,0 +1,152 @@ |
| +// 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" |
| + |
| +#include <cmath> |
| + |
| +#include "base/logging.h" |
| +#include "ui/events/latency_info.h" |
|
jdduke (slow)
2015/09/22 18:52:37
Do we need the latency_info include?
ericrk
2015/09/22 21:46:26
nope.
|
| + |
| +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. |
| +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)); |
|
jdduke (slow)
2015/09/22 18:52:37
Hmm, yeah, this parameter should really have just
ericrk
2015/09/22 21:46:26
Done - filed a bug as well.
|
| + 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 |