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

Side by Side Diff: ui/base/gestures/gesture_recognizer_impl.cc

Issue 10825323: gesture: Make sure a combination of sync/async touch-events work correctly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 8 years, 4 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
« no previous file with comments | « ui/base/gestures/gesture_recognizer_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « ui/base/gestures/gesture_recognizer_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698