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 |