OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "ui/events/gesture_detection/motion_event_buffer.h" | 5 #include "ui/events/gesture_detection/motion_event_buffer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 PointerProperties p(event0, event0_pointer_index); | 110 PointerProperties p(event0, event0_pointer_index); |
111 p.x = Lerp(p.x, event1.GetX(event1_pointer_index), alpha); | 111 p.x = Lerp(p.x, event1.GetX(event1_pointer_index), alpha); |
112 p.y = Lerp(p.y, event1.GetY(event1_pointer_index), alpha); | 112 p.y = Lerp(p.y, event1.GetY(event1_pointer_index), alpha); |
113 p.raw_x = Lerp(p.raw_x, event1.GetRawX(event1_pointer_index), alpha); | 113 p.raw_x = Lerp(p.raw_x, event1.GetRawX(event1_pointer_index), alpha); |
114 p.raw_y = Lerp(p.raw_y, event1.GetRawY(event1_pointer_index), alpha); | 114 p.raw_y = Lerp(p.raw_y, event1.GetRawY(event1_pointer_index), alpha); |
115 return p; | 115 return p; |
116 } | 116 } |
117 | 117 |
118 // Linearly interpolate the pointers between two event samples using the | 118 // Linearly interpolate the pointers between two event samples using the |
119 // provided |resample_time|. | 119 // provided |resample_time|. |
120 scoped_ptr<MotionEventGeneric> ResampleMotionEvent( | 120 std::unique_ptr<MotionEventGeneric> ResampleMotionEvent( |
121 const MotionEvent& event0, | 121 const MotionEvent& event0, |
122 const MotionEvent& event1, | 122 const MotionEvent& event1, |
123 base::TimeTicks resample_time) { | 123 base::TimeTicks resample_time) { |
124 DCHECK_EQ(MotionEvent::ACTION_MOVE, event0.GetAction()); | 124 DCHECK_EQ(MotionEvent::ACTION_MOVE, event0.GetAction()); |
125 DCHECK_EQ(event0.GetPointerCount(), event1.GetPointerCount()); | 125 DCHECK_EQ(event0.GetPointerCount(), event1.GetPointerCount()); |
126 | 126 |
127 const base::TimeTicks time0 = event0.GetEventTime(); | 127 const base::TimeTicks time0 = event0.GetEventTime(); |
128 const base::TimeTicks time1 = event1.GetEventTime(); | 128 const base::TimeTicks time1 = event1.GetEventTime(); |
129 DCHECK(time0 < time1); | 129 DCHECK(time0 < time1); |
130 DCHECK(time0 <= resample_time); | 130 DCHECK(time0 <= resample_time); |
131 | 131 |
132 const float alpha = (resample_time - time0).InMillisecondsF() / | 132 const float alpha = (resample_time - time0).InMillisecondsF() / |
133 (time1 - time0).InMillisecondsF(); | 133 (time1 - time0).InMillisecondsF(); |
134 | 134 |
135 scoped_ptr<MotionEventGeneric> event; | 135 std::unique_ptr<MotionEventGeneric> event; |
136 const size_t pointer_count = event0.GetPointerCount(); | 136 const size_t pointer_count = event0.GetPointerCount(); |
137 DCHECK_EQ(pointer_count, event1.GetPointerCount()); | 137 DCHECK_EQ(pointer_count, event1.GetPointerCount()); |
138 for (size_t event0_i = 0; event0_i < pointer_count; ++event0_i) { | 138 for (size_t event0_i = 0; event0_i < pointer_count; ++event0_i) { |
139 int event1_i = event1.FindPointerIndexOfId(event0.GetPointerId(event0_i)); | 139 int event1_i = event1.FindPointerIndexOfId(event0.GetPointerId(event0_i)); |
140 DCHECK_NE(event1_i, -1); | 140 DCHECK_NE(event1_i, -1); |
141 PointerProperties pointer = ResamplePointer( | 141 PointerProperties pointer = ResamplePointer( |
142 event0, event1, event0_i, static_cast<size_t>(event1_i), alpha); | 142 event0, event1, event0_i, static_cast<size_t>(event1_i), alpha); |
143 | 143 |
144 if (event0_i == 0) { | 144 if (event0_i == 0) { |
145 event.reset(new MotionEventGeneric( | 145 event.reset(new MotionEventGeneric( |
146 MotionEvent::ACTION_MOVE, resample_time, pointer)); | 146 MotionEvent::ACTION_MOVE, resample_time, pointer)); |
147 } else { | 147 } else { |
148 event->PushPointer(pointer); | 148 event->PushPointer(pointer); |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
152 DCHECK(event); | 152 DCHECK(event); |
153 event->set_button_state(event0.GetButtonState()); | 153 event->set_button_state(event0.GetButtonState()); |
154 return event; | 154 return event; |
155 } | 155 } |
156 | 156 |
157 // Synthesize a compound MotionEventGeneric event from a sequence of events. | 157 // Synthesize a compound MotionEventGeneric event from a sequence of events. |
158 // Events must be in non-decreasing (time) order. | 158 // Events must be in non-decreasing (time) order. |
159 scoped_ptr<MotionEventGeneric> ConsumeSamples(MotionEventVector events) { | 159 std::unique_ptr<MotionEventGeneric> ConsumeSamples(MotionEventVector events) { |
160 DCHECK(!events.empty()); | 160 DCHECK(!events.empty()); |
161 scoped_ptr<MotionEventGeneric> event(events.back()); | 161 std::unique_ptr<MotionEventGeneric> event(events.back()); |
162 for (size_t i = 0; i + 1 < events.size(); ++i) | 162 for (size_t i = 0; i + 1 < events.size(); ++i) |
163 event->PushHistoricalEvent(scoped_ptr<MotionEvent>(events[i])); | 163 event->PushHistoricalEvent(std::unique_ptr<MotionEvent>(events[i])); |
164 events.weak_clear(); | 164 events.weak_clear(); |
165 return event; | 165 return event; |
166 } | 166 } |
167 | 167 |
168 // Consume a series of event samples, attempting to synthesize a new, synthetic | 168 // Consume a series of event samples, attempting to synthesize a new, synthetic |
169 // event if the samples and sample time meet certain interpolation/extrapolation | 169 // event if the samples and sample time meet certain interpolation/extrapolation |
170 // conditions. If such conditions are met, the provided samples will be added | 170 // conditions. If such conditions are met, the provided samples will be added |
171 // to the synthetic event's history, otherwise, the samples will be used to | 171 // to the synthetic event's history, otherwise, the samples will be used to |
172 // generate a basic, compound event. | 172 // generate a basic, compound event. |
173 // TODO(jdduke): Revisit resampling to handle cases where alternating frames | 173 // TODO(jdduke): Revisit resampling to handle cases where alternating frames |
174 // are resampled or resampling is otherwise inconsistent, e.g., a 90hz input | 174 // are resampled or resampling is otherwise inconsistent, e.g., a 90hz input |
175 // and 60hz frame signal could phase-align such that even frames yield an | 175 // and 60hz frame signal could phase-align such that even frames yield an |
176 // extrapolated event and odd frames are not resampled, crbug.com/399381. | 176 // extrapolated event and odd frames are not resampled, crbug.com/399381. |
177 scoped_ptr<MotionEventGeneric> ConsumeSamplesAndTryResampling( | 177 std::unique_ptr<MotionEventGeneric> ConsumeSamplesAndTryResampling( |
178 base::TimeTicks resample_time, | 178 base::TimeTicks resample_time, |
179 MotionEventVector events, | 179 MotionEventVector events, |
180 const MotionEvent* next) { | 180 const MotionEvent* next) { |
181 const ui::MotionEvent* event0 = nullptr; | 181 const ui::MotionEvent* event0 = nullptr; |
182 const ui::MotionEvent* event1 = nullptr; | 182 const ui::MotionEvent* event1 = nullptr; |
183 if (next) { | 183 if (next) { |
184 DCHECK(resample_time < next->GetEventTime()); | 184 DCHECK(resample_time < next->GetEventTime()); |
185 // Interpolate between current sample and future sample. | 185 // Interpolate between current sample and future sample. |
186 event0 = events.back(); | 186 event0 = events.back(); |
187 event1 = next; | 187 event1 = next; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 base::TimeDelta delta = time1 - time0; | 219 base::TimeDelta delta = time1 - time0; |
220 if (delta < base::TimeDelta::FromMilliseconds(kResampleMinDeltaMs)) { | 220 if (delta < base::TimeDelta::FromMilliseconds(kResampleMinDeltaMs)) { |
221 TRACE_EVENT_INSTANT1("input", | 221 TRACE_EVENT_INSTANT1("input", |
222 "MotionEventBuffer::TryResample failure", | 222 "MotionEventBuffer::TryResample failure", |
223 TRACE_EVENT_SCOPE_THREAD, | 223 TRACE_EVENT_SCOPE_THREAD, |
224 "event_delta_too_small(ms)", | 224 "event_delta_too_small(ms)", |
225 delta.InMilliseconds()); | 225 delta.InMilliseconds()); |
226 return ConsumeSamples(std::move(events)); | 226 return ConsumeSamples(std::move(events)); |
227 } | 227 } |
228 | 228 |
229 scoped_ptr<MotionEventGeneric> resampled_event = | 229 std::unique_ptr<MotionEventGeneric> resampled_event = |
230 ResampleMotionEvent(*event0, *event1, resample_time); | 230 ResampleMotionEvent(*event0, *event1, resample_time); |
231 for (size_t i = 0; i < events.size(); ++i) | 231 for (size_t i = 0; i < events.size(); ++i) |
232 resampled_event->PushHistoricalEvent(scoped_ptr<MotionEvent>(events[i])); | 232 resampled_event->PushHistoricalEvent( |
| 233 std::unique_ptr<MotionEvent>(events[i])); |
233 events.weak_clear(); | 234 events.weak_clear(); |
234 return resampled_event; | 235 return resampled_event; |
235 } | 236 } |
236 | 237 |
237 } // namespace | 238 } // namespace |
238 | 239 |
239 MotionEventBuffer::MotionEventBuffer(MotionEventBufferClient* client, | 240 MotionEventBuffer::MotionEventBuffer(MotionEventBufferClient* client, |
240 bool enable_resampling) | 241 bool enable_resampling) |
241 : client_(client), resample_(enable_resampling) { | 242 : client_(client), resample_(enable_resampling) { |
242 } | 243 } |
(...skipping 13 matching lines...) Expand all Loading... |
256 | 257 |
257 // Guard against events that are *older* than the last one that may have been | 258 // Guard against events that are *older* than the last one that may have been |
258 // artificially synthesized. | 259 // artificially synthesized. |
259 if (!last_extrapolated_event_time_.is_null()) { | 260 if (!last_extrapolated_event_time_.is_null()) { |
260 DCHECK(buffered_events_.empty()); | 261 DCHECK(buffered_events_.empty()); |
261 if (event.GetEventTime() < last_extrapolated_event_time_) | 262 if (event.GetEventTime() < last_extrapolated_event_time_) |
262 return; | 263 return; |
263 last_extrapolated_event_time_ = base::TimeTicks(); | 264 last_extrapolated_event_time_ = base::TimeTicks(); |
264 } | 265 } |
265 | 266 |
266 scoped_ptr<MotionEventGeneric> clone = MotionEventGeneric::CloneEvent(event); | 267 std::unique_ptr<MotionEventGeneric> clone = |
| 268 MotionEventGeneric::CloneEvent(event); |
267 if (buffered_events_.empty()) { | 269 if (buffered_events_.empty()) { |
268 buffered_events_.push_back(std::move(clone)); | 270 buffered_events_.push_back(std::move(clone)); |
269 client_->SetNeedsFlush(); | 271 client_->SetNeedsFlush(); |
270 return; | 272 return; |
271 } | 273 } |
272 | 274 |
273 if (CanAddSample(*buffered_events_.front(), *clone)) { | 275 if (CanAddSample(*buffered_events_.front(), *clone)) { |
274 DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime()); | 276 DCHECK(buffered_events_.back()->GetEventTime() <= clone->GetEventTime()); |
275 } else { | 277 } else { |
276 FlushWithoutResampling(std::move(buffered_events_)); | 278 FlushWithoutResampling(std::move(buffered_events_)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 FlushWithResampling(std::move(events), frame_time); | 311 FlushWithResampling(std::move(events), frame_time); |
310 } | 312 } |
311 | 313 |
312 void MotionEventBuffer::FlushWithResampling(MotionEventVector events, | 314 void MotionEventBuffer::FlushWithResampling(MotionEventVector events, |
313 base::TimeTicks resample_time) { | 315 base::TimeTicks resample_time) { |
314 DCHECK(!events.empty()); | 316 DCHECK(!events.empty()); |
315 base::TimeTicks original_event_time = events.back()->GetEventTime(); | 317 base::TimeTicks original_event_time = events.back()->GetEventTime(); |
316 const MotionEvent* next_event = | 318 const MotionEvent* next_event = |
317 !buffered_events_.empty() ? buffered_events_.front() : nullptr; | 319 !buffered_events_.empty() ? buffered_events_.front() : nullptr; |
318 | 320 |
319 scoped_ptr<MotionEventGeneric> resampled_event = | 321 std::unique_ptr<MotionEventGeneric> resampled_event = |
320 ConsumeSamplesAndTryResampling(resample_time, std::move(events), | 322 ConsumeSamplesAndTryResampling(resample_time, std::move(events), |
321 next_event); | 323 next_event); |
322 DCHECK(resampled_event); | 324 DCHECK(resampled_event); |
323 | 325 |
324 // Log the extrapolated event time, guarding against subsequently queued | 326 // Log the extrapolated event time, guarding against subsequently queued |
325 // events that might have an earlier timestamp. | 327 // events that might have an earlier timestamp. |
326 if (!next_event && resampled_event->GetEventTime() > original_event_time) { | 328 if (!next_event && resampled_event->GetEventTime() > original_event_time) { |
327 last_extrapolated_event_time_ = resampled_event->GetEventTime(); | 329 last_extrapolated_event_time_ = resampled_event->GetEventTime(); |
328 } else { | 330 } else { |
329 last_extrapolated_event_time_ = base::TimeTicks(); | 331 last_extrapolated_event_time_ = base::TimeTicks(); |
330 } | 332 } |
331 | 333 |
332 client_->ForwardMotionEvent(*resampled_event); | 334 client_->ForwardMotionEvent(*resampled_event); |
333 if (!buffered_events_.empty()) | 335 if (!buffered_events_.empty()) |
334 client_->SetNeedsFlush(); | 336 client_->SetNeedsFlush(); |
335 } | 337 } |
336 | 338 |
337 void MotionEventBuffer::FlushWithoutResampling(MotionEventVector events) { | 339 void MotionEventBuffer::FlushWithoutResampling(MotionEventVector events) { |
338 last_extrapolated_event_time_ = base::TimeTicks(); | 340 last_extrapolated_event_time_ = base::TimeTicks(); |
339 if (events.empty()) | 341 if (events.empty()) |
340 return; | 342 return; |
341 | 343 |
342 client_->ForwardMotionEvent(*ConsumeSamples(std::move(events))); | 344 client_->ForwardMotionEvent(*ConsumeSamples(std::move(events))); |
343 } | 345 } |
344 | 346 |
345 } // namespace ui | 347 } // namespace ui |
OLD | NEW |