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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/gestures/gesture_recognizer_impl.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/base/gestures/gesture_recognizer_impl.cc
diff --git a/ui/base/gestures/gesture_recognizer_impl.cc b/ui/base/gestures/gesture_recognizer_impl.cc
index 990a188924c288ea26af604ca34817b6e623c0f4..718f0442af8b1e8731215c45c2f2a37230a52d7c 100644
--- a/ui/base/gestures/gesture_recognizer_impl.cc
+++ b/ui/base/gestures/gesture_recognizer_impl.cc
@@ -51,10 +51,27 @@ class MirroredTouchEvent : public TouchEvent {
}
private:
-
DISALLOW_COPY_AND_ASSIGN(MirroredTouchEvent);
};
+class QueuedTouchEvent : public MirroredTouchEvent {
+ public:
+ QueuedTouchEvent(const TouchEvent* real, TouchStatus status)
+ : MirroredTouchEvent(real),
+ status_(status) {
+ }
+
+ virtual ~QueuedTouchEvent() {
+ }
+
+ TouchStatus status() const { return status_; }
+
+ private:
+ TouchStatus status_;
+
+ DISALLOW_COPY_AND_ASSIGN(QueuedTouchEvent);
+};
+
// A mirrored event, except for the type, which is always ET_TOUCH_CANCELLED.
class CancelledTouchEvent : public MirroredTouchEvent {
public:
@@ -227,10 +244,8 @@ GestureSequence* GestureRecognizerImpl::GetGestureSequenceForConsumer(
return gesture_sequence;
}
-GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture(
- const TouchEvent& event,
- ui::TouchStatus status,
- GestureConsumer* target) {
+void GestureRecognizerImpl::SetupTargets(const TouchEvent& event,
+ GestureConsumer* target) {
if (event.type() == ui::ET_TOUCH_RELEASED ||
event.type() == ui::ET_TOUCH_CANCELLED) {
touch_id_target_[event.touch_id()] = NULL;
@@ -239,6 +254,42 @@ GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture(
if (target)
touch_id_target_for_gestures_[event.touch_id()] = target;
}
+}
+
+GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueueByOne(
+ GestureConsumer* consumer,
+ ui::TouchStatus status) {
+ CHECK(event_queue_[consumer]);
+ CHECK(!event_queue_[consumer]->empty());
+
+ ScopedPop pop(event_queue_[consumer]);
+ TouchEvent* event = event_queue_[consumer]->front();
+ GestureSequence* sequence = GetGestureSequenceForConsumer(consumer);
+ if (status != ui::TOUCH_STATUS_UNKNOWN &&
+ event->type() == ui::ET_TOUCH_RELEASED) {
+ // A touch release was was processed (e.g. preventDefault()ed by a
+ // web-page), but we still need to process a touch cancel.
+ CancelledTouchEvent cancelled(event);
+ return sequence->ProcessTouchEventForGesture(cancelled,
+ ui::TOUCH_STATUS_UNKNOWN);
+ }
+ return sequence->ProcessTouchEventForGesture(*event, status);
+}
+
+GestureSequence::Gestures* GestureRecognizerImpl::ProcessTouchEventForGesture(
+ const TouchEvent& event,
+ ui::TouchStatus status,
+ GestureConsumer* target) {
+ if (event_queue_[target] && event_queue_[target]->size() > 0) {
+ // There are some queued touch-events for this target. Processing |event|
+ // before those queued events will result in unexpected gestures. So
+ // postpone the processing of the events until the queued events have been
+ // processed.
+ event_queue_[target]->push(new QueuedTouchEvent(&event, status));
+ return NULL;
+ }
+
+ SetupTargets(event, target);
GestureSequence* gesture_sequence = GetGestureSequenceForConsumer(target);
return gesture_sequence->ProcessTouchEventForGesture(event, status);
@@ -248,7 +299,10 @@ void GestureRecognizerImpl::QueueTouchEventForGesture(GestureConsumer* consumer,
const TouchEvent& event) {
if (!event_queue_[consumer])
event_queue_[consumer] = new std::queue<TouchEvent*>();
- event_queue_[consumer]->push(new MirroredTouchEvent(&event));
+ event_queue_[consumer]->push(
+ new QueuedTouchEvent(&event, TOUCH_STATUS_QUEUED));
+
+ SetupTargets(event, consumer);
}
GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue(
@@ -259,22 +313,30 @@ GestureSequence::Gestures* GestureRecognizerImpl::AdvanceTouchQueue(
return NULL;
}
- ScopedPop pop(event_queue_[consumer]);
- TouchEvent* event = event_queue_[consumer]->front();
-
- GestureSequence* sequence = GetGestureSequenceForConsumer(consumer);
-
- if (processed && event->type() == ui::ET_TOUCH_RELEASED) {
- // A touch release was was processed (e.g. preventDefault()ed by a
- // web-page), but we still need to process a touch cancel.
- CancelledTouchEvent cancelled(event);
- return sequence->ProcessTouchEventForGesture(cancelled,
- ui::TOUCH_STATUS_UNKNOWN);
+ scoped_ptr<GestureSequence::Gestures> gestures(
+ AdvanceTouchQueueByOne(consumer, processed ? TOUCH_STATUS_CONTINUE :
+ TOUCH_STATUS_UNKNOWN));
+
+ // Are there any queued touch-events that should be auto-dequeued?
+ while (!event_queue_[consumer]->empty()) {
+ QueuedTouchEvent* event =
+ static_cast<QueuedTouchEvent*>(event_queue_[consumer]->front());
+ if (event->status() == TOUCH_STATUS_QUEUED)
+ break;
+
+ GestureSequence::Gestures* current_gestures = AdvanceTouchQueueByOne(
+ consumer, event->status());
+ if (current_gestures) {
+ if (!gestures.get()) {
+ gestures.reset(current_gestures);
+ } else {
+ gestures->insert(gestures->end(), current_gestures->begin(),
+ current_gestures->end());
+ }
+ }
}
- return sequence->ProcessTouchEventForGesture(
- *event,
- processed ? ui::TOUCH_STATUS_CONTINUE : ui::TOUCH_STATUS_UNKNOWN);
+ return gestures.release();
}
void GestureRecognizerImpl::FlushTouchQueue(GestureConsumer* consumer) {
« 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