1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "content/browser/renderer_host/input/touch_event_queue.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/auto_reset.h"
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/command_line.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/debug/trace_event.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/browser/renderer_host/input/timeout_monitor.h"
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/common/input/web_input_event_traits.h"
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/public/common/content_switches.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using blink::WebInputEvent;
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using blink::WebTouchEvent;
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using blink::WebTouchPoint;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const InputEventAckState kDefaultNotForwardedAck =
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const TouchEventWithLatencyInfo& event_to_cancel) {
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TouchEventWithLatencyInfo event = event_to_cancel;
30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  event.event.type = WebInputEvent::TouchCancel;
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < event.event.touchesLength; i++)
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    event.event.touches[i].state = WebTouchPoint::StateCancelled;
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return event;
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool IsNewTouchGesture(const WebTouchEvent& event) {
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (event.type != WebInputEvent::TouchStart)
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!event.touchesLength)
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < event.touchesLength; i++) {
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (event.touches[i].state != WebTouchPoint::StatePressed)
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return false;
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) {
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return type == WebInputEvent::TouchStart ||
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         type == WebInputEvent::TouchMove;
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class TouchEventQueue::TouchTimeoutHandler {
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TouchTimeoutHandler(TouchEventQueue* touch_queue, size_t timeout_delay_ms)
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : touch_queue_(touch_queue),
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        timeout_delay_(base::TimeDelta::FromMilliseconds(timeout_delay_ms)),
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        pending_ack_state_(PENDING_ACK_NONE),
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                    base::Unretained(this))) {}
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~TouchTimeoutHandler() {}
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Start(const TouchEventWithLatencyInfo& event) {
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(ShouldTouchTypeTriggerTimeout(event.event.type));
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    timeout_event_ = event;
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    timeout_monitor_.Restart(timeout_delay_);
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool ConfirmTouchEvent(InputEventAckState ack_result) {
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switch (pending_ack_state_) {
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_NONE:
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        timeout_monitor_.Stop();
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return false;
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_ORIGINAL_EVENT:
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (AckedTimeoutEventRequiresCancel(ack_result)) {
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          TouchEventWithLatencyInfo cancel_event =
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              ObtainCancelEventForTouchEvent(timeout_event_);
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          touch_queue_->UpdateTouchAckStates(
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)              cancel_event.event, kDefaultNotForwardedAck);
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          touch_queue_->client_->SendTouchEventImmediately(cancel_event);
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        } else {
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          SetPendingAckState(PENDING_ACK_NONE);
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          touch_queue_->UpdateTouchAckStates(timeout_event_.event, ack_result);
89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return true;
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_CANCEL_EVENT:
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SetPendingAckState(PENDING_ACK_NONE);
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        return true;
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool HasTimeoutEvent() const {
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return pending_ack_state_ != PENDING_ACK_NONE;
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool IsTimeoutTimerRunning() const {
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return timeout_monitor_.IsRunning();
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  enum PendingAckState {
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PENDING_ACK_NONE,
109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PENDING_ACK_ORIGINAL_EVENT,
110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PENDING_ACK_CANCEL_EVENT,
111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  };
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void OnTimeOut() {
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT);
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    touch_queue_->FlushQueue();
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Skip a cancel event if the timed-out event had no consumer and was the
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // initial event in the gesture.
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const {
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(HasTimeoutEvent());
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return true;
124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return !IsNewTouchGesture(timeout_event_.event);
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void SetPendingAckState(PendingAckState new_pending_ack_state) {
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK_NE(pending_ack_state_, new_pending_ack_state);
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    switch (new_pending_ack_state) {
130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_ORIGINAL_EVENT:
131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this);
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_CANCEL_EVENT:
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK_EQ(pending_ack_state_, PENDING_ACK_ORIGINAL_EVENT);
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK(!timeout_monitor_.IsRunning());
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK(touch_queue_->empty());
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        TRACE_EVENT_ASYNC_STEP_INTO0(
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            "input", "TouchEventTimeout", this, "CancelEvent");
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      case PENDING_ACK_NONE:
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK(!timeout_monitor_.IsRunning());
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        DCHECK(touch_queue_->empty());
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        TRACE_EVENT_ASYNC_END0("input", "TouchEventTimeout", this);
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        break;
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    pending_ack_state_ = new_pending_ack_state;
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TouchEventQueue* touch_queue_;
152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // How long to wait on a touch ack before cancelling the touch sequence.
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TimeDelta timeout_delay_;
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The touch event source for which we expect the next ack.
157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PendingAckState pending_ack_state_;
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The event for which the ack timeout is triggered.
160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TouchEventWithLatencyInfo timeout_event_;
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Provides timeout-based callback behavior.
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TimeoutMonitor timeout_monitor_;
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class represents a single coalesced touch event. However, it also keeps
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// track of all the original touch-events that were coalesced into a single
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// event. The coalesced event is forwarded to the renderer, while the original
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// touch-events are sent to the Client (on ACK for the coalesced event) so that
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the Client receives the event with their original timestamp.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CoalescedWebTouchEvent {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         bool ignore_ack)
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : coalesced_event_(event),
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ignore_ack_(ignore_ack) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(event);
179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN0(
180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "input", "TouchEventQueue::QueueEvent", this);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ~CoalescedWebTouchEvent() {
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0(
185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "input", "TouchEventQueue::QueueEvent", this);
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Coalesces the event with the existing event if possible. Returns whether
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the event was coalesced.
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool CoalesceEventIfPossible(
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const TouchEventWithLatencyInfo& event_with_latency) {
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (ignore_ack_)
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!coalesced_event_.CanCoalesceWith(event_with_latency))
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TRACE_EVENT_INSTANT0(
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    coalesced_event_.CoalesceWith(event_with_latency);
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    events_.push_back(event_with_latency);
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const TouchEventWithLatencyInfo& coalesced_event() const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return coalesced_event_;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebTouchEventWithLatencyList::iterator begin() {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_.begin();
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebTouchEventWithLatencyList::iterator end() {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_.end();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const { return events_.size(); }
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ignore_ack() const { return ignore_ack_; }
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the event that is forwarded to the renderer.
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TouchEventWithLatencyInfo coalesced_event_;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the list of the original events that were coalesced.
2267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WebTouchEventWithLatencyList events_;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If |ignore_ack_| is true, don't send this touch event to client
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // when the event is acked.
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ignore_ack_;
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : client_(client),
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dispatching_touch_ack_(NULL),
238a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dispatching_touch_(false),
239a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      no_touch_to_renderer_(false),
240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      renderer_is_consuming_touch_gesture_(false),
241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ack_timeout_enabled_(false) {
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(client);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchEventQueue::~TouchEventQueue() {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!touch_queue_.empty())
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&touch_queue_);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
2517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the queueing of |event| was triggered by an ack dispatch, defer
2527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // processing the event until the dispatch has finished.
2537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (touch_queue_.empty() && !dispatching_touch_ack_) {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no touch event in the queue. Forward it to the renderer
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // immediately.
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
25768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    TryForwardNextEventToRenderer();
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the last queued touch-event was a touch-move, and the current event is
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // also a touch-move, then the events can be coalesced into a single event.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (touch_queue_.size() > 1) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoalescedWebTouchEvent* last_event = touch_queue_.back();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_event->CoalesceEventIfPossible(event))
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
2723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                      const ui::LatencyInfo& latency_info) {
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!dispatching_touch_ack_);
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  dispatching_touch_ = false;
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result))
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (touch_queue_.empty())
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
283a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    renderer_is_consuming_touch_gesture_ = true;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const WebTouchEvent& acked_event =
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      touch_queue_.front()->coalesced_event().event;
287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UpdateTouchAckStates(acked_event, ack_result);
2883240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PopTouchEventToClient(ack_result, latency_info);
28968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TryForwardNextEventToRenderer();
29068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
29268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TouchEventQueue::TryForwardNextEventToRenderer() {
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!dispatching_touch_ack_);
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there are queued touch events, then try to forward them to the renderer
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // immediately, or ACK the events back to the client if appropriate.
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!touch_queue_.empty()) {
2977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const TouchEventWithLatencyInfo& touch =
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        touch_queue_.front()->coalesced_event();
299a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IsNewTouchGesture(touch.event))
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      renderer_is_consuming_touch_gesture_ = false;
3017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (ShouldForwardToRenderer(touch.event)) {
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ForwardToRenderer(touch);
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TouchEventQueue::ForwardToRenderer(
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const TouchEventWithLatencyInfo& touch) {
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!dispatching_touch_);
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // A synchronous ack will reset |dispatching_touch_|, in which case
313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // the touch timeout should not be started.
314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  client_->SendTouchEventImmediately(touch);
316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (ack_timeout_enabled_ &&
317a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dispatching_touch_ &&
318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !renderer_is_consuming_touch_gesture_ &&
319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ShouldTouchTypeTriggerTimeout(touch.event.type)) {
320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(timeout_handler_);
321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    timeout_handler_->Start(touch);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TouchEventQueue::OnGestureScrollEvent(
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GestureEventWithLatencyInfo& gesture_event) {
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  blink::WebInputEvent::Type type = gesture_event.event.type;
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (type == blink::WebInputEvent::GestureScrollBegin) {
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // We assume the scroll event are generated synchronously from
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // dispatching a touch event ack, so that we can fake a cancel
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // event that has the correct touch ids as the touch event that
3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // is being acked. If not, we don't do the touch-cancel optimization.
3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (no_touch_to_renderer_ || !dispatching_touch_ack_)
3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    no_touch_to_renderer_ = true;
336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // If we have a timeout event, a cancel has already been dispatched
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // for the current touch stream.
339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (HasTimeoutEvent())
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return;
341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Fake a TouchCancel to cancel the touch points of the touch event
3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // that is currently being acked.
344a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // are in the scope of PopTouchEventToClient() and that no touch event
3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // in the queue is waiting for ack from renderer. So we can just insert
3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // the touch cancel at the beginning of the queue.
348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    touch_queue_.push_front(new CoalescedWebTouchEvent(
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ObtainCancelEventForTouchEvent(
350a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            dispatching_touch_ack_->coalesced_event()), true));
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else if (type == blink::WebInputEvent::GestureScrollEnd ||
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             type == blink::WebInputEvent::GestureFlingStart) {
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    no_touch_to_renderer_ = false;
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchEventQueue::FlushQueue() {
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!dispatching_touch_ack_);
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!dispatching_touch_);
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!touch_queue_.empty())
361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
362a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
363a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
364a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool TouchEventQueue::IsPendingAckTouchStart() const {
365a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!dispatching_touch_ack_);
366a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (touch_queue_.empty())
367a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const blink::WebTouchEvent& event =
370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      touch_queue_.front()->coalesced_event().event;
371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return (event.type == WebInputEvent::TouchStart);
372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TouchEventQueue::SetAckTimeoutEnabled(bool enabled,
375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           size_t ack_timeout_delay_ms) {
376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!enabled) {
377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Avoid resetting |timeout_handler_|, as an outstanding timeout may
378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // be active and must be completed for ack handling consistency.
379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ack_timeout_enabled_ = false;
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ack_timeout_enabled_ = true;
384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!timeout_handler_)
385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay_ms));
386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool TouchEventQueue::HasTimeoutEvent() const {
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return timeout_handler_ && timeout_handler_->HasTimeoutEvent();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool TouchEventQueue::IsTimeoutRunningForTesting() const {
393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const TouchEventWithLatencyInfo&
397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)TouchEventQueue::GetLatestEventForTesting() const {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return touch_queue_.back()->coalesced_event();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid TouchEventQueue::PopTouchEventToClient(
4023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    InputEventAckState ack_result,
4033240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ui::LatencyInfo& renderer_latency_info) {
404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(!dispatching_touch_ack_);
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (touch_queue_.empty())
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  touch_queue_.pop_front();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (acked_event->ignore_ack())
4114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that acking the touch-event may result in multiple gestures being sent
4147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to the renderer, or touch-events being queued.
4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::AutoReset<CoalescedWebTouchEvent*>
4164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get());
4177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(),
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       end = acked_event->end();
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != end; ++iter) {
4214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    iter->latency.AddNewLatencyFrom(renderer_latency_info);
422ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    client_->OnTouchEventAck((*iter), ack_result);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TouchEventQueue::ShouldForwardToRenderer(
427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const WebTouchEvent& event) const {
428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (HasTimeoutEvent())
429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (no_touch_to_renderer_ &&
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event.type != blink::WebInputEvent::TouchCancel)
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Touch press events should always be forwarded to the renderer.
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (event.type == WebInputEvent::TouchStart)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned int i = 0; i < event.touchesLength; ++i) {
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const WebTouchPoint& point = event.touches[i];
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If a point has been stationary, then don't take it into account.
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (point.state == WebTouchPoint::StateStationary)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (touch_ack_states_.count(point.id) > 0) {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (touch_ack_states_.find(point.id)->second !=
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the ACK status of a point is unknown, then the event should be
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // forwarded to the renderer.
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event,
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                           InputEventAckState ack_result) {
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Update the ACK status for each touch point in the ACKed event.
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (event.type == WebInputEvent::TouchEnd ||
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      event.type == WebInputEvent::TouchCancel) {
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The points have been released. Erase the ACK states.
465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (unsigned i = 0; i < event.touchesLength; ++i) {
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const WebTouchPoint& point = event.touches[i];
467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (point.state == WebTouchPoint::StateReleased ||
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          point.state == WebTouchPoint::StateCancelled)
469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        touch_ack_states_.erase(point.id);
470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else if (event.type == WebInputEvent::TouchStart) {
472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (unsigned i = 0; i < event.touchesLength; ++i) {
473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const WebTouchPoint& point = event.touches[i];
474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (point.state == WebTouchPoint::StatePressed)
475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        touch_ack_states_[point.id] = ack_result;
476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
481