Chromium Code Reviews| 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 #include "content/browser/renderer_host/input/touch_event_queue.h" | 5 #include "content/browser/renderer_host/input/touch_event_queue.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/command_line.h" | |
| 8 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 9 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 11 #include "content/browser/renderer_host/input/timeout_monitor.h" | |
| 12 #include "content/common/input/web_input_event_traits.h" | |
| 13 #include "content/public/common/content_switches.h" | |
| 14 | |
| 15 using blink::WebInputEvent; | |
| 16 using blink::WebTouchEvent; | |
| 17 using blink::WebTouchPoint; | |
| 10 | 18 |
| 11 namespace content { | 19 namespace content { |
| 20 namespace { | |
| 21 | |
| 22 const InputEventAckState kDefaultNotForwardedAck = | |
| 23 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; | |
| 12 | 24 |
| 13 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 25 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| 26 typedef std::map<int, InputEventAckState> AckStates; | |
| 27 | |
| 28 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( | |
| 29 const TouchEventWithLatencyInfo& event_to_cancel) { | |
| 30 TouchEventWithLatencyInfo event = event_to_cancel; | |
| 31 event.event.type = WebInputEvent::TouchCancel; | |
| 32 for (size_t i = 0; i < event.event.touchesLength; i++) | |
| 33 event.event.touches[i].state = WebTouchPoint::StateCancelled; | |
| 34 return event; | |
| 35 } | |
| 36 | |
| 37 } // namespace | |
| 38 | |
| 39 class TouchEventQueue::TouchTimeoutHandler { | |
| 40 public: | |
| 41 TouchTimeoutHandler(TouchEventQueue* touch_queue, size_t timeout_delay_ms) | |
| 42 : touch_queue_(touch_queue), | |
| 43 timeout_delay_(base::TimeDelta::FromMilliseconds(timeout_delay_ms)), | |
| 44 pending_ack_state_(PENDING_ACK_NONE), | |
| 45 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut, | |
| 46 base::Unretained(this))) {} | |
| 47 | |
| 48 ~TouchTimeoutHandler() {} | |
| 49 | |
| 50 void Start(const TouchEventWithLatencyInfo& event) { | |
| 51 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); | |
| 52 timeout_event_ = event; | |
| 53 timeout_monitor_.Restart(timeout_delay_); | |
| 54 } | |
| 55 | |
| 56 bool ConfirmTouchEvent() { | |
| 57 switch (pending_ack_state_) { | |
| 58 case PENDING_ACK_NONE: | |
| 59 timeout_monitor_.Stop(); | |
| 60 return false; | |
| 61 case PENDING_ACK_ORIGINAL_EVENT: | |
|
Xianzhu
2013/12/05 17:48:40
In original Java method, because we can only have
jdduke (slow)
2013/12/05 18:26:04
The restriction is important only when we care abo
Xianzhu
2013/12/05 18:30:18
Then pending_ack_state_ could be pending_ack_count
| |
| 62 DCHECK(!timeout_monitor_.IsRunning()); | |
| 63 DCHECK(touch_queue_->empty()); | |
| 64 TRACE_EVENT_ASYNC_STEP_INTO0( | |
| 65 "input", "TouchEventQueue::TouchEventTimeout", this, "CancelEvent"); | |
| 66 pending_ack_state_ = PENDING_ACK_CANCEL_EVENT; | |
| 67 return true; | |
| 68 case PENDING_ACK_CANCEL_EVENT: | |
| 69 DCHECK(!timeout_monitor_.IsRunning()); | |
| 70 DCHECK(touch_queue_->empty()); | |
| 71 TRACE_EVENT_ASYNC_BEGIN0( | |
|
Xianzhu
2013/12/05 17:48:40
TRACE_EVENT_ASYNC_END0?
jdduke (slow)
2013/12/05 18:26:04
Good catch, fixed.
| |
| 72 "input", "TouchEventQueue::TouchEventTimeout", this); | |
| 73 pending_ack_state_ = PENDING_ACK_NONE; | |
| 74 return true; | |
| 75 } | |
| 76 return false; | |
| 77 } | |
| 78 | |
| 79 bool HasTimeoutEvent() const { | |
| 80 return pending_ack_state_ != PENDING_ACK_NONE; | |
| 81 } | |
| 82 | |
| 83 bool IsTimeoutTimerRunning() const { | |
| 84 return timeout_monitor_.IsRunning(); | |
| 85 } | |
| 86 | |
| 87 private: | |
| 88 void OnTimeOut() { | |
| 89 TRACE_EVENT_ASYNC_BEGIN0( | |
| 90 "input", "TouchEventQueue::TouchEventTimeout", this); | |
| 91 pending_ack_state_ = PENDING_ACK_ORIGINAL_EVENT; | |
| 92 touch_queue_->FlushQueue(); | |
| 93 DCHECK(touch_queue_->empty()); | |
| 94 | |
| 95 TouchEventWithLatencyInfo cancel_event = | |
| 96 ObtainCancelEventForTouchEvent(timeout_event_); | |
| 97 touch_queue_->UpdateTouchAckStates( | |
| 98 cancel_event.event, kDefaultNotForwardedAck); | |
| 99 touch_queue_->client_->SendTouchEventImmediately(cancel_event); | |
| 100 } | |
| 101 | |
| 102 | |
| 103 TouchEventQueue* touch_queue_; | |
| 104 | |
| 105 // How long to wait on a touch ack before cancelling the touch sequence. | |
| 106 base::TimeDelta timeout_delay_; | |
| 107 | |
| 108 // The touch event source for which we expect the next ack. | |
| 109 enum PendingAckState { | |
| 110 PENDING_ACK_NONE, | |
| 111 PENDING_ACK_ORIGINAL_EVENT, | |
| 112 PENDING_ACK_CANCEL_EVENT, | |
| 113 }; | |
| 114 PendingAckState pending_ack_state_; | |
| 115 | |
| 116 // The event for which the ack timeout is triggered. | |
| 117 TouchEventWithLatencyInfo timeout_event_; | |
| 118 | |
| 119 // Provides timeout-based callback behavior. | |
| 120 TimeoutMonitor timeout_monitor_; | |
| 121 }; | |
| 122 | |
| 14 | 123 |
| 15 // This class represents a single coalesced touch event. However, it also keeps | 124 // This class represents a single coalesced touch event. However, it also keeps |
| 16 // track of all the original touch-events that were coalesced into a single | 125 // track of all the original touch-events that were coalesced into a single |
| 17 // event. The coalesced event is forwarded to the renderer, while the original | 126 // event. The coalesced event is forwarded to the renderer, while the original |
| 18 // touch-events are sent to the Client (on ACK for the coalesced event) so that | 127 // touch-events are sent to the Client (on ACK for the coalesced event) so that |
| 19 // the Client receives the event with their original timestamp. | 128 // the Client receives the event with their original timestamp. |
| 20 class CoalescedWebTouchEvent { | 129 class CoalescedWebTouchEvent { |
| 21 public: | 130 public: |
| 22 explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event) | 131 explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, |
| 132 bool ignore_ack) | |
| 23 : coalesced_event_(event), | 133 : coalesced_event_(event), |
| 24 ignore_ack_(false) { | 134 ignore_ack_(ignore_ack) { |
| 25 events_.push_back(event); | 135 events_.push_back(event); |
| 26 TRACE_EVENT_ASYNC_BEGIN0( | 136 TRACE_EVENT_ASYNC_BEGIN0( |
| 27 "input", "TouchEventQueue::QueueEvent", this); | 137 "input", "TouchEventQueue::QueueEvent", this); |
| 28 } | 138 } |
| 29 | 139 |
| 30 ~CoalescedWebTouchEvent() { | 140 ~CoalescedWebTouchEvent() { |
| 31 TRACE_EVENT_ASYNC_END0( | 141 TRACE_EVENT_ASYNC_END0( |
| 32 "input", "TouchEventQueue::QueueEvent", this); | 142 "input", "TouchEventQueue::QueueEvent", this); |
| 33 } | 143 } |
| 34 | 144 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 57 return events_.begin(); | 167 return events_.begin(); |
| 58 } | 168 } |
| 59 | 169 |
| 60 WebTouchEventWithLatencyList::iterator end() { | 170 WebTouchEventWithLatencyList::iterator end() { |
| 61 return events_.end(); | 171 return events_.end(); |
| 62 } | 172 } |
| 63 | 173 |
| 64 size_t size() const { return events_.size(); } | 174 size_t size() const { return events_.size(); } |
| 65 | 175 |
| 66 bool ignore_ack() const { return ignore_ack_; } | 176 bool ignore_ack() const { return ignore_ack_; } |
| 67 void set_ignore_ack(bool value) { ignore_ack_ = value; } | |
| 68 | 177 |
| 69 private: | 178 private: |
| 70 // This is the event that is forwarded to the renderer. | 179 // This is the event that is forwarded to the renderer. |
| 71 TouchEventWithLatencyInfo coalesced_event_; | 180 TouchEventWithLatencyInfo coalesced_event_; |
| 72 | 181 |
| 73 // This is the list of the original events that were coalesced. | 182 // This is the list of the original events that were coalesced. |
| 74 WebTouchEventWithLatencyList events_; | 183 WebTouchEventWithLatencyList events_; |
| 75 | 184 |
| 76 // If |ignore_ack_| is true, don't send this touch event to client | 185 // If |ignore_ack_| is true, don't send this touch event to client |
| 77 // when the event is acked. | 186 // when the event is acked. |
| 78 bool ignore_ack_; | 187 bool ignore_ack_; |
| 79 | 188 |
| 80 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); | 189 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
| 81 }; | 190 }; |
| 82 | 191 |
| 83 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) | 192 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) |
| 84 : client_(client), | 193 : client_(client), |
| 85 dispatching_touch_ack_(NULL), | 194 dispatching_touch_ack_(NULL), |
| 86 no_touch_to_renderer_(false) { | 195 dispatching_touch_(false), |
| 196 no_touch_to_renderer_(false), | |
| 197 renderer_is_consuming_gesture_(false), | |
| 198 ack_timeout_enabled_(false) { | |
| 87 DCHECK(client); | 199 DCHECK(client); |
| 88 } | 200 } |
| 89 | 201 |
| 90 TouchEventQueue::~TouchEventQueue() { | 202 TouchEventQueue::~TouchEventQueue() { |
| 91 if (!touch_queue_.empty()) | 203 if (!touch_queue_.empty()) |
| 92 STLDeleteElements(&touch_queue_); | 204 STLDeleteElements(&touch_queue_); |
| 93 } | 205 } |
| 94 | 206 |
| 95 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { | 207 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { |
| 96 // If the queueing of |event| was triggered by an ack dispatch, defer | 208 // If the queueing of |event| was triggered by an ack dispatch, defer |
| 97 // processing the event until the dispatch has finished. | 209 // processing the event until the dispatch has finished. |
| 98 if (touch_queue_.empty() && !dispatching_touch_ack_) { | 210 if (touch_queue_.empty() && !dispatching_touch_ack_) { |
| 99 // There is no touch event in the queue. Forward it to the renderer | 211 // There is no touch event in the queue. Forward it to the renderer |
| 100 // immediately. | 212 // immediately. |
| 101 touch_queue_.push_back(new CoalescedWebTouchEvent(event)); | 213 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); |
| 102 TryForwardNextEventToRenderer(); | 214 TryForwardNextEventToRenderer(); |
| 103 return; | 215 return; |
| 104 } | 216 } |
| 105 | 217 |
| 106 // If the last queued touch-event was a touch-move, and the current event is | 218 // If the last queued touch-event was a touch-move, and the current event is |
| 107 // also a touch-move, then the events can be coalesced into a single event. | 219 // also a touch-move, then the events can be coalesced into a single event. |
| 108 if (touch_queue_.size() > 1) { | 220 if (touch_queue_.size() > 1) { |
| 109 CoalescedWebTouchEvent* last_event = touch_queue_.back(); | 221 CoalescedWebTouchEvent* last_event = touch_queue_.back(); |
| 110 if (last_event->CoalesceEventIfPossible(event)) | 222 if (last_event->CoalesceEventIfPossible(event)) |
| 111 return; | 223 return; |
| 112 } | 224 } |
| 113 touch_queue_.push_back(new CoalescedWebTouchEvent(event)); | 225 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); |
| 114 } | 226 } |
| 115 | 227 |
| 116 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, | 228 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, |
| 117 const ui::LatencyInfo& latency_info) { | 229 const ui::LatencyInfo& latency_info) { |
| 118 DCHECK(!dispatching_touch_ack_); | 230 DCHECK(!dispatching_touch_ack_); |
| 231 dispatching_touch_ = false; | |
| 232 | |
| 233 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent()) | |
| 234 return; | |
| 235 | |
| 119 if (touch_queue_.empty()) | 236 if (touch_queue_.empty()) |
| 120 return; | 237 return; |
| 121 | 238 |
| 122 // Update the ACK status for each touch point in the ACKed event. | 239 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 123 const blink::WebTouchEvent& event = | 240 renderer_is_consuming_gesture_ = true; |
| 241 | |
| 242 const WebTouchEvent& acked_event = | |
| 124 touch_queue_.front()->coalesced_event().event; | 243 touch_queue_.front()->coalesced_event().event; |
| 125 if (event.type == blink::WebInputEvent::TouchEnd || | 244 UpdateTouchAckStates(acked_event, ack_result); |
| 126 event.type == blink::WebInputEvent::TouchCancel) { | |
| 127 // The points have been released. Erase the ACK states. | |
| 128 for (unsigned i = 0; i < event.touchesLength; ++i) { | |
| 129 const blink::WebTouchPoint& point = event.touches[i]; | |
| 130 if (point.state == blink::WebTouchPoint::StateReleased || | |
| 131 point.state == blink::WebTouchPoint::StateCancelled) | |
| 132 touch_ack_states_.erase(point.id); | |
| 133 } | |
| 134 } else if (event.type == blink::WebInputEvent::TouchStart) { | |
| 135 for (unsigned i = 0; i < event.touchesLength; ++i) { | |
| 136 const blink::WebTouchPoint& point = event.touches[i]; | |
| 137 if (point.state == blink::WebTouchPoint::StatePressed) | |
| 138 touch_ack_states_[point.id] = ack_result; | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 PopTouchEventToClient(ack_result, latency_info); | 245 PopTouchEventToClient(ack_result, latency_info); |
| 143 TryForwardNextEventToRenderer(); | 246 TryForwardNextEventToRenderer(); |
| 144 } | 247 } |
| 145 | 248 |
| 146 void TouchEventQueue::TryForwardNextEventToRenderer() { | 249 void TouchEventQueue::TryForwardNextEventToRenderer() { |
| 147 DCHECK(!dispatching_touch_ack_); | 250 DCHECK(!dispatching_touch_ack_); |
| 148 // If there are queued touch events, then try to forward them to the renderer | 251 // If there are queued touch events, then try to forward them to the renderer |
| 149 // immediately, or ACK the events back to the client if appropriate. | 252 // immediately, or ACK the events back to the client if appropriate. |
| 150 while (!touch_queue_.empty()) { | 253 while (!touch_queue_.empty()) { |
| 151 const TouchEventWithLatencyInfo& touch = | 254 const TouchEventWithLatencyInfo& touch = |
| 152 touch_queue_.front()->coalesced_event(); | 255 touch_queue_.front()->coalesced_event(); |
| 256 if (touch.event.type == WebInputEvent::TouchStart) | |
| 257 renderer_is_consuming_gesture_ = false; | |
| 153 if (ShouldForwardToRenderer(touch.event)) { | 258 if (ShouldForwardToRenderer(touch.event)) { |
| 154 client_->SendTouchEventImmediately(touch); | 259 ForwardToRenderer(touch); |
| 155 break; | 260 break; |
| 156 } | 261 } |
| 157 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, | 262 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); |
| 158 ui::LatencyInfo()); | |
| 159 } | 263 } |
| 160 } | 264 } |
| 161 | 265 |
| 266 void TouchEventQueue::ForwardToRenderer( | |
| 267 const TouchEventWithLatencyInfo& touch) { | |
| 268 DCHECK(!dispatching_touch_); | |
| 269 // A synchronous ack will reset |dispatching_touch_|, in which case | |
| 270 // the touch timeout should not be started. | |
| 271 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | |
| 272 client_->SendTouchEventImmediately(touch); | |
| 273 if (ack_timeout_enabled_ && | |
| 274 dispatching_touch_ && | |
| 275 !renderer_is_consuming_gesture_ && | |
| 276 (touch.event.type == WebInputEvent::TouchStart || | |
| 277 touch.event.type == WebInputEvent::TouchMove)) { | |
| 278 DCHECK(timeout_handler_); | |
| 279 timeout_handler_->Start(touch); | |
| 280 } | |
| 281 } | |
| 282 | |
| 162 void TouchEventQueue::OnGestureScrollEvent( | 283 void TouchEventQueue::OnGestureScrollEvent( |
| 163 const GestureEventWithLatencyInfo& gesture_event) { | 284 const GestureEventWithLatencyInfo& gesture_event) { |
| 164 blink::WebInputEvent::Type type = gesture_event.event.type; | 285 blink::WebInputEvent::Type type = gesture_event.event.type; |
| 165 if (type == blink::WebInputEvent::GestureScrollBegin) { | 286 if (type == blink::WebInputEvent::GestureScrollBegin) { |
| 166 // We assume the scroll event are generated synchronously from | 287 // We assume the scroll event are generated synchronously from |
| 167 // dispatching a touch event ack, so that we can fake a cancel | 288 // dispatching a touch event ack, so that we can fake a cancel |
| 168 // event that has the correct touch ids as the touch event that | 289 // event that has the correct touch ids as the touch event that |
| 169 // is being acked. If not, we don't do the touch-cancel optimization. | 290 // is being acked. If not, we don't do the touch-cancel optimization. |
| 170 if (no_touch_to_renderer_ || !dispatching_touch_ack_) | 291 if (no_touch_to_renderer_ || !dispatching_touch_ack_) |
| 171 return; | 292 return; |
| 172 no_touch_to_renderer_ = true; | 293 no_touch_to_renderer_ = true; |
| 294 | |
| 295 // If we have a timeout event, a cancel has already been dispatched | |
| 296 // for the current touch stream. | |
| 297 if (HasTimeoutEvent()) | |
| 298 return; | |
| 299 | |
| 173 // Fake a TouchCancel to cancel the touch points of the touch event | 300 // Fake a TouchCancel to cancel the touch points of the touch event |
| 174 // that is currently being acked. | 301 // that is currently being acked. |
| 175 TouchEventWithLatencyInfo cancel_event = | 302 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we |
| 176 dispatching_touch_ack_->coalesced_event(); | |
| 177 cancel_event.event.type = blink::WebInputEvent::TouchCancel; | |
| 178 for (size_t i = 0; i < cancel_event.event.touchesLength; i++) | |
| 179 cancel_event.event.touches[i].state = | |
| 180 blink::WebTouchPoint::StateCancelled; | |
| 181 CoalescedWebTouchEvent* coalesced_cancel_event = | |
| 182 new CoalescedWebTouchEvent(cancel_event); | |
| 183 // Ignore the ack of the touch cancel so when it is acked, it won't get | |
| 184 // sent to gesture recognizer. | |
| 185 coalesced_cancel_event->set_ignore_ack(true); | |
| 186 // |dispatching_touch_ack_| is non-null when we reach here, meaning we | |
| 187 // are in the scope of PopTouchEventToClient() and that no touch event | 303 // are in the scope of PopTouchEventToClient() and that no touch event |
| 188 // in the queue is waiting for ack from renderer. So we can just insert | 304 // in the queue is waiting for ack from renderer. So we can just insert |
| 189 // the touch cancel at the beginning of the queue. | 305 // the touch cancel at the beginning of the queue. |
| 190 touch_queue_.push_front(coalesced_cancel_event); | 306 touch_queue_.push_front(new CoalescedWebTouchEvent( |
| 307 ObtainCancelEventForTouchEvent( | |
| 308 dispatching_touch_ack_->coalesced_event()), | |
| 309 true)); | |
| 191 } else if (type == blink::WebInputEvent::GestureScrollEnd || | 310 } else if (type == blink::WebInputEvent::GestureScrollEnd || |
| 192 type == blink::WebInputEvent::GestureFlingStart) { | 311 type == blink::WebInputEvent::GestureFlingStart) { |
| 193 no_touch_to_renderer_ = false; | 312 no_touch_to_renderer_ = false; |
| 194 } | 313 } |
| 195 } | 314 } |
| 196 | 315 |
| 197 void TouchEventQueue::FlushQueue() { | 316 void TouchEventQueue::FlushQueue() { |
| 198 DCHECK(!dispatching_touch_ack_); | 317 DCHECK(!dispatching_touch_ack_); |
| 318 DCHECK(!dispatching_touch_); | |
| 199 while (!touch_queue_.empty()) | 319 while (!touch_queue_.empty()) |
| 200 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, | 320 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); |
| 201 ui::LatencyInfo()); | |
| 202 } | 321 } |
| 203 | 322 |
| 204 size_t TouchEventQueue::GetQueueSize() const { | 323 void TouchEventQueue::SetAckTimeoutEnabled(bool enabled, |
| 205 return touch_queue_.size(); | 324 size_t ack_timeout_delay_ms) { |
| 325 if (!enabled) { | |
| 326 // Avoid resetting |timeout_handler_|, as an outstanding timeout may | |
| 327 // be active and must be completed for ack handling consistency. | |
| 328 ack_timeout_enabled_ = false; | |
| 329 return; | |
| 330 } | |
| 331 | |
| 332 ack_timeout_enabled_ = true; | |
| 333 if (!timeout_handler_) | |
| 334 timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay_ms)); | |
| 206 } | 335 } |
| 207 | 336 |
| 208 const TouchEventWithLatencyInfo& TouchEventQueue::GetLatestEvent() const { | 337 bool TouchEventQueue::HasTimeoutEvent() const { |
| 338 return timeout_handler_ && timeout_handler_->HasTimeoutEvent(); | |
| 339 } | |
| 340 | |
| 341 bool TouchEventQueue::IsTimeoutRunningForTesting() const { | |
| 342 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); | |
| 343 } | |
| 344 | |
| 345 const TouchEventWithLatencyInfo& | |
| 346 TouchEventQueue::GetLatestEventForTesting() const { | |
| 209 return touch_queue_.back()->coalesced_event(); | 347 return touch_queue_.back()->coalesced_event(); |
| 210 } | 348 } |
| 211 | 349 |
| 212 void TouchEventQueue::PopTouchEventToClient( | 350 void TouchEventQueue::PopTouchEventToClient( |
| 213 InputEventAckState ack_result, | 351 InputEventAckState ack_result, |
| 214 const ui::LatencyInfo& renderer_latency_info) { | 352 const ui::LatencyInfo& renderer_latency_info) { |
| 353 DCHECK(!dispatching_touch_ack_); | |
| 215 if (touch_queue_.empty()) | 354 if (touch_queue_.empty()) |
| 216 return; | 355 return; |
| 217 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); | 356 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); |
| 218 touch_queue_.pop_front(); | 357 touch_queue_.pop_front(); |
| 219 | 358 |
| 220 if (acked_event->ignore_ack()) | 359 if (acked_event->ignore_ack()) |
| 221 return; | 360 return; |
| 222 | 361 |
| 223 // Note that acking the touch-event may result in multiple gestures being sent | 362 // Note that acking the touch-event may result in multiple gestures being sent |
| 224 // to the renderer, or touch-events being queued. | 363 // to the renderer, or touch-events being queued. |
| 225 base::AutoReset<CoalescedWebTouchEvent*> | 364 base::AutoReset<CoalescedWebTouchEvent*> |
| 226 dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get()); | 365 dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get()); |
| 227 | 366 |
| 228 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(), | 367 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(), |
| 229 end = acked_event->end(); | 368 end = acked_event->end(); |
| 230 iter != end; ++iter) { | 369 iter != end; ++iter) { |
| 231 iter->latency.AddNewLatencyFrom(renderer_latency_info); | 370 iter->latency.AddNewLatencyFrom(renderer_latency_info); |
| 232 client_->OnTouchEventAck((*iter), ack_result); | 371 client_->OnTouchEventAck((*iter), ack_result); |
| 233 } | 372 } |
| 234 } | 373 } |
| 235 | 374 |
| 236 bool TouchEventQueue::ShouldForwardToRenderer( | 375 bool TouchEventQueue::ShouldForwardToRenderer( |
| 237 const blink::WebTouchEvent& event) const { | 376 const WebTouchEvent& event) const { |
| 377 if (HasTimeoutEvent()) | |
| 378 return false; | |
| 379 | |
| 238 if (no_touch_to_renderer_ && | 380 if (no_touch_to_renderer_ && |
| 239 event.type != blink::WebInputEvent::TouchCancel) | 381 event.type != blink::WebInputEvent::TouchCancel) |
| 240 return false; | 382 return false; |
| 241 | 383 |
| 242 // Touch press events should always be forwarded to the renderer. | 384 // Touch press events should always be forwarded to the renderer. |
| 243 if (event.type == blink::WebInputEvent::TouchStart) | 385 if (event.type == WebInputEvent::TouchStart) |
| 244 return true; | 386 return true; |
| 245 | 387 |
| 246 for (unsigned int i = 0; i < event.touchesLength; ++i) { | 388 for (unsigned int i = 0; i < event.touchesLength; ++i) { |
| 247 const blink::WebTouchPoint& point = event.touches[i]; | 389 const WebTouchPoint& point = event.touches[i]; |
| 248 // If a point has been stationary, then don't take it into account. | 390 // If a point has been stationary, then don't take it into account. |
| 249 if (point.state == blink::WebTouchPoint::StateStationary) | 391 if (point.state == WebTouchPoint::StateStationary) |
| 250 continue; | 392 continue; |
| 251 | 393 |
| 252 if (touch_ack_states_.count(point.id) > 0) { | 394 if (touch_ack_states_.count(point.id) > 0) { |
| 253 if (touch_ack_states_.find(point.id)->second != | 395 if (touch_ack_states_.find(point.id)->second != |
| 254 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 396 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 255 return true; | 397 return true; |
| 256 } else { | 398 } else { |
| 257 // If the ACK status of a point is unknown, then the event should be | 399 // If the ACK status of a point is unknown, then the event should be |
| 258 // forwarded to the renderer. | 400 // forwarded to the renderer. |
| 259 return true; | 401 return true; |
| 260 } | 402 } |
| 261 } | 403 } |
| 262 | 404 |
| 263 return false; | 405 return false; |
| 264 } | 406 } |
| 265 | 407 |
| 408 void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event, | |
| 409 InputEventAckState ack_result) { | |
| 410 // Update the ACK status for each touch point in the ACKed event. | |
| 411 if (event.type == WebInputEvent::TouchEnd || | |
| 412 event.type == WebInputEvent::TouchCancel) { | |
| 413 // The points have been released. Erase the ACK states. | |
| 414 for (unsigned i = 0; i < event.touchesLength; ++i) { | |
| 415 const WebTouchPoint& point = event.touches[i]; | |
| 416 if (point.state == WebTouchPoint::StateReleased || | |
| 417 point.state == WebTouchPoint::StateCancelled) | |
| 418 touch_ack_states_.erase(point.id); | |
| 419 } | |
| 420 } else if (event.type == WebInputEvent::TouchStart) { | |
| 421 for (unsigned i = 0; i < event.touchesLength; ++i) { | |
| 422 const WebTouchPoint& point = event.touches[i]; | |
| 423 if (point.state == WebTouchPoint::StatePressed) | |
| 424 touch_ack_states_[point.id] = ack_result; | |
| 425 } | |
| 426 } | |
| 427 } | |
| 428 | |
| 266 } // namespace content | 429 } // namespace content |
| OLD | NEW |