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

Unified Diff: content/browser/renderer_host/input/touch_disposition_gesture_filter.cc

Issue 156783006: Consuming a touch move prevents only the next scroll update. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clean up error handling and tests. Created 6 years, 10 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
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
index 35db76779b68b34b26912e864c09b3983abf38ee..067293b5e0d9585225c54564c9a753c33ff07c7c 100644
--- a/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc
+++ b/content/browser/renderer_host/input/touch_disposition_gesture_filter.cc
@@ -41,23 +41,19 @@ TouchDispositionGestureFilter::~TouchDispositionGestureFilter() {}
TouchDispositionGestureFilter::PacketResult
TouchDispositionGestureFilter::OnGestureEventPacket(
const GestureEventPacket& packet) {
- if (packet.gesture_source() == GestureEventPacket::INVALID)
+ if (packet.gesture_source() == GestureEventPacket::INVALID)
return INVALID_PACKET_TYPE;
- if (packet.gesture_source() == GestureEventPacket::TOUCH_BEGIN)
+ if (packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_BEGIN)
sequences_.push(GestureSequence());
- if (IsEmpty())
+ if (packet.gesture_source() == GestureEventPacket::OUT_OF_ORDER || IsEmpty())
return INVALID_PACKET_ORDER;
- if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT) {
- // Handle the timeout packet immediately if the packet preceding the
- // timeout has already been dispatched.
- if (Tail().IsEmpty()) {
- if (!Tail().IsGesturePrevented())
- SendPacket(packet);
- return SUCCESS;
- }
+ if (packet.gesture_source() == GestureEventPacket::TOUCH_TIMEOUT &&
+ Tail().IsEmpty()) {
+ FilterAndSendPacket(packet, Tail(), INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ return SUCCESS;
}
Tail().Push(packet);
@@ -70,14 +66,7 @@ void TouchDispositionGestureFilter::OnTouchEventAck(
if (IsEmpty() || (Head().IsEmpty() && sequences_.size() == 1))
return;
- if (Head().IsEmpty()) {
- CancelTapIfNecessary();
- CancelFlingIfNecessary();
- sequences_.pop();
- }
-
GestureSequence& sequence = Head();
- sequence.UpdateState(ack_state);
// Dispatch the packet corresponding to the ack'ed touch, as well as any
// additional timeout-based packets queued before the ack was received.
@@ -85,36 +74,56 @@ void TouchDispositionGestureFilter::OnTouchEventAck(
while (!sequence.IsEmpty()) {
const GestureEventPacket& packet = sequence.Front();
- if (packet.gesture_source() == GestureEventPacket::TOUCH_BEGIN ||
- packet.gesture_source() == GestureEventPacket::TOUCH) {
+ if(packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_BEGIN)
+ CancelFlingIfNecessary();
+
+ if (packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_BEGIN ||
+ packet.gesture_source() == GestureEventPacket::TOUCH_SEQUENCE_END ||
+ packet.gesture_source() == GestureEventPacket::TOUCH_BEGIN ||
+ packet.gesture_source() == GestureEventPacket::TOUCH_MOVE ||
+ packet.gesture_source() == GestureEventPacket::TOUCH_END) {
// We should handle at most one touch-based packet corresponding to a
// given ack.
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, ack_state);
- if (!sequence.IsGesturePrevented())
- SendPacket(packet);
-
+ GestureEventPacket::GestureSource gesture_source = packet.gesture_source();
sequence.Pop();
+
+ if (gesture_source == GestureEventPacket::TOUCH_SEQUENCE_END) {
+ DCHECK(Head().IsEmpty());
+ CancelTapIfNecessary();
jdduke (slow) 2014/02/13 16:53:06 I'm not sure we can cancel the tap here... With th
tdresser 2014/02/13 18:14:09 Done.
+ sequences_.pop();
+ }
}
DCHECK(touch_packet_for_current_ack_handled);
-
- // Immediately cancel a TapDown if TouchStart went unconsumed, but a
- // subsequent TouchMove is consumed.
- if (sequence.IsGesturePrevented())
- CancelTapIfNecessary();
}
bool TouchDispositionGestureFilter::IsEmpty() const {
return sequences_.empty();
}
-void TouchDispositionGestureFilter::SendPacket(
- const GestureEventPacket& packet) {
- for (size_t i = 0; i < packet.gesture_count(); ++i)
- SendGesture(packet.gesture(i));
+void TouchDispositionGestureFilter::FilterAndSendPacket(
+ const GestureEventPacket& packet,
+ const GestureSequence& sequence,
+ InputEventAckState ack_state) {
+ for (size_t i = 0; i < packet.gesture_count(); ++i) {
+ const blink::WebGestureEvent& gesture = packet.gesture(i);
+ bool dropped = IsGesturePrevented(
+ gesture.type, ack_state, sequence.state());
+ if (!dropped)
+ SendGesture(gesture);
+ else
+ CancelTapIfNecessary();
+ if (dropped)
+ last_event_of_type_dropped_.insert(gesture.type);
+ else
+ last_event_of_type_dropped_.erase(gesture.type);
+ }
}
void TouchDispositionGestureFilter::SendGesture(const WebGestureEvent& event) {
@@ -124,6 +133,7 @@ void TouchDispositionGestureFilter::SendGesture(const WebGestureEvent& event) {
CancelFlingIfNecessary();
break;
case WebInputEvent::GestureTapDown:
+ DCHECK(!needs_tap_ending_event_);
jdduke (slow) 2014/02/13 16:53:06 As noted above, we may need to switch this to |Can
tdresser 2014/02/13 18:14:09 This will have been handled above in the Head().Is
needs_tap_ending_event_ = true;
break;
case WebInputEvent::GestureTapCancel:
@@ -177,11 +187,7 @@ TouchDispositionGestureFilter::Tail() {
return sequences_.back();
}
-
-// TouchDispositionGestureFilter::GestureSequence
-
-TouchDispositionGestureFilter::GestureSequence::GestureSequence()
- : state_(PENDING) {}
+TouchDispositionGestureFilter::GestureSequence::GestureSequence() {}
TouchDispositionGestureFilter::GestureSequence::~GestureSequence() {}
@@ -202,25 +208,93 @@ TouchDispositionGestureFilter::GestureSequence::Front() const {
}
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_ != PENDING && state_ != ALLOWED_UNTIL_PREVENTED)
+ if (state_.no_consumer || (state_.start_consumed && state_.move_consumed))
return;
// |NO_CONSUMER| should only be effective when the *first* touch is ack'ed.
- if (state_ == PENDING &&
- ack_state == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
- state_ = ALWAYS_ALLOWED;
- else if (ack_state == INPUT_EVENT_ACK_STATE_CONSUMED)
- state_ = ALWAYS_PREVENTED;
- else
- state_ = ALLOWED_UNTIL_PREVENTED;
-}
-
-bool TouchDispositionGestureFilter::GestureSequence::IsGesturePrevented()
- const {
- return state_ == ALWAYS_PREVENTED;
+ 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_BEGIN ||
+ gesture_source == GestureEventPacket::TOUCH_BEGIN) {
+ state_.start_consumed = true;
+ } else if (gesture_source == GestureEventPacket::TOUCH_MOVE) {
+ state_.move_consumed = true;
+ }
+ }
+ state_.seen_ack = true;
+}
+
+bool TouchDispositionGestureFilter::IsGesturePrevented(
jdduke (slow) 2014/02/13 16:53:06 This is another mostly static function that we sho
tdresser 2014/02/13 18:14:09 This would require making GestureHandlingState pub
+ 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_MOVE && state.move_consumed) ||
+ (required_touches & RT_CURRENT && current_consumed) ||
+ (last_event_of_type_dropped_.count(
+ disposition_handling_info.antecedent_event_type))) {
+ return true;
+ }
+ return false;
+}
+
+TouchDispositionGestureFilter::DispositionHandlingInfo
+TouchDispositionGestureFilter::GetDispositionHandlingInfo(
+ blink::WebInputEvent::Type type) const {
+ 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_MOVE);
+ 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);
+ }
}
bool TouchDispositionGestureFilter::GestureSequence::IsEmpty() const {

Powered by Google App Engine
This is Rietveld 408576698