Index: content/browser/renderer_host/input/gesture_event_queue.cc |
diff --git a/content/browser/renderer_host/input/gesture_event_queue.cc b/content/browser/renderer_host/input/gesture_event_queue.cc |
index 6333de09646b4921801840f7026e742ee3888241..498379f0de35d9532a3d3385a8423a92668c6f87 100644 |
--- a/content/browser/renderer_host/input/gesture_event_queue.cc |
+++ b/content/browser/renderer_host/input/gesture_event_queue.cc |
@@ -31,7 +31,9 @@ WebGestureEvent CreateGesture(WebInputEvent::Type type) { |
GestureEventQueue::GestureEventQueue(GestureEventQueueClient* client) |
: client_(client), |
needs_tap_ending_event_(false), |
- needs_fling_ending_event_(false) { |
+ needs_fling_ending_event_(false), |
+ needs_scroll_ending_event_(false), |
+ needs_pinch_ending_event_(false) { |
DCHECK(client_); |
} |
@@ -50,8 +52,8 @@ void GestureEventQueue::OnGestureEventPacket(const GestureEventPacket& packet) { |
// Handle the timeout packet immediately if the packet preceding the |
// timeout has already been dispatched. |
if (Tail().IsEmpty()) { |
- if (!Tail().IsGesturePrevented()) |
- SendPacket(packet); |
+ FilterAndSendPacket(packet, Tail().IsGesturePrevented(), |
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
return; |
} |
break; |
@@ -72,7 +74,6 @@ void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) { |
} |
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. |
@@ -86,11 +87,11 @@ void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) { |
// given ack. |
if (touch_packet_for_current_ack_handled) |
break; |
+ if (!packet.is_independent() || packet.gesture_count() == 0) |
+ sequence.UpdateState(ack_state); |
touch_packet_for_current_ack_handled = true; |
} |
- |
- if (!sequence.IsGesturePrevented()) |
- SendPacket(packet); |
+ FilterAndSendPacket(packet, sequence.IsGesturePrevented(), ack_state); |
sequence.Pop(); |
} |
@@ -102,18 +103,45 @@ void GestureEventQueue::OnTouchEventAck(InputEventAckState ack_state) { |
CancelTapIfNecessary(); |
} |
-void GestureEventQueue::SendPacket(const GestureEventPacket& packet) { |
- for (size_t i = 0; i < packet.gesture_count(); ++i) |
- SendGesture(packet.gesture(i)); |
+void GestureEventQueue::FilterAndSendPacket( |
+ const GestureEventPacket& packet, |
+ bool gesturePrevented, |
+ InputEventAckState ack_state) { |
+ for (size_t i = 0; i < packet.gesture_count(); ++i) { |
+ const blink::WebGestureEvent& gesture = packet.gesture(i); |
+ |
+ // Scroll and pinch ending events are sent if and only if their |
+ // corresponding begin event was sent, regardless of the filtering state. |
+ bool send = false; |
+ if (needs_scroll_ending_event_ && |
+ (gesture.type == WebInputEvent::GestureScrollEnd || |
+ gesture.type == WebInputEvent::GestureFlingStart)) { |
+ send = true; |
+ } else if (needs_pinch_ending_event_ && |
+ gesture.type == WebInputEvent::GesturePinchEnd) { |
+ send = true; |
+ // Other gestures are sent only when the current filtering state allows. |
+ } else if (!gesturePrevented) { |
+ // Independent packets can be suppressed by the current ack state. |
+ if (!(packet.is_independent() && |
+ ack_state == INPUT_EVENT_ACK_STATE_CONSUMED)) |
+ send = true; |
+ } |
+ |
+ if (send) |
+ SendGesture(gesture); |
+ } |
} |
void GestureEventQueue::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: |
@@ -125,14 +153,28 @@ void GestureEventQueue::SendGesture(const WebGestureEvent& event) { |
case WebInputEvent::GestureScrollBegin: |
CancelTapIfNecessary(); |
CancelFlingIfNecessary(); |
+ DCHECK(!needs_scroll_ending_event_); |
+ needs_scroll_ending_event_ = true; |
break; |
case WebInputEvent::GestureFlingStart: |
CancelFlingIfNecessary(); |
needs_fling_ending_event_ = true; |
+ // FALL THROUGH |
+ case WebInputEvent::GestureScrollEnd: |
+ DCHECK(needs_scroll_ending_event_); |
+ needs_scroll_ending_event_ = false; |
break; |
case WebInputEvent::GestureFlingCancel: |
needs_fling_ending_event_ = false; |
break; |
+ case WebInputEvent::GesturePinchBegin: |
+ DCHECK(!needs_pinch_ending_event_); |
+ needs_pinch_ending_event_ = true; |
+ break; |
+ case WebInputEvent::GesturePinchEnd: |
+ DCHECK(needs_pinch_ending_event_); |
+ needs_pinch_ending_event_ = false; |
+ break; |
default: |
break; |
} |