| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/input/synthetic_pinch_gesture.h" | 5 #include "content/browser/renderer_host/input/synthetic_touchscreen_pinch_gestur
e.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "ui/events/latency_info.h" | 10 #include "ui/events/latency_info.h" |
| 11 | 11 |
| 12 namespace content { | 12 namespace content { |
| 13 | 13 |
| 14 SyntheticPinchGesture::SyntheticPinchGesture( | 14 SyntheticTouchscreenPinchGesture::SyntheticTouchscreenPinchGesture( |
| 15 const SyntheticPinchGestureParams& params) | 15 const SyntheticPinchGestureParams& params) |
| 16 : params_(params), | 16 : params_(params), |
| 17 start_y_0_(0.0f), | 17 start_y_0_(0.0f), |
| 18 start_y_1_(0.0f), | 18 start_y_1_(0.0f), |
| 19 max_pointer_delta_0_(0.0f), | 19 max_pointer_delta_0_(0.0f), |
| 20 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), | 20 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), |
| 21 state_(SETUP) { | 21 state_(SETUP) { |
| 22 DCHECK_GT(params_.scale_factor, 0.0f); | 22 DCHECK_GT(params_.scale_factor, 0.0f); |
| 23 } | 23 } |
| 24 | 24 |
| 25 SyntheticPinchGesture::~SyntheticPinchGesture() {} | 25 SyntheticTouchscreenPinchGesture::~SyntheticTouchscreenPinchGesture() {} |
| 26 | 26 |
| 27 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents( | 27 SyntheticGesture::Result SyntheticTouchscreenPinchGesture::ForwardInputEvents( |
| 28 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { | 28 const base::TimeTicks& timestamp, |
| 29 SyntheticGestureTarget* target) { |
| 29 if (state_ == SETUP) { | 30 if (state_ == SETUP) { |
| 30 gesture_source_type_ = params_.gesture_source_type; | 31 gesture_source_type_ = params_.gesture_source_type; |
| 31 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) | 32 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) |
| 32 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); | 33 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); |
| 33 | 34 |
| 34 state_ = STARTED; | 35 state_ = STARTED; |
| 35 start_time_ = timestamp; | 36 start_time_ = timestamp; |
| 36 } | 37 } |
| 37 | 38 |
| 38 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); | 39 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); |
| 39 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) | 40 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) { |
| 40 ForwardTouchInputEvents(timestamp, target); | 41 ForwardTouchInputEvents(timestamp, target); |
| 41 else | 42 } else { |
| 42 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; | 43 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; |
| 44 } |
| 43 | 45 |
| 44 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED | 46 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED |
| 45 : SyntheticGesture::GESTURE_RUNNING; | 47 : SyntheticGesture::GESTURE_RUNNING; |
| 46 } | 48 } |
| 47 | 49 |
| 48 void SyntheticPinchGesture::ForwardTouchInputEvents( | 50 void SyntheticTouchscreenPinchGesture::ForwardTouchInputEvents( |
| 49 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { | 51 const base::TimeTicks& timestamp, |
| 52 SyntheticGestureTarget* target) { |
| 50 switch (state_) { | 53 switch (state_) { |
| 51 case STARTED: | 54 case STARTED: |
| 52 // Check for an early finish. | 55 // Check for an early finish. |
| 53 if (params_.scale_factor == 1.0f) { | 56 if (params_.scale_factor == 1.0f) { |
| 54 state_ = DONE; | 57 state_ = DONE; |
| 55 break; | 58 break; |
| 56 } | 59 } |
| 57 SetupCoordinatesAndStopTime(target); | 60 SetupCoordinatesAndStopTime(target); |
| 58 PressTouchPoints(target, timestamp); | 61 PressTouchPoints(target, timestamp); |
| 59 state_ = MOVING; | 62 state_ = MOVING; |
| 60 break; | 63 break; |
| 61 case MOVING: { | 64 case MOVING: { |
| 62 base::TimeTicks event_timestamp = ClampTimestamp(timestamp); | 65 base::TimeTicks event_timestamp = ClampTimestamp(timestamp); |
| 63 float delta = GetDeltaForPointer0AtTime(event_timestamp); | 66 float delta = GetDeltaForPointer0AtTime(event_timestamp); |
| 64 MoveTouchPoints(target, delta, event_timestamp); | 67 MoveTouchPoints(target, delta, event_timestamp); |
| 65 if (HasReachedTarget(event_timestamp)) { | 68 if (HasReachedTarget(event_timestamp)) { |
| 66 ReleaseTouchPoints(target, event_timestamp); | 69 ReleaseTouchPoints(target, event_timestamp); |
| 67 state_ = DONE; | 70 state_ = DONE; |
| 68 } | 71 } |
| 69 } break; | 72 } break; |
| 70 case SETUP: | 73 case SETUP: |
| 71 NOTREACHED() << "State SETUP invalid for synthetic pinch."; | 74 NOTREACHED() << "State SETUP invalid for synthetic pinch."; |
| 72 case DONE: | 75 case DONE: |
| 73 NOTREACHED() << "State DONE invalid for synthetic pinch."; | 76 NOTREACHED() << "State DONE invalid for synthetic pinch."; |
| 74 } | 77 } |
| 75 } | 78 } |
| 76 | 79 |
| 77 void SyntheticPinchGesture::PressTouchPoints(SyntheticGestureTarget* target, | 80 void SyntheticTouchscreenPinchGesture::PressTouchPoints( |
| 78 const base::TimeTicks& timestamp) { | 81 SyntheticGestureTarget* target, |
| 82 const base::TimeTicks& timestamp) { |
| 79 touch_event_.PressPoint(params_.anchor.x(), start_y_0_); | 83 touch_event_.PressPoint(params_.anchor.x(), start_y_0_); |
| 80 touch_event_.PressPoint(params_.anchor.x(), start_y_1_); | 84 touch_event_.PressPoint(params_.anchor.x(), start_y_1_); |
| 81 ForwardTouchEvent(target, timestamp); | 85 ForwardTouchEvent(target, timestamp); |
| 82 } | 86 } |
| 83 | 87 |
| 84 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target, | 88 void SyntheticTouchscreenPinchGesture::MoveTouchPoints( |
| 85 float delta, | 89 SyntheticGestureTarget* target, |
| 86 const base::TimeTicks& timestamp) { | 90 float delta, |
| 91 const base::TimeTicks& timestamp) { |
| 87 // The two pointers move in opposite directions. | 92 // The two pointers move in opposite directions. |
| 88 float current_y_0 = start_y_0_ + delta; | 93 float current_y_0 = start_y_0_ + delta; |
| 89 float current_y_1 = start_y_1_ - delta; | 94 float current_y_1 = start_y_1_ - delta; |
| 90 | 95 |
| 91 touch_event_.MovePoint(0, params_.anchor.x(), current_y_0); | 96 touch_event_.MovePoint(0, params_.anchor.x(), current_y_0); |
| 92 touch_event_.MovePoint(1, params_.anchor.x(), current_y_1); | 97 touch_event_.MovePoint(1, params_.anchor.x(), current_y_1); |
| 93 ForwardTouchEvent(target, timestamp); | 98 ForwardTouchEvent(target, timestamp); |
| 94 } | 99 } |
| 95 | 100 |
| 96 void SyntheticPinchGesture::ReleaseTouchPoints( | 101 void SyntheticTouchscreenPinchGesture::ReleaseTouchPoints( |
| 97 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { | 102 SyntheticGestureTarget* target, |
| 103 const base::TimeTicks& timestamp) { |
| 98 touch_event_.ReleasePoint(0); | 104 touch_event_.ReleasePoint(0); |
| 99 touch_event_.ReleasePoint(1); | 105 touch_event_.ReleasePoint(1); |
| 100 ForwardTouchEvent(target, timestamp); | 106 ForwardTouchEvent(target, timestamp); |
| 101 } | 107 } |
| 102 | 108 |
| 103 void SyntheticPinchGesture::ForwardTouchEvent( | 109 void SyntheticTouchscreenPinchGesture::ForwardTouchEvent( |
| 104 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { | 110 SyntheticGestureTarget* target, |
| 111 const base::TimeTicks& timestamp) { |
| 105 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); | 112 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); |
| 106 target->DispatchInputEventToPlatform(touch_event_); | 113 target->DispatchInputEventToPlatform(touch_event_); |
| 107 } | 114 } |
| 108 | 115 |
| 109 void SyntheticPinchGesture::SetupCoordinatesAndStopTime( | 116 void SyntheticTouchscreenPinchGesture::SetupCoordinatesAndStopTime( |
| 110 SyntheticGestureTarget* target) { | 117 SyntheticGestureTarget* target) { |
| 111 // To achieve the specified scaling factor, the ratio of the final to the | 118 // To achieve the specified scaling factor, the ratio of the final to the |
| 112 // initial span (distance between the pointers) has to be equal to the scaling | 119 // initial span (distance between the pointers) has to be equal to the scaling |
| 113 // factor. Since we're moving both pointers at the same speed, each pointer's | 120 // factor. Since we're moving both pointers at the same speed, each pointer's |
| 114 // distance to the anchor is half the span. | 121 // distance to the anchor is half the span. |
| 115 float initial_distance_to_anchor, final_distance_to_anchor; | 122 float initial_distance_to_anchor, final_distance_to_anchor; |
| 116 if (params_.scale_factor > 1.0f) { // zooming in | 123 if (params_.scale_factor > 1.0f) { // zooming in |
| 117 initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; | 124 initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; |
| 118 final_distance_to_anchor = | 125 final_distance_to_anchor = |
| 119 (initial_distance_to_anchor + target->GetTouchSlopInDips()) * | 126 (initial_distance_to_anchor + target->GetTouchSlopInDips()) * |
| 120 params_.scale_factor; | 127 params_.scale_factor; |
| 121 } else { // zooming out | 128 } else { // zooming out |
| 122 final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; | 129 final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; |
| 123 initial_distance_to_anchor = | 130 initial_distance_to_anchor = |
| 124 (final_distance_to_anchor / params_.scale_factor) + | 131 (final_distance_to_anchor / params_.scale_factor) + |
| 125 target->GetTouchSlopInDips(); | 132 target->GetTouchSlopInDips(); |
| 126 } | 133 } |
| 127 | 134 |
| 128 start_y_0_ = params_.anchor.y() - initial_distance_to_anchor; | 135 start_y_0_ = params_.anchor.y() - initial_distance_to_anchor; |
| 129 start_y_1_ = params_.anchor.y() + initial_distance_to_anchor; | 136 start_y_1_ = params_.anchor.y() + initial_distance_to_anchor; |
| 130 | 137 |
| 131 max_pointer_delta_0_ = initial_distance_to_anchor - final_distance_to_anchor; | 138 max_pointer_delta_0_ = initial_distance_to_anchor - final_distance_to_anchor; |
| 132 | 139 |
| 133 int64 total_duration_in_us = static_cast<int64>( | 140 int64 total_duration_in_us = static_cast<int64>( |
| 134 1e6 * (static_cast<double>(std::abs(2 * max_pointer_delta_0_)) / | 141 1e6 * (static_cast<double>(std::abs(2 * max_pointer_delta_0_)) / |
| 135 params_.relative_pointer_speed_in_pixels_s)); | 142 params_.relative_pointer_speed_in_pixels_s)); |
| 136 DCHECK_GT(total_duration_in_us, 0); | 143 DCHECK_GT(total_duration_in_us, 0); |
| 137 stop_time_ = | 144 stop_time_ = |
| 138 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us); | 145 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us); |
| 139 } | 146 } |
| 140 | 147 |
| 141 float SyntheticPinchGesture::GetDeltaForPointer0AtTime( | 148 float SyntheticTouchscreenPinchGesture::GetDeltaForPointer0AtTime( |
| 142 const base::TimeTicks& timestamp) const { | 149 const base::TimeTicks& timestamp) const { |
| 143 // Make sure the final delta is correct. Using the computation below can lead | 150 // Make sure the final delta is correct. Using the computation below can lead |
| 144 // to issues with floating point precision. | 151 // to issues with floating point precision. |
| 145 if (HasReachedTarget(timestamp)) | 152 if (HasReachedTarget(timestamp)) |
| 146 return max_pointer_delta_0_; | 153 return max_pointer_delta_0_; |
| 147 | 154 |
| 148 float total_abs_delta = params_.relative_pointer_speed_in_pixels_s * | 155 float total_abs_delta = params_.relative_pointer_speed_in_pixels_s * |
| 149 (timestamp - start_time_).InSecondsF(); | 156 (timestamp - start_time_).InSecondsF(); |
| 150 float abs_delta_pointer_0 = total_abs_delta / 2.0f; | 157 float abs_delta_pointer_0 = total_abs_delta / 2.0f; |
| 151 return (params_.scale_factor > 1.0f) ? -abs_delta_pointer_0 | 158 return (params_.scale_factor > 1.0f) ? -abs_delta_pointer_0 |
| 152 : abs_delta_pointer_0; | 159 : abs_delta_pointer_0; |
| 153 } | 160 } |
| 154 | 161 |
| 155 base::TimeTicks SyntheticPinchGesture::ClampTimestamp( | 162 base::TimeTicks SyntheticTouchscreenPinchGesture::ClampTimestamp( |
| 156 const base::TimeTicks& timestamp) const { | 163 const base::TimeTicks& timestamp) const { |
| 157 return std::min(timestamp, stop_time_); | 164 return std::min(timestamp, stop_time_); |
| 158 } | 165 } |
| 159 | 166 |
| 160 bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp) | 167 bool SyntheticTouchscreenPinchGesture::HasReachedTarget( |
| 161 const { | 168 const base::TimeTicks& timestamp) const { |
| 162 return timestamp >= stop_time_; | 169 return timestamp >= stop_time_; |
| 163 } | 170 } |
| 164 | 171 |
| 165 } // namespace content | 172 } // namespace content |
| OLD | NEW |