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