touch_event_queue.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/debug/trace_event.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class represents a single coalesced touch event. However, it also keeps
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// track of all the original touch-events that were coalesced into a single
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// event. The coalesced event is forwarded to the renderer, while the original
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// touch-events are sent to the Client (on ACK for the coalesced event) so that
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// the Client receives the event with their original timestamp.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CoalescedWebTouchEvent {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event)
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : coalesced_event_(event),
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        ignore_ack_(false) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(event);
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TRACE_EVENT_ASYNC_BEGIN0(
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "input", "TouchEventQueue::QueueEvent", this);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ~CoalescedWebTouchEvent() {
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TRACE_EVENT_ASYNC_END0(
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        "input", "TouchEventQueue::QueueEvent", this);
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Coalesces the event with the existing event if possible. Returns whether
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the event was coalesced.
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool CoalesceEventIfPossible(
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const TouchEventWithLatencyInfo& event_with_latency) {
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (ignore_ack_)
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!coalesced_event_.CanCoalesceWith(event_with_latency))
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return false;
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TRACE_EVENT_INSTANT0(
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    coalesced_event_.CoalesceWith(event_with_latency);
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    events_.push_back(event_with_latency);
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return true;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const TouchEventWithLatencyInfo& coalesced_event() const {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return coalesced_event_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebTouchEventWithLatencyList::iterator begin() {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_.begin();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebTouchEventWithLatencyList::iterator end() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return events_.end();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size() const { return events_.size(); }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ignore_ack() const { return ignore_ack_; }
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void set_ignore_ack(bool value) { ignore_ack_ = value; }
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the event that is forwarded to the renderer.
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TouchEventWithLatencyInfo coalesced_event_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the list of the original events that were coalesced.
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WebTouchEventWithLatencyList events_;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If |ignore_ack_| is true, don't send this touch event to client
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // when the event is acked.
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool ignore_ack_;
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : client_(client),
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dispatching_touch_ack_(NULL),
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      no_touch_to_renderer_(false) {
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(client);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TouchEventQueue::~TouchEventQueue() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!touch_queue_.empty())
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    STLDeleteElements(&touch_queue_);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // If the queueing of |event| was triggered by an ack dispatch, defer
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // processing the event until the dispatch has finished.
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (touch_queue_.empty() && !dispatching_touch_ack_) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // There is no touch event in the queue. Forward it to the renderer
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // immediately.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    touch_queue_.push_back(new CoalescedWebTouchEvent(event));
10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    TryForwardNextEventToRenderer();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the last queued touch-event was a touch-move, and the current event is
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // also a touch-move, then the events can be coalesced into a single event.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (touch_queue_.size() > 1) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoalescedWebTouchEvent* last_event = touch_queue_.back();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_event->CoalesceEventIfPossible(event))
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  touch_queue_.push_back(new CoalescedWebTouchEvent(event));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1163240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
1173240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                                      const ui::LatencyInfo& latency_info) {
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!dispatching_touch_ack_);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (touch_queue_.empty())
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Update the ACK status for each touch point in the ACKed event.
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const WebKit::WebTouchEvent& event =
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      touch_queue_.front()->coalesced_event().event;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event.type == WebKit::WebInputEvent::TouchEnd ||
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event.type == WebKit::WebInputEvent::TouchCancel) {
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The points have been released. Erase the ACK states.
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned i = 0; i < event.touchesLength; ++i) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const WebKit::WebTouchPoint& point = event.touches[i];
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (point.state == WebKit::WebTouchPoint::StateReleased ||
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          point.state == WebKit::WebTouchPoint::StateCancelled)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        touch_ack_states_.erase(point.id);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (event.type == WebKit::WebInputEvent::TouchStart) {
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned i = 0; i < event.touchesLength; ++i) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const WebKit::WebTouchPoint& point = event.touches[i];
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (point.state == WebKit::WebTouchPoint::StatePressed)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        touch_ack_states_[point.id] = ack_result;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1423240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PopTouchEventToClient(ack_result, latency_info);
14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  TryForwardNextEventToRenderer();
14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void TouchEventQueue::TryForwardNextEventToRenderer() {
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(!dispatching_touch_ack_);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there are queued touch events, then try to forward them to the renderer
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // immediately, or ACK the events back to the client if appropriate.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (!touch_queue_.empty()) {
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const TouchEventWithLatencyInfo& touch =
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        touch_queue_.front()->coalesced_event();
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (ShouldForwardToRenderer(touch.event)) {
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      client_->SendTouchEventImmediately(touch);
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1573240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
1583240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                          ui::LatencyInfo());
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TouchEventQueue::OnGestureScrollEvent(
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const GestureEventWithLatencyInfo& gesture_event) {
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  WebKit::WebInputEvent::Type type = gesture_event.event.type;
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (type == WebKit::WebInputEvent::GestureScrollBegin) {
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // We assume the scroll event are generated synchronously from
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // dispatching a touch event ack, so that we can fake a cancel
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // event that has the correct touch ids as the touch event that
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // is being acked. If not, we don't do the touch-cancel optimization.
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (no_touch_to_renderer_ || !dispatching_touch_ack_)
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    no_touch_to_renderer_ = true;
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Fake a TouchCancel to cancel the touch points of the touch event
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // that is currently being acked.
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TouchEventWithLatencyInfo cancel_event =
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        dispatching_touch_ack_->coalesced_event();
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    cancel_event.event.type = WebKit::WebInputEvent::TouchCancel;
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < cancel_event.event.touchesLength; i++)
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      cancel_event.event.touches[i].state =
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          WebKit::WebTouchPoint::StateCancelled;
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    CoalescedWebTouchEvent* coalesced_cancel_event =
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        new CoalescedWebTouchEvent(cancel_event);
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Ignore the ack of the touch cancel so when it is acked, it won't get
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // sent to gesture recognizer.
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    coalesced_cancel_event->set_ignore_ack(true);
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // |dispatching_touch_ack_| is non-null when we reach here, meaning we
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // are in the scope of PopTouchEventToClient() and that no touch event
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // in the queue is waiting for ack from renderer. So we can just insert
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // the touch cancel at the beginning of the queue.
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    touch_queue_.push_front(coalesced_cancel_event);
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else if (type == WebKit::WebInputEvent::GestureScrollEnd ||
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)             type == WebKit::WebInputEvent::GestureFlingStart) {
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    no_touch_to_renderer_ = false;
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TouchEventQueue::FlushQueue() {
1987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(!dispatching_touch_ack_);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!touch_queue_.empty())
2003240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
2013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                          ui::LatencyInfo());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t TouchEventQueue::GetQueueSize() const {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return touch_queue_.size();
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const TouchEventWithLatencyInfo& TouchEventQueue::GetLatestEvent() const {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return touch_queue_.back()->coalesced_event();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2123240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdochvoid TouchEventQueue::PopTouchEventToClient(
2133240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    InputEventAckState ack_result,
2143240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    const ui::LatencyInfo& renderer_latency_info) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (touch_queue_.empty())
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  touch_queue_.pop_front();
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (acked_event->ignore_ack())
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that acking the touch-event may result in multiple gestures being sent
2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // to the renderer, or touch-events being queued.
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::AutoReset<CoalescedWebTouchEvent*>
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get());
2277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       end = acked_event->end();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       iter != end; ++iter) {
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    iter->latency.AddNewLatencyFrom(renderer_latency_info);
232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    client_->OnTouchEventAck((*iter), ack_result);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TouchEventQueue::ShouldForwardToRenderer(
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const WebKit::WebTouchEvent& event) const {
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (no_touch_to_renderer_ &&
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      event.type != WebKit::WebInputEvent::TouchCancel)
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return false;
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Touch press events should always be forwarded to the renderer.
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event.type == WebKit::WebInputEvent::TouchStart)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned int i = 0; i < event.touchesLength; ++i) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const WebKit::WebTouchPoint& point = event.touches[i];
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If a point has been stationary, then don't take it into account.
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (point.state == WebKit::WebTouchPoint::StateStationary)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (touch_ack_states_.count(point.id) > 0) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (touch_ack_states_.find(point.id)->second !=
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return true;
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the ACK status of a point is unknown, then the event should be
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // forwarded to the renderer.
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
267