summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortdresser@chromium.org <tdresser@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-08 18:43:16 +0000
committertdresser@chromium.org <tdresser@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-08 18:43:16 +0000
commita5e38520049d0335802646ddb9840ea6b0e9c91d (patch)
treed25320b8fbccdcae408f589c347a4e1e395e9daf
parent9669e87114aee295dcd97467d44eb7061f717e38 (diff)
downloadchromium_src-a5e38520049d0335802646ddb9840ea6b0e9c91d.zip
chromium_src-a5e38520049d0335802646ddb9840ea6b0e9c91d.tar.gz
chromium_src-a5e38520049d0335802646ddb9840ea6b0e9c91d.tar.bz2
Events ignoring ack disposition receive synthetic acks.
Logic to handle events which ignore ack disposition has moved from the |GestureEventFilter| to the |ImmediateInputRouter|, and |WebInputEventTraits|. This will allow us to make more events ignore their ack disposition, including touch events. Gesture event types which will eventually ignore their ack disposition include Tap, ScrollBegin, PinchBegin, PinchEnd, etc. BUG=302852,275611 TEST=ImmediateInputRouterTest.EventsIgnoringAckDispositionDontWaitForAcks, ImmediateInputRouterTest.EventsIgnoringAckDispositionStayInOrder Review URL: https://codereview.chromium.org/44983003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233946 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--content/browser/renderer_host/input/gesture_event_filter.cc31
-rw-r--r--content/browser/renderer_host/input/gesture_event_filter.h7
-rw-r--r--content/browser/renderer_host/input/gesture_event_filter_unittest.cc187
-rw-r--r--content/browser/renderer_host/input/immediate_input_router.cc12
-rw-r--r--content/browser/renderer_host/input/immediate_input_router.h1
-rw-r--r--content/browser/renderer_host/input/immediate_input_router_unittest.cc123
-rw-r--r--content/common/input/web_input_event_traits.cc7
-rw-r--r--content/common/input/web_input_event_traits.h1
-rw-r--r--content/port/common/input_event_ack_state.h1
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java6
10 files changed, 214 insertions, 162 deletions
diff --git a/content/browser/renderer_host/input/gesture_event_filter.cc b/content/browser/renderer_host/input/gesture_event_filter.cc
index cb8f4a3..194fe66 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.cc
+++ b/content/browser/renderer_host/input/gesture_event_filter.cc
@@ -162,19 +162,12 @@ bool GestureEventFilter::ShouldForwardForCoalescing(
break;
}
EnqueueEvent(gesture_event);
-
- // Ensure that if the added event ignores its ack, it is fired and
- // removed from |coalesced_gesture_events_|.
- SendEventsIgnoringAck();
return ShouldHandleEventNow();
}
void GestureEventFilter::ProcessGestureAck(InputEventAckState ack_result,
WebInputEvent::Type type,
const ui::LatencyInfo& latency) {
- if (ShouldIgnoreAckForGestureType(type))
- return;
-
if (coalesced_gesture_events_.empty()) {
DLOG(ERROR) << "Received unexpected ACK for event type " << type;
return;
@@ -198,10 +191,6 @@ void GestureEventFilter::ProcessGestureAck(InputEventAckState ack_result,
}
coalesced_gesture_events_.pop_front();
- // If the event which was just ACKed was blocking events ignoring ack, fire
- // those events now.
- SendEventsIgnoringAck();
-
if (ignore_next_ack_) {
ignore_next_ack_ = false;
return;
@@ -362,26 +351,6 @@ gfx::Transform GestureEventFilter::GetTransformForEvent(
return gesture_transform;
}
-void GestureEventFilter::SendEventsIgnoringAck() {
- GestureEventWithLatencyInfo gesture_event;
- while (!coalesced_gesture_events_.empty()) {
- gesture_event = coalesced_gesture_events_.front();
- if (!GestureEventFilter::ShouldIgnoreAckForGestureType(
- gesture_event.event.type)) {
- return;
- }
- coalesced_gesture_events_.pop_front();
- client_->SendGestureEventImmediately(gesture_event);
- }
-}
-
-bool GestureEventFilter::ShouldIgnoreAckForGestureType(
- WebInputEvent::Type type) {
- return type == WebInputEvent::GestureTapDown ||
- type == WebInputEvent::GestureShowPress ||
- type == WebInputEvent::GestureTapCancel;
-}
-
void GestureEventFilter::EnqueueEvent(
const GestureEventWithLatencyInfo& gesture_event) {
coalesced_gesture_events_.push_back(gesture_event);
diff --git a/content/browser/renderer_host/input/gesture_event_filter.h b/content/browser/renderer_host/input/gesture_event_filter.h
index 7ed57de..c868405 100644
--- a/content/browser/renderer_host/input/gesture_event_filter.h
+++ b/content/browser/renderer_host/input/gesture_event_filter.h
@@ -93,8 +93,6 @@ class CONTENT_EXPORT GestureEventFilter {
friend class MockRenderWidgetHost;
friend class GestureEventFilterTest;
- static bool ShouldIgnoreAckForGestureType(blink::WebInputEvent::Type type);
-
// TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard...
// methods that are getting confusing. This should be somehow fixed. Maybe
// while refactoring GEF: http://crbug.com/148443.
@@ -152,11 +150,6 @@ class CONTENT_EXPORT GestureEventFilter {
gfx::Transform GetTransformForEvent(
const GestureEventWithLatencyInfo& gesture_event) const;
- // Pops and sends events ignoring ack from the head of
- // |coalesced_gesture_events_| until the queue is empty or the event at the
- // head requires an ack.
- void SendEventsIgnoringAck();
-
// Adds |gesture_event| to the |coalesced_gesture_events_|, resetting the
// accumulation of |combined_scroll_pinch_|.
void EnqueueEvent(const GestureEventWithLatencyInfo& gesture_event);
diff --git a/content/browser/renderer_host/input/gesture_event_filter_unittest.cc b/content/browser/renderer_host/input/gesture_event_filter_unittest.cc
index 4dfda33..5b9107f 100644
--- a/content/browser/renderer_host/input/gesture_event_filter_unittest.cc
+++ b/content/browser/renderer_host/input/gesture_event_filter_unittest.cc
@@ -58,6 +58,8 @@ class GestureEventFilterTest : public testing::Test,
InputEventAckState ack_result) OVERRIDE {
++acked_gesture_event_count_;
last_acked_event_ = event.event;
+ if (sync_followup_event_)
+ SimulateGestureEvent(*sync_followup_event_.Pass());
}
// TouchpadTapSuppressionControllerClient
@@ -72,7 +74,7 @@ class GestureEventFilterTest : public testing::Test,
GestureEventWithLatencyInfo gesture_with_latency(gesture,
ui::LatencyInfo());
if (filter()->ShouldForward(gesture_with_latency)) {
- ++sent_gesture_event_count_;
+ SendGestureEventImmediately(gesture_with_latency);
return true;
}
return false;
@@ -143,6 +145,12 @@ class GestureEventFilterTest : public testing::Test,
sync_ack_result_.reset(new InputEventAckState(ack_result));
}
+ void set_sync_followup_event(WebInputEvent::Type type,
+ WebGestureEvent::SourceDevice sourceDevice) {
+ sync_followup_event_.reset(new WebGestureEvent(
+ SyntheticWebGestureEventBuilder::Build(type, sourceDevice)));
+ }
+
unsigned GestureEventQueueSize() {
return filter()->coalesced_gesture_events_.size();
}
@@ -186,6 +194,7 @@ class GestureEventFilterTest : public testing::Test,
size_t sent_gesture_event_count_;
WebGestureEvent last_acked_event_;
scoped_ptr<InputEventAckState> sync_ack_result_;
+ scoped_ptr<WebGestureEvent> sync_followup_event_;
base::MessageLoopForUI message_loop_;
};
@@ -581,6 +590,61 @@ TEST_F(GestureEventFilterTest, CoalescesMultiplePinchEventSequences) {
EXPECT_EQ(1, merged_event.modifiers);
}
+// Tests a single event with an synchronous ack.
+TEST_F(GestureEventFilterTest, SimpleSyncAck) {
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+}
+
+// Tests an event with an synchronous ack which enqueues an additional event.
+TEST_F(GestureEventFilterTest, SyncAckQueuesEvent) {
+ scoped_ptr<WebGestureEvent> queued_event;
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ set_sync_followup_event(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+ // This event enqueues the show press event.
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+
+ SendInputEventACK(WebInputEvent::GestureShowPress,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(1U, GetAndResetAckedGestureEventCount());
+}
+
+// Tests an event with an async ack followed by an event with a sync ack.
+TEST_F(GestureEventFilterTest, AsyncThenSyncAck) {
+ // Turn off debounce handling for test isolation.
+ set_debounce_interval_time_ms(0);
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GetAndResetAckedGestureEventCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ WebGestureEvent::Touchscreen);
+ set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+ EXPECT_EQ(0U, GetAndResetAckedGestureEventCount());
+
+ SendInputEventACK(WebInputEvent::GestureTapDown,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(0U, GestureEventQueueSize());
+ EXPECT_EQ(2U, GetAndResetAckedGestureEventCount());
+}
TEST_F(GestureEventFilterTest, CoalescesScrollAndPinchEventWithSyncAck) {
// Turn off debounce handling for test isolation.
@@ -725,127 +789,6 @@ INSTANTIATE_TEST_CASE_P(AllSources,
WebGestureEvent::Touchpad));
#endif // GTEST_HAS_PARAM_TEST
-// Test that GestureShowPress, GestureTapDown and GestureTapCancel events don't
-// wait for ACKs.
-TEST_F(GestureEventFilterTest, GestureTypesIgnoringAck) {
- set_debounce_interval_time_ms(0);
-
- // The show press, tap down and tap cancel events will escape the queue
- // immediately when they reach the queue head, since they ignore acks.
- SimulateGestureEvent(WebInputEvent::GestureShowPress,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureShowPress,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapCancel,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-
- // Interleave a few events that do and do not ignore acks, ensuring that
- // ack-ignoring events remain queued until they reach the queue head.
- SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
- WebGestureEvent::Touchpad);
- ASSERT_EQ(1U, GetAndResetSentGestureEventCount());
- ASSERT_EQ(1U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapDown,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(2U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
- WebGestureEvent::Touchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(3U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureShowPress,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(4U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GesturePinchEnd,
- WebGestureEvent::Touchpad);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(5U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureTapCancel,
- WebGestureEvent::Touchscreen);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(6U, GestureEventQueueSize());
-
- // Now ack each event. Ack-ignoring events should remain queued until they
- // reach the head of the queue, at which point they should be sent immediately
- // and removed from the queue, unblocking subsequent events.
- SendInputEventACK(WebInputEvent::GesturePinchBegin,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(4U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GestureTapDown,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(4U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GesturePinchUpdate,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(2U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GestureShowPress,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(2U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GesturePinchEnd,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GestureTapCancel,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-}
-
-// Test that GestureShowPress events don't get out of order due to
-// ignoring their acks.
-TEST_F(GestureEventFilterTest, GestureShowPressIsInOrder) {
- SimulateGestureEvent(WebInputEvent::GestureTap,
- WebGestureEvent::Touchscreen);
-
- EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(1U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureShowPress,
- WebGestureEvent::Touchscreen);
-
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- // The ShowPress, though it ignores ack, is still stuck in the queue
- // behind the Tap which requires an ack.
- EXPECT_EQ(2U, GestureEventQueueSize());
-
- SimulateGestureEvent(WebInputEvent::GestureShowPress,
- WebGestureEvent::Touchscreen);
-
- EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
- // ShowPress has entered the queue.
- EXPECT_EQ(3U, GestureEventQueueSize());
-
- SendInputEventACK(WebInputEvent::GestureTap,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
-
- // Now that the Tap has been ACKed, the ShowPress events should fire
- // immediately.
- EXPECT_EQ(2U, GetAndResetSentGestureEventCount());
- EXPECT_EQ(0U, GestureEventQueueSize());
-}
-
// Test that a GestureScrollEnd | GestureFlingStart are deferred during the
// debounce interval, that Scrolls are not and that the deferred events are
// sent after that timer fires.
diff --git a/content/browser/renderer_host/input/immediate_input_router.cc b/content/browser/renderer_host/input/immediate_input_router.cc
index 06bbc95..a52c0ee 100644
--- a/content/browser/renderer_host/input/immediate_input_router.cc
+++ b/content/browser/renderer_host/input/immediate_input_router.cc
@@ -339,6 +339,14 @@ void ImmediateInputRouter::OfferToHandlers(const WebInputEvent& input_event,
return;
OfferToRenderer(input_event, latency_info, is_keyboard_shortcut);
+
+ // If we don't care about the ack disposition, send the ack immediately.
+ if (WebInputEventTraits::IgnoresAckDisposition(input_event.type)) {
+ ProcessInputEventAck(input_event.type,
+ INPUT_EVENT_ACK_STATE_IGNORED,
+ latency_info,
+ IGNORING_DISPOSITION);
+ }
}
bool ImmediateInputRouter::OfferToOverscrollController(
@@ -424,6 +432,10 @@ void ImmediateInputRouter::OnInputEventAck(
client_->DecrementInFlightEventCount();
+ // A synthetic ack will already have been sent for this event.
+ if (WebInputEventTraits::IgnoresAckDisposition(event_type))
+ return;
+
ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER);
// WARNING: |this| may be deleted at this point.
diff --git a/content/browser/renderer_host/input/immediate_input_router.h b/content/browser/renderer_host/input/immediate_input_router.h
index 0c6a71a..56e4987 100644
--- a/content/browser/renderer_host/input/immediate_input_router.h
+++ b/content/browser/renderer_host/input/immediate_input_router.h
@@ -130,6 +130,7 @@ private:
RENDERER,
CLIENT,
OVERSCROLL_CONTROLLER,
+ IGNORING_DISPOSITION,
ACK_SOURCE_NONE
};
// Note: This function may result in |this| being deleted, and as such
diff --git a/content/browser/renderer_host/input/immediate_input_router_unittest.cc b/content/browser/renderer_host/input/immediate_input_router_unittest.cc
index 5162555..cddc2ad 100644
--- a/content/browser/renderer_host/input/immediate_input_router_unittest.cc
+++ b/content/browser/renderer_host/input/immediate_input_router_unittest.cc
@@ -558,4 +558,127 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
}
+// Test that GestureShowPress, GestureTapDown and GestureTapCancel events don't
+// wait for ACKs.
+TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAck) {
+ // The show press, tap down and tap cancel events will be acked immediately,
+ // since they ignore ack disposition.
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapCancel,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+
+ // Interleave a few events that do and do not ignore acks, ensuring that
+ // ack-ignoring events aren't dispatched until all prior events which observe
+ // their ack disposition have been dispatched.
+ SimulateGestureEvent(WebInputEvent::GesturePinchBegin,
+ WebGestureEvent::Touchpad);
+ ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapDown,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
+ WebGestureEvent::Touchpad);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GesturePinchEnd,
+ WebGestureEvent::Touchpad);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureTapCancel,
+ WebGestureEvent::Touchscreen);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ // Now ack each event. Ack-ignoring events should not be dispatched until all
+ // prior events which observe ack disposition have been fired, at which
+ // point they should be sent immediately.
+ SendInputEventACK(WebInputEvent::GesturePinchBegin,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureTapDown,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureShowPress,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SendInputEventACK(WebInputEvent::GesturePinchEnd,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+
+ // For events which ignore ack disposition, non-synthetic acks are ignored.
+ SendInputEventACK(WebInputEvent::GestureTapCancel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+}
+
+// Test that GestureShowPress events don't get out of order due to
+// ignoring their acks.
+TEST_F(ImmediateInputRouterTest, GestureShowPressIsInOrder) {
+ SimulateGestureEvent(WebInputEvent::GestureTap,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // The ShowPress, though it ignores ack, is still stuck in the queue
+ // behind the Tap which requires an ack.
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SimulateGestureEvent(WebInputEvent::GestureShowPress,
+ WebGestureEvent::Touchscreen);
+
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // ShowPress has entered the queue.
+ EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
+
+ SendInputEventACK(WebInputEvent::GestureTap,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Now that the Tap has been ACKed, the ShowPress events should receive
+ // synthetics acks, and fire immediately.
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(3U, ack_handler_->GetAndResetAckCount());
+}
+
} // namespace content
diff --git a/content/common/input/web_input_event_traits.cc b/content/common/input/web_input_event_traits.cc
index 48787a2..08d66ba 100644
--- a/content/common/input/web_input_event_traits.cc
+++ b/content/common/input/web_input_event_traits.cc
@@ -283,4 +283,11 @@ void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
}
+bool WebInputEventTraits::IgnoresAckDisposition(
+ blink::WebInputEvent::Type type) {
+ return type == WebInputEvent::GestureTapDown ||
+ type == WebInputEvent::GestureShowPress ||
+ type == WebInputEvent::GestureTapCancel;
+}
+
} // namespace content
diff --git a/content/common/input/web_input_event_traits.h b/content/common/input/web_input_event_traits.h
index b3b6d07..efacee5 100644
--- a/content/common/input/web_input_event_traits.h
+++ b/content/common/input/web_input_event_traits.h
@@ -22,6 +22,7 @@ class WebInputEventTraits {
const blink::WebInputEvent& event);
static void Coalesce(const blink::WebInputEvent& event_to_coalesce,
blink::WebInputEvent* event);
+ static bool IgnoresAckDisposition(blink::WebInputEvent::Type type);
};
} // namespace content
diff --git a/content/port/common/input_event_ack_state.h b/content/port/common/input_event_ack_state.h
index 4458b62..087b22f 100644
--- a/content/port/common/input_event_ack_state.h
+++ b/content/port/common/input_event_ack_state.h
@@ -11,6 +11,7 @@ namespace content {
enum InputEventAckState {
INPUT_EVENT_ACK_STATE_UNKNOWN,
INPUT_EVENT_ACK_STATE_CONSUMED,
+ INPUT_EVENT_ACK_STATE_IGNORED,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
INPUT_EVENT_ACK_STATE_MAX = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
index 2b23fc9..3e79dbe 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewGestureHandler.java
@@ -207,8 +207,9 @@ class ContentViewGestureHandler implements LongPressDelegate {
// These have to be kept in sync with content/port/common/input_event_ack_state.h
static final int INPUT_EVENT_ACK_STATE_UNKNOWN = 0;
static final int INPUT_EVENT_ACK_STATE_CONSUMED = 1;
- static final int INPUT_EVENT_ACK_STATE_NOT_CONSUMED = 2;
- static final int INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS = 3;
+ static final int INPUT_EVENT_ACK_STATE_IGNORED = 2;
+ static final int INPUT_EVENT_ACK_STATE_NOT_CONSUMED = 3;
+ static final int INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS = 4;
// Return values of sendPendingEventToNative();
static final int EVENT_FORWARDED_TO_NATIVE = 0;
@@ -1121,6 +1122,7 @@ class ContentViewGestureHandler implements LongPressDelegate {
assert(false);
break;
case INPUT_EVENT_ACK_STATE_CONSUMED:
+ case INPUT_EVENT_ACK_STATE_IGNORED:
mJavaScriptIsConsumingGesture = true;
mZoomManager.passTouchEventThrough(ackedEvent);
trySendPendingEventsToNative();