| Index: ui/events/gesture_detection/touch_disposition_gesture_filter.cc
|
| diff --git a/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
|
| similarity index 54%
|
| rename from content/browser/renderer_host/input/touch_disposition_gesture_filter.cc
|
| rename to ui/events/gesture_detection/touch_disposition_gesture_filter.cc
|
| index 7ae2efa34ab2d610848fe440f6eabf679977aca7..a5aec86067b4ed61da9a8e4b42cc60fa23a1e26a 100644
|
| --- a/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc
|
| +++ b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
|
| @@ -2,44 +2,40 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| -#include "content/browser/renderer_host/input/touch_disposition_gesture_filter.h"
|
| +#include "ui/events/gesture_detection/touch_disposition_gesture_filter.h"
|
|
|
| #include "base/auto_reset.h"
|
| -#include "base/bind.h"
|
| #include "base/logging.h"
|
|
|
| -using blink::WebGestureEvent;
|
| -using blink::WebInputEvent;
|
| -using blink::WebTouchEvent;
|
| -using blink::WebTouchPoint;
|
| -
|
| -namespace content {
|
| +namespace ui {
|
| namespace {
|
|
|
| -WebGestureEvent CreateGesture(WebInputEvent::Type type) {
|
| - DCHECK(WebInputEvent::isGestureEventType(type));
|
| - WebGestureEvent event;
|
| - event.type = type;
|
| - event.sourceDevice = WebGestureEvent::Touchscreen;
|
| - return event;
|
| +// A BitSet32 is used for tracking dropped gesture types.
|
| +COMPILE_ASSERT(
|
| + GESTURE_TYPE_FIRST + (GESTURE_TYPE_LAST - GESTURE_TYPE_FIRST) < 32,
|
| + gesture_type_count_too_large);
|
| +
|
| +GestureEventData CreateGesture(GestureEventType type) {
|
| + return GestureEventData(
|
| + type, base::TimeTicks(), 0, 0, GestureEventData::Details());
|
| }
|
|
|
| enum RequiredTouches {
|
| - RT_NONE = 0,
|
| - RT_START = 1 << 0,
|
| + RT_NONE = 0,
|
| + RT_START = 1 << 0,
|
| RT_CURRENT = 1 << 1,
|
| };
|
|
|
| struct DispositionHandlingInfo {
|
| // A bitwise-OR of |RequiredTouches|.
|
| int required_touches;
|
| - blink::WebInputEvent::Type antecedent_event_type;
|
| + GestureEventType antecedent_event_type;
|
|
|
| DispositionHandlingInfo(int required_touches)
|
| : required_touches(required_touches) {}
|
|
|
| DispositionHandlingInfo(int required_touches,
|
| - blink::WebInputEvent::Type antecedent_event_type)
|
| + GestureEventType antecedent_event_type)
|
| : required_touches(required_touches),
|
| antecedent_event_type(antecedent_event_type) {}
|
| };
|
| @@ -49,52 +45,50 @@ DispositionHandlingInfo Info(int required_touches) {
|
| }
|
|
|
| DispositionHandlingInfo Info(int required_touches,
|
| - blink::WebInputEvent::Type antecedent_event_type) {
|
| + GestureEventType antecedent_event_type) {
|
| return DispositionHandlingInfo(required_touches, antecedent_event_type);
|
| }
|
|
|
| // This approach to disposition handling is described at http://goo.gl/5G8PWJ.
|
| -DispositionHandlingInfo GetDispositionHandlingInfo(
|
| - blink::WebInputEvent::Type type) {
|
| +DispositionHandlingInfo GetDispositionHandlingInfo(GestureEventType type) {
|
| switch (type) {
|
| - case WebInputEvent::GestureTapDown:
|
| + case GESTURE_TAP_DOWN:
|
| return Info(RT_START);
|
| - case WebInputEvent::GestureTapCancel:
|
| + case GESTURE_TAP_CANCEL:
|
| return Info(RT_START);
|
| - case WebInputEvent::GestureShowPress:
|
| + case GESTURE_SHOW_PRESS:
|
| return Info(RT_START);
|
| - case WebInputEvent::GestureLongPress:
|
| + case GESTURE_LONG_PRESS:
|
| return Info(RT_START);
|
| - case WebInputEvent::GestureLongTap:
|
| - return Info(RT_START | RT_CURRENT);
|
| - case WebInputEvent::GestureTap:
|
| - return Info(RT_START | RT_CURRENT, WebInputEvent::GestureTapUnconfirmed);
|
| - case WebInputEvent::GestureTwoFingerTap:
|
| + case GESTURE_LONG_TAP:
|
| return Info(RT_START | RT_CURRENT);
|
| - case WebInputEvent::GestureTapUnconfirmed:
|
| + case GESTURE_TAP:
|
| + return Info(RT_START | RT_CURRENT, GESTURE_TAP_UNCONFIRMED);
|
| + case GESTURE_TAP_UNCONFIRMED:
|
| return Info(RT_START | RT_CURRENT);
|
| - case WebInputEvent::GestureDoubleTap:
|
| - return Info(RT_START | RT_CURRENT, WebInputEvent::GestureTapUnconfirmed);
|
| - case WebInputEvent::GestureScrollBegin:
|
| + case GESTURE_DOUBLE_TAP:
|
| + return Info(RT_START | RT_CURRENT, GESTURE_TAP_UNCONFIRMED);
|
| + case GESTURE_SCROLL_BEGIN:
|
| return Info(RT_START | RT_CURRENT);
|
| - case WebInputEvent::GestureScrollUpdate:
|
| - return Info(RT_CURRENT, WebInputEvent::GestureScrollBegin);
|
| - case WebInputEvent::GestureScrollEnd:
|
| - return Info(RT_NONE, WebInputEvent::GestureScrollBegin);
|
| - case WebInputEvent::GestureFlingStart:
|
| - return Info(RT_NONE, WebInputEvent::GestureScrollBegin);
|
| - case WebInputEvent::GestureFlingCancel:
|
| - return Info(RT_NONE, WebInputEvent::GestureFlingStart);
|
| - case WebInputEvent::GesturePinchBegin:
|
| - return Info(RT_START, WebInputEvent::GestureScrollBegin);
|
| - case WebInputEvent::GesturePinchUpdate:
|
| - return Info(RT_CURRENT, WebInputEvent::GesturePinchBegin);
|
| - case WebInputEvent::GesturePinchEnd:
|
| - return Info(RT_NONE, WebInputEvent::GesturePinchBegin);
|
| - default:
|
| - NOTREACHED();
|
| - return Info(RT_NONE);
|
| + case GESTURE_SCROLL_UPDATE:
|
| + return Info(RT_CURRENT, GESTURE_SCROLL_BEGIN);
|
| + case GESTURE_SCROLL_END:
|
| + return Info(RT_NONE, GESTURE_SCROLL_BEGIN);
|
| + case GESTURE_FLING_START:
|
| + return Info(RT_NONE, GESTURE_SCROLL_BEGIN);
|
| + case GESTURE_FLING_CANCEL:
|
| + return Info(RT_NONE, GESTURE_FLING_START);
|
| + case GESTURE_PINCH_BEGIN:
|
| + return Info(RT_START, GESTURE_SCROLL_BEGIN);
|
| + case GESTURE_PINCH_UPDATE:
|
| + return Info(RT_CURRENT, GESTURE_PINCH_BEGIN);
|
| + case GESTURE_PINCH_END:
|
| + return Info(RT_NONE, GESTURE_PINCH_BEGIN);
|
| + case GESTURE_TYPE_INVALID:
|
| + break;
|
| }
|
| + NOTREACHED();
|
| + return Info(RT_NONE);
|
| }
|
|
|
| } // namespace
|
| @@ -105,31 +99,31 @@ TouchDispositionGestureFilter::TouchDispositionGestureFilter(
|
| TouchDispositionGestureFilterClient* client)
|
| : client_(client),
|
| needs_tap_ending_event_(false),
|
| - needs_fling_ending_event_(false) {
|
| + needs_fling_ending_event_(false),
|
| + needs_scroll_ending_event_(false) {
|
| DCHECK(client_);
|
| }
|
|
|
| TouchDispositionGestureFilter::~TouchDispositionGestureFilter() {}
|
|
|
| TouchDispositionGestureFilter::PacketResult
|
| -TouchDispositionGestureFilter::OnGestureEventPacket(
|
| - const GestureEventPacket& packet) {
|
| - if (packet.gesture_source() == GestureEventPacket::UNDEFINED ||
|
| - packet.gesture_source() == GestureEventPacket::INVALID)
|
| +TouchDispositionGestureFilter::OnGesturePacket(
|
| + const GestureEventDataPacket& packet) {
|
| + if (packet.gesture_source() == GestureEventDataPacket::UNDEFINED ||
|
| + packet.gesture_source() == GestureEventDataPacket::INVALID)
|
| return INVALID_PACKET_TYPE;
|
|
|
| - if (packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_START)
|
| + if (packet.gesture_source() == GestureEventDataPacket::TOUCH_SEQUENCE_START)
|
| sequences_.push(GestureSequence());
|
|
|
| if (IsEmpty())
|
| return INVALID_PACKET_ORDER;
|
|
|
| - if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT &&
|
| + if (packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT &&
|
| Tail().IsEmpty()) {
|
| // Handle the timeout packet immediately if the packet preceding the timeout
|
| // has already been dispatched.
|
| - FilterAndSendPacket(
|
| - packet, Tail().state(), INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + FilterAndSendPacket(packet, Tail().state(), NOT_CONSUMED);
|
| return SUCCESS;
|
| }
|
|
|
| @@ -137,8 +131,7 @@ TouchDispositionGestureFilter::OnGestureEventPacket(
|
| return SUCCESS;
|
| }
|
|
|
| -void TouchDispositionGestureFilter::OnTouchEventAck(
|
| - InputEventAckState ack_state) {
|
| +void TouchDispositionGestureFilter::OnTouchEventAck(TouchEventAck ack_result) {
|
| // Spurious touch acks from the renderer should not trigger a crash.
|
| if (IsEmpty() || (Head().IsEmpty() && sequences_.size() == 1))
|
| return;
|
| @@ -146,6 +139,7 @@ void TouchDispositionGestureFilter::OnTouchEventAck(
|
| if (Head().IsEmpty()) {
|
| CancelTapIfNecessary();
|
| CancelFlingIfNecessary();
|
| + EndScrollIfNecessary();
|
| last_event_of_type_dropped_.clear();
|
| sequences_.pop();
|
| }
|
| @@ -156,18 +150,18 @@ void TouchDispositionGestureFilter::OnTouchEventAck(
|
| // additional timeout-based packets queued before the ack was received.
|
| bool touch_packet_for_current_ack_handled = false;
|
| while (!sequence.IsEmpty()) {
|
| - const GestureEventPacket& packet = sequence.Front();
|
| - DCHECK_NE(packet.gesture_source(), GestureEventPacket::UNDEFINED);
|
| - DCHECK_NE(packet.gesture_source(), GestureEventPacket::INVALID);
|
| + const GestureEventDataPacket& packet = sequence.Front();
|
| + DCHECK_NE(packet.gesture_source(), GestureEventDataPacket::UNDEFINED);
|
| + DCHECK_NE(packet.gesture_source(), GestureEventDataPacket::INVALID);
|
|
|
| - if (packet.gesture_source() != GestureEventPacket::TOUCH_TIMEOUT) {
|
| + if (packet.gesture_source() != GestureEventDataPacket::TOUCH_TIMEOUT) {
|
| // We should handle at most one non-timeout based packet.
|
| if (touch_packet_for_current_ack_handled)
|
| break;
|
| - sequence.UpdateState(packet.gesture_source(), ack_state);
|
| + sequence.UpdateState(packet.gesture_source(), ack_result);
|
| touch_packet_for_current_ack_handled = true;
|
| }
|
| - FilterAndSendPacket(packet, sequence.state(), ack_state);
|
| + FilterAndSendPacket(packet, sequence.state(), ack_result);
|
| sequence.Pop();
|
| }
|
| DCHECK(touch_packet_for_current_ack_handled);
|
| @@ -178,46 +172,55 @@ bool TouchDispositionGestureFilter::IsEmpty() const {
|
| }
|
|
|
| void TouchDispositionGestureFilter::FilterAndSendPacket(
|
| - const GestureEventPacket& packet,
|
| + const GestureEventDataPacket& packet,
|
| const GestureSequence::GestureHandlingState& sequence_state,
|
| - InputEventAckState ack_state) {
|
| + TouchEventAck ack_result) {
|
| for (size_t i = 0; i < packet.gesture_count(); ++i) {
|
| - const blink::WebGestureEvent& gesture = packet.gesture(i);
|
| - if (IsGesturePrevented(gesture.type, ack_state, sequence_state)) {
|
| - last_event_of_type_dropped_.insert(gesture.type);
|
| + const GestureEventData& gesture = packet.gesture(i);
|
| + DCHECK_NE(GESTURE_TYPE_INVALID, gesture.type);
|
| + if (IsGesturePrevented(gesture.type, ack_result, sequence_state)) {
|
| + last_event_of_type_dropped_.mark_bit(gesture.type);
|
| CancelTapIfNecessary();
|
| continue;
|
| }
|
| - last_event_of_type_dropped_.erase(gesture.type);
|
| + last_event_of_type_dropped_.clear_bit(gesture.type);
|
| SendGesture(gesture);
|
| }
|
| }
|
|
|
| -void TouchDispositionGestureFilter::SendGesture(const WebGestureEvent& event) {
|
| +void TouchDispositionGestureFilter::SendGesture(const GestureEventData& event) {
|
| + // TODO(jdduke): Factor out gesture stream reparation code into a standalone
|
| + // utility class.
|
| switch (event.type) {
|
| - case WebInputEvent::GestureLongTap:
|
| + case GESTURE_LONG_TAP:
|
| CancelTapIfNecessary();
|
| CancelFlingIfNecessary();
|
| break;
|
| - case WebInputEvent::GestureTapDown:
|
| + case GESTURE_TAP_DOWN:
|
| DCHECK(!needs_tap_ending_event_);
|
| needs_tap_ending_event_ = true;
|
| break;
|
| - case WebInputEvent::GestureTapCancel:
|
| - case WebInputEvent::GestureTap:
|
| - case WebInputEvent::GestureTapUnconfirmed:
|
| - case WebInputEvent::GestureDoubleTap:
|
| + case GESTURE_TAP:
|
| + case GESTURE_TAP_CANCEL:
|
| + case GESTURE_TAP_UNCONFIRMED:
|
| + case GESTURE_DOUBLE_TAP:
|
| needs_tap_ending_event_ = false;
|
| break;
|
| - case WebInputEvent::GestureScrollBegin:
|
| + case GESTURE_SCROLL_BEGIN:
|
| CancelTapIfNecessary();
|
| CancelFlingIfNecessary();
|
| + EndScrollIfNecessary();
|
| + needs_scroll_ending_event_ = true;
|
| + break;
|
| + case GESTURE_SCROLL_END:
|
| + needs_scroll_ending_event_ = false;
|
| break;
|
| - case WebInputEvent::GestureFlingStart:
|
| + case GESTURE_FLING_START:
|
| CancelFlingIfNecessary();
|
| needs_fling_ending_event_ = true;
|
| + needs_scroll_ending_event_ = false;
|
| break;
|
| - case WebInputEvent::GestureFlingCancel:
|
| + case GESTURE_FLING_CANCEL:
|
| needs_fling_ending_event_ = false;
|
| break;
|
| default:
|
| @@ -230,7 +233,7 @@ void TouchDispositionGestureFilter::CancelTapIfNecessary() {
|
| if (!needs_tap_ending_event_)
|
| return;
|
|
|
| - SendGesture(CreateGesture(WebInputEvent::GestureTapCancel));
|
| + SendGesture(CreateGesture(GESTURE_TAP_CANCEL));
|
| DCHECK(!needs_tap_ending_event_);
|
| }
|
|
|
| @@ -238,17 +241,23 @@ void TouchDispositionGestureFilter::CancelFlingIfNecessary() {
|
| if (!needs_fling_ending_event_)
|
| return;
|
|
|
| - SendGesture(CreateGesture(WebInputEvent::GestureFlingCancel));
|
| + SendGesture(CreateGesture(GESTURE_FLING_CANCEL));
|
| DCHECK(!needs_fling_ending_event_);
|
| }
|
|
|
| +void TouchDispositionGestureFilter::EndScrollIfNecessary() {
|
| + if (!needs_scroll_ending_event_)
|
| + return;
|
| +
|
| + SendGesture(CreateGesture(GESTURE_SCROLL_END));
|
| + DCHECK(!needs_scroll_ending_event_);
|
| +}
|
| +
|
| // TouchDispositionGestureFilter::GestureSequence
|
|
|
| TouchDispositionGestureFilter::GestureSequence::GestureHandlingState::
|
| GestureHandlingState()
|
| - : seen_ack(false),
|
| - start_consumed(false),
|
| - no_consumer(false) {}
|
| + : seen_ack(false), start_consumed(false), no_consumer(false) {}
|
|
|
| TouchDispositionGestureFilter::GestureSequence&
|
| TouchDispositionGestureFilter::Head() {
|
| @@ -267,7 +276,7 @@ TouchDispositionGestureFilter::GestureSequence::GestureSequence() {}
|
| TouchDispositionGestureFilter::GestureSequence::~GestureSequence() {}
|
|
|
| void TouchDispositionGestureFilter::GestureSequence::Push(
|
| - const GestureEventPacket& packet) {
|
| + const GestureEventDataPacket& packet) {
|
| packets_.push(packet);
|
| }
|
|
|
| @@ -276,27 +285,26 @@ void TouchDispositionGestureFilter::GestureSequence::Pop() {
|
| packets_.pop();
|
| }
|
|
|
| -const GestureEventPacket&
|
| +const GestureEventDataPacket&
|
| TouchDispositionGestureFilter::GestureSequence::Front() const {
|
| DCHECK(!IsEmpty());
|
| return packets_.front();
|
| }
|
|
|
| void TouchDispositionGestureFilter::GestureSequence::UpdateState(
|
| - GestureEventPacket::GestureSource gesture_source,
|
| - InputEventAckState ack_state) {
|
| - DCHECK_NE(INPUT_EVENT_ACK_STATE_UNKNOWN, ack_state);
|
| + GestureEventDataPacket::GestureSource gesture_source,
|
| + TouchEventAck ack_result) {
|
| +
|
| // Permanent states will not be affected by subsequent ack's.
|
| if (state_.no_consumer || state_.start_consumed)
|
| return;
|
|
|
| // |NO_CONSUMER| should only be effective when the *first* touch is ack'ed.
|
| - if (!state_.seen_ack &&
|
| - ack_state == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) {
|
| + if (!state_.seen_ack && ack_result == NO_CONSUMER_EXISTS) {
|
| state_.no_consumer = true;
|
| - } else if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED) {
|
| - if (gesture_source == GestureEventPacket::TOUCH_SEQUENCE_START ||
|
| - gesture_source == GestureEventPacket::TOUCH_START) {
|
| + } else if (ack_result == CONSUMED) {
|
| + if (gesture_source == GestureEventDataPacket::TOUCH_SEQUENCE_START ||
|
| + gesture_source == GestureEventDataPacket::TOUCH_START) {
|
| state_.start_consumed = true;
|
| }
|
| }
|
| @@ -304,8 +312,8 @@ void TouchDispositionGestureFilter::GestureSequence::UpdateState(
|
| }
|
|
|
| bool TouchDispositionGestureFilter::IsGesturePrevented(
|
| - WebInputEvent::Type gesture_type,
|
| - InputEventAckState current,
|
| + GestureEventType gesture_type,
|
| + TouchEventAck current,
|
| const GestureSequence::GestureHandlingState& state) const {
|
|
|
| if (state.no_consumer)
|
| @@ -315,11 +323,11 @@ bool TouchDispositionGestureFilter::IsGesturePrevented(
|
| GetDispositionHandlingInfo(gesture_type);
|
|
|
| int required_touches = disposition_handling_info.required_touches;
|
| - bool current_consumed = current == INPUT_EVENT_ACK_STATE_CONSUMED;
|
| + bool current_consumed = current == CONSUMED;
|
| if ((required_touches & RT_START && state.start_consumed) ||
|
| (required_touches & RT_CURRENT && current_consumed) ||
|
| - (last_event_of_type_dropped_.count(
|
| - disposition_handling_info.antecedent_event_type) > 0)) {
|
| + (last_event_of_type_dropped_.has_bit(
|
| + disposition_handling_info.antecedent_event_type))) {
|
| return true;
|
| }
|
| return false;
|
|
|