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_pinch_gesture.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 SyntheticPinchGesture::SyntheticPinchGesture( |
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 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), | 20 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), |
20 state_(SETUP) { | 21 state_(SETUP) { |
21 DCHECK_GE(params_.total_num_pixels_covered, 0); | 22 DCHECK_GT(params_.scale_factor, 0.0f); |
22 } | 23 } |
23 | 24 |
24 SyntheticPinchGesture::~SyntheticPinchGesture() {} | 25 SyntheticPinchGesture::~SyntheticPinchGesture() {} |
25 | 26 |
26 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents( | 27 SyntheticGesture::Result SyntheticPinchGesture::ForwardInputEvents( |
27 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { | 28 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { |
28 if (state_ == SETUP) { | 29 if (state_ == SETUP) { |
29 gesture_source_type_ = params_.gesture_source_type; | 30 gesture_source_type_ = params_.gesture_source_type; |
30 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) | 31 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) |
31 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); | 32 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); |
(...skipping 10 matching lines...) Expand all Loading... |
42 | 43 |
43 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED | 44 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED |
44 : SyntheticGesture::GESTURE_RUNNING; | 45 : SyntheticGesture::GESTURE_RUNNING; |
45 } | 46 } |
46 | 47 |
47 void SyntheticPinchGesture::ForwardTouchInputEvents( | 48 void SyntheticPinchGesture::ForwardTouchInputEvents( |
48 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { | 49 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) { |
49 switch (state_) { | 50 switch (state_) { |
50 case STARTED: | 51 case STARTED: |
51 // Check for an early finish. | 52 // Check for an early finish. |
52 if (params_.total_num_pixels_covered == 0) { | 53 if (params_.scale_factor == 1.0f) { |
53 state_ = DONE; | 54 state_ = DONE; |
54 break; | 55 break; |
55 } | 56 } |
56 SetupCoordinatesAndStopTime(target); | 57 SetupCoordinatesAndStopTime(target); |
57 PressTouchPoints(target, timestamp); | 58 PressTouchPoints(target, timestamp); |
58 state_ = MOVING; | 59 state_ = MOVING; |
59 break; | 60 break; |
60 case MOVING: { | 61 case MOVING: { |
61 base::TimeTicks event_timestamp = ClampTimestamp(timestamp); | 62 base::TimeTicks event_timestamp = ClampTimestamp(timestamp); |
62 float delta = GetDeltaForPointer0AtTime(event_timestamp); | 63 float delta = GetDeltaForPointer0AtTime(event_timestamp); |
(...skipping 17 matching lines...) Expand all Loading... |
80 ForwardTouchEvent(target, timestamp); | 81 ForwardTouchEvent(target, timestamp); |
81 } | 82 } |
82 | 83 |
83 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target, | 84 void SyntheticPinchGesture::MoveTouchPoints(SyntheticGestureTarget* target, |
84 float delta, | 85 float delta, |
85 const base::TimeTicks& timestamp) { | 86 const base::TimeTicks& timestamp) { |
86 // The two pointers move in opposite directions. | 87 // The two pointers move in opposite directions. |
87 float current_y_0 = start_y_0_ + delta; | 88 float current_y_0 = start_y_0_ + delta; |
88 float current_y_1 = start_y_1_ - delta; | 89 float current_y_1 = start_y_1_ - delta; |
89 | 90 |
90 // The current pointer positions are stored as float but the pointer | 91 touch_event_.MovePoint(0, params_.anchor.x(), current_y_0); |
91 // coordinates of the input event are integers. Floor both positions so that | 92 touch_event_.MovePoint(1, params_.anchor.x(), current_y_1); |
92 // in case of an odd distance one of the pointers (the one whose position goes | |
93 // down) moves one pixel further than the other. The explicit flooring is only | |
94 // needed for negative values. | |
95 touch_event_.MovePoint(0, params_.anchor.x(), floor(current_y_0)); | |
96 touch_event_.MovePoint(1, params_.anchor.x(), floor(current_y_1)); | |
97 ForwardTouchEvent(target, timestamp); | 93 ForwardTouchEvent(target, timestamp); |
98 } | 94 } |
99 | 95 |
100 void SyntheticPinchGesture::ReleaseTouchPoints( | 96 void SyntheticPinchGesture::ReleaseTouchPoints( |
101 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { | 97 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { |
102 touch_event_.ReleasePoint(0); | 98 touch_event_.ReleasePoint(0); |
103 touch_event_.ReleasePoint(1); | 99 touch_event_.ReleasePoint(1); |
104 ForwardTouchEvent(target, timestamp); | 100 ForwardTouchEvent(target, timestamp); |
105 } | 101 } |
106 | 102 |
107 void SyntheticPinchGesture::ForwardTouchEvent( | 103 void SyntheticPinchGesture::ForwardTouchEvent( |
108 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { | 104 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) { |
109 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); | 105 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp); |
110 target->DispatchInputEventToPlatform(touch_event_); | 106 target->DispatchInputEventToPlatform(touch_event_); |
111 } | 107 } |
112 | 108 |
113 void SyntheticPinchGesture::SetupCoordinatesAndStopTime( | 109 void SyntheticPinchGesture::SetupCoordinatesAndStopTime( |
114 SyntheticGestureTarget* target) { | 110 SyntheticGestureTarget* target) { |
115 const int kTouchSlopInDips = target->GetTouchSlopInDips(); | 111 // To achieve the specified scaling factor, the ratio of the final to the |
116 params_.total_num_pixels_covered += 2 * kTouchSlopInDips; | 112 // initial span (distance between the pointers) has to be equal to the scaling |
117 float inner_distance_to_anchor = 2 * kTouchSlopInDips; | 113 // factor. Since we're moving both pointers at the same speed, each pointer's |
118 float outer_distance_to_anchor = | 114 // distance to the anchor is half the span. |
119 inner_distance_to_anchor + params_.total_num_pixels_covered / 2.0f; | 115 float initial_distance_to_anchor, final_distance_to_anchor; |
120 | 116 if (params_.scale_factor > 1.0f) { // zooming in |
121 // Move pointers away from each other to zoom in | 117 initial_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; |
122 // or towards each other to zoom out. | 118 final_distance_to_anchor = |
123 if (params_.zoom_in) { | 119 (initial_distance_to_anchor + target->GetTouchSlopInDips()) * |
124 start_y_0_ = params_.anchor.y() - inner_distance_to_anchor; | 120 params_.scale_factor; |
125 start_y_1_ = params_.anchor.y() + inner_distance_to_anchor; | 121 } else { // zooming out |
126 } else { | 122 final_distance_to_anchor = target->GetMinScalingSpanInDips() / 2.0f; |
127 start_y_0_ = params_.anchor.y() - outer_distance_to_anchor; | 123 initial_distance_to_anchor = |
128 start_y_1_ = params_.anchor.y() + outer_distance_to_anchor; | 124 (final_distance_to_anchor / params_.scale_factor) + |
| 125 target->GetTouchSlopInDips(); |
129 } | 126 } |
130 | 127 |
| 128 start_y_0_ = params_.anchor.y() - initial_distance_to_anchor; |
| 129 start_y_1_ = params_.anchor.y() + initial_distance_to_anchor; |
| 130 |
| 131 max_pointer_delta_0_ = initial_distance_to_anchor - final_distance_to_anchor; |
| 132 |
131 int64 total_duration_in_us = static_cast<int64>( | 133 int64 total_duration_in_us = static_cast<int64>( |
132 1e6 * (static_cast<double>(params_.total_num_pixels_covered) / | 134 1e6 * (static_cast<double>(std::abs(2 * max_pointer_delta_0_)) / |
133 params_.relative_pointer_speed_in_pixels_s)); | 135 params_.relative_pointer_speed_in_pixels_s)); |
134 DCHECK_GT(total_duration_in_us, 0); | 136 DCHECK_GT(total_duration_in_us, 0); |
135 stop_time_ = | 137 stop_time_ = |
136 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us); | 138 start_time_ + base::TimeDelta::FromMicroseconds(total_duration_in_us); |
137 } | 139 } |
138 | 140 |
139 float SyntheticPinchGesture::GetDeltaForPointer0AtTime( | 141 float SyntheticPinchGesture::GetDeltaForPointer0AtTime( |
140 const base::TimeTicks& timestamp) const { | 142 const base::TimeTicks& timestamp) const { |
141 float total_abs_delta; | |
142 | |
143 // Make sure the final delta is correct. Using the computation below can lead | 143 // Make sure the final delta is correct. Using the computation below can lead |
144 // to issues with floating point precision. | 144 // to issues with floating point precision. |
145 if (HasReachedTarget(timestamp)) | 145 if (HasReachedTarget(timestamp)) |
146 total_abs_delta = params_.total_num_pixels_covered; | 146 return max_pointer_delta_0_; |
147 else | |
148 total_abs_delta = params_.relative_pointer_speed_in_pixels_s * | |
149 (timestamp - start_time_).InSecondsF(); | |
150 | 147 |
| 148 float total_abs_delta = params_.relative_pointer_speed_in_pixels_s * |
| 149 (timestamp - start_time_).InSecondsF(); |
151 float abs_delta_pointer_0 = total_abs_delta / 2.0f; | 150 float abs_delta_pointer_0 = total_abs_delta / 2.0f; |
152 return params_.zoom_in ? -abs_delta_pointer_0 : abs_delta_pointer_0; | 151 return (params_.scale_factor > 1.0f) ? -abs_delta_pointer_0 |
| 152 : abs_delta_pointer_0; |
153 } | 153 } |
154 | 154 |
155 base::TimeTicks SyntheticPinchGesture::ClampTimestamp( | 155 base::TimeTicks SyntheticPinchGesture::ClampTimestamp( |
156 const base::TimeTicks& timestamp) const { | 156 const base::TimeTicks& timestamp) const { |
157 return std::min(timestamp, stop_time_); | 157 return std::min(timestamp, stop_time_); |
158 } | 158 } |
159 | 159 |
160 bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp) | 160 bool SyntheticPinchGesture::HasReachedTarget(const base::TimeTicks& timestamp) |
161 const { | 161 const { |
162 return timestamp >= stop_time_; | 162 return timestamp >= stop_time_; |
163 } | 163 } |
164 | 164 |
165 } // namespace content | 165 } // namespace content |
OLD | NEW |