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

Unified Diff: ui/events/gestures/gesture_event_queue.cc

Issue 101933004: Eager Gesture Recognizer (WIP) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Starting work on Android. Created 6 years, 11 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/events/gestures/gesture_event_queue.h ('k') | ui/events/gestures/gesture_event_queue_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/events/gestures/gesture_event_queue.cc
diff --git a/ui/events/gestures/gesture_event_queue.cc b/ui/events/gestures/gesture_event_queue.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b7bca7999986eef346b08fc7210c522806dc11c3
--- /dev/null
+++ b/ui/events/gestures/gesture_event_queue.cc
@@ -0,0 +1,238 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/gestures/gesture_event_queue.h"
+#include "ui/events/gestures/gesture_sequence.h"
+
+namespace ui {
+
+GestureEventQueue::GestureWithState::GestureWithState(
+ GestureEvent* event,
+ std::vector<TouchPointState*>& touch_point_states)
+ : event_(event) {
+ touch_point_states_.swap(touch_point_states);
+}
+
+GestureEventQueue::GestureWithState::~GestureWithState() {
+ CHECK(event_->IsGestureEvent());
+}
+
+GestureEventQueue::GestureEventQueue(GestureEventQueueDelegate* geqd)
+ : gesture_event_queue_delegate_(geqd) {
+ touch_point_states_.resize(GestureSequence::kMaxGesturePoints);
+ acked_touch_point_states_.resize(GestureSequence::kMaxGesturePoints);
+ consumed_touch_point_states_.resize(GestureSequence::kMaxGesturePoints);
+
+ for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) {
+ touch_point_states_[i] = new TouchPointState(i);
+ acked_touch_point_states_[i] = new TouchPointState(i);
+ consumed_touch_point_states_[i] = new TouchPointState(i);
+ }
+}
+
+GestureEventQueue::~GestureEventQueue() {
+ while (!sequences_.empty()) {
+ delete sequences_.front();
+ sequences_.pop_front();
+ }
+}
+
+void GestureEventQueue::OnTouchEvent(const TouchEvent& event) {
+ touch_point_states_[event.touch_id()]->Update(event);
+
+ // TODO - remove this
+ if (!sequences_.empty() && !(*sequences_.begin())->empty()) {
+ LOG(ERROR) << "length of first sequence is "
+ << (*sequences_.begin())->size();
+ }
+}
+
+void GestureEventQueue::OnTouchEventAck(
+ const TouchEvent& event,
+ EventResult result) {
+ if (result == ER_CONSUMED)
+ consumed_touch_point_states_[event.touch_id()]->Update(event);
+ else
+ acked_touch_point_states_[event.touch_id()]->Update(event);
+
+ DeleteConsumedEvents();
+ SendAckedEvents();
+
+ if (event.type() == ET_TOUCH_RELEASED ||
+ event.type() == ET_TOUCH_CANCELLED) {
+ touch_point_states_[event.touch_id()]->Reset();
+ consumed_touch_point_states_[event.touch_id()]->Reset();
+ acked_touch_point_states_[event.touch_id()]->Reset();
+ }
+}
+
+void GestureEventQueue::QueueGestureEvent(
+ GestureEvent* event,
+ TouchPointState::RequiresAck requires_ack) {
+ std::vector<TouchPointState*> tps;
+
+ for (ScopedVector<TouchPointState>::iterator it = touch_point_states_.begin();
+ it != touch_point_states_.end();
+ ++it) {
+ if ((*it)->has_press())
+ tps.push_back((*it)->CopyForGestureType(event->type(), requires_ack));
+ }
+ // Takes ownership of entries in tps.
+ QueueGestureEvent(event, tps);
+}
+
+void GestureEventQueue::TimerFired() {
+ for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) {
+ if (touch_point_states_[i]->has_press())
+ acked_touch_point_states_[i]->TimerFired();
+ }
+ SendAckedEvents();
+}
+
+void GestureEventQueue::TimerCancelled() {
+ for (int i = 0; i < GestureSequence::kMaxGesturePoints; ++i) {
+ if (touch_point_states_[i]->has_press())
+ consumed_touch_point_states_[i]->TimerFired();
+ }
+ DeleteConsumedEvents();
+ SendAckedEvents();
+}
+
+void GestureEventQueue::QueueGestureEvent(
+ GestureEvent* event,
+ std::vector<TouchPointState*>& touch_point_states) {
+ CHECK(event->IsGestureEvent()) << "Event of type " << event->type();
+ // If this marks the beginning of a new sequence, construct a new
+ // |Sequence|. Deleted in |OnTouchEventAck|, and |~GestureEventQueue|.
+ if (event->type() == ET_GESTURE_BEGIN && event->details().touch_points() == 1)
+ sequences_.push_back(new Sequence());
+
+ DCHECK(!sequences_.empty()) << "Possibly missing a gesture begin";
+
+ if (sequences_.empty())
+ LOG(ERROR) << "Missing a gesture begin?";
+ // TODO - this shouldn't be necessary...
+ if (sequences_.empty())
+ sequences_.push_back(new Sequence());
+
+ Sequence* sequence = sequences_.back();
+
+ // The GestureWithState takes ownership of the elements of touch_point_states.
+ sequence->push_back(new GestureWithState(event, touch_point_states));
+
+ if (sequences_.empty()) {
+ LOG(ERROR) << "No sequence";
+ } else if ((*sequences_.begin())->empty())
+ LOG(ERROR) << "First sequence empty";
+ else {
+ LOG(ERROR) << "length of first sequence is "
+ << (*sequences_.begin())->size();
+ LOG(ERROR) << "First element is "
+ << (*(*sequences_.begin())->begin())->event()->type();
+ }
+
+ DeleteConsumedEvents();
+ SendAckedEvents();
+}
+
+void GestureEventQueue::SendGestureEvent(GestureEvent* event) {
+ gesture_event_queue_delegate_->DispatchGestureEvent(event);
+}
+
+bool GestureEventQueue::CanSend(
+ const std::vector<TouchPointState*>& gesture_touches) const {
+ if (gesture_touches.empty())
+ return true;
+ std::vector<TouchPointState*>::const_iterator it;
+ for (it = gesture_touches.begin();
+ it != gesture_touches.end();
+ ++it) {
+ const TouchPointState& current =
+ *acked_touch_point_states_[(*it)->touch_id()];
+
+ if (!current.Contains(*(*it)))
+ return false;
+ }
+ return true;
+}
+
+bool GestureEventQueue::CanDelete(
+ const std::vector<TouchPointState*>& gesture_touches) const {
+ if (gesture_touches.empty())
+ return false;
+ std::vector<TouchPointState*>::const_iterator it;
+ for (it = gesture_touches.begin();
+ it != gesture_touches.end();
+ ++it) {
+ const TouchPointState& current =
+ *consumed_touch_point_states_[(*it)->touch_id()];
+ if (!current.HasEmptyIntersection(*(*it)))
+ return true;
+ }
+ return false;
+}
+
+void GestureEventQueue::SendAckedEvents() {
+ RemoveEmptyFirstSequence();
+ LOG(ERROR) << "SendAckedEvents";
+ // TODO - should these be DCHECKs?
+ if (sequences_.empty()) {
+ LOG(ERROR) << "sequences_ is empty, bailing";
+ return;
+ }
+ Sequence* sequence = sequences_.front();
+ if (sequence->empty()) {
+ LOG(ERROR) << "sequence is empty, bailing";
+ return;
+ }
+ DCHECK(!sequence->empty());
+ for (Sequence::iterator it = sequence->begin();
+ it != sequence->end();) {
+ GestureEvent* event = (*it)->event();
+ CHECK(event->IsGestureEvent()) << "Event of type " << event->type();
+ if (CanSend((*it)->touch_point_states())) {
+ SendGestureEvent(event);
+ LOG(ERROR) << "SENT! " << event->type();
+ it = sequence->erase(it);
+ LOG(ERROR) << "ERASED!";
+ } else if (event->type() == ET_GESTURE_LONG_PRESS ||
+ event->type() == ET_GESTURE_SHOW_PRESS) {
+ // We don't need to respect the ordering of timed events.
+ ++it;
+ } else {
+ break;
+ }
+ }
+}
+
+void GestureEventQueue::DeleteConsumedEvents() {
+ RemoveEmptyFirstSequence();
+ // TODO - should this be a CHECK?
+ if (sequences_.empty())
+ return;
+ Sequence* sequence = sequences_.front();
+ if (sequence->empty())
+ return;
+ DCHECK(!sequence->empty());
+ for (Sequence::iterator it = sequence->begin();
+ it != sequence->end();) {
+ GestureEvent* event = (*it)->event();
+ CHECK(event->IsGestureEvent()) << "Event of type " << event->type();
+ if (CanDelete((*it)->touch_point_states())) {
+ it = sequence->erase(it);
+ } else
+ ++it;
+ }
+}
+
+void GestureEventQueue::RemoveEmptyFirstSequence() {
+ // If we've sent or deleted everything in the current sequence, and a new
+ // sequence has started, get rid of the current sequence.
+ if (sequences_.size() > 1 && sequences_.front()->empty()) {
+ delete sequences_.front();
+ sequences_.pop_front();
+ }
+}
+
+} // namespace ui
« no previous file with comments | « ui/events/gestures/gesture_event_queue.h ('k') | ui/events/gestures/gesture_event_queue_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698