| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ | 5 #ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ |
| 6 #define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ | 6 #define CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ |
| 7 | 7 |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| 11 #include <deque> | |
| 12 #include <list> | |
| 13 #include <memory> | |
| 14 | |
| 15 #include "base/macros.h" | 11 #include "base/macros.h" |
| 16 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 17 #include "content/browser/renderer_host/event_with_latency_info.h" | 13 #include "content/browser/renderer_host/event_with_latency_info.h" |
| 18 #include "content/common/content_export.h" | 14 #include "content/common/content_export.h" |
| 19 #include "content/common/input/input_event_ack_state.h" | 15 #include "content/common/input/input_event_ack_state.h" |
| 20 #include "third_party/WebKit/public/platform/WebInputEvent.h" | |
| 21 #include "ui/gfx/geometry/point_f.h" | |
| 22 | 16 |
| 23 namespace content { | 17 namespace content { |
| 24 | 18 |
| 25 class CoalescedWebTouchEvent; | |
| 26 | |
| 27 // Interface with which TouchEventQueue can forward touch events, and dispatch | 19 // Interface with which TouchEventQueue can forward touch events, and dispatch |
| 28 // touch event responses. | 20 // touch event responses. |
| 29 class CONTENT_EXPORT TouchEventQueueClient { | 21 class CONTENT_EXPORT TouchEventQueueClient { |
| 30 public: | 22 public: |
| 31 virtual ~TouchEventQueueClient() {} | 23 virtual ~TouchEventQueueClient() {} |
| 32 | 24 |
| 33 virtual void SendTouchEventImmediately( | 25 virtual void SendTouchEventImmediately( |
| 34 const TouchEventWithLatencyInfo& event) = 0; | 26 const TouchEventWithLatencyInfo& event) = 0; |
| 35 | 27 |
| 36 virtual void OnTouchEventAck( | 28 virtual void OnTouchEventAck( |
| 37 const TouchEventWithLatencyInfo& event, | 29 const TouchEventWithLatencyInfo& event, |
| 38 InputEventAckState ack_result) = 0; | 30 InputEventAckState ack_result) = 0; |
| 39 | 31 |
| 40 virtual void OnFilteringTouchEvent( | 32 virtual void OnFilteringTouchEvent( |
| 41 const blink::WebTouchEvent& touch_event) = 0; | 33 const blink::WebTouchEvent& touch_event) = 0; |
| 42 }; | 34 }; |
| 43 | 35 |
| 44 // A queue for throttling and coalescing touch-events. | 36 // A queue for throttling and coalescing touch-events. |
| 45 class CONTENT_EXPORT TouchEventQueue { | 37 class CONTENT_EXPORT TouchEventQueue { |
| 46 public: | 38 public: |
| 47 struct CONTENT_EXPORT Config { | 39 struct CONTENT_EXPORT Config { |
| 48 Config(); | 40 Config() |
| 41 : desktop_touch_ack_timeout_delay( |
| 42 base::TimeDelta::FromMilliseconds(200)), |
| 43 mobile_touch_ack_timeout_delay( |
| 44 base::TimeDelta::FromMilliseconds(1000)), |
| 45 touch_ack_timeout_supported(false) {} |
| 49 | 46 |
| 50 // Touch ack timeout delay for desktop sites. If zero, timeout behavior | 47 // Touch ack timeout delay for desktop sites. If zero, timeout behavior |
| 51 // is disabled for such sites. Defaults to 200ms. | 48 // is disabled for such sites. Defaults to 200ms. |
| 52 base::TimeDelta desktop_touch_ack_timeout_delay; | 49 base::TimeDelta desktop_touch_ack_timeout_delay; |
| 53 | 50 |
| 54 // Touch ack timeout delay for mobile sites. If zero, timeout behavior | 51 // Touch ack timeout delay for mobile sites. If zero, timeout behavior |
| 55 // is disabled for such sites. Defaults to 1000ms. | 52 // is disabled for such sites. Defaults to 1000ms. |
| 56 base::TimeDelta mobile_touch_ack_timeout_delay; | 53 base::TimeDelta mobile_touch_ack_timeout_delay; |
| 57 | 54 |
| 58 // Whether the platform supports touch ack timeout behavior. | 55 // Whether the platform supports touch ack timeout behavior. |
| 59 // Defaults to false (disabled). | 56 // Defaults to false (disabled). |
| 60 bool touch_ack_timeout_supported; | 57 bool touch_ack_timeout_supported; |
| 61 }; | 58 }; |
| 62 | 59 |
| 63 // The |client| must outlive the TouchEventQueue. | 60 TouchEventQueue() {} |
| 64 TouchEventQueue(TouchEventQueueClient* client, const Config& config); | |
| 65 | 61 |
| 66 ~TouchEventQueue(); | 62 virtual ~TouchEventQueue() {} |
| 67 | 63 |
| 68 // Adds an event to the queue. The event may be coalesced with previously | 64 // Adds an event to the queue. The event may be coalesced with previously |
| 69 // queued events (e.g. consecutive touch-move events can be coalesced into a | 65 // queued events (e.g. consecutive touch-move events can be coalesced into a |
| 70 // single touch-move event). The event may also be immediately forwarded to | 66 // single touch-move event). The event may also be immediately forwarded to |
| 71 // the renderer (e.g. when there are no other queued touch event). | 67 // the renderer (e.g. when there are no other queued touch event). |
| 72 void QueueEvent(const TouchEventWithLatencyInfo& event); | 68 virtual void QueueEvent(const TouchEventWithLatencyInfo& event) = 0; |
| 73 | 69 |
| 74 // Insert a TouchScrollStarted event in the queue ahead of all not-in-flight | 70 // Insert a TouchScrollStarted event in the queue ahead of all not-in-flight |
| 75 // events. | 71 // events. |
| 76 void PrependTouchScrollNotification(); | 72 virtual void PrependTouchScrollNotification() = 0; |
| 77 | 73 |
| 78 // Notifies the queue that a touch-event has been processed by the renderer. | 74 // Notifies the queue that a touch-event has been processed by the renderer. |
| 79 // At this point, if the ack is for async touchmove, remove the uncancelable | 75 // At this point, if the ack is for async touchmove, remove the uncancelable |
| 80 // touchmove from the front of the queue and decide if it should dispatch the | 76 // touchmove from the front of the queue and decide if it should dispatch the |
| 81 // next pending async touch move event, otherwise the queue may send one or | 77 // next pending async touch move event, otherwise the queue may send one or |
| 82 // more gesture events and/or additional queued touch-events to the renderer. | 78 // more gesture events and/or additional queued touch-events to the renderer. |
| 83 void ProcessTouchAck(InputEventAckState ack_result, | 79 virtual void ProcessTouchAck(InputEventAckState ack_result, |
| 84 const ui::LatencyInfo& latency_info, | 80 const ui::LatencyInfo& latency_info, |
| 85 const uint32_t unique_touch_event_id); | 81 const uint32_t unique_touch_event_id) = 0; |
| 86 | 82 |
| 87 // When GestureScrollBegin is received, we send a touch cancel to renderer, | 83 // When GestureScrollBegin is received, we send a touch cancel to renderer, |
| 88 // route all the following touch events directly to client, and ignore the | 84 // route all the following touch events directly to client, and ignore the |
| 89 // ack for the touch cancel. When Gesture{ScrollEnd,FlingStart} is received, | 85 // ack for the touch cancel. When Gesture{ScrollEnd,FlingStart} is received, |
| 90 // resume the normal flow of sending touch events to the renderer. | 86 // resume the normal flow of sending touch events to the renderer. |
| 91 void OnGestureScrollEvent(const GestureEventWithLatencyInfo& gesture_event); | 87 virtual void OnGestureScrollEvent( |
| 88 const GestureEventWithLatencyInfo& gesture_event) = 0; |
| 92 | 89 |
| 93 void OnGestureEventAck( | 90 virtual void OnGestureEventAck(const GestureEventWithLatencyInfo& event, |
| 94 const GestureEventWithLatencyInfo& event, | 91 InputEventAckState ack_result) = 0; |
| 95 InputEventAckState ack_result); | |
| 96 | 92 |
| 97 // Notifies the queue whether the renderer has at least one touch handler. | 93 // Notifies the queue whether the renderer has at least one touch handler. |
| 98 void OnHasTouchEventHandlers(bool has_handlers); | 94 virtual void OnHasTouchEventHandlers(bool has_handlers) = 0; |
| 99 | 95 |
| 100 // Returns whether the currently pending touch event (waiting ACK) is for | 96 // Returns whether the currently pending touch event (waiting ACK) is for |
| 101 // a touch start event. | 97 // a touch start event. |
| 102 bool IsPendingAckTouchStart() const; | 98 virtual bool IsPendingAckTouchStart() const = 0; |
| 103 | 99 |
| 104 // Sets whether a delayed touch ack will cancel and flush the current | 100 // Sets whether a delayed touch ack will cancel and flush the current |
| 105 // touch sequence. Note that, if the timeout was previously disabled, enabling | 101 // touch sequence. Note that, if the timeout was previously disabled, enabling |
| 106 // it will take effect only for the following touch sequence. | 102 // it will take effect only for the following touch sequence. |
| 107 void SetAckTimeoutEnabled(bool enabled); | 103 virtual void SetAckTimeoutEnabled(bool enabled) = 0; |
| 108 | 104 |
| 109 // Sets whether the current site has a mobile friendly viewport. This | 105 // Sets whether the current site has a mobile friendly viewport. This |
| 110 // determines which ack timeout delay will be used for *future* touch events. | 106 // determines which ack timeout delay will be used for *future* touch events. |
| 111 // The default assumption is that the site is *not* mobile-optimized. | 107 // The default assumption is that the site is *not* mobile-optimized. |
| 112 void SetIsMobileOptimizedSite(bool mobile_optimized_site); | 108 virtual void SetIsMobileOptimizedSite(bool mobile_optimized_site) = 0; |
| 113 | 109 |
| 114 // Whether ack timeout behavior is supported and enabled for the current site. | 110 // Whether ack timeout behavior is supported and enabled for the current site. |
| 115 bool IsAckTimeoutEnabled() const; | 111 virtual bool IsAckTimeoutEnabled() const = 0; |
| 116 | 112 |
| 117 bool empty() const WARN_UNUSED_RESULT { | 113 virtual bool Empty() const WARN_UNUSED_RESULT = 0; |
| 118 return touch_queue_.empty(); | |
| 119 } | |
| 120 | |
| 121 size_t size() const { | |
| 122 return touch_queue_.size(); | |
| 123 } | |
| 124 | |
| 125 bool has_handlers() const { return has_handlers_; } | |
| 126 | |
| 127 size_t uncancelable_touch_moves_pending_ack_count() const { | |
| 128 return ack_pending_async_touchmove_ids_.size(); | |
| 129 } | |
| 130 | 114 |
| 131 private: | 115 private: |
| 132 class TouchTimeoutHandler; | |
| 133 class TouchMoveSlopSuppressor; | |
| 134 friend class TouchTimeoutHandler; | |
| 135 friend class TouchEventQueueTest; | |
| 136 | |
| 137 bool HasPendingAsyncTouchMoveForTesting() const; | |
| 138 bool IsTimeoutRunningForTesting() const; | |
| 139 const TouchEventWithLatencyInfo& GetLatestEventForTesting() const; | |
| 140 | |
| 141 // Empties the queue of touch events. This may result in any number of gesture | |
| 142 // events being sent to the renderer. | |
| 143 void FlushQueue(); | |
| 144 | |
| 145 // Walks the queue, checking each event with |FilterBeforeForwarding()|. | |
| 146 // If allowed, forwards the touch event and stops processing further events. | |
| 147 // Otherwise, acks the event with |INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS|. | |
| 148 void TryForwardNextEventToRenderer(); | |
| 149 | |
| 150 // Forwards the event at the head of the queue to the renderer. | |
| 151 void ForwardNextEventToRenderer(); | |
| 152 | |
| 153 // Pops the touch-event from the head of the queue and acks it to the client. | |
| 154 void PopTouchEventToClient(InputEventAckState ack_result); | |
| 155 | |
| 156 // Pops the touch-event from the top of the queue and acks it to the client, | |
| 157 // updating the event with |renderer_latency_info|. | |
| 158 void PopTouchEventToClient(InputEventAckState ack_result, | |
| 159 const ui::LatencyInfo& renderer_latency_info); | |
| 160 | |
| 161 // Ack all coalesced events at the head of the queue to the client with | |
| 162 // |ack_result|, updating the acked events with |optional_latency_info| if it | |
| 163 // exists, and popping the head of the queue. | |
| 164 void AckTouchEventToClient(InputEventAckState ack_result, | |
| 165 const ui::LatencyInfo* optional_latency_info); | |
| 166 | |
| 167 // Dispatch |touch| to the client. Before dispatching, updates pointer | |
| 168 // states in touchmove events for pointers that have not changed position. | |
| 169 void SendTouchEventImmediately(TouchEventWithLatencyInfo* touch); | |
| 170 | |
| 171 enum PreFilterResult { | |
| 172 ACK_WITH_NO_CONSUMER_EXISTS, | |
| 173 ACK_WITH_NOT_CONSUMED, | |
| 174 FORWARD_TO_RENDERER, | |
| 175 }; | |
| 176 // Filter touches prior to forwarding to the renderer, e.g., if the renderer | |
| 177 // has no touch handler. | |
| 178 PreFilterResult FilterBeforeForwarding(const blink::WebTouchEvent& event); | |
| 179 void ForwardToRenderer(const TouchEventWithLatencyInfo& event); | |
| 180 void UpdateTouchConsumerStates(const blink::WebTouchEvent& event, | |
| 181 InputEventAckState ack_result); | |
| 182 void FlushPendingAsyncTouchmove(); | |
| 183 | |
| 184 // Handles touch event forwarding and ack'ed event dispatch. | |
| 185 TouchEventQueueClient* client_; | |
| 186 | |
| 187 std::list<std::unique_ptr<CoalescedWebTouchEvent>> touch_queue_; | |
| 188 | |
| 189 // Position of the first touch in the most recent sequence forwarded to the | |
| 190 // client. | |
| 191 gfx::PointF touch_sequence_start_position_; | |
| 192 | |
| 193 // Used to defer touch forwarding when ack dispatch triggers |QueueEvent()|. | |
| 194 // True within the scope of |AckTouchEventToClient()|. | |
| 195 bool dispatching_touch_ack_; | |
| 196 | |
| 197 // Used to prevent touch timeout scheduling and increase the count for async | |
| 198 // touchmove if we receive a synchronous ack after forwarding a touch event | |
| 199 // to the client. | |
| 200 bool dispatching_touch_; | |
| 201 | |
| 202 // Whether the renderer has at least one touch handler. | |
| 203 bool has_handlers_; | |
| 204 | |
| 205 // Whether any pointer in the touch sequence reported having a consumer. | |
| 206 bool has_handler_for_current_sequence_; | |
| 207 | |
| 208 // Whether to allow any remaining touches for the current sequence. Note that | |
| 209 // this is a stricter condition than an empty |touch_consumer_states_|, as it | |
| 210 // also prevents forwarding of touchstart events for new pointers in the | |
| 211 // current sequence. This is only used when the event is synthetically | |
| 212 // cancelled after a touch timeout. | |
| 213 bool drop_remaining_touches_in_sequence_; | |
| 214 | |
| 215 // Optional handler for timed-out touch event acks. | |
| 216 std::unique_ptr<TouchTimeoutHandler> timeout_handler_; | |
| 217 | |
| 218 // Suppression of TouchMove's within a slop region when a sequence has not yet | |
| 219 // been preventDefaulted. | |
| 220 std::unique_ptr<TouchMoveSlopSuppressor> touchmove_slop_suppressor_; | |
| 221 | |
| 222 // Whether touch events should remain buffered and dispatched asynchronously | |
| 223 // while a scroll sequence is active. In this mode, touchmove's are throttled | |
| 224 // and ack'ed immediately, but remain buffered in |pending_async_touchmove_| | |
| 225 // until a sufficient time period has elapsed since the last sent touch event. | |
| 226 // For details see the design doc at http://goo.gl/lVyJAa. | |
| 227 bool send_touch_events_async_; | |
| 228 std::unique_ptr<TouchEventWithLatencyInfo> pending_async_touchmove_; | |
| 229 | |
| 230 // For uncancelable touch moves, not only we send a fake ack, but also a real | |
| 231 // ack from render, which we use to decide when to send the next async | |
| 232 // touchmove. This can help avoid the touch event queue keep growing when | |
| 233 // render handles touchmove slow. We use a queue | |
| 234 // ack_pending_async_touchmove_ids to store the recent dispatched | |
| 235 // uncancelable touchmoves which are still waiting for their acks back from | |
| 236 // render. We do not put them back to the front the touch_event_queue any | |
| 237 // more. | |
| 238 std::deque<uint32_t> ack_pending_async_touchmove_ids_; | |
| 239 | |
| 240 double last_sent_touch_timestamp_sec_; | |
| 241 | |
| 242 // Event is saved to compare pointer positions for new touchmove events. | |
| 243 std::unique_ptr<blink::WebTouchEvent> last_sent_touchevent_; | |
| 244 | |
| 245 DISALLOW_COPY_AND_ASSIGN(TouchEventQueue); | 116 DISALLOW_COPY_AND_ASSIGN(TouchEventQueue); |
| 246 }; | 117 }; |
| 247 | 118 |
| 248 } // namespace content | 119 } // namespace content |
| 249 | 120 |
| 250 #endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ | 121 #endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_TOUCH_EVENT_QUEUE_H_ |
| OLD | NEW |