Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(276)

Side by Side Diff: content/browser/renderer_host/input/touch_event_queue.cc

Issue 565033002: Avoid heap allocation with uncoalesced touch events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/renderer_host/input/touch_event_queue.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/renderer_host/input/touch_event_queue.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698