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