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/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
10 #include "content/browser/renderer_host/input/timeout_monitor.h" | 10 #include "content/browser/renderer_host/input/timeout_monitor.h" |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); | 246 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); |
247 }; | 247 }; |
248 | 248 |
249 // This class represents a single coalesced touch event. However, it also keeps | 249 // This class represents a single coalesced touch event. However, it also keeps |
250 // track of all the original touch-events that were coalesced into a single | 250 // track of all the original touch-events that were coalesced into a single |
251 // event. The coalesced event is forwarded to the renderer, while the original | 251 // event. The coalesced event is forwarded to the renderer, while the original |
252 // touch-events are sent to the Client (on ACK for the coalesced event) so that | 252 // touch-events are sent to the Client (on ACK for the coalesced event) so that |
253 // the Client receives the event with their original timestamp. | 253 // the Client receives the event with their original timestamp. |
254 class CoalescedWebTouchEvent { | 254 class CoalescedWebTouchEvent { |
255 public: | 255 public: |
256 // Events for which |async| is true will not be ack'ed to the client after the | 256 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, |
257 // corresponding ack is received following dispatch. | 257 bool suppress_client_ack) |
258 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, bool async) | 258 : coalesced_event_(event), suppress_client_ack_(suppress_client_ack) { |
259 : coalesced_event_(event) { | |
260 if (async) | |
261 coalesced_event_.event.cancelable = false; | |
262 else | |
263 events_to_ack_.push_back(event); | |
264 | |
265 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventQueue::QueueEvent", this); | 259 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventQueue::QueueEvent", this); |
266 } | 260 } |
267 | 261 |
268 ~CoalescedWebTouchEvent() { | 262 ~CoalescedWebTouchEvent() { |
269 TRACE_EVENT_ASYNC_END0("input", "TouchEventQueue::QueueEvent", this); | 263 TRACE_EVENT_ASYNC_END0("input", "TouchEventQueue::QueueEvent", this); |
270 } | 264 } |
271 | 265 |
272 // Coalesces the event with the existing event if possible. Returns whether | 266 // Coalesces the event with the existing event if possible. Returns whether |
273 // the event was coalesced. | 267 // the event was coalesced. |
274 bool CoalesceEventIfPossible( | 268 bool CoalesceEventIfPossible( |
275 const TouchEventWithLatencyInfo& event_with_latency) { | 269 const TouchEventWithLatencyInfo& event_with_latency) { |
276 if (!WillDispatchAckToClient()) | 270 if (suppress_client_ack_) |
277 return false; | 271 return false; |
278 | 272 |
279 if (!coalesced_event_.CanCoalesceWith(event_with_latency)) | 273 if (!coalesced_event_.CanCoalesceWith(event_with_latency)) |
280 return false; | 274 return false; |
281 | 275 |
| 276 // Addition of the first event to |uncoaleseced_events_to_ack_| is deferred |
| 277 // until the first coalesced event, optimizing the (common) case where the |
| 278 // event is not coalesced at all. |
| 279 if (uncoaleseced_events_to_ack_.empty()) |
| 280 uncoaleseced_events_to_ack_.push_back(coalesced_event_); |
| 281 |
282 TRACE_EVENT_INSTANT0( | 282 TRACE_EVENT_INSTANT0( |
283 "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD); | 283 "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD); |
284 coalesced_event_.CoalesceWith(event_with_latency); | 284 coalesced_event_.CoalesceWith(event_with_latency); |
285 events_to_ack_.push_back(event_with_latency); | 285 uncoaleseced_events_to_ack_.push_back(event_with_latency); |
| 286 DCHECK_GE(uncoaleseced_events_to_ack_.size(), 2U); |
286 return true; | 287 return true; |
287 } | 288 } |
288 | 289 |
289 void UpdateLatencyInfoForAck(const ui::LatencyInfo& renderer_latency_info) { | 290 void DispatchAckToClient(InputEventAckState ack_result, |
290 if (!WillDispatchAckToClient()) | 291 const ui::LatencyInfo* optional_latency_info, |
| 292 TouchEventQueueClient* client) { |
| 293 DCHECK(client); |
| 294 if (suppress_client_ack_) |
291 return; | 295 return; |
292 | 296 |
293 for (WebTouchEventWithLatencyList::iterator iter = events_to_ack_.begin(), | 297 if (uncoaleseced_events_to_ack_.empty()) { |
294 end = events_to_ack_.end(); | 298 if (optional_latency_info) |
| 299 coalesced_event_.latency.AddNewLatencyFrom(*optional_latency_info); |
| 300 client->OnTouchEventAck(coalesced_event_, ack_result); |
| 301 return; |
| 302 } |
| 303 |
| 304 DCHECK_GE(uncoaleseced_events_to_ack_.size(), 2U); |
| 305 for (WebTouchEventWithLatencyList::iterator |
| 306 iter = uncoaleseced_events_to_ack_.begin(), |
| 307 end = uncoaleseced_events_to_ack_.end(); |
295 iter != end; | 308 iter != end; |
296 ++iter) { | 309 ++iter) { |
297 iter->latency.AddNewLatencyFrom(renderer_latency_info); | 310 if (optional_latency_info) |
298 } | 311 iter->latency.AddNewLatencyFrom(*optional_latency_info); |
299 } | |
300 | |
301 void DispatchAckToClient(InputEventAckState ack_result, | |
302 TouchEventQueueClient* client) { | |
303 DCHECK(client); | |
304 if (!WillDispatchAckToClient()) | |
305 return; | |
306 | |
307 for (WebTouchEventWithLatencyList::const_iterator | |
308 iter = events_to_ack_.begin(), | |
309 end = events_to_ack_.end(); | |
310 iter != end; | |
311 ++iter) { | |
312 client->OnTouchEventAck(*iter, ack_result); | 312 client->OnTouchEventAck(*iter, ack_result); |
313 } | 313 } |
314 } | 314 } |
315 | 315 |
316 const TouchEventWithLatencyInfo& coalesced_event() const { | 316 const TouchEventWithLatencyInfo& coalesced_event() const { |
317 return coalesced_event_; | 317 return coalesced_event_; |
318 } | 318 } |
319 | 319 |
320 private: | 320 private: |
321 bool WillDispatchAckToClient() const { return !events_to_ack_.empty(); } | |
322 | |
323 // This is the event that is forwarded to the renderer. | 321 // This is the event that is forwarded to the renderer. |
324 TouchEventWithLatencyInfo coalesced_event_; | 322 TouchEventWithLatencyInfo coalesced_event_; |
325 | 323 |
326 // This is the list of the original events that were coalesced, each requiring | 324 // This is the list of the original events that were coalesced, each requiring |
327 // future ack dispatch to the client. | 325 // future ack dispatch to the client. |
| 326 // Note that this will be empty if no coalescing has occurred. |
328 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 327 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
329 WebTouchEventWithLatencyList events_to_ack_; | 328 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; |
| 329 |
| 330 bool suppress_client_ack_; |
330 | 331 |
331 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); | 332 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
332 }; | 333 }; |
333 | 334 |
334 TouchEventQueue::Config::Config() | 335 TouchEventQueue::Config::Config() |
335 : touchmove_slop_suppression_length_dips(0), | 336 : touchmove_slop_suppression_length_dips(0), |
336 touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), | 337 touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), |
337 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), | 338 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), |
338 touch_ack_timeout_supported(false) { | 339 touch_ack_timeout_supported(false) { |
339 } | 340 } |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 DCHECK(!dispatching_touch_ack_); | 689 DCHECK(!dispatching_touch_ack_); |
689 DCHECK(!dispatching_touch_); | 690 DCHECK(!dispatching_touch_); |
690 pending_async_touchmove_.reset(); | 691 pending_async_touchmove_.reset(); |
691 if (touch_filtering_state_ != DROP_ALL_TOUCHES) | 692 if (touch_filtering_state_ != DROP_ALL_TOUCHES) |
692 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; | 693 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; |
693 while (!touch_queue_.empty()) | 694 while (!touch_queue_.empty()) |
694 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); | 695 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); |
695 } | 696 } |
696 | 697 |
697 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) { | 698 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) { |
698 AckTouchEventToClient(ack_result, PopTouchEvent()); | 699 AckTouchEventToClient(ack_result, PopTouchEvent(), NULL); |
699 } | 700 } |
700 | 701 |
701 void TouchEventQueue::PopTouchEventToClient( | 702 void TouchEventQueue::PopTouchEventToClient( |
702 InputEventAckState ack_result, | 703 InputEventAckState ack_result, |
703 const LatencyInfo& renderer_latency_info) { | 704 const LatencyInfo& renderer_latency_info) { |
704 scoped_ptr<CoalescedWebTouchEvent> acked_event = PopTouchEvent(); | 705 AckTouchEventToClient(ack_result, PopTouchEvent(), &renderer_latency_info); |
705 acked_event->UpdateLatencyInfoForAck(renderer_latency_info); | |
706 AckTouchEventToClient(ack_result, acked_event.Pass()); | |
707 } | 706 } |
708 | 707 |
709 void TouchEventQueue::AckTouchEventToClient( | 708 void TouchEventQueue::AckTouchEventToClient( |
710 InputEventAckState ack_result, | 709 InputEventAckState ack_result, |
711 scoped_ptr<CoalescedWebTouchEvent> acked_event) { | 710 scoped_ptr<CoalescedWebTouchEvent> acked_event, |
| 711 const ui::LatencyInfo* optional_latency_info) { |
712 DCHECK(acked_event); | 712 DCHECK(acked_event); |
713 DCHECK(!dispatching_touch_ack_); | 713 DCHECK(!dispatching_touch_ack_); |
714 UpdateTouchAckStates(acked_event->coalesced_event().event, ack_result); | 714 UpdateTouchAckStates(acked_event->coalesced_event().event, ack_result); |
715 | 715 |
716 // Note that acking the touch-event may result in multiple gestures being sent | 716 // Note that acking the touch-event may result in multiple gestures being sent |
717 // to the renderer, or touch-events being queued. | 717 // to the renderer, or touch-events being queued. |
718 base::AutoReset<const CoalescedWebTouchEvent*> dispatching_touch_ack( | 718 base::AutoReset<const CoalescedWebTouchEvent*> dispatching_touch_ack( |
719 &dispatching_touch_ack_, acked_event.get()); | 719 &dispatching_touch_ack_, acked_event.get()); |
720 acked_event->DispatchAckToClient(ack_result, client_); | 720 acked_event->DispatchAckToClient(ack_result, optional_latency_info, client_); |
721 } | 721 } |
722 | 722 |
723 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { | 723 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { |
724 DCHECK(!touch_queue_.empty()); | 724 DCHECK(!touch_queue_.empty()); |
725 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); | 725 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); |
726 touch_queue_.pop_front(); | 726 touch_queue_.pop_front(); |
727 return event.Pass(); | 727 return event.Pass(); |
728 } | 728 } |
729 | 729 |
730 void TouchEventQueue::SendTouchEventImmediately( | 730 void TouchEventQueue::SendTouchEventImmediately( |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
815 iter != end; | 815 iter != end; |
816 ++iter) { | 816 ++iter) { |
817 if (iter->second != ack_state) | 817 if (iter->second != ack_state) |
818 return false; | 818 return false; |
819 } | 819 } |
820 | 820 |
821 return true; | 821 return true; |
822 } | 822 } |
823 | 823 |
824 } // namespace content | 824 } // namespace content |
OLD | NEW |