Commit 06e924a1 authored by jdduke@chromium.org's avatar jdduke@chromium.org

Ignore TouchCancel ack dispositions

TouchCancel ack dispositions have no bearing on touch or gesture input
behavior.  As such, ignore the disposition, eliminating unnecessary blocking
of touch event dispatch.

BUG=302849,302852

Review URL: https://codereview.chromium.org/78263003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236849 0039d316-1c4b-4281-b951-d872f2087c98
parent b35f5d7e
......@@ -561,19 +561,47 @@ TEST_F(ImmediateInputRouterTest, UnhandledWheelEvent) {
EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
}
TEST_F(ImmediateInputRouterTest, TouchTypesIgnoringAck) {
int start_type = static_cast<int>(WebInputEvent::TouchStart);
int end_type = static_cast<int>(WebInputEvent::TouchCancel);
for (int i = start_type; i <= end_type; ++i) {
WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
if (!WebInputEventTraits::IgnoresAckDisposition(type))
continue;
// The TouchEventQueue requires an initial TouchStart for it to begin
// forwarding other touch event types.
if (type != WebInputEvent::TouchStart) {
SimulateTouchEvent(WebInputEvent::TouchStart);
SendInputEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED);
ASSERT_EQ(1U, GetSentMessageCountAndResetSink());
ASSERT_EQ(1U, ack_handler_->GetAndResetAckCount());
}
SimulateTouchEvent(type);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
}
}
TEST_F(ImmediateInputRouterTest, GestureTypesIgnoringAck) {
int start_type = static_cast<int>(WebInputEvent::GestureScrollBegin);
int end_type = static_cast<int>(WebInputEvent::GesturePinchUpdate);
for (int i = start_type; i <= end_type; ++i) {
WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
if (WebInputEventTraits::IgnoresAckDisposition(type)) {
SimulateGestureEvent(type, WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
}
if (!WebInputEventTraits::IgnoresAckDisposition(type))
continue;
SimulateGestureEvent(type, WebGestureEvent::Touchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
SendInputEventACK(type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
}
}
......
......@@ -74,14 +74,12 @@ void InputRouterTest::SimulateWheelEventWithPhase(
SyntheticWebMouseWheelEventBuilder::Build(phase), ui::LatencyInfo()));
}
// Inject provided synthetic WebGestureEvent instance.
void InputRouterTest::SimulateGestureEvent(
const WebGestureEvent& gesture) {
GestureEventWithLatencyInfo gesture_with_latency(gesture, ui::LatencyInfo());
input_router_->SendGestureEvent(gesture_with_latency);
}
// Inject simple synthetic WebGestureEvent instances.
void InputRouterTest::SimulateGestureEvent(
WebInputEvent::Type type,
WebGestureEvent::SourceDevice sourceDevice) {
......@@ -107,7 +105,6 @@ void InputRouterTest::SimulateGesturePinchUpdateEvent(float scale,
modifiers));
}
// Inject synthetic GestureFlingStart events.
void InputRouterTest::SimulateGestureFlingStartEvent(
float velocityX,
float velocityY,
......@@ -118,18 +115,33 @@ void InputRouterTest::SimulateGestureFlingStartEvent(
sourceDevice));
}
void InputRouterTest::SimulateTouchEvent(int x, int y) {
PressTouchPoint(x, y);
void InputRouterTest::SimulateTouchEvent(WebInputEvent::Type type) {
touch_event_.ResetPoints();
int index = PressTouchPoint(0, 0);
switch (type) {
case WebInputEvent::TouchStart:
// Already handled by |PressTouchPoint()|.
break;
case WebInputEvent::TouchMove:
MoveTouchPoint(index, 5, 5);
break;
case WebInputEvent::TouchEnd:
ReleaseTouchPoint(index);
break;
case WebInputEvent::TouchCancel:
CancelTouchPoint(index);
break;
default:
FAIL() << "Invalid touch event type.";
break;
}
SendTouchEvent();
}
// Set the timestamp for the touch-event.
void InputRouterTest::SetTouchTimestamp(base::TimeDelta timestamp) {
touch_event_.SetTimestamp(timestamp);
}
// Sends a touch event (irrespective of whether the page has a touch-event
// handler or not).
void InputRouterTest::SendTouchEvent() {
input_router_->SendTouchEvent(
TouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()));
......@@ -148,4 +160,8 @@ void InputRouterTest::ReleaseTouchPoint(int index) {
touch_event_.ReleasePoint(index);
}
void InputRouterTest::CancelTouchPoint(int index) {
touch_event_.CancelPoint(index);
}
} // namespace content
......@@ -55,7 +55,7 @@ class InputRouterTest : public testing::Test {
float velocityX,
float velocityY,
blink::WebGestureEvent::SourceDevice sourceDevice);
void SimulateTouchEvent(int x, int y);
void SimulateTouchEvent(blink::WebInputEvent::Type type);
void SetTouchTimestamp(base::TimeDelta timestamp);
// Sends a touch event (irrespective of whether the page has a touch-event
......@@ -65,6 +65,7 @@ class InputRouterTest : public testing::Test {
int PressTouchPoint(int x, int y);
void MoveTouchPoint(int index, int x, int y);
void ReleaseTouchPoint(int index);
void CancelTouchPoint(int index);
scoped_ptr<MockRenderProcessHost> process_;
scoped_ptr<MockInputRouterClient> client_;
......
......@@ -168,6 +168,12 @@ void SyntheticWebTouchEvent::ReleasePoint(int index) {
type = WebInputEvent::TouchEnd;
}
void SyntheticWebTouchEvent::CancelPoint(int index) {
CHECK(index >= 0 && index < touchesLengthCap);
touches[index].state = WebTouchPoint::StateCancelled;
type = WebInputEvent::TouchCancel;
}
void SyntheticWebTouchEvent::SetTimestamp(base::TimeDelta timestamp) {
timeStampSeconds = timestamp.InSecondsF();
}
......
......@@ -68,6 +68,7 @@ class CONTENT_EXPORT SyntheticWebTouchEvent
int PressPoint(int x, int y);
void MovePoint(int index, int x, int y);
void ReleasePoint(int index);
void CancelPoint(int index);
void SetTimestamp(base::TimeDelta timestamp);
};
......
......@@ -41,6 +41,8 @@ class TouchEventQueueTest : public testing::Test,
const TouchEventWithLatencyInfo& event) OVERRIDE {
++sent_event_count_;
last_sent_event_ = event.event;
if (sync_ack_result_)
SendTouchEventACK(*sync_ack_result_.Pass());
}
virtual void OnTouchEventAck(
......@@ -93,6 +95,10 @@ class TouchEventQueueTest : public testing::Test,
followup_gesture_event_.reset(new WebGestureEvent(event));
}
void SetSyncAckResult(InputEventAckState sync_ack_result) {
sync_ack_result_.reset(new InputEventAckState(sync_ack_result));
}
int PressTouchPoint(int x, int y) {
return touch_event_.PressPoint(x, y);
}
......@@ -105,6 +111,10 @@ class TouchEventQueueTest : public testing::Test,
touch_event_.ReleasePoint(index);
}
void CancelTouchPoint(int index) {
touch_event_.CancelPoint(index);
}
size_t GetAndResetAckedEventCount() {
size_t count = acked_event_count_;
acked_event_count_ = 0;
......@@ -159,6 +169,7 @@ class TouchEventQueueTest : public testing::Test,
SyntheticWebTouchEvent touch_event_;
scoped_ptr<WebTouchEvent> followup_touch_event_;
scoped_ptr<WebGestureEvent> followup_gesture_event_;
scoped_ptr<InputEventAckState> sync_ack_result_;
};
......@@ -620,6 +631,51 @@ TEST_F(TouchEventQueueTest, AckWithFollowupEvents) {
EXPECT_EQ(1U, GetAndResetAckedEventCount());
}
// Tests that touch-events can be synchronously ack'ed.
TEST_F(TouchEventQueueTest, SynchronousAcks) {
// TouchStart
SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
PressTouchPoint(1, 1);
SendTouchEvent();
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
// TouchMove
SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
PressTouchPoint(1, 1);
MoveTouchPoint(0, 2, 2);
SendTouchEvent();
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
// TouchEnd
SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
PressTouchPoint(1, 1);
ReleaseTouchPoint(0);
SendTouchEvent();
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
// TouchCancel (first inserting a TouchStart so the TouchCancel will be sent)
PressTouchPoint(1, 1);
SendTouchEvent();
SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
SetSyncAckResult(INPUT_EVENT_ACK_STATE_CONSUMED);
PressTouchPoint(1, 1);
CancelTouchPoint(0);
SendTouchEvent();
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
}
// Tests that followup events triggered by an immediate ack from
// TouchEventQueue::QueueEvent() are properly handled.
TEST_F(TouchEventQueueTest, ImmediateAckWithFollowupEvents) {
......
......@@ -285,13 +285,20 @@ void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
bool WebInputEventTraits::IgnoresAckDisposition(
blink::WebInputEvent::Type type) {
return type == WebInputEvent::GestureTapDown ||
type == WebInputEvent::GestureShowPress ||
type == WebInputEvent::GestureTapCancel ||
type == WebInputEvent::GesturePinchBegin ||
type == WebInputEvent::GesturePinchEnd ||
type == WebInputEvent::GestureScrollBegin ||
type == WebInputEvent::GestureScrollEnd;
switch (type) {
case WebInputEvent::GestureTapDown:
case WebInputEvent::GestureShowPress:
case WebInputEvent::GestureTapCancel:
case WebInputEvent::GesturePinchBegin:
case WebInputEvent::GesturePinchEnd:
case WebInputEvent::GestureScrollBegin:
case WebInputEvent::GestureScrollEnd:
case WebInputEvent::TouchCancel:
return true;
default:
break;
}
return false;
}
} // namespace content
......@@ -275,9 +275,10 @@ class ContentViewGestureHandler implements LongPressDelegate {
// The ACK to the original event is received after timeout.
// Inject a touchcancel event.
mPendingAckState = PENDING_ACK_CANCEL_EVENT;
mMotionEventDelegate.sendTouchEvent(mEventTime + TOUCH_EVENT_TIMEOUT,
TouchPoint.TOUCH_EVENT_TYPE_CANCEL, mTouchPoints);
final TouchPoint[] touchPoints = mTouchPoints;
mTouchPoints = null;
mMotionEventDelegate.sendTouchEvent(mEventTime + TOUCH_EVENT_TIMEOUT,
TouchPoint.TOUCH_EVENT_TYPE_CANCEL, touchPoints);
return true;
case PENDING_ACK_CANCEL_EVENT:
TraceEvent.instant("TouchEventTimeout:ConfirmCancelEvent");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment