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

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: tot-merge 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
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
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