| 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
|
|
|