Chromium Code Reviews| 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 |