OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h
" |
| 6 |
| 7 namespace content { |
| 8 namespace { |
| 9 |
| 10 float Lerp(float start, float end, float progress) { |
| 11 return start + progress * (end - start); |
| 12 } |
| 13 |
| 14 } // namespace |
| 15 |
| 16 SyntheticTouchpadPinchGesture::SyntheticTouchpadPinchGesture( |
| 17 const SyntheticPinchGestureParams& params) |
| 18 : params_(params), |
| 19 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), |
| 20 state_(SETUP), |
| 21 current_scale_(1.0f) { |
| 22 DCHECK_GT(params_.scale_factor, 0.0f); |
| 23 } |
| 24 |
| 25 SyntheticTouchpadPinchGesture::~SyntheticTouchpadPinchGesture() {} |
| 26 |
| 27 SyntheticGesture::Result SyntheticTouchpadPinchGesture::ForwardInputEvents( |
| 28 const base::TimeTicks& timestamp, |
| 29 SyntheticGestureTarget* target) { |
| 30 if (state_ == SETUP) { |
| 31 gesture_source_type_ = params_.gesture_source_type; |
| 32 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) |
| 33 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); |
| 34 |
| 35 state_ = STARTED; |
| 36 start_time_ = timestamp; |
| 37 } |
| 38 |
| 39 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); |
| 40 if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) { |
| 41 ForwardGestureEvents(timestamp, target); |
| 42 } else { |
| 43 // Touch input should be using SyntheticTouchscreenPinchGesture. |
| 44 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; |
| 45 } |
| 46 |
| 47 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED |
| 48 : SyntheticGesture::GESTURE_RUNNING; |
| 49 } |
| 50 |
| 51 void SyntheticTouchpadPinchGesture::ForwardGestureEvents( |
| 52 const base::TimeTicks& timestamp, |
| 53 SyntheticGestureTarget* target) { |
| 54 switch (state_) { |
| 55 case STARTED: |
| 56 // Check for an early finish. |
| 57 if (params_.scale_factor == 1.0f) { |
| 58 state_ = DONE; |
| 59 break; |
| 60 } |
| 61 |
| 62 CalculateEndTime(target); |
| 63 |
| 64 // Send the start event. |
| 65 target->DispatchInputEventToPlatform( |
| 66 SyntheticWebGestureEventBuilder::Build( |
| 67 blink::WebGestureEvent::GesturePinchBegin, |
| 68 blink::WebGestureDeviceTouchpad)); |
| 69 state_ = IN_PROGRESS; |
| 70 break; |
| 71 case IN_PROGRESS: { |
| 72 base::TimeTicks event_timestamp = ClampTimestamp(timestamp); |
| 73 |
| 74 float target_scale = CalculateTargetScale(event_timestamp); |
| 75 float incremental_scale = target_scale / current_scale_; |
| 76 current_scale_ = target_scale; |
| 77 |
| 78 // Send the incremental scale event. |
| 79 target->DispatchInputEventToPlatform( |
| 80 SyntheticWebGestureEventBuilder::BuildPinchUpdate( |
| 81 incremental_scale, params_.anchor.x(), params_.anchor.y(), |
| 82 0 /* modifierFlags */, blink::WebGestureDeviceTouchpad)); |
| 83 |
| 84 if (HasReachedTarget(event_timestamp)) { |
| 85 target->DispatchInputEventToPlatform( |
| 86 SyntheticWebGestureEventBuilder::Build( |
| 87 blink::WebGestureEvent::GesturePinchEnd, |
| 88 blink::WebGestureDeviceTouchpad)); |
| 89 state_ = DONE; |
| 90 } |
| 91 break; |
| 92 } |
| 93 case SETUP: |
| 94 NOTREACHED() << "State SETUP invalid for synthetic pinch."; |
| 95 case DONE: |
| 96 NOTREACHED() << "State DONE invalid for synthetic pinch."; |
| 97 } |
| 98 } |
| 99 |
| 100 float SyntheticTouchpadPinchGesture::CalculateTargetScale( |
| 101 const base::TimeTicks& timestamp) const { |
| 102 // Make sure the final delta is correct. Using the computation below can lead |
| 103 // to issues with floating point precision. |
| 104 if (HasReachedTarget(timestamp)) |
| 105 return params_.scale_factor; |
| 106 |
| 107 float progress = (timestamp - start_time_).InSecondsF() / |
| 108 (stop_time_ - start_time_).InSecondsF(); |
| 109 return Lerp(1.0f, params_.scale_factor, progress); |
| 110 } |
| 111 |
| 112 // Calculate an end time based on the amount of scaling to be done and the |
| 113 // |relative_pointer_speed_in_pixels_s|. Because we don't have an actual pixel |
| 114 // delta, we assume that a pinch of 200 pixels is needed to double the screen |
| 115 // size and generate a stop time based on that. |
| 116 // TODO(ericrk): We should not calculate duration from |
| 117 // |relative_pointer_speed_in_pixels_s|, but should instead get a duration from |
| 118 // a SyntheticTouchpadPinchGestureParams type. crbug.com/534976 |
| 119 void SyntheticTouchpadPinchGesture::CalculateEndTime( |
| 120 SyntheticGestureTarget* target) { |
| 121 const int kPixelsNeededToDoubleOrHalve = 200; |
| 122 |
| 123 float scale_factor = params_.scale_factor; |
| 124 if (scale_factor < 1.0f) { |
| 125 // If we are scaling down, calculate the time based on the inverse so that |
| 126 // halving or doubling the scale takes the same amount of time. |
| 127 scale_factor = 1.0f / scale_factor; |
| 128 } |
| 129 float scale_factor_delta = |
| 130 (scale_factor - 1.0f) * kPixelsNeededToDoubleOrHalve; |
| 131 |
| 132 int64 total_duration_in_us = |
| 133 static_cast<int64>(1e6 * (static_cast<double>(scale_factor_delta) / |
| 134 params_.relative_pointer_speed_in_pixels_s)); |
| 135 DCHECK_GT(total_duration_in_us, 0); |
| 136 stop_time_ = |
| 137 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us); |
| 138 } |
| 139 |
| 140 base::TimeTicks SyntheticTouchpadPinchGesture::ClampTimestamp( |
| 141 const base::TimeTicks& timestamp) const { |
| 142 return std::min(timestamp, stop_time_); |
| 143 } |
| 144 |
| 145 bool SyntheticTouchpadPinchGesture::HasReachedTarget( |
| 146 const base::TimeTicks& timestamp) const { |
| 147 return timestamp >= stop_time_; |
| 148 } |
| 149 |
| 150 } // namespace content |
OLD | NEW |