| Index: content/browser/renderer_host/input/touch_event_queue.cc
|
| diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc
|
| index a36520fdcb1df30f6bc05fbd2274c6c61b983a30..b92b24aaa23e6efba589c23ce32705ab4feaeef7 100644
|
| --- a/content/browser/renderer_host/input/touch_event_queue.cc
|
| +++ b/content/browser/renderer_host/input/touch_event_queue.cc
|
| @@ -28,8 +28,7 @@ namespace {
|
| const double kAsyncTouchMoveIntervalSec = .2;
|
|
|
| // A sanity check on touches received to ensure that touch movement outside
|
| -// the platform slop region will cause scrolling, as indicated by the event's
|
| -// |causesScrollingIfUncanceled| bit.
|
| +// the platform slop region will cause scrolling.
|
| const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.;
|
|
|
| TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
|
| @@ -491,6 +490,32 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
|
| touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
|
| }
|
|
|
| +void TouchEventQueue::PrependTouchScrollNotification() {
|
| + TRACE_EVENT0("input", "TouchEventQueue::PrependTouchScrollNotification");
|
| +
|
| + // The queue should have an in-flight event when this method is called because
|
| + // this method is triggered by InputRouterImpl::SendGestureEvent, which is
|
| + // triggered by TouchEventQueue::AckTouchEventToClient, which has just
|
| + // received an ack for the in-flight event. We leave the head of the queue
|
| + // untouched since it is the in-flight event.
|
| + //
|
| + // However, for the (integration) tests in RenderWidgetHostTest that trigger
|
| + // this method indirectly, they push the TouchScrollStarted event into
|
| + // TouchEventQueue without any way to dispatch it. Below we added a check for
|
| + // non-empty queue to keep those tests as-is w/o exposing internals of this
|
| + // class all the way up.
|
| + if (!touch_queue_.empty()) {
|
| + TouchEventWithLatencyInfo touch;
|
| + touch.event.type = WebInputEvent::TouchScrollStarted;
|
| + touch.event.uniqueTouchEventId = 0;
|
| + touch.event.touchesLength = 0;
|
| +
|
| + auto it = touch_queue_.begin();
|
| + DCHECK(it != touch_queue_.end());
|
| + touch_queue_.insert(++it, new CoalescedWebTouchEvent(touch, false));
|
| + }
|
| +}
|
| +
|
| void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
|
| const LatencyInfo& latency_info,
|
| const uint32_t unique_touch_event_id) {
|
| @@ -525,8 +550,14 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
|
| if (touch_queue_.empty())
|
| return;
|
|
|
| - DCHECK_EQ(touch_queue_.front()->coalesced_event().event.uniqueTouchEventId,
|
| - unique_touch_event_id);
|
| + // We don't care about the ordering of the acks vs the ordering of the
|
| + // dispatched events because we can receive the ack for event B before the ack
|
| + // for event A even though A was sent before B. This seems to be happening
|
| + // when, for example, A is acked from renderer but B isn't, so the ack for B
|
| + // is synthesized "locally" in InputRouter.
|
| + //
|
| + // TODO(crbug.com/600773): Bring the id checks back when dispatch triggering
|
| + // is sane.
|
|
|
| PopTouchEventToClient(ack_result, latency_info);
|
| TryForwardNextEventToRenderer();
|
| @@ -719,38 +750,45 @@ void TouchEventQueue::FlushQueue() {
|
| }
|
|
|
| void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) {
|
| - AckTouchEventToClient(ack_result, PopTouchEvent(), nullptr);
|
| + AckTouchEventToClient(ack_result, nullptr);
|
| }
|
|
|
| void TouchEventQueue::PopTouchEventToClient(
|
| InputEventAckState ack_result,
|
| const LatencyInfo& renderer_latency_info) {
|
| - AckTouchEventToClient(ack_result, PopTouchEvent(), &renderer_latency_info);
|
| + AckTouchEventToClient(ack_result, &renderer_latency_info);
|
| }
|
|
|
| void TouchEventQueue::AckTouchEventToClient(
|
| InputEventAckState ack_result,
|
| - std::unique_ptr<CoalescedWebTouchEvent> acked_event,
|
| const ui::LatencyInfo* optional_latency_info) {
|
| - DCHECK(acked_event);
|
| DCHECK(!dispatching_touch_ack_);
|
| + DCHECK(!touch_queue_.empty());
|
| + std::unique_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
|
| + DCHECK(acked_event);
|
| +
|
| UpdateTouchConsumerStates(acked_event->coalesced_event().event, ack_result);
|
|
|
| // Note that acking the touch-event may result in multiple gestures being sent
|
| // to the renderer, or touch-events being queued.
|
| base::AutoReset<bool> dispatching_touch_ack(&dispatching_touch_ack_, true);
|
| - acked_event->DispatchAckToClient(ack_result, optional_latency_info, client_);
|
| -}
|
|
|
| -std::unique_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() {
|
| - DCHECK(!touch_queue_.empty());
|
| - std::unique_ptr<CoalescedWebTouchEvent> event(touch_queue_.front());
|
| + // Skip ack for TouchScrollStarted since it was synthesized within the queue.
|
| + if (acked_event->coalesced_event().event.type !=
|
| + WebInputEvent::TouchScrollStarted) {
|
| + acked_event->DispatchAckToClient(ack_result, optional_latency_info,
|
| + client_);
|
| + }
|
| +
|
| touch_queue_.pop_front();
|
| - return event;
|
| }
|
|
|
| void TouchEventQueue::SendTouchEventImmediately(
|
| TouchEventWithLatencyInfo* touch) {
|
| + // TODO(crbug.com/600773): Hack to avoid cyclic reentry to this method.
|
| + if (dispatching_touch_)
|
| + return;
|
| +
|
| // For touchmove events, compare touch points position from current event
|
| // to last sent event and update touch points state.
|
| if (touch->event.type == WebInputEvent::TouchMove) {
|
| @@ -772,10 +810,12 @@ void TouchEventQueue::SendTouchEventImmediately(
|
| }
|
| }
|
|
|
| - if (last_sent_touchevent_)
|
| - *last_sent_touchevent_ = touch->event;
|
| - else
|
| - last_sent_touchevent_.reset(new WebTouchEvent(touch->event));
|
| + if (touch->event.type != WebInputEvent::TouchScrollStarted) {
|
| + if (last_sent_touchevent_)
|
| + *last_sent_touchevent_ = touch->event;
|
| + else
|
| + last_sent_touchevent_.reset(new WebTouchEvent(touch->event));
|
| + }
|
|
|
| base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
|
|
|
| @@ -805,6 +845,9 @@ void TouchEventQueue::SendTouchEventImmediately(
|
|
|
| TouchEventQueue::PreFilterResult
|
| TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
|
| + if (event.type == WebInputEvent::TouchScrollStarted)
|
| + return FORWARD_TO_RENDERER;
|
| +
|
| if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
|
| has_handler_for_current_sequence_ = false;
|
| send_touch_events_async_ = false;
|
|
|