Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(182)

Side by Side Diff: content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc

Issue 119323007: Add timestamps to synthesized events. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleanup. Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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_smooth_scroll_gesture.h" 5 #include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/common/input/input_event.h" 8 #include "content/common/input/input_event.h"
9 #include "ui/events/latency_info.h" 9 #include "ui/events/latency_info.h"
10 #include "ui/gfx/point_f.h" 10 #include "ui/gfx/point_f.h"
(...skipping 17 matching lines...) Expand all
28 28
29 SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture( 29 SyntheticSmoothScrollGesture::SyntheticSmoothScrollGesture(
30 const SyntheticSmoothScrollGestureParams& params) 30 const SyntheticSmoothScrollGestureParams& params)
31 : params_(params), 31 : params_(params),
32 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT), 32 gesture_source_type_(SyntheticGestureParams::DEFAULT_INPUT),
33 state_(SETUP) {} 33 state_(SETUP) {}
34 34
35 SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() {} 35 SyntheticSmoothScrollGesture::~SyntheticSmoothScrollGesture() {}
36 36
37 SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents( 37 SyntheticGesture::Result SyntheticSmoothScrollGesture::ForwardInputEvents(
38 const base::TimeDelta& interval, SyntheticGestureTarget* target) { 38 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
39 if (state_ == SETUP) { 39 if (state_ == SETUP) {
40 gesture_source_type_ = params_.gesture_source_type; 40 gesture_source_type_ = params_.gesture_source_type;
41 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT) 41 if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
42 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType(); 42 gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
43 43
44 if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_)) 44 if (!target->SupportsSyntheticGestureSourceType(gesture_source_type_))
45 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM; 45 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_SUPPORTED_BY_PLATFORM;
46 46
47 state_ = STARTED; 47 state_ = STARTED;
48 start_time_ = timestamp;
48 } 49 }
49 50
50 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT); 51 DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
51 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT) 52 if (gesture_source_type_ == SyntheticGestureParams::TOUCH_INPUT)
52 ForwardTouchInputEvents(interval, target); 53 ForwardTouchInputEvents(timestamp, target);
53 else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT) 54 else if (gesture_source_type_ == SyntheticGestureParams::MOUSE_INPUT)
54 ForwardMouseInputEvents(interval, target); 55 ForwardMouseInputEvents(timestamp, target);
55 else 56 else
56 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED; 57 return SyntheticGesture::GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED;
57 58
58 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED 59 return (state_ == DONE) ? SyntheticGesture::GESTURE_FINISHED
59 : SyntheticGesture::GESTURE_RUNNING; 60 : SyntheticGesture::GESTURE_RUNNING;
60 } 61 }
61 62
62 void SyntheticSmoothScrollGesture::ForwardTouchInputEvents( 63 void SyntheticSmoothScrollGesture::ForwardTouchInputEvents(
63 const base::TimeDelta& interval, SyntheticGestureTarget* target) { 64 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
65 base::TimeTicks event_timestamp = timestamp;
64 switch (state_) { 66 switch (state_) {
65 case STARTED: 67 case STARTED:
66 // Check for an early finish. 68 // Check for an early finish.
67 if (params_.distance.IsZero()) { 69 if (params_.distance.IsZero()) {
68 state_ = DONE; 70 state_ = DONE;
69 break; 71 break;
70 } 72 }
71 AddTouchSlopToDistance(target); 73 AddTouchSlopToDistance(target);
72 PressTouchPoint(target); 74 PressTouchPoint(target, event_timestamp);
73 state_ = MOVING; 75 state_ = MOVING;
74 break; 76 break;
75 case MOVING: 77 case MOVING: {
76 total_delta_ += GetPositionDelta(interval); 78 gfx::Vector2dF delta =
77 MoveTouchPoint(target); 79 GetPositionDeltaAndUpdateTimestamp(&event_timestamp);
80 MoveTouchPoint(target, delta, event_timestamp);
78 81
79 if (HasScrolledEntireDistance()) { 82 if (HasScrolledEntireDistance(delta)) {
80 if (params_.prevent_fling) { 83 if (params_.prevent_fling) {
84 stopping_start_time_ = event_timestamp;
81 state_ = STOPPING; 85 state_ = STOPPING;
82 } else { 86 } else {
83 ReleaseTouchPoint(target); 87 ReleaseTouchPoint(target, event_timestamp);
84 state_ = DONE; 88 state_ = DONE;
85 } 89 }
86 } 90 }
87 break; 91 } break;
88 case STOPPING: 92 case STOPPING:
89 total_stopping_wait_time_ += interval; 93 if (timestamp - stopping_start_time_ >=
90 if (total_stopping_wait_time_ >= target->PointerAssumedStoppedTime()) { 94 target->PointerAssumedStoppedTime()) {
95 event_timestamp =
96 stopping_start_time_ + target->PointerAssumedStoppedTime();
91 // Send one last move event, but don't change the location. Without this 97 // Send one last move event, but don't change the location. Without this
92 // we'd still sometimes cause a fling on Android. 98 // we'd still sometimes cause a fling on Android.
93 MoveTouchPoint(target); 99 ForwardTouchEvent(target, event_timestamp);
94 ReleaseTouchPoint(target); 100 ReleaseTouchPoint(target, event_timestamp);
95 state_ = DONE; 101 state_ = DONE;
96 } 102 }
97 break; 103 break;
98 case SETUP: 104 case SETUP:
99 NOTREACHED() 105 NOTREACHED()
100 << "State STARTED invalid for synthetic scroll using touch input."; 106 << "State STARTED invalid for synthetic scroll using touch input.";
101 case DONE: 107 case DONE:
102 NOTREACHED() 108 NOTREACHED()
103 << "State DONE invalid for synthetic scroll using touch input."; 109 << "State DONE invalid for synthetic scroll using touch input.";
104 } 110 }
105 } 111 }
106 112
107 void SyntheticSmoothScrollGesture::ForwardMouseInputEvents( 113 void SyntheticSmoothScrollGesture::ForwardMouseInputEvents(
108 const base::TimeDelta& interval, SyntheticGestureTarget* target) { 114 const base::TimeTicks& timestamp, SyntheticGestureTarget* target) {
109 switch (state_) { 115 switch (state_) {
110 case STARTED: 116 case STARTED:
111 // Check for an early finish. 117 // Check for an early finish.
112 if (params_.distance.IsZero()) { 118 if (params_.distance.IsZero()) {
113 state_ = DONE; 119 state_ = DONE;
114 break; 120 break;
115 } 121 }
116 state_ = MOVING; 122 state_ = MOVING;
117 // Fall through to forward the first event. 123 // Fall through to forward the first event.
118 case MOVING: 124 case MOVING: {
119 { 125 // Even though WebMouseWheelEvents take floating point deltas,
120 // Even though WebMouseWheelEvents take floating point deltas, 126 // internally the scroll position is stored as an integer. We therefore
121 // internally the scroll position is stored as an integer. We therefore 127 // keep track of the discrete delta which is consistent with the
122 // keep track of the discrete delta which is consistent with the 128 // internal scrolling state. This ensures that when the gesture has
123 // internal scrolling state. This ensures that when the gesture has 129 // finished we've scrolled exactly the specified distance.
124 // finished we've scrolled exactly the specified distance. 130 base::TimeTicks event_timestamp = timestamp;
125 total_delta_ += GetPositionDelta(interval); 131 gfx::Vector2dF total_delta =
126 gfx::Vector2d delta_discrete = 132 GetPositionDeltaAndUpdateTimestamp(&event_timestamp);
127 FloorTowardZero(total_delta_ - total_delta_discrete_); 133 gfx::Vector2d delta_discrete =
128 ForwardMouseWheelEvent(target, delta_discrete); 134 FloorTowardZero(total_delta - total_delta_discrete_);
129 total_delta_discrete_ += delta_discrete; 135 ForwardMouseWheelEvent(target, delta_discrete, event_timestamp);
130 } 136 total_delta_discrete_ += delta_discrete;
131 if (HasScrolledEntireDistance()) 137
138 if (HasScrolledEntireDistance(total_delta))
132 state_ = DONE; 139 state_ = DONE;
133 break; 140 } break;
134 case SETUP: 141 case SETUP:
135 NOTREACHED() 142 NOTREACHED()
136 << "State STARTED invalid for synthetic scroll using touch input."; 143 << "State STARTED invalid for synthetic scroll using touch input.";
137 case STOPPING: 144 case STOPPING:
138 NOTREACHED() 145 NOTREACHED()
139 << "State STOPPING invalid for synthetic scroll using touch input."; 146 << "State STOPPING invalid for synthetic scroll using touch input.";
140 case DONE: 147 case DONE:
141 NOTREACHED() 148 NOTREACHED()
142 << "State DONE invalid for synthetic scroll using touch input."; 149 << "State DONE invalid for synthetic scroll using touch input.";
143 } 150 }
144 } 151 }
145 152
146 void SyntheticSmoothScrollGesture::ForwardTouchEvent( 153 void SyntheticSmoothScrollGesture::ForwardTouchEvent(
147 SyntheticGestureTarget* target) const { 154 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
155 touch_event_.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
156
148 target->DispatchInputEventToPlatform( 157 target->DispatchInputEventToPlatform(
149 InputEvent(touch_event_, ui::LatencyInfo(), false)); 158 InputEvent(touch_event_, ui::LatencyInfo(), false));
150 } 159 }
151 160
152 void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent( 161 void SyntheticSmoothScrollGesture::ForwardMouseWheelEvent(
153 SyntheticGestureTarget* target, const gfx::Vector2dF& delta) const { 162 SyntheticGestureTarget* target,
163 const gfx::Vector2dF& delta,
164 const base::TimeTicks& timestamp) const {
154 blink::WebMouseWheelEvent mouse_wheel_event = 165 blink::WebMouseWheelEvent mouse_wheel_event =
155 SyntheticWebMouseWheelEventBuilder::Build(delta.x(), delta.y(), 0, false); 166 SyntheticWebMouseWheelEventBuilder::Build(delta.x(), delta.y(), 0, false);
156 167
157 mouse_wheel_event.x = params_.anchor.x(); 168 mouse_wheel_event.x = params_.anchor.x();
158 mouse_wheel_event.y = params_.anchor.y(); 169 mouse_wheel_event.y = params_.anchor.y();
159 170
171 mouse_wheel_event.timeStampSeconds = ConvertTimestampToSeconds(timestamp);
172
160 target->DispatchInputEventToPlatform( 173 target->DispatchInputEventToPlatform(
161 InputEvent(mouse_wheel_event, ui::LatencyInfo(), false)); 174 InputEvent(mouse_wheel_event, ui::LatencyInfo(), false));
162 } 175 }
163 176
164 void SyntheticSmoothScrollGesture::PressTouchPoint( 177 void SyntheticSmoothScrollGesture::PressTouchPoint(
165 SyntheticGestureTarget* target) { 178 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
166 touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y()); 179 touch_event_.PressPoint(params_.anchor.x(), params_.anchor.y());
167 ForwardTouchEvent(target); 180 ForwardTouchEvent(target, timestamp);
168 } 181 }
169 182
170 void SyntheticSmoothScrollGesture::MoveTouchPoint( 183 void SyntheticSmoothScrollGesture::MoveTouchPoint(
171 SyntheticGestureTarget* target) { 184 SyntheticGestureTarget* target,
172 gfx::PointF touch_position = params_.anchor + total_delta_; 185 const gfx::Vector2dF& delta,
186 const base::TimeTicks& timestamp) {
187 gfx::PointF touch_position = params_.anchor + delta;
173 touch_event_.MovePoint(0, touch_position.x(), touch_position.y()); 188 touch_event_.MovePoint(0, touch_position.x(), touch_position.y());
174 ForwardTouchEvent(target); 189 ForwardTouchEvent(target, timestamp);
175 } 190 }
176 191
177 void SyntheticSmoothScrollGesture::ReleaseTouchPoint( 192 void SyntheticSmoothScrollGesture::ReleaseTouchPoint(
178 SyntheticGestureTarget* target) { 193 SyntheticGestureTarget* target, const base::TimeTicks& timestamp) {
179 touch_event_.ReleasePoint(0); 194 touch_event_.ReleasePoint(0);
180 ForwardTouchEvent(target); 195 ForwardTouchEvent(target, timestamp);
181 } 196 }
182 197
183 void SyntheticSmoothScrollGesture::AddTouchSlopToDistance( 198 void SyntheticSmoothScrollGesture::AddTouchSlopToDistance(
184 SyntheticGestureTarget* target) { 199 SyntheticGestureTarget* target) {
185 // Android uses euclidean distance to compute if a touch pointer has moved 200 // Android uses euclidean distance to compute if a touch pointer has moved
186 // beyond the slop, while Aura uses Manhattan distance. We're using Euclidean 201 // beyond the slop, while Aura uses Manhattan distance. We're using Euclidean
187 // distance and round up to the nearest integer. 202 // distance and round up to the nearest integer.
188 // For vertical and horizontal scrolls (the common case), both methods produce 203 // For vertical and horizontal scrolls (the common case), both methods produce
189 // the same result. 204 // the same result.
190 gfx::Vector2dF touch_slop_delta = ProjectLengthOntoScrollDirection( 205 gfx::Vector2dF touch_slop_delta =
191 target->GetTouchSlopInDips()); 206 ProjectLengthOntoScrollDirection(target->GetTouchSlopInDips());
192 params_.distance += CeilFromZero(touch_slop_delta); 207 params_.distance += CeilFromZero(touch_slop_delta);
193 } 208 }
194 209
195 gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDelta( 210 gfx::Vector2dF SyntheticSmoothScrollGesture::GetPositionDeltaAndUpdateTimestamp(
196 const base::TimeDelta& interval) const { 211 base::TimeTicks* timestamp) const {
jdduke (slow) 2014/01/03 18:24:30 DCHECK(timestamp);
Dominik Grewe 2014/01/06 11:46:07 Done.
197 float delta_length = params_.speed_in_pixels_s * interval.InSecondsF(); 212 float delta_length =
213 params_.speed_in_pixels_s * (*timestamp - start_time_).InSecondsF();
198 214
199 // Make sure we're not scrolling too far. 215 // Make sure we're not scrolling too far.
200 gfx::Vector2dF remaining_delta = ComputeRemainingDelta(); 216 if (delta_length > params_.distance.Length()) {
201 if (delta_length > remaining_delta.Length()) 217 // Update the timestamp to match the end of the scroll.
218 int total_duration_in_ms =
219 (1000 * params_.distance.Length()) / params_.speed_in_pixels_s;
jdduke (slow) 2014/01/03 18:24:30 Same as above, multiplying the time scale by the d
Dominik Grewe 2014/01/06 11:46:07 Done.
220 *timestamp =
221 start_time_ + base::TimeDelta::FromMilliseconds(total_duration_in_ms);
222
202 // In order to scroll in a certain direction we need to move the 223 // In order to scroll in a certain direction we need to move the
203 // touch pointer/mouse wheel in the opposite direction. 224 // touch pointer/mouse wheel in the opposite direction.
204 return -remaining_delta; 225 return -params_.distance;
205 else 226 } else {
206 return -ProjectLengthOntoScrollDirection(delta_length); 227 return -ProjectLengthOntoScrollDirection(delta_length);
228 }
207 } 229 }
208 230
209 gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection( 231 gfx::Vector2dF SyntheticSmoothScrollGesture::ProjectLengthOntoScrollDirection(
210 float delta_length) const { 232 float delta_length) const {
211 const float kTotalLength = params_.distance.Length(); 233 const float kTotalLength = params_.distance.Length();
212 return ScaleVector2d(params_.distance, delta_length / kTotalLength); 234 return ScaleVector2d(params_.distance, delta_length / kTotalLength);
213 } 235 }
214 236
215 gfx::Vector2dF SyntheticSmoothScrollGesture::ComputeRemainingDelta() const { 237 bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance(
216 return params_.distance + total_delta_; 238 const gfx::Vector2dF& delta) const {
217 } 239 return delta == -params_.distance;
218
219 bool SyntheticSmoothScrollGesture::HasScrolledEntireDistance() const {
220 return ComputeRemainingDelta().IsZero();
221 } 240 }
222 241
223 } // namespace content 242 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698