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 |
| 271 // web-page), but we still need to process a touch cancel. |
| 272 CancelledTouchEvent cancelled(event); |
| 273 return sequence->ProcessTouchEventForGesture(cancelled, |
| 274 ui::TOUCH_STATUS_UNKNOWN); |
| 275 } |
| 276 return sequence->ProcessTouchEventForGesture(*event, status); |
| 277 } |
| 278 |
| 279 GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture( |
| 280 const TouchEvent& event, |
| 281 ui::TouchStatus status, |
| 282 GestureConsumer* target) { |
| 283 if (event_queue_[target] && event_queue_[target]->size() > 0) { |
| 284 // There are some queued touch-events for this target. Processing |event| |
| 285 // before those queued events will result in unexpected gestures. So |
| 286 // postpone the processing of the events until the queued events have been |
| 287 // processed. |
| 288 event_queue_[target]->push(new QueuedTouchEvent(&event, status)); |
| 289 return NULL; |
| 290 } |
| 291 |
| 292 SetupTargets(event, target); |
242 | 293 |
243 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); | 294 GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target); |
244 return gesture_sequence->ProcessTouchEventForGesture(event, status); | 295 return gesture_sequence->ProcessTouchEventForGesture(event, status); |
245 } | 296 } |
246 | 297 |
247 void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer, | 298 void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer, |
248 const TouchEvent& event) { | 299 const TouchEvent& event) { |
249 if (!event_queue_[consumer]) | 300 if (!event_queue_[consumer]) |
250 event_queue_[consumer] = new std::queue<TouchEvent*>(); | 301 event_queue_[consumer] = new std::queue<TouchEvent*>(); |
251 event_queue_[consumer]->push(new MirroredTouchEvent(&event)); | 302 event_queue_[consumer]->push( |
| 303 new QueuedTouchEvent(&event, TOUCH_STATUS_QUEUED)); |
| 304 |
| 305 SetupTargets(event, consumer); |
252 } | 306 } |
253 | 307 |
254 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue( | 308 GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue( |
255 GestureConsumer* consumer, | 309 GestureConsumer* consumer, |
256 bool processed) { | 310 bool processed) { |
257 if (!event_queue_[consumer] || event_queue_[consumer]->empty()) { | 311 if (!event_queue_[consumer] || event_queue_[consumer]->empty()) { |
258 LOG(ERROR) << "Trying to advance an empty gesture queue for " << consumer; | 312 LOG(ERROR) << "Trying to advance an empty gesture queue for " << consumer; |
259 return NULL; | 313 return NULL; |
260 } | 314 } |
261 | 315 |
262 ScopedPop pop(event_queue_[consumer]); | 316 scoped_ptr<GestureSequence::Gestures> gestures( |
263 TouchEvent* event = event_queue_[consumer]->front(); | 317 AdvanceTouchQueueByOne(consumer, processed ? TOUCH_STATUS_CONTINUE : |
| 318 TOUCH_STATUS_UNKNOWN)); |
264 | 319 |
265 GestureSequence* sequence = GetGestureSequenceForConsumer(consumer); | 320 // Are there any queued touch-events that should be auto-dequeued? |
| 321 while (!event_queue_[consumer]->empty()) { |
| 322 QueuedTouchEvent* event = |
| 323 static_cast<QueuedTouchEvent*>(event_queue_[consumer]->front()); |
| 324 if (event->status() == TOUCH_STATUS_QUEUED) |
| 325 break; |
266 | 326 |
267 if (processed && event->type() == ui::ET_TOUCH_RELEASED) { | 327 GestureSequence::Gestures* current_gestures = AdvanceTouchQueueByOne( |
268 // A touch release was was processed (e.g. preventDefault()ed by a | 328 consumer, event->status()); |
269 // web-page), but we still need to process a touch cancel. | 329 if (current_gestures) { |
270 CancelledTouchEvent cancelled(event); | 330 if (!gestures.get()) { |
271 return sequence->ProcessTouchEventForGesture(cancelled, | 331 gestures.reset(current_gestures); |
272 ui::TOUCH_STATUS_UNKNOWN); | 332 } else { |
| 333 gestures->insert(gestures->end(), current_gestures->begin(), |
| 334 current_gestures->end()); |
| 335 } |
| 336 } |
273 } | 337 } |
274 | 338 |
275 return sequence->ProcessTouchEventForGesture( | 339 return gestures.release(); |
276 *event, | |
277 processed ? ui::TOUCH_STATUS_CONTINUE : ui::TOUCH_STATUS_UNKNOWN); | |
278 } | 340 } |
279 | 341 |
280 void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) { | 342 void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) { |
281 if (consumer_sequence_.count(consumer)) { | 343 if (consumer_sequence_.count(consumer)) { |
282 delete consumer_sequence_[consumer]; | 344 delete consumer_sequence_[consumer]; |
283 consumer_sequence_.erase(consumer); | 345 consumer_sequence_.erase(consumer); |
284 } | 346 } |
285 | 347 |
286 if (event_queue_.count(consumer)) { | 348 if (event_queue_.count(consumer)) { |
287 delete event_queue_[consumer]; | 349 delete event_queue_[consumer]; |
288 event_queue_.erase(consumer); | 350 event_queue_.erase(consumer); |
289 } | 351 } |
290 | 352 |
291 RemoveConsumerFromMap(consumer, &touch_id_target_); | 353 RemoveConsumerFromMap(consumer, &touch_id_target_); |
292 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); | 354 RemoveConsumerFromMap(consumer, &touch_id_target_for_gestures_); |
293 } | 355 } |
294 | 356 |
295 // GestureRecognizer, static | 357 // GestureRecognizer, static |
296 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { | 358 GestureRecognizer* GestureRecognizer::Create(GestureEventHelper* helper) { |
297 return new GestureRecognizerImpl(helper); | 359 return new GestureRecognizerImpl(helper); |
298 } | 360 } |
299 | 361 |
300 } // namespace ui | 362 } // namespace ui |
OLD | NEW |