Commit f1a2283b authored by lanwei's avatar lanwei Committed by Commit bot

Coalesce async touch move events until the ack back from render.

In order to avoid the touch event queue keep growing when render handles
async touchmove events longer than 200ms, which is the async touchmove
interval, we keep coalesce touch moves and send the next touchmove
until passing the async touchmove interval and receive the ACK from render.

BUG=448760

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

Cr-Commit-Position: refs/heads/master@{#330548}
parent 0da16bda
...@@ -358,19 +358,22 @@ void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, ...@@ -358,19 +358,22 @@ void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); OfferToRenderer(input_event, latency_info, is_keyboard_shortcut);
// Touch events should always indicate in the event whether they are // Touch events should always indicate in the event whether they are
// cancelable (respect ACK disposition) or not. // cancelable (respect ACK disposition) or not except touchmove.
bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event); bool needs_synthetic_ack =
if (WebInputEvent::isTouchEventType(input_event.type)) { !WebInputEventTraits::WillReceiveAckFromRenderer(input_event);
if (WebInputEvent::isTouchEventType(input_event.type) &&
input_event.type != WebInputEvent::TouchMove) {
const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event); const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event);
DCHECK_NE(ignores_ack, !!touch.cancelable); DCHECK_EQ(needs_synthetic_ack, !touch.cancelable);
} }
// If we don't care about the ack disposition, send the ack immediately. // The synthetic acks are sent immediately.
if (ignores_ack) { if (needs_synthetic_ack) {
ProcessInputEventAck(input_event.type, ProcessInputEventAck(
INPUT_EVENT_ACK_STATE_IGNORED, input_event.type, INPUT_EVENT_ACK_STATE_IGNORED, latency_info,
latency_info, WebInputEventTraits::GetUniqueTouchEventId(input_event),
IGNORING_DISPOSITION); IGNORING_DISPOSITION);
} }
} }
...@@ -385,7 +388,9 @@ bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event, ...@@ -385,7 +388,9 @@ bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event,
case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
// Send the ACK and early exit. // Send the ACK and early exit.
next_mouse_move_.reset(); next_mouse_move_.reset();
ProcessInputEventAck(input_event.type, filter_ack, latency_info, CLIENT); ProcessInputEventAck(
input_event.type, filter_ack, latency_info,
WebInputEventTraits::GetUniqueTouchEventId(input_event), CLIENT);
// WARNING: |this| may be deleted at this point. // WARNING: |this| may be deleted at this point.
consumed = true; consumed = true;
break; break;
...@@ -408,7 +413,7 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, ...@@ -408,7 +413,7 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
// Ack messages for ignored ack event types should never be sent by the // Ack messages for ignored ack event types should never be sent by the
// renderer. Consequently, such event types should not affect event time // renderer. Consequently, such event types should not affect event time
// or in-flight event count metrics. // or in-flight event count metrics.
if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { if (WebInputEventTraits::WillReceiveAckFromRenderer(input_event)) {
input_event_start_time_ = TimeTicks::Now(); input_event_start_time_ = TimeTicks::Now();
client_->IncrementInFlightEventCount(); client_->IncrementInFlightEventCount();
} }
...@@ -417,10 +422,8 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, ...@@ -417,10 +422,8 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
return false; return false;
} }
void InputRouterImpl::OnInputEventAck( void InputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
const InputHostMsg_HandleInputEvent_ACK_Params& ack) {
client_->DecrementInFlightEventCount(); client_->DecrementInFlightEventCount();
// Log the time delta for processing an input event. // Log the time delta for processing an input event.
TimeDelta delta = TimeTicks::Now() - input_event_start_time_; TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
...@@ -431,21 +434,8 @@ void InputRouterImpl::OnInputEventAck( ...@@ -431,21 +434,8 @@ void InputRouterImpl::OnInputEventAck(
OnDidOverscroll(*ack.overscroll); OnDidOverscroll(*ack.overscroll);
} }
ProcessInputEventAck(ack.type, ack.state, ack.latency, RENDERER); ProcessInputEventAck(ack.type, ack.state, ack.latency,
// WARNING: |this| may be deleted at this point. ack.unique_touch_event_id, RENDERER);
// This is used only for testing, and the other end does not use the
// source object. On linux, specifying
// Source<RenderWidgetHost> results in a very strange
// runtime error in the epilogue of the enclosing
// (ProcessInputEventAck) method, but not on other platforms; using
// 'void' instead is just as safe (since NotificationSource
// is not actually typesafe) and avoids this error.
int type = static_cast<int>(ack.type);
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
Source<void>(this),
Details<int>(&type));
} }
void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) { void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) {
...@@ -509,11 +499,11 @@ void InputRouterImpl::OnDidStopFlinging() { ...@@ -509,11 +499,11 @@ void InputRouterImpl::OnDidStopFlinging() {
client_->DidStopFlinging(); client_->DidStopFlinging();
} }
void InputRouterImpl::ProcessInputEventAck( void InputRouterImpl::ProcessInputEventAck(WebInputEvent::Type event_type,
WebInputEvent::Type event_type, InputEventAckState ack_result,
InputEventAckState ack_result, const ui::LatencyInfo& latency_info,
const ui::LatencyInfo& latency_info, uint32 unique_touch_event_id,
AckSource ack_source) { AckSource ack_source) {
TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck",
"type", WebInputEventTraits::GetName(event_type), "type", WebInputEventTraits::GetName(event_type),
"ack", GetEventAckName(ack_result)); "ack", GetEventAckName(ack_result));
...@@ -535,7 +525,7 @@ void InputRouterImpl::ProcessInputEventAck( ...@@ -535,7 +525,7 @@ void InputRouterImpl::ProcessInputEventAck(
} else if (event_type == WebInputEvent::MouseWheel) { } else if (event_type == WebInputEvent::MouseWheel) {
ProcessWheelAck(ack_result, latency_info); ProcessWheelAck(ack_result, latency_info);
} else if (WebInputEvent::isTouchEventType(event_type)) { } else if (WebInputEvent::isTouchEventType(event_type)) {
ProcessTouchAck(ack_result, latency_info); ProcessTouchAck(ack_result, latency_info, unique_touch_event_id);
} else if (WebInputEvent::isGestureEventType(event_type)) { } else if (WebInputEvent::isGestureEventType(event_type)) {
ProcessGestureAck(event_type, ack_result, latency_info); ProcessGestureAck(event_type, ack_result, latency_info);
} else if (event_type != WebInputEvent::Undefined) { } else if (event_type != WebInputEvent::Undefined) {
...@@ -620,11 +610,12 @@ void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, ...@@ -620,11 +610,12 @@ void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type,
gesture_event_queue_.ProcessGestureAck(ack_result, type, latency); gesture_event_queue_.ProcessGestureAck(ack_result, type, latency);
} }
void InputRouterImpl::ProcessTouchAck( void InputRouterImpl::ProcessTouchAck(InputEventAckState ack_result,
InputEventAckState ack_result, const ui::LatencyInfo& latency,
const ui::LatencyInfo& latency) { uint32 unique_touch_event_id) {
// |touch_event_queue_| will forward to OnTouchEventAck when appropriate. // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
touch_event_queue_.ProcessTouchAck(ack_result, latency); touch_event_queue_.ProcessTouchAck(ack_result, latency,
unique_touch_event_id);
} }
void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { void InputRouterImpl::UpdateTouchAckTimeoutEnabled() {
......
...@@ -18,8 +18,6 @@ ...@@ -18,8 +18,6 @@
#include "content/common/input/input_event_stream_validator.h" #include "content/common/input/input_event_stream_validator.h"
#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/native_web_keyboard_event.h"
struct InputHostMsg_HandleInputEvent_ACK_Params;
namespace IPC { namespace IPC {
class Sender; class Sender;
} }
...@@ -34,6 +32,7 @@ class InputAckHandler; ...@@ -34,6 +32,7 @@ class InputAckHandler;
class InputRouterClient; class InputRouterClient;
class OverscrollController; class OverscrollController;
struct DidOverscrollParams; struct DidOverscrollParams;
struct InputEventAck;
// A default implementation for browser input event routing. // A default implementation for browser input event routing.
class CONTENT_EXPORT InputRouterImpl class CONTENT_EXPORT InputRouterImpl
...@@ -124,7 +123,7 @@ private: ...@@ -124,7 +123,7 @@ private:
bool is_keyboard_shortcut); bool is_keyboard_shortcut);
// IPC message handlers // IPC message handlers
void OnInputEventAck(const InputHostMsg_HandleInputEvent_ACK_Params& ack); void OnInputEventAck(const InputEventAck& ack);
void OnDidOverscroll(const DidOverscrollParams& params); void OnDidOverscroll(const DidOverscrollParams& params);
void OnMsgMoveCaretAck(); void OnMsgMoveCaretAck();
void OnSelectMessageAck(); void OnSelectMessageAck();
...@@ -145,6 +144,7 @@ private: ...@@ -145,6 +144,7 @@ private:
void ProcessInputEventAck(blink::WebInputEvent::Type event_type, void ProcessInputEventAck(blink::WebInputEvent::Type event_type,
InputEventAckState ack_result, InputEventAckState ack_result,
const ui::LatencyInfo& latency_info, const ui::LatencyInfo& latency_info,
uint32 unique_touch_event_id,
AckSource ack_source); AckSource ack_source);
// Dispatches the ack'ed event to |ack_handler_|. // Dispatches the ack'ed event to |ack_handler_|.
...@@ -169,7 +169,8 @@ private: ...@@ -169,7 +169,8 @@ private:
// Forwards the event ack to |touch_event_queue_|, potentially triggering // Forwards the event ack to |touch_event_queue_|, potentially triggering
// dispatch of queued touch events, or the creation of gesture events. // dispatch of queued touch events, or the creation of gesture events.
void ProcessTouchAck(InputEventAckState ack_result, void ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency); const ui::LatencyInfo& latency,
uint32 unique_touch_event_id);
// Called when a touch timeout-affecting bit has changed, in turn toggling the // Called when a touch timeout-affecting bit has changed, in turn toggling the
// touch ack timeout feature of the |touch_event_queue_| as appropriate. Input // touch ack timeout feature of the |touch_event_queue_| as appropriate. Input
......
...@@ -233,11 +233,9 @@ class InputRouterImplPerfTest : public testing::Test { ...@@ -233,11 +233,9 @@ class InputRouterImplPerfTest : public testing::Test {
void SendEventAckIfNecessary(const blink::WebInputEvent& event, void SendEventAckIfNecessary(const blink::WebInputEvent& event,
InputEventAckState ack_result) { InputEventAckState ack_result) {
if (WebInputEventTraits::IgnoresAckDisposition(event)) if (!WebInputEventTraits::WillReceiveAckFromRenderer(event))
return; return;
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(event.type, ack_result);
ack.type = event.type;
ack.state = ack_result;
InputHostMsg_HandleInputEvent_ACK response(0, ack); InputHostMsg_HandleInputEvent_ACK response(0, ack);
input_router_->OnMessageReceived(response); input_router_->OnMessageReceived(response);
} }
......
...@@ -42,7 +42,8 @@ TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( ...@@ -42,7 +42,8 @@ TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) { bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) {
return (event.type == WebInputEvent::TouchStart || return (event.type == WebInputEvent::TouchStart ||
event.type == WebInputEvent::TouchMove) && event.type == WebInputEvent::TouchMove) &&
!WebInputEventTraits::IgnoresAckDisposition(event); WebInputEventTraits::WillReceiveAckFromRenderer(event) &&
event.cancelable;
} }
// Compare all properties of touch points to determine the state. // Compare all properties of touch points to determine the state.
...@@ -82,7 +83,9 @@ class TouchEventQueue::TouchTimeoutHandler { ...@@ -82,7 +83,9 @@ class TouchEventQueue::TouchTimeoutHandler {
~TouchTimeoutHandler() {} ~TouchTimeoutHandler() {}
void StartIfNecessary(const TouchEventWithLatencyInfo& event) { void StartIfNecessary(const TouchEventWithLatencyInfo& event) {
DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); if (pending_ack_state_ != PENDING_ACK_NONE)
return;
if (!enabled_) if (!enabled_)
return; return;
...@@ -420,9 +423,28 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { ...@@ -420,9 +423,28 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
} }
void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
const LatencyInfo& latency_info) { const LatencyInfo& latency_info,
const uint32 unique_touch_event_id) {
TRACE_EVENT0("input", "TouchEventQueue::ProcessTouchAck"); TRACE_EVENT0("input", "TouchEventQueue::ProcessTouchAck");
// We receive an ack for async touchmove from render.
if (!ack_pending_async_touchmove_ids_.empty() &&
ack_pending_async_touchmove_ids_.front() == unique_touch_event_id) {
// Remove the first touchmove from the ack_pending_async_touchmove queue.
ack_pending_async_touchmove_ids_.pop_front();
// Send the next pending async touch move once we receive all acks back.
if (pending_async_touchmove_ && ack_pending_async_touchmove_ids_.empty()) {
DCHECK(touch_queue_.empty());
// Dispatch the next pending async touch move when time expires.
if (pending_async_touchmove_->event.timeStampSeconds >=
last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec) {
FlushPendingAsyncTouchmove();
}
}
return;
}
DCHECK(!dispatching_touch_ack_); DCHECK(!dispatching_touch_ack_);
dispatching_touch_ = false; dispatching_touch_ = false;
...@@ -434,6 +456,9 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, ...@@ -434,6 +456,9 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
if (touch_queue_.empty()) if (touch_queue_.empty())
return; return;
DCHECK_EQ(touch_queue_.front()->coalesced_event().event.uniqueTouchEventId,
unique_touch_event_id);
PopTouchEventToClient(ack_result, latency_info); PopTouchEventToClient(ack_result, latency_info);
TryForwardNextEventToRenderer(); TryForwardNextEventToRenderer();
} }
...@@ -477,8 +502,9 @@ void TouchEventQueue::ForwardNextEventToRenderer() { ...@@ -477,8 +502,9 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
send_touchmove_now |= pending_async_touchmove_ && send_touchmove_now |= pending_async_touchmove_ &&
!pending_async_touchmove_->CanCoalesceWith(touch); !pending_async_touchmove_->CanCoalesceWith(touch);
send_touchmove_now |= send_touchmove_now |=
touch.event.timeStampSeconds >= ack_pending_async_touchmove_ids_.empty() &&
last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec; (touch.event.timeStampSeconds >=
last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec);
if (!send_touchmove_now) { if (!send_touchmove_now) {
if (!pending_async_touchmove_) { if (!pending_async_touchmove_) {
...@@ -510,11 +536,7 @@ void TouchEventQueue::ForwardNextEventToRenderer() { ...@@ -510,11 +536,7 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
touch = *pending_async_touchmove_; touch = *pending_async_touchmove_;
pending_async_touchmove_.reset(); pending_async_touchmove_.reset();
} else { } else {
scoped_ptr<TouchEventWithLatencyInfo> async_move = FlushPendingAsyncTouchmove();
pending_async_touchmove_.Pass();
async_move->event.cancelable = false;
touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true));
SendTouchEventImmediately(async_move.get());
return; return;
} }
} }
...@@ -525,12 +547,15 @@ void TouchEventQueue::ForwardNextEventToRenderer() { ...@@ -525,12 +547,15 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart)
touch.event.cancelable = false; touch.event.cancelable = false;
// A synchronous ack will reset |dispatching_touch_|, in which case
// the touch timeout should not be started.
base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
SendTouchEventImmediately(&touch); SendTouchEventImmediately(&touch);
if (dispatching_touch_ && timeout_handler_) }
timeout_handler_->StartIfNecessary(touch);
void TouchEventQueue::FlushPendingAsyncTouchmove() {
DCHECK(!dispatching_touch_);
scoped_ptr<TouchEventWithLatencyInfo> touch = pending_async_touchmove_.Pass();
touch->event.cancelable = false;
touch_queue_.push_front(new CoalescedWebTouchEvent(*touch, true));
SendTouchEventImmediately(touch.get());
} }
void TouchEventQueue::OnGestureScrollEvent( void TouchEventQueue::OnGestureScrollEvent(
...@@ -670,7 +695,30 @@ void TouchEventQueue::SendTouchEventImmediately( ...@@ -670,7 +695,30 @@ void TouchEventQueue::SendTouchEventImmediately(
else else
last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); last_sent_touchevent_.reset(new WebTouchEvent(touch->event));
base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
client_->SendTouchEventImmediately(*touch); client_->SendTouchEventImmediately(*touch);
// A synchronous ack will reset |dispatching_touch_|, in which case the touch
// timeout should not be started and the count also should not be increased.
if (dispatching_touch_) {
if (touch->event.type == WebInputEvent::TouchMove &&
!touch->event.cancelable) {
// When we send out a uncancelable touch move, we increase the count and
// we do not process input event ack any more, we will just ack to client
// and wait for the ack from render. Also we will remove it from the front
// of the queue.
ack_pending_async_touchmove_ids_.push_back(
touch->event.uniqueTouchEventId);
dispatching_touch_ = false;
PopTouchEventToClient(INPUT_EVENT_ACK_STATE_IGNORED);
TryForwardNextEventToRenderer();
return;
}
if (timeout_handler_)
timeout_handler_->StartIfNecessary(*touch);
}
} }
TouchEventQueue::PreFilterResult TouchEventQueue::PreFilterResult
......
...@@ -61,10 +61,13 @@ class CONTENT_EXPORT TouchEventQueue { ...@@ -61,10 +61,13 @@ class CONTENT_EXPORT TouchEventQueue {
void QueueEvent(const TouchEventWithLatencyInfo& event); void QueueEvent(const TouchEventWithLatencyInfo& event);
// Notifies the queue that a touch-event has been processed by the renderer. // Notifies the queue that a touch-event has been processed by the renderer.
// At this point, the queue may send one or more gesture events and/or // At this point, if the ack is for async touchmove, remove the uncancelable
// additional queued touch-events to the renderer. // touchmove from the front of the queue and decide if it should dispatch the
// next pending async touch move event, otherwise the queue may send one or
// more gesture events and/or additional queued touch-events to the renderer.
void ProcessTouchAck(InputEventAckState ack_result, void ProcessTouchAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency_info); const ui::LatencyInfo& latency_info,
const uint32 unique_touch_event_id);
// When GestureScrollBegin is received, we send a touch cancel to renderer, // When GestureScrollBegin is received, we send a touch cancel to renderer,
// route all the following touch events directly to client, and ignore the // route all the following touch events directly to client, and ignore the
...@@ -102,6 +105,10 @@ class CONTENT_EXPORT TouchEventQueue { ...@@ -102,6 +105,10 @@ class CONTENT_EXPORT TouchEventQueue {
bool has_handlers() const { return has_handlers_; } bool has_handlers() const { return has_handlers_; }
size_t uncancelable_touch_moves_pending_ack_count() const {
return ack_pending_async_touchmove_ids_.size();
}
private: private:
class TouchTimeoutHandler; class TouchTimeoutHandler;
class TouchMoveSlopSuppressor; class TouchMoveSlopSuppressor;
...@@ -156,6 +163,7 @@ class CONTENT_EXPORT TouchEventQueue { ...@@ -156,6 +163,7 @@ class CONTENT_EXPORT TouchEventQueue {
void ForwardToRenderer(const TouchEventWithLatencyInfo& event); void ForwardToRenderer(const TouchEventWithLatencyInfo& event);
void UpdateTouchConsumerStates(const blink::WebTouchEvent& event, void UpdateTouchConsumerStates(const blink::WebTouchEvent& event,
InputEventAckState ack_result); InputEventAckState ack_result);
void FlushPendingAsyncTouchmove();
// Handles touch event forwarding and ack'ed event dispatch. // Handles touch event forwarding and ack'ed event dispatch.
TouchEventQueueClient* client_; TouchEventQueueClient* client_;
...@@ -171,8 +179,9 @@ class CONTENT_EXPORT TouchEventQueue { ...@@ -171,8 +179,9 @@ class CONTENT_EXPORT TouchEventQueue {
// True within the scope of |AckTouchEventToClient()|. // True within the scope of |AckTouchEventToClient()|.
bool dispatching_touch_ack_; bool dispatching_touch_ack_;
// Used to prevent touch timeout scheduling if we receive a synchronous // Used to prevent touch timeout scheduling and increase the count for async
// ack after forwarding a touch event to the client. // touchmove if we receive a synchronous ack after forwarding a touch event
// to the client.
bool dispatching_touch_; bool dispatching_touch_;
// Whether the renderer has at least one touch handler. // Whether the renderer has at least one touch handler.
...@@ -202,6 +211,17 @@ class CONTENT_EXPORT TouchEventQueue { ...@@ -202,6 +211,17 @@ class CONTENT_EXPORT TouchEventQueue {
// For details see the design doc at http://goo.gl/lVyJAa. // For details see the design doc at http://goo.gl/lVyJAa.
bool send_touch_events_async_; bool send_touch_events_async_;
scoped_ptr<TouchEventWithLatencyInfo> pending_async_touchmove_; scoped_ptr<TouchEventWithLatencyInfo> pending_async_touchmove_;
// For uncancelable touch moves, not only we send a fake ack, but also a real
// ack from render, which we use to decide when to send the next async
// touchmove. This can help avoid the touch event queue keep growing when
// render handles touchmove slow. We use a queue
// ack_pending_async_touchmove_ids to store the recent dispatched
// uncancelable touchmoves which are still waiting for their acks back from
// render. We do not put them back to the front the touch_event_queue any
// more.
std::deque<uint32> ack_pending_async_touchmove_ids_;
double last_sent_touch_timestamp_sec_; double last_sent_touch_timestamp_sec_;
// Event is saved to compare pointer positions for new touchmove events. // Event is saved to compare pointer positions for new touchmove events.
......
...@@ -466,9 +466,8 @@ class RenderWidgetHostTest : public testing::Test { ...@@ -466,9 +466,8 @@ class RenderWidgetHostTest : public testing::Test {
void SendInputEventACK(WebInputEvent::Type type, void SendInputEventACK(WebInputEvent::Type type,
InputEventAckState ack_result) { InputEventAckState ack_result) {
InputHostMsg_HandleInputEvent_ACK_Params ack; DCHECK(!WebInputEvent::isTouchEventType(type));
ack.type = type; InputEventAck ack(type, ack_result);
ack.state = ack_result;
host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack)); host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
} }
...@@ -551,10 +550,12 @@ class RenderWidgetHostTest : public testing::Test { ...@@ -551,10 +550,12 @@ class RenderWidgetHostTest : public testing::Test {
// Sends a touch event (irrespective of whether the page has a touch-event // Sends a touch event (irrespective of whether the page has a touch-event
// handler or not). // handler or not).
void SendTouchEvent() { uint32 SendTouchEvent() {
uint32 touch_event_id = touch_event_.uniqueTouchEventId;
host_->ForwardTouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo()); host_->ForwardTouchEventWithLatencyInfo(touch_event_, ui::LatencyInfo());
touch_event_.ResetPoints(); touch_event_.ResetPoints();
return touch_event_id;
} }
int PressTouchPoint(int x, int y) { int PressTouchPoint(int x, int y) {
...@@ -1482,10 +1483,12 @@ TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) { ...@@ -1482,10 +1483,12 @@ TEST_F(RenderWidgetHostTest, InputEventRWHLatencyComponent) {
// Tests RWHI::ForwardTouchEventWithLatencyInfo(). // Tests RWHI::ForwardTouchEventWithLatencyInfo().
PressTouchPoint(0, 1); PressTouchPoint(0, 1);
SendTouchEvent(); uint32 touch_event_id = SendTouchEvent();
InputEventAck ack(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED,
touch_event_id);
host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
CheckLatencyInfoComponentInMessage( CheckLatencyInfoComponentInMessage(
process_, GetLatencyComponentId(), WebInputEvent::TouchStart); process_, GetLatencyComponentId(), WebInputEvent::TouchStart);
SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED);
} }
TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) { TEST_F(RenderWidgetHostTest, RendererExitedResetsInputRouter) {
......
...@@ -445,9 +445,17 @@ class RenderWidgetHostViewAuraTest : public testing::Test { ...@@ -445,9 +445,17 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
void SendInputEventACK(WebInputEvent::Type type, void SendInputEventACK(WebInputEvent::Type type,
InputEventAckState ack_result) { InputEventAckState ack_result) {
InputHostMsg_HandleInputEvent_ACK_Params ack; DCHECK(!WebInputEvent::isTouchEventType(type));
ack.type = type; InputEventAck ack(type, ack_result);
ack.state = ack_result; InputHostMsg_HandleInputEvent_ACK response(0, ack);
widget_host_->OnMessageReceived(response);
}
void SendTouchEventACK(WebInputEvent::Type type,
InputEventAckState ack_result,
uint32 event_id) {
DCHECK(WebInputEvent::isTouchEventType(type));
InputEventAck ack(type, ack_result, event_id);
InputHostMsg_HandleInputEvent_ACK response(0, ack); InputHostMsg_HandleInputEvent_ACK response(0, ack);
widget_host_->OnMessageReceived(response); widget_host_->OnMessageReceived(response);
} }
...@@ -468,10 +476,12 @@ class RenderWidgetHostViewAuraTest : public testing::Test { ...@@ -468,10 +476,12 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
return; return;
} }
if (WebInputEventTraits::IgnoresAckDisposition(*get<0>(params))) if (!WebInputEventTraits::WillReceiveAckFromRenderer(*get<0>(params)))
return; return;
SendInputEventACK(get<0>(params)->type, ack_result); const blink::WebInputEvent* event = get<0>(params);
SendTouchEventACK(event->type, ack_result,
WebInputEventTraits::GetUniqueTouchEventId(*event));
} }
protected: protected:
...@@ -698,25 +708,24 @@ class RenderWidgetHostViewAuraOverscrollTest ...@@ -698,25 +708,24 @@ class RenderWidgetHostViewAuraOverscrollTest
return overscroll_delegate_.get(); return overscroll_delegate_.get();
} }
void SendTouchEvent() { uint32 SendTouchEvent() {
uint32 touch_event_id = touch_event_.uniqueTouchEventId;
widget_host_->ForwardTouchEventWithLatencyInfo(touch_event_, widget_host_->ForwardTouchEventWithLatencyInfo(touch_event_,
ui::LatencyInfo()); ui::LatencyInfo());
touch_event_.ResetPoints(); touch_event_.ResetPoints();
return touch_event_id;
} }
void PressTouchPoint(int x, int y) { void PressTouchPoint(int x, int y) {
touch_event_.PressPoint(x, y); touch_event_.PressPoint(x, y);
SendTouchEvent();
} }
void MoveTouchPoint(int index, int x, int y) { void MoveTouchPoint(int index, int x, int y) {
touch_event_.MovePoint(index, x, y); touch_event_.MovePoint(index, x, y);
SendTouchEvent();
} }
void ReleaseTouchPoint(int index) { void ReleaseTouchPoint(int index) {
touch_event_.ReleasePoint(index); touch_event_.ReleasePoint(index);
SendTouchEvent();
} }
SyntheticWebTouchEvent touch_event_; SyntheticWebTouchEvent touch_event_;
...@@ -1104,9 +1113,9 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { ...@@ -1104,9 +1113,9 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) {
widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false));
// Ack'ing the outstanding event should flush the pending touch queue. // Ack'ing the outstanding event should flush the pending touch queue.
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(blink::WebInputEvent::TouchStart,
ack.type = blink::WebInputEvent::TouchStart; INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
ack.state = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; press.unique_event_id());
widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack)); widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
...@@ -1138,8 +1147,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { ...@@ -1138,8 +1147,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::EventTimeForNow()); ui::EventTimeForNow());
view_->OnTouchEvent(&press0); view_->OnTouchEvent(&press0);
SendInputEventACK(blink::WebInputEvent::TouchStart, SendTouchEventACK(blink::WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED,
press0.unique_event_id());
EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type);
EXPECT_EQ(1U, view_->touch_event_->touchesLength); EXPECT_EQ(1U, view_->touch_event_->touchesLength);
EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
...@@ -1148,8 +1158,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { ...@@ -1148,8 +1158,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::EventTimeForNow()); ui::EventTimeForNow());
view_->OnTouchEvent(&move0); view_->OnTouchEvent(&move0);
SendInputEventACK(blink::WebInputEvent::TouchMove, SendTouchEventACK(blink::WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED,
move0.unique_event_id());
EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type);
EXPECT_EQ(1U, view_->touch_event_->touchesLength); EXPECT_EQ(1U, view_->touch_event_->touchesLength);
EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
...@@ -1160,8 +1171,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { ...@@ -1160,8 +1171,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::EventTimeForNow()); ui::EventTimeForNow());
view_->OnTouchEvent(&press1); view_->OnTouchEvent(&press1);
SendInputEventACK(blink::WebInputEvent::TouchStart, SendTouchEventACK(blink::WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED,
press1.unique_event_id());
EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type);
EXPECT_EQ(2U, view_->touch_event_->touchesLength); EXPECT_EQ(2U, view_->touch_event_->touchesLength);
EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
...@@ -1172,8 +1184,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { ...@@ -1172,8 +1184,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::EventTimeForNow()); ui::EventTimeForNow());
view_->OnTouchEvent(&move1); view_->OnTouchEvent(&move1);
SendInputEventACK(blink::WebInputEvent::TouchMove, SendTouchEventACK(blink::WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED,
move1.unique_event_id());
EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type);
EXPECT_EQ(2U, view_->touch_event_->touchesLength); EXPECT_EQ(2U, view_->touch_event_->touchesLength);
EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
...@@ -1184,8 +1197,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { ...@@ -1184,8 +1197,9 @@ TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
ui::EventTimeForNow()); ui::EventTimeForNow());
view_->OnTouchEvent(&move2); view_->OnTouchEvent(&move2);
SendInputEventACK(blink::WebInputEvent::TouchMove, SendTouchEventACK(blink::WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED,
move2.unique_event_id());
EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type);
EXPECT_EQ(2U, view_->touch_event_->touchesLength); EXPECT_EQ(2U, view_->touch_event_->touchesLength);
EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
...@@ -2868,14 +2882,16 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) { ...@@ -2868,14 +2882,16 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// The test sends an intermingled sequence of touch and gesture events. // The test sends an intermingled sequence of touch and gesture events.
PressTouchPoint(0, 1); PressTouchPoint(0, 1);
SendInputEventACK(WebInputEvent::TouchStart, uint32 touch_press_event_id1 = SendTouchEvent();
INPUT_EVENT_ACK_STATE_NOT_CONSUMED); SendTouchEventACK(WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_press_event_id1);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
MoveTouchPoint(0, 20, 5); MoveTouchPoint(0, 20, 5);
uint32 touch_move_event_id1 = SendTouchEvent();
SendTouchEventACK(WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED, touch_move_event_id1);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
SendInputEventACK(WebInputEvent::TouchMove,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode()); EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode()); EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
...@@ -2894,6 +2910,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) { ...@@ -2894,6 +2910,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// started yet. Note that touch events sent during the scroll period may // started yet. Note that touch events sent during the scroll period may
// not require an ack (having been marked uncancelable). // not require an ack (having been marked uncancelable).
MoveTouchPoint(0, 65, 10); MoveTouchPoint(0, 65, 10);
SendTouchEvent();
AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
...@@ -2910,6 +2927,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) { ...@@ -2910,6 +2927,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// Send another touch event. The page should get the touch-move event, even // Send another touch event. The page should get the touch-move event, even
// though overscroll has started. // though overscroll has started.
MoveTouchPoint(0, 55, 5); MoveTouchPoint(0, 55, 5);
SendTouchEvent();
EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode()); EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode()); EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
EXPECT_EQ(65.f, overscroll_delta_x()); EXPECT_EQ(65.f, overscroll_delta_x());
...@@ -2927,6 +2945,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) { ...@@ -2927,6 +2945,7 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
EXPECT_EQ(0.f, overscroll_delegate()->delta_y()); EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
PressTouchPoint(255, 5); PressTouchPoint(255, 5);
SendTouchEvent();
AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
...@@ -2941,9 +2960,11 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) { ...@@ -2941,9 +2960,11 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollWithTouchEvents) {
// The touch-end/cancel event should always reach the renderer if the page has // The touch-end/cancel event should always reach the renderer if the page has
// touch handlers. // touch handlers.
ReleaseTouchPoint(1); ReleaseTouchPoint(1);
SendTouchEvent();
AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
ReleaseTouchPoint(0); ReleaseTouchPoint(0);
SendTouchEvent();
AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
...@@ -3400,14 +3421,14 @@ TEST_F(RenderWidgetHostViewAuraTest, CorrectNumberOfAcksAreDispatched) { ...@@ -3400,14 +3421,14 @@ TEST_F(RenderWidgetHostViewAuraTest, CorrectNumberOfAcksAreDispatched) {
ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), 0, ui::EventTimeForNow()); ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), 0, ui::EventTimeForNow());
view_->OnTouchEvent(&press1); view_->OnTouchEvent(&press1);
SendInputEventACK(blink::WebInputEvent::TouchStart, SendTouchEventACK(blink::WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED, press1.unique_event_id());
ui::TouchEvent press2( ui::TouchEvent press2(
ui::ET_TOUCH_PRESSED, gfx::Point(20, 20), 1, ui::EventTimeForNow()); ui::ET_TOUCH_PRESSED, gfx::Point(20, 20), 1, ui::EventTimeForNow());
view_->OnTouchEvent(&press2); view_->OnTouchEvent(&press2);
SendInputEventACK(blink::WebInputEvent::TouchStart, SendTouchEventACK(blink::WebInputEvent::TouchStart,
INPUT_EVENT_ACK_STATE_CONSUMED); INPUT_EVENT_ACK_STATE_CONSUMED, press2.unique_event_id());
EXPECT_EQ(2U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); EXPECT_EQ(2U, view_->dispatcher_->GetAndResetProcessedTouchEventCount());
} }
......
...@@ -711,9 +711,8 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) { ...@@ -711,9 +711,8 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
ASSERT_EQ(1U, process_host->sink().message_count()); ASSERT_EQ(1U, process_host->sink().message_count());
// Send an ACK for the first wheel event, so that the queue will be flushed. // Send an ACK for the first wheel event, so that the queue will be flushed.
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(blink::WebInputEvent::MouseWheel,
ack.type = blink::WebInputEvent::MouseWheel; INPUT_EVENT_ACK_STATE_CONSUMED);
ack.state = INPUT_EVENT_ACK_STATE_CONSUMED;
scoped_ptr<IPC::Message> response( scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, ack)); new InputHostMsg_HandleInputEvent_ACK(0, ack));
host->OnMessageReceived(*response); host->OnMessageReceived(*response);
...@@ -757,9 +756,8 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) { ...@@ -757,9 +756,8 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
process_host->sink().ClearMessages(); process_host->sink().ClearMessages();
// Indicate that the wheel event was unhandled. // Indicate that the wheel event was unhandled.
InputHostMsg_HandleInputEvent_ACK_Params unhandled_ack; InputEventAck unhandled_ack(blink::WebInputEvent::MouseWheel,
unhandled_ack.type = blink::WebInputEvent::MouseWheel; INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
unhandled_ack.state = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
scoped_ptr<IPC::Message> response1( scoped_ptr<IPC::Message> response1(
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack)); new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
host->OnMessageReceived(*response1); host->OnMessageReceived(*response1);
...@@ -914,9 +912,8 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) { ...@@ -914,9 +912,8 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false); RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
// We'll use this IPC message to ack events. // We'll use this IPC message to ack events.
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(blink::WebInputEvent::GesturePinchUpdate,
ack.type = blink::WebInputEvent::GesturePinchUpdate; INPUT_EVENT_ACK_STATE_CONSUMED);
ack.state = INPUT_EVENT_ACK_STATE_CONSUMED;
scoped_ptr<IPC::Message> response( scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(0, ack)); new InputHostMsg_HandleInputEvent_ACK(0, ack));
......
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/input_event_ack.h"
namespace content {
InputEventAck::InputEventAck(
blink::WebInputEvent::Type type,
InputEventAckState state,
const ui::LatencyInfo& latency,
scoped_ptr<content::DidOverscrollParams> overscroll,
uint32 unique_touch_event_id)
: type(type),
state(state),
latency(latency),
overscroll(overscroll.Pass()),
unique_touch_event_id(unique_touch_event_id) {
}
InputEventAck::InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state,
const ui::LatencyInfo& latency,
uint32 unique_touch_event_id)
: InputEventAck(type, state, latency, nullptr, unique_touch_event_id) {
}
InputEventAck::InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state,
uint32 unique_touch_event_id)
: InputEventAck(type, state, ui::LatencyInfo(), unique_touch_event_id) {
}
InputEventAck::InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state)
: InputEventAck(type, state, 0) {
}
InputEventAck::InputEventAck()
: InputEventAck(blink::WebInputEvent::Undefined,
INPUT_EVENT_ACK_STATE_UNKNOWN) {
}
InputEventAck::~InputEventAck() {
}
} // namespace content
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_INPUT_EVENT_ACK_H_
#define CONTENT_COMMON_INPUT_INPUT_EVENT_ACK_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input/input_event_ack_state.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/latency_info.h"
namespace content {
// InputEventAck.
struct CONTENT_EXPORT InputEventAck {
InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state,
const ui::LatencyInfo& latency,
scoped_ptr<content::DidOverscrollParams> overscroll,
uint32 unique_touch_event_id);
InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state,
const ui::LatencyInfo& latency,
uint32 unique_touch_event_id);
InputEventAck(blink::WebInputEvent::Type type,
InputEventAckState state,
uint32 unique_touch_event_id);
InputEventAck(blink::WebInputEvent::Type type, InputEventAckState state);
InputEventAck();
~InputEventAck();
blink::WebInputEvent::Type type;
InputEventAckState state;
ui::LatencyInfo latency;
scoped_ptr<content::DidOverscrollParams> overscroll;
uint32 unique_touch_event_id;
};
} // namespace content
#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_ACK_H_
...@@ -168,6 +168,7 @@ void SyntheticWebTouchEvent::ResetPoints() { ...@@ -168,6 +168,7 @@ void SyntheticWebTouchEvent::ResetPoints() {
touchesLength = point; touchesLength = point;
type = WebInputEvent::Undefined; type = WebInputEvent::Undefined;
causesScrollingIfUncanceled = false; causesScrollingIfUncanceled = false;
uniqueTouchEventId = ui::GetNextTouchEventId();
} }
int SyntheticWebTouchEvent::PressPoint(float x, float y) { int SyntheticWebTouchEvent::PressPoint(float x, float y) {
......
...@@ -110,10 +110,8 @@ void ApppendEventDetails(const WebTouchEvent& event, std::string* result) { ...@@ -110,10 +110,8 @@ void ApppendEventDetails(const WebTouchEvent& event, std::string* result) {
StringAppendF(result, StringAppendF(result,
"{\n Touches: %u, Cancelable: %d, CausesScrolling: %d," "{\n Touches: %u, Cancelable: %d, CausesScrolling: %d,"
" uniqueTouchEventId: %u\n[\n", " uniqueTouchEventId: %u\n[\n",
event.touchesLength, event.touchesLength, event.cancelable,
event.cancelable, event.causesScrollingIfUncanceled, event.uniqueTouchEventId);
event.causesScrollingIfUncanceled,
static_cast<uint32>(event.uniqueTouchEventId));
for (unsigned i = 0; i < event.touchesLength; ++i) for (unsigned i = 0; i < event.touchesLength; ++i)
ApppendTouchPointDetails(event.touches[i], result); ApppendTouchPointDetails(event.touches[i], result);
result->append(" ]\n}"); result->append(" ]\n}");
...@@ -463,7 +461,8 @@ void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce, ...@@ -463,7 +461,8 @@ void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event); Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
} }
bool WebInputEventTraits::IgnoresAckDisposition(const WebInputEvent& event) { bool WebInputEventTraits::WillReceiveAckFromRenderer(
const WebInputEvent& event) {
switch (event.type) { switch (event.type) {
case WebInputEvent::MouseDown: case WebInputEvent::MouseDown:
case WebInputEvent::MouseUp: case WebInputEvent::MouseUp:
...@@ -479,14 +478,20 @@ bool WebInputEventTraits::IgnoresAckDisposition(const WebInputEvent& event) { ...@@ -479,14 +478,20 @@ bool WebInputEventTraits::IgnoresAckDisposition(const WebInputEvent& event) {
case WebInputEvent::GesturePinchBegin: case WebInputEvent::GesturePinchBegin:
case WebInputEvent::GesturePinchEnd: case WebInputEvent::GesturePinchEnd:
case WebInputEvent::TouchCancel: case WebInputEvent::TouchCancel:
return true; return false;
case WebInputEvent::TouchStart: case WebInputEvent::TouchStart:
case WebInputEvent::TouchMove:
case WebInputEvent::TouchEnd: case WebInputEvent::TouchEnd:
return !static_cast<const WebTouchEvent&>(event).cancelable; return static_cast<const WebTouchEvent&>(event).cancelable;
default: default:
return false; return true;
}
}
uint32 WebInputEventTraits::GetUniqueTouchEventId(const WebInputEvent& event) {
if (WebInputEvent::isTouchEventType(event.type)) {
return static_cast<const WebTouchEvent&>(event).uniqueTouchEventId;
} }
return 0U;
} }
} // namespace content } // namespace content
...@@ -25,7 +25,10 @@ class CONTENT_EXPORT WebInputEventTraits { ...@@ -25,7 +25,10 @@ class CONTENT_EXPORT WebInputEventTraits {
const blink::WebInputEvent& event); const blink::WebInputEvent& event);
static void Coalesce(const blink::WebInputEvent& event_to_coalesce, static void Coalesce(const blink::WebInputEvent& event_to_coalesce,
blink::WebInputEvent* event); blink::WebInputEvent* event);
static bool IgnoresAckDisposition(const blink::WebInputEvent& event); static bool WillReceiveAckFromRenderer(const blink::WebInputEvent& event);
// Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
static uint32 GetUniqueTouchEventId(const blink::WebInputEvent& event);
}; };
} // namespace content } // namespace content
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "content/common/edit_command.h" #include "content/common/edit_command.h"
#include "content/common/input/did_overscroll_params.h" #include "content/common/input/did_overscroll_params.h"
#include "content/common/input/input_event.h" #include "content/common/input/input_event.h"
#include "content/common/input/input_event_ack.h"
#include "content/common/input/input_event_ack_state.h" #include "content/common/input/input_event_ack_state.h"
#include "content/common/input/input_param_traits.h" #include "content/common/input/input_param_traits.h"
#include "content/common/input/synthetic_gesture_packet.h" #include "content/common/input/synthetic_gesture_packet.h"
...@@ -106,13 +107,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticTapGestureParams) ...@@ -106,13 +107,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticTapGestureParams)
IPC_STRUCT_TRAITS_MEMBER(duration_ms) IPC_STRUCT_TRAITS_MEMBER(duration_ms)
IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(InputHostMsg_HandleInputEvent_ACK_Params) IPC_STRUCT_TRAITS_BEGIN(content::InputEventAck)
IPC_STRUCT_MEMBER(blink::WebInputEvent::Type, type) IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_MEMBER(content::InputEventAckState, state) IPC_STRUCT_TRAITS_MEMBER(state)
IPC_STRUCT_MEMBER(ui::LatencyInfo, latency) IPC_STRUCT_TRAITS_MEMBER(latency)
// TODO(jdduke): Use Optional<T> type to avoid heap alloc, crbug.com/375002. IPC_STRUCT_TRAITS_MEMBER(overscroll)
IPC_STRUCT_MEMBER(scoped_ptr<content::DidOverscrollParams>, overscroll) IPC_STRUCT_TRAITS_MEMBER(unique_touch_event_id)
IPC_STRUCT_END() IPC_STRUCT_TRAITS_END()
// Sends an input event to the render widget. // Sends an input event to the render widget.
IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent, IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
...@@ -239,7 +240,7 @@ IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted) ...@@ -239,7 +240,7 @@ IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted)
// Acknowledges receipt of a InputMsg_HandleInputEvent message. // Acknowledges receipt of a InputMsg_HandleInputEvent message.
IPC_MESSAGE_ROUTED1(InputHostMsg_HandleInputEvent_ACK, IPC_MESSAGE_ROUTED1(InputHostMsg_HandleInputEvent_ACK,
InputHostMsg_HandleInputEvent_ACK_Params) content::InputEventAck /* ack */)
IPC_MESSAGE_ROUTED1(InputHostMsg_QueueSyntheticGesture, IPC_MESSAGE_ROUTED1(InputHostMsg_QueueSyntheticGesture,
content::SyntheticGesturePacket) content::SyntheticGesturePacket)
......
...@@ -367,6 +367,8 @@ ...@@ -367,6 +367,8 @@
'common/input/gesture_event_stream_validator.h', 'common/input/gesture_event_stream_validator.h',
'common/input/input_event.cc', 'common/input/input_event.cc',
'common/input/input_event.h', 'common/input/input_event.h',
'common/input/input_event_ack.cc',
'common/input/input_event_ack.h',
'common/input/input_event_stream_validator.cc', 'common/input/input_event_stream_validator.cc',
'common/input/input_event_stream_validator.h', 'common/input/input_event_stream_validator.h',
'common/input/input_param_traits.cc', 'common/input/input_param_traits.cc',
......
...@@ -150,7 +150,7 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { ...@@ -150,7 +150,7 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
bool is_keyboard_shortcut = get<2>(params); bool is_keyboard_shortcut = get<2>(params);
DCHECK(event); DCHECK(event);
const bool send_ack = !WebInputEventTraits::IgnoresAckDisposition(*event); const bool send_ack = WebInputEventTraits::WillReceiveAckFromRenderer(*event);
// Intercept |DidOverscroll| notifications, bundling any triggered overscroll // Intercept |DidOverscroll| notifications, bundling any triggered overscroll
// response with the input event ack. // response with the input event ack.
...@@ -176,11 +176,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) { ...@@ -176,11 +176,9 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
if (!send_ack) if (!send_ack)
return; return;
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(event->type, ack_state, latency_info,
ack.type = event->type; overscroll_params.Pass(),
ack.state = ack_state; WebInputEventTraits::GetUniqueTouchEventId(*event));
ack.latency = latency_info;
ack.overscroll = overscroll_params.Pass();
SendMessage(scoped_ptr<IPC::Message>( SendMessage(scoped_ptr<IPC::Message>(
new InputHostMsg_HandleInputEvent_ACK(routing_id, ack))); new InputHostMsg_HandleInputEvent_ACK(routing_id, ack)));
} }
......
...@@ -1239,11 +1239,10 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event, ...@@ -1239,11 +1239,10 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
// by reentrant calls for events after the paused one. // by reentrant calls for events after the paused one.
bool no_ack = ignore_ack_for_mouse_move_from_debugger_ && bool no_ack = ignore_ack_for_mouse_move_from_debugger_ &&
input_event->type == WebInputEvent::MouseMove; input_event->type == WebInputEvent::MouseMove;
if (!WebInputEventTraits::IgnoresAckDisposition(*input_event) && !no_ack) { if (WebInputEventTraits::WillReceiveAckFromRenderer(*input_event) &&
InputHostMsg_HandleInputEvent_ACK_Params ack; !no_ack) {
ack.type = input_event->type; InputEventAck ack(input_event->type, ack_result, swap_latency_info,
ack.state = ack_result; WebInputEventTraits::GetUniqueTouchEventId(*input_event));
ack.latency = swap_latency_info;
scoped_ptr<IPC::Message> response( scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack)); new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
if (rate_limiting_wanted && frame_pending && !is_hidden_) { if (rate_limiting_wanted && frame_pending && !is_hidden_) {
...@@ -1794,9 +1793,7 @@ bool RenderWidget::SendAckForMouseMoveFromDebugger() { ...@@ -1794,9 +1793,7 @@ bool RenderWidget::SendAckForMouseMoveFromDebugger() {
// If we pause multiple times during a single mouse move event, we should // If we pause multiple times during a single mouse move event, we should
// only send ACK once. // only send ACK once.
if (!ignore_ack_for_mouse_move_from_debugger_) { if (!ignore_ack_for_mouse_move_from_debugger_) {
InputHostMsg_HandleInputEvent_ACK_Params ack; InputEventAck ack(handling_event_type_, INPUT_EVENT_ACK_STATE_CONSUMED);
ack.type = handling_event_type_;
ack.state = INPUT_EVENT_ACK_STATE_CONSUMED;
Send(new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack)); Send(new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
return true; return true;
} }
......
...@@ -518,7 +518,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent { ...@@ -518,7 +518,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// The id of the pointer this event modifies. // The id of the pointer this event modifies.
int touch_id() const { return touch_id_; } int touch_id() const { return touch_id_; }
// A unique identifier for this event. // A unique identifier for this event.
uint64 unique_event_id() const { return unique_event_id_; } uint32 unique_event_id() const { return unique_event_id_; }
// If we aren't provided with a radius on one axis, use the // If we aren't provided with a radius on one axis, use the
// information from the other axis. // information from the other axis.
float radius_x() const { return radius_x_ > 0 ? radius_x_ : radius_y_; } float radius_x() const { return radius_x_ > 0 ? radius_x_ : radius_y_; }
...@@ -558,7 +558,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent { ...@@ -558,7 +558,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
const int touch_id_; const int touch_id_;
// A unique identifier for the touch event. // A unique identifier for the touch event.
const uint64 unique_event_id_; const uint32 unique_event_id_;
// Radius of the X (major) axis of the touch ellipse. 0.0 if unknown. // Radius of the X (major) axis of the touch ellipse. 0.0 if unknown.
float radius_x_; float radius_x_;
......
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