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#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/content_export.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "content/port/browser/event_with_latency_info.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/port/common/input_event_ack_state.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebInputEvent.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CoalescedWebTouchEvent;
20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Interface with which TouchEventQueue can forward touch events, and dispatch
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// touch event responses.
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class CONTENT_EXPORT TouchEventQueueClient {
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual ~TouchEventQueueClient() {}
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual void SendTouchEventImmediately(
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const TouchEventWithLatencyInfo& event) = 0;
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual void OnTouchEventAck(
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      const TouchEventWithLatencyInfo& event,
32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      InputEventAckState ack_result) = 0;
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A queue for throttling and coalescing touch-events.
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class CONTENT_EXPORT TouchEventQueue {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // The |client| must outlive the TouchEventQueue.
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  explicit TouchEventQueue(TouchEventQueueClient* client);
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~TouchEventQueue();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adds an event to the queue. The event may be coalesced with previously
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // queued events (e.g. consecutive touch-move events can be coalesced into a
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single touch-move event). The event may also be immediately forwarded to
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the renderer (e.g. when there are no other queued touch event).
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  void QueueEvent(const TouchEventWithLatencyInfo& event);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifies the queue that a touch-event has been processed by the renderer.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this point, the queue may send one or more gesture events and/or
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // additional queued touch-events to the renderer.
523240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void ProcessTouchAck(InputEventAckState ack_result,
533240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                       const ui::LatencyInfo& latency_info);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // When GestureScrollBegin is received, we send a touch cancel to renderer,
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // route all the following touch events directly to client, and ignore the
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ack for the touch cancel. When Gesture{ScrollEnd,FlingStart} is received,
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // resume the normal flow of sending touch events to the renderer.
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void OnGestureScrollEvent(const GestureEventWithLatencyInfo& gesture_event);
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Empties the queue of touch events. This may result in any number of gesture
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // events being sent to the renderer.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FlushQueue();
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Returns whether the currently pending touch event (waiting ACK) is for
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // a touch start event.
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool IsPendingAckTouchStart() const;
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Sets whether a delayed touch ack will cancel and flush the current
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // touch sequence.
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void SetAckTimeoutEnabled(bool enabled, size_t ack_timeout_delay_ms);
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool empty() const WARN_UNUSED_RESULT {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return touch_queue_.empty();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  size_t size() const {
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return touch_queue_.size();
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool ack_timeout_enabled() const {
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return ack_timeout_enabled_;
833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  class TouchTimeoutHandler;
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  friend class TouchTimeoutHandler;
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  friend class TouchEventQueueTest;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool HasTimeoutEvent() const;
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool IsTimeoutRunningForTesting() const;
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const TouchEventWithLatencyInfo& GetLatestEventForTesting() const;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // Walks the queue, checking each event for |ShouldForwardToRenderer()|.
9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If true, forwards the touch event and stops processing further events.
9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  // If false, acks the event with |INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS|.
9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void TryForwardNextEventToRenderer();
9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pops the touch-event from the top of the queue and sends it to the
100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // TouchEventQueueClient. This reduces the size of the queue by one.
1013240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  void PopTouchEventToClient(InputEventAckState ack_result,
1023240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch                             const ui::LatencyInfo& renderer_latency_info);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  bool ShouldForwardToRenderer(const blink::WebTouchEvent& event) const;
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void ForwardToRenderer(const TouchEventWithLatencyInfo& event);
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void UpdateTouchAckStates(const blink::WebTouchEvent& event,
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            InputEventAckState ack_result);
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Handles touch event forwarding and ack'ed event dispatch.
111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TouchEventQueueClient* client_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::deque<CoalescedWebTouchEvent*> TouchQueue;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TouchQueue touch_queue_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Maintain the ACK status for each touch point.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<int, InputEventAckState> TouchPointAckStates;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TouchPointAckStates touch_ack_states_;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Used to defer touch forwarding when ack dispatch triggers |QueueEvent()|.
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If not NULL, |dispatching_touch_ack_| is the touch event of which the ack
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // is being dispatched.
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CoalescedWebTouchEvent* dispatching_touch_ack_;
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Used to prevent touch timeout scheduling if we receive a synchronous
126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ack after forwarding a touch event to the client.
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool dispatching_touch_;
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Don't send touch events to the renderer while scrolling.
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool no_touch_to_renderer_;
1313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Whether an event in the current (multi)touch sequence was consumed by the
133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // renderer.  The touch timeout will never be activated when this is true.
134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool renderer_is_consuming_touch_gesture_;
135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Optional handler for timed-out touch event acks, disabled by default.
137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool ack_timeout_enabled_;
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<TouchTimeoutHandler> timeout_handler_;
139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TouchEventQueue);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_
146