OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/base/gestures/gesture_recognizer_impl.h" | 5 #include "ui/base/gestures/gesture_recognizer_impl.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "ui/base/event.h" | 10 #include "ui/base/event.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
44 set_flags(real->flags()); | 44 set_flags(real->flags()); |
45 set_radius(real->radius_x(), real->radius_y()); | 45 set_radius(real->radius_x(), real->radius_y()); |
46 set_rotation_angle(real->rotation_angle()); | 46 set_rotation_angle(real->rotation_angle()); |
47 set_force(real->force()); | 47 set_force(real->force()); |
48 } | 48 } |
49 | 49 |
50 virtual ~MirroredTouchEvent() { | 50 virtual ~MirroredTouchEvent() { |
51 } | 51 } |
52 | 52 |
53 private: | 53 private: |
54 DISALLOW_COPY_AND_ASSIGN(MirroredTouchEvent); | |
55 }; | |
54 | 56 |
55 DISALLOW_COPY_AND_ASSIGN(MirroredTouchEvent); | 57 class QueuedTouchEvent : public MirroredTouchEvent { |
58 public: | |
59 QueuedTouchEvent(const TouchEvent* real, TouchStatus status) | |
60 : MirroredTouchEvent(real), | |
61 status_(status) { | |
62 } | |
63 | |
64 virtual ~QueuedTouchEvent() { | |
65 } | |
66 | |
67 TouchStatus status() const { return status_; } | |
68 | |
69 private: | |
70 TouchStatus status_; | |
71 | |
72 DISALLOW_COPY_AND_ASSIGN(QueuedTouchEvent); | |
56 }; | 73 }; |
57 | 74 |
58 // A mirrored event, except for the type, which is always ET_TOUCH_CANCELLED. | 75 // A mirrored event, except for the type, which is always ET_TOUCH_CANCELLED. |
59 class CancelledTouchEvent : public MirroredTouchEvent { | 76 class CancelledTouchEvent : public MirroredTouchEvent { |
60 public: | 77 public: |
61 explicit CancelledTouchEvent(const TouchEvent* src) | 78 explicit CancelledTouchEvent(const TouchEvent* src) |
62 : MirroredTouchEvent(src) { | 79 : MirroredTouchEvent(src) { |
63 set_type(ET_TOUCH_CANCELLED); | 80 set_type(ET_TOUCH_CANCELLED); |
64 } | 81 } |
65 | 82 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
220 GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer( | 237 GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer( |
221 GestureConsumer* consumer) { | 238 GestureConsumer* consumer) { |
222 GestureSequence* gesture_sequence = consumer_sequence_[consumer]; | 239 GestureSequence* gesture_sequence = consumer_sequence_[consumer]; |
223 if (!gesture_sequence) { | 240 if (!gesture_sequence) { |
224 gesture_sequence = CreateSequence(helper_); | 241 gesture_sequence = CreateSequence(helper_); |
225 consumer_sequence_[consumer] = gesture_sequence; | 242 consumer_sequence_[consumer] = gesture_sequence; |
226 } | 243 } |
227 return gesture_sequence; | 244 return gesture_sequence; |
228 } | 245 } |
229 | 246 |
230 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( | 247 void GestureRecognizerImpl::SetupTargets(const TouchEvent& event, |
231 const TouchEvent& event, | 248 GestureConsumer* target) { |
232 ui::TouchStatus status, | |
233 GestureConsumer* target) { | |
234 if (event.type() == ui::ET_TOUCH_RELEASED || | 249 if (event.type() == ui::ET_TOUCH_RELEASED || |
235 event.type() == ui::ET_TOUCH_CANCELLED) { | 250 event.type() == ui::ET_TOUCH_CANCELLED) { |
236 touch_id_target_[event.touch_id()] = NULL; | 251 touch_id_target_[event.touch_id()] = NULL; |
237 } else { | 252 } else { |
238 touch_id_target_[event.touch_id()] = target; | 253 touch_id_target_[event.touch_id()] = target; |
239 if (target) | 254 if (target) |
240 touch_id_target_for_gestures_[event.touch_id()] = target; | 255 touch_id_target_for_gestures_[event.touch_id()] = target; |
241 } | 256 } |
257 } | |
258 | |
259 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueueByOne( | |
260 GestureConsumer* consumer, | |
261 ui::TouchStatus status) { | |
262 CHECK(event_queue_[consumer]); | |
263 CHECK(!event_queue_[consumer]->empty()); | |
264 | |
265 ScopedPop pop(event_queue_[consumer]); | |
266 TouchEvent* event = event_queue_[consumer]->front(); | |
267 GestureSequence* sequence = GetGestureSequenceForConsumer(consumer); | |
268 if (status != ui::TOUCH_STATUS_UNKNOWN && | |
269 event->type() == ui::ET_TOUCH_RELEASED) { | |
270 // A touch release was was processed (e.g. preventDefault()ed by a | |
rjkroege
2012/08/13 20:43:53
per our discussion earlier about gestures not bein
sadrul
2012/08/13 20:52:56
This is specifically for the case that if the touc
| |
271 // web-page), but we still need to process a touch cancel. | |
272 return sequence->ProcessTouchEventForGesture(CancelledTouchEvent(event), | |
273 ui::TOUCH_STATUS_UNKNOWN); | |
274 } | |
275 return sequence->ProcessTouchEventForGesture(*event, status); | |
276 } | |
277 | |
278 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( | |
279 const TouchEvent& event, | |
280 ui::TouchStatus status, | |
281 GestureConsumer* target) { | |
282 if (event_queue_[target] && event_queue_[target]->size() > 0) { | |
283 // There are some queued touch-events for this target. Processing |event| | |
284 // before those queued events will result in unexpected gestures. So | |
285 // postpone the processing of the events until the queued events have been | |
286 // processed. | |
287 event_queue_[target]->push(new QueuedTouchEvent(&event, status)); | |
288 return NULL; | |
289 } | |
290 | |
291 SetupTargets(event, target); | |
242 | 292 |
243 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); | 293 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); |
244 return gesture_sequence->ProcessTouchEventForGesture(event, status); | 294 return gesture_sequence->ProcessTouchEventForGesture(event, status); |
245 } | 295 } |
246 | 296 |
247 void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer, | 297 void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer, |
248 const TouchEvent& event) { | 298 const TouchEvent& event) { |
249 if (!event_queue_[consumer]) | 299 if (!event_queue_[consumer]) |
250 event_queue_[consumer] = new std::queue<TouchEvent*>(); | 300 event_queue_[consumer] = new std::queue<TouchEvent*>(); |
251 event_queue_[consumer]->push(new MirroredTouchEvent(&event)); | 301 event_queue_[consumer]->push( |
302 new QueuedTouchEvent(&event, TOUCH_STATUS_QUEUED)); | |
303 | |
304 SetupTargets(event, consumer); | |
252 } | 305 } |
253 | 306 |
254 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue( | 307 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue( |
255 GestureConsumer* consumer, | 308 GestureConsumer* consumer, |
256 bool processed) { | 309 bool processed) { |
257 if (!event_queue_[consumer] || event_queue_[consumer]->empty()) { | 310 if (!event_queue_[consumer] || event_queue_[consumer]->empty()) { |
258 LOG(ERROR) << "Trying to advance an empty gesture queue for " << consumer; | 311 LOG(ERROR) << "Trying to advance an empty gesture queue for " << consumer; |
259 return NULL; | 312 return NULL; |
260 } | 313 } |
261 | 314 |
262 ScopedPop pop(event_queue_[consumer]); | 315 scoped_ptr<GestureSequence::Gestures> gestures( |
263 TouchEvent* event = event_queue_[consumer]->front(); | 316 AdvanceTouchQueueByOne(consumer, processed ? TOUCH_STATUS_CONTINUE : |
317 TOUCH_STATUS_UNKNOWN)); | |
264 | 318 |
265 GestureSequence* sequence = GetGestureSequenceForConsumer(consumer); | 319 // Are there any queued touch-events that should be auto-dequeued? |
320 while (!event_queue_[consumer]->empty()) { | |
321 QueuedTouchEvent* event = | |
322 static_cast<QueuedTouchEvent*>(event_queue_[consumer]->front()); | |
323 if (event->status() == TOUCH_STATUS_QUEUED) | |
324 break; | |
266 | 325 |
267 if (processed && event->type() == ui::ET_TOUCH_RELEASED) { | 326 GestureSequence::Gestures* current_gestures = AdvanceTouchQueueByOne( |
268 // A touch release was was processed (e.g. preventDefault()ed by a | 327 consumer, event->status()); |
269 // web-page), but we still need to process a touch cancel. | 328 if (current_gestures) { |
270 CancelledTouchEvent cancelled(event); | 329 if (!gestures.get()) { |
271 return sequence->ProcessTouchEventForGesture(cancelled, | 330 gestures.reset(current_gestures); |
272 ui::TOUCH_STATUS_UNKNOWN); | 331 } else { |
332 gestures->insert(gestures->end(), current_gestures->begin(), | |
333 current_gestures->end()); | |
334 } | |
335 } | |
273 } | 336 } |
274 | 337 |
275 return sequence->ProcessTouchEventForGesture( | 338 return gestures.release(); |
276 *event, | |
277 processed ? ui::TOUCH_STATUS_CONTINUE : ui::TOUCH_STATUS_UNKNOWN); | |
278 } | 339 } |
279 | 340 |
280 void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) { | 341 void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) { |
281 if (consumer_sequence_.count(consumer)) { | 342 if (consumer_sequence_.count(consumer)) { |
282 delete consumer_sequence_[consumer]; | 343 delete consumer_sequence_[consumer]; |
283 consumer_sequence_.erase(consumer); | 344 consumer_sequence_.erase(consumer); |
284 } | 345 } |
285 | 346 |
286 if (event_queue_.count(consumer)) { | 347 if (event_queue_.count(consumer)) { |
287 delete event_queue_[consumer]; | 348 delete event_queue_[consumer]; |
288 event_queue_.erase(consumer); | 349 event_queue_.erase(consumer); |
289 } | 350 } |
290 | 351 |
291 RemoveConsumerFromMap(consumer, &touch_id_target_); | 352 RemoveConsumerFromMap(consumer, &touch_id_target_); |
292 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); | 353 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); |
293 } | 354 } |
294 | 355 |
295 // GestureRecognizer, static | 356 // GestureRecognizer, static |
296 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { | 357 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { |
297 return new GestureRecognizerImpl(helper); | 358 return new GestureRecognizerImpl(helper); |
298 } | 359 } |
299 | 360 |
300 } // namespace ui | 361 } // namespace ui |
OLD | NEW |