Index: content/browser/renderer_host/input/touch_disposition_gesture_filter.cc |
diff --git a/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc b/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc |
deleted file mode 100644 |
index 7ae2efa34ab2d610848fe440f6eabf679977aca7..0000000000000000000000000000000000000000 |
--- a/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc |
+++ /dev/null |
@@ -1,332 +0,0 @@ |
-// Copyright 2014 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 "content/browser/renderer_host/input/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 { |
- |
-WebGestureEvent CreateGesture(WebInputEvent::Type type) { |
- DCHECK(WebInputEvent::isGestureEventType(type)); |
- WebGestureEvent event; |
- event.type = type; |
- event.sourceDevice = WebGestureEvent::Touchscreen; |
- return event; |
-} |
- |
-enum RequiredTouches { |
- 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; |
- |
- DispositionHandlingInfo(int required_touches) |
- : required_touches(required_touches) {} |
- |
- DispositionHandlingInfo(int required_touches, |
- blink::WebInputEvent::Type antecedent_event_type) |
- : required_touches(required_touches), |
- antecedent_event_type(antecedent_event_type) {} |
-}; |
- |
-DispositionHandlingInfo Info(int required_touches) { |
- return DispositionHandlingInfo(required_touches); |
-} |
- |
-DispositionHandlingInfo Info(int required_touches, |
- blink::WebInputEvent::Type 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) { |
- switch (type) { |
- case WebInputEvent::GestureTapDown: |
- return Info(RT_START); |
- case WebInputEvent::GestureTapCancel: |
- return Info(RT_START); |
- case WebInputEvent::GestureShowPress: |
- return Info(RT_START); |
- case WebInputEvent::GestureLongPress: |
- 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: |
- return Info(RT_START | RT_CURRENT); |
- case WebInputEvent::GestureTapUnconfirmed: |
- return Info(RT_START | RT_CURRENT); |
- case WebInputEvent::GestureDoubleTap: |
- return Info(RT_START | RT_CURRENT, WebInputEvent::GestureTapUnconfirmed); |
- case WebInputEvent::GestureScrollBegin: |
- 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); |
- } |
-} |
- |
-} // namespace |
- |
-// TouchDispositionGestureFilter |
- |
-TouchDispositionGestureFilter::TouchDispositionGestureFilter( |
- TouchDispositionGestureFilterClient* client) |
- : client_(client), |
- needs_tap_ending_event_(false), |
- needs_fling_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) |
- return INVALID_PACKET_TYPE; |
- |
- if (packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_START) |
- sequences_.push(GestureSequence()); |
- |
- if (IsEmpty()) |
- return INVALID_PACKET_ORDER; |
- |
- if (packet.gesture_source() == GestureEventPacket::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); |
- return SUCCESS; |
- } |
- |
- Tail().Push(packet); |
- return SUCCESS; |
-} |
- |
-void TouchDispositionGestureFilter::OnTouchEventAck( |
- InputEventAckState ack_state) { |
- // Spurious touch acks from the renderer should not trigger a crash. |
- if (IsEmpty() || (Head().IsEmpty() && sequences_.size() == 1)) |
- return; |
- |
- if (Head().IsEmpty()) { |
- CancelTapIfNecessary(); |
- CancelFlingIfNecessary(); |
- last_event_of_type_dropped_.clear(); |
- sequences_.pop(); |
- } |
- |
- GestureSequence& sequence = Head(); |
- |
- // Dispatch the packet corresponding to the ack'ed touch, as well as any |
- // 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); |
- |
- if (packet.gesture_source() != GestureEventPacket::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); |
- touch_packet_for_current_ack_handled = true; |
- } |
- FilterAndSendPacket(packet, sequence.state(), ack_state); |
- sequence.Pop(); |
- } |
- DCHECK(touch_packet_for_current_ack_handled); |
-} |
- |
-bool TouchDispositionGestureFilter::IsEmpty() const { |
- return sequences_.empty(); |
-} |
- |
-void TouchDispositionGestureFilter::FilterAndSendPacket( |
- const GestureEventPacket& packet, |
- const GestureSequence::GestureHandlingState& sequence_state, |
- InputEventAckState ack_state) { |
- 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); |
- CancelTapIfNecessary(); |
- continue; |
- } |
- last_event_of_type_dropped_.erase(gesture.type); |
- SendGesture(gesture); |
- } |
-} |
- |
-void TouchDispositionGestureFilter::SendGesture(const WebGestureEvent& event) { |
- switch (event.type) { |
- case WebInputEvent::GestureLongTap: |
- CancelTapIfNecessary(); |
- CancelFlingIfNecessary(); |
- break; |
- case WebInputEvent::GestureTapDown: |
- DCHECK(!needs_tap_ending_event_); |
- needs_tap_ending_event_ = true; |
- break; |
- case WebInputEvent::GestureTapCancel: |
- case WebInputEvent::GestureTap: |
- case WebInputEvent::GestureTapUnconfirmed: |
- case WebInputEvent::GestureDoubleTap: |
- needs_tap_ending_event_ = false; |
- break; |
- case WebInputEvent::GestureScrollBegin: |
- CancelTapIfNecessary(); |
- CancelFlingIfNecessary(); |
- break; |
- case WebInputEvent::GestureFlingStart: |
- CancelFlingIfNecessary(); |
- needs_fling_ending_event_ = true; |
- break; |
- case WebInputEvent::GestureFlingCancel: |
- needs_fling_ending_event_ = false; |
- break; |
- default: |
- break; |
- } |
- client_->ForwardGestureEvent(event); |
-} |
- |
-void TouchDispositionGestureFilter::CancelTapIfNecessary() { |
- if (!needs_tap_ending_event_) |
- return; |
- |
- SendGesture(CreateGesture(WebInputEvent::GestureTapCancel)); |
- DCHECK(!needs_tap_ending_event_); |
-} |
- |
-void TouchDispositionGestureFilter::CancelFlingIfNecessary() { |
- if (!needs_fling_ending_event_) |
- return; |
- |
- SendGesture(CreateGesture(WebInputEvent::GestureFlingCancel)); |
- DCHECK(!needs_fling_ending_event_); |
-} |
- |
-// TouchDispositionGestureFilter::GestureSequence |
- |
-TouchDispositionGestureFilter::GestureSequence::GestureHandlingState:: |
- GestureHandlingState() |
- : seen_ack(false), |
- start_consumed(false), |
- no_consumer(false) {} |
- |
-TouchDispositionGestureFilter::GestureSequence& |
-TouchDispositionGestureFilter::Head() { |
- DCHECK(!sequences_.empty()); |
- return sequences_.front(); |
-} |
- |
-TouchDispositionGestureFilter::GestureSequence& |
-TouchDispositionGestureFilter::Tail() { |
- DCHECK(!sequences_.empty()); |
- return sequences_.back(); |
-} |
- |
-TouchDispositionGestureFilter::GestureSequence::GestureSequence() {} |
- |
-TouchDispositionGestureFilter::GestureSequence::~GestureSequence() {} |
- |
-void TouchDispositionGestureFilter::GestureSequence::Push( |
- const GestureEventPacket& packet) { |
- packets_.push(packet); |
-} |
- |
-void TouchDispositionGestureFilter::GestureSequence::Pop() { |
- DCHECK(!IsEmpty()); |
- packets_.pop(); |
-} |
- |
-const GestureEventPacket& |
-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); |
- // 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) { |
- 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) { |
- state_.start_consumed = true; |
- } |
- } |
- state_.seen_ack = true; |
-} |
- |
-bool TouchDispositionGestureFilter::IsGesturePrevented( |
- WebInputEvent::Type gesture_type, |
- InputEventAckState current, |
- const GestureSequence::GestureHandlingState& state) const { |
- |
- if (state.no_consumer) |
- return false; |
- |
- DispositionHandlingInfo disposition_handling_info = |
- GetDispositionHandlingInfo(gesture_type); |
- |
- int required_touches = disposition_handling_info.required_touches; |
- bool current_consumed = current == INPUT_EVENT_ACK_STATE_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)) { |
- return true; |
- } |
- return false; |
-} |
- |
-bool TouchDispositionGestureFilter::GestureSequence::IsEmpty() const { |
- return packets_.empty(); |
-} |
- |
-} // namespace content |