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

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

Issue 1050993004: Route touchmove existence notifications to the TouchEventQueue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 5 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
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/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/trace_event/trace_event.h" 10 #include "base/trace_event/trace_event.h"
(...skipping 11 matching lines...) Expand all
22 22
23 // Time interval at which touchmove events will be forwarded to the client while 23 // Time interval at which touchmove events will be forwarded to the client while
24 // scrolling is active and possible. 24 // scrolling is active and possible.
25 const double kAsyncTouchMoveIntervalSec = .2; 25 const double kAsyncTouchMoveIntervalSec = .2;
26 26
27 // A sanity check on touches received to ensure that touch movement outside 27 // A sanity check on touches received to ensure that touch movement outside
28 // the platform slop region will cause scrolling, as indicated by the event's 28 // the platform slop region will cause scrolling, as indicated by the event's
29 // |causesScrollingIfUncanceled| bit. 29 // |causesScrollingIfUncanceled| bit.
30 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.; 30 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.;
31 31
32 // These values should be synchronized with those in histograms.xml.
33 enum TouchSequenceHandlerType {
34 HAS_HANDLER,
35 HAS_HANDLER_BUT_NO_MOVE_HANDLERS_FOR_PAGE,
36 NO_HANDLERS_FOR_PAGE,
37 NO_HANDLER_FOR_SEQUENCE,
38 UNKNOWN_BECAUSE_TIMEOUT,
39 TOUCH_SEQUENCE_HANDLER_TYPE_COUNT
40 };
41
42 void LogSequenceHandlerType(TouchSequenceHandlerType type) {
43 UMA_HISTOGRAM_ENUMERATION("Event.TouchSequence.HandlerType", type,
44 TOUCH_SEQUENCE_HANDLER_TYPE_COUNT);
45 }
46
32 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( 47 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
33 const TouchEventWithLatencyInfo& event_to_cancel) { 48 const TouchEventWithLatencyInfo& event_to_cancel) {
34 TouchEventWithLatencyInfo event = event_to_cancel; 49 TouchEventWithLatencyInfo event = event_to_cancel;
35 WebTouchEventTraits::ResetTypeAndTouchStates( 50 WebTouchEventTraits::ResetTypeAndTouchStates(
36 WebInputEvent::TouchCancel, 51 WebInputEvent::TouchCancel,
37 // TODO(rbyers): Shouldn't we use a fresh timestamp? 52 // TODO(rbyers): Shouldn't we use a fresh timestamp?
38 event.event.timeStampSeconds, 53 event.event.timeStampSeconds,
39 &event.event); 54 &event.event);
40 return event; 55 return event;
41 } 56 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 timeout_monitor_.Stop(); 139 timeout_monitor_.Stop();
125 return false; 140 return false;
126 case PENDING_ACK_ORIGINAL_EVENT: 141 case PENDING_ACK_ORIGINAL_EVENT:
127 if (AckedTimeoutEventRequiresCancel(ack_result)) { 142 if (AckedTimeoutEventRequiresCancel(ack_result)) {
128 SetPendingAckState(PENDING_ACK_CANCEL_EVENT); 143 SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
129 TouchEventWithLatencyInfo cancel_event = 144 TouchEventWithLatencyInfo cancel_event =
130 ObtainCancelEventForTouchEvent(timeout_event_); 145 ObtainCancelEventForTouchEvent(timeout_event_);
131 touch_queue_->SendTouchEventImmediately(&cancel_event); 146 touch_queue_->SendTouchEventImmediately(&cancel_event);
132 } else { 147 } else {
133 SetPendingAckState(PENDING_ACK_NONE); 148 SetPendingAckState(PENDING_ACK_NONE);
134 touch_queue_->UpdateTouchConsumerStates(timeout_event_.event,
135 ack_result);
136 } 149 }
137 return true; 150 return true;
138 case PENDING_ACK_CANCEL_EVENT: 151 case PENDING_ACK_CANCEL_EVENT:
139 SetPendingAckState(PENDING_ACK_NONE); 152 SetPendingAckState(PENDING_ACK_NONE);
140 return true; 153 return true;
141 } 154 }
142 return false; 155 return false;
143 } 156 }
144 157
145 bool FilterEvent(const WebTouchEvent& event) { 158 bool FilterEvent(const WebTouchEvent& event) {
(...skipping 28 matching lines...) Expand all
174 timeout_monitor_.Stop(); 187 timeout_monitor_.Stop();
175 } 188 }
176 } 189 }
177 190
178 void SetUseMobileTimeout(bool use_mobile_timeout) { 191 void SetUseMobileTimeout(bool use_mobile_timeout) {
179 use_mobile_timeout_ = use_mobile_timeout; 192 use_mobile_timeout_ = use_mobile_timeout;
180 } 193 }
181 194
182 bool IsTimeoutTimerRunning() const { return timeout_monitor_.IsRunning(); } 195 bool IsTimeoutTimerRunning() const { return timeout_monitor_.IsRunning(); }
183 196
197 bool HasTimeoutEvent() const {
198 return pending_ack_state_ != PENDING_ACK_NONE;
199 }
200
184 bool IsEnabled() const { 201 bool IsEnabled() const {
185 return enabled_ && !GetTimeoutDelay().is_zero(); 202 return enabled_ && !GetTimeoutDelay().is_zero();
186 } 203 }
187 204
188 private: 205 private:
189 enum PendingAckState { 206 enum PendingAckState {
190 PENDING_ACK_NONE, 207 PENDING_ACK_NONE,
191 PENDING_ACK_ORIGINAL_EVENT, 208 PENDING_ACK_ORIGINAL_EVENT,
192 PENDING_ACK_CANCEL_EVENT, 209 PENDING_ACK_CANCEL_EVENT,
193 }; 210 };
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnMobileSite", timed_out); 264 UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnMobileSite", timed_out);
248 } else { 265 } else {
249 UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnDesktopSite", timed_out); 266 UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnDesktopSite", timed_out);
250 } 267 }
251 } 268 }
252 269
253 base::TimeDelta GetTimeoutDelay() const { 270 base::TimeDelta GetTimeoutDelay() const {
254 return use_mobile_timeout_ ? mobile_timeout_delay_ : desktop_timeout_delay_; 271 return use_mobile_timeout_ ? mobile_timeout_delay_ : desktop_timeout_delay_;
255 } 272 }
256 273
257 bool HasTimeoutEvent() const {
258 return pending_ack_state_ != PENDING_ACK_NONE;
259 }
260
261 274
262 TouchEventQueue* touch_queue_; 275 TouchEventQueue* touch_queue_;
263 276
264 // How long to wait on a touch ack before cancelling the touch sequence. 277 // How long to wait on a touch ack before cancelling the touch sequence.
265 const base::TimeDelta desktop_timeout_delay_; 278 const base::TimeDelta desktop_timeout_delay_;
266 const base::TimeDelta mobile_timeout_delay_; 279 const base::TimeDelta mobile_timeout_delay_;
267 bool use_mobile_timeout_; 280 bool use_mobile_timeout_;
268 281
269 // The touch event source for which we expect the next ack. 282 // The touch event source for which we expect the next ack.
270 PendingAckState pending_ack_state_; 283 PendingAckState pending_ack_state_;
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 mobile_touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(1000)), 439 mobile_touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(1000)),
427 touch_ack_timeout_supported(false) { 440 touch_ack_timeout_supported(false) {
428 } 441 }
429 442
430 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, 443 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
431 const Config& config) 444 const Config& config)
432 : client_(client), 445 : client_(client),
433 dispatching_touch_ack_(false), 446 dispatching_touch_ack_(false),
434 dispatching_touch_(false), 447 dispatching_touch_(false),
435 has_handlers_(true), 448 has_handlers_(true),
449 has_move_handlers_(true),
436 has_handler_for_current_sequence_(false), 450 has_handler_for_current_sequence_(false),
437 drop_remaining_touches_in_sequence_(false), 451 drop_remaining_touches_in_sequence_(false),
438 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), 452 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor),
439 send_touch_events_async_(false), 453 send_touch_events_async_(false),
440 last_sent_touch_timestamp_sec_(0) { 454 last_sent_touch_timestamp_sec_(0) {
441 DCHECK(client); 455 DCHECK(client);
442 if (config.touch_ack_timeout_supported) { 456 if (config.touch_ack_timeout_supported) {
443 timeout_handler_.reset( 457 timeout_handler_.reset(
444 new TouchTimeoutHandler(this, 458 new TouchTimeoutHandler(this,
445 config.desktop_touch_ack_timeout_delay, 459 config.desktop_touch_ack_timeout_delay,
446 config.mobile_touch_ack_timeout_delay)); 460 config.mobile_touch_ack_timeout_delay));
447 } 461 }
448 } 462 }
449 463
450 TouchEventQueue::~TouchEventQueue() { 464 TouchEventQueue::~TouchEventQueue() {
451 if (!touch_queue_.empty()) 465 if (!touch_queue_.empty())
452 STLDeleteElements(&touch_queue_); 466 STLDeleteElements(&touch_queue_);
453 } 467 }
454 468
455 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 469 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
456 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); 470 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent");
457 471
458 // If the queueing of |event| was triggered by an ack dispatch, defer 472 // If the queueing of |event| was triggered by an ack dispatch, defer
459 // processing the event until the dispatch has finished. 473 // processing the event until the dispatch has finished.
460 if (touch_queue_.empty() && !dispatching_touch_ack_) { 474 if (touch_queue_.empty() && !dispatching_touch_ack_) {
461 // Optimization of the case without touch handlers. Removing this path 475 // Optimization of the case without touch handlers. Removing this path
462 // yields identical results, but this avoids unnecessary allocations. 476 // yields identical results, but this avoids unnecessary allocations.
463 PreFilterResult filter_result = FilterBeforeForwarding(event.event); 477 PreFilterResult filter_result = FilterBeforeForwarding(event.event);
464 if (filter_result != FORWARD_TO_RENDERER) { 478 if (filter_result != FORWARD_TO_RENDERER) {
465 client_->OnTouchEventAck(event, 479 InputEventAckState ack_result =
466 filter_result == ACK_WITH_NO_CONSUMER_EXISTS 480 filter_result == ACK_WITH_NO_CONSUMER_EXISTS
467 ? INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS 481 ? INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
468 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 482 : INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
483 UpdateTouchConsumerStates(event.event, ack_result);
484 client_->OnTouchEventAck(event, ack_result);
469 return; 485 return;
470 } 486 }
471 487
472 // There is no touch event in the queue. Forward it to the renderer 488 // There is no touch event in the queue. Forward it to the renderer
473 // immediately. 489 // immediately.
474 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); 490 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
475 ForwardNextEventToRenderer(); 491 ForwardNextEventToRenderer();
476 return; 492 return;
477 } 493 }
478 494
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 if (event.event.type == blink::WebInputEvent::GestureScrollUpdate) 668 if (event.event.type == blink::WebInputEvent::GestureScrollUpdate)
653 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); 669 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
654 } 670 }
655 671
656 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { 672 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
657 DCHECK(!dispatching_touch_ack_); 673 DCHECK(!dispatching_touch_ack_);
658 DCHECK(!dispatching_touch_); 674 DCHECK(!dispatching_touch_);
659 has_handlers_ = has_handlers; 675 has_handlers_ = has_handlers;
660 } 676 }
661 677
678 void TouchEventQueue::OnHasTouchMoveEventHandlers(bool has_handlers) {
679 DCHECK(!dispatching_touch_ack_);
680 DCHECK(!dispatching_touch_);
681 has_move_handlers_ = has_handlers;
682 }
683
662 bool TouchEventQueue::IsPendingAckTouchStart() const { 684 bool TouchEventQueue::IsPendingAckTouchStart() const {
663 DCHECK(!dispatching_touch_ack_); 685 DCHECK(!dispatching_touch_ack_);
664 if (touch_queue_.empty()) 686 if (touch_queue_.empty())
665 return false; 687 return false;
666 688
667 const blink::WebTouchEvent& event = 689 const blink::WebTouchEvent& event =
668 touch_queue_.front()->coalesced_event().event; 690 touch_queue_.front()->coalesced_event().event;
669 return (event.type == WebInputEvent::TouchStart); 691 return (event.type == WebInputEvent::TouchStart);
670 } 692 }
671 693
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
816 event.type != WebInputEvent::TouchCancel) { 838 event.type != WebInputEvent::TouchCancel) {
817 return ACK_WITH_NO_CONSUMER_EXISTS; 839 return ACK_WITH_NO_CONSUMER_EXISTS;
818 } 840 }
819 841
820 if (event.type == WebInputEvent::TouchStart) { 842 if (event.type == WebInputEvent::TouchStart) {
821 return (has_handlers_ || has_handler_for_current_sequence_) 843 return (has_handlers_ || has_handler_for_current_sequence_)
822 ? FORWARD_TO_RENDERER 844 ? FORWARD_TO_RENDERER
823 : ACK_WITH_NO_CONSUMER_EXISTS; 845 : ACK_WITH_NO_CONSUMER_EXISTS;
824 } 846 }
825 847
848 if (event.type == WebInputEvent::TouchMove && !has_move_handlers_)
849 return ACK_WITH_NO_CONSUMER_EXISTS;
850
826 if (has_handler_for_current_sequence_) { 851 if (has_handler_for_current_sequence_) {
827 // Only forward a touch if it has a non-stationary pointer that is active 852 // Only forward a touch if it has a non-stationary pointer that is active
828 // in the current touch sequence. 853 // in the current touch sequence.
829 for (size_t i = 0; i < event.touchesLength; ++i) { 854 for (size_t i = 0; i < event.touchesLength; ++i) {
830 const WebTouchPoint& point = event.touches[i]; 855 const WebTouchPoint& point = event.touches[i];
831 if (point.state == WebTouchPoint::StateStationary) 856 if (point.state == WebTouchPoint::StateStationary)
832 continue; 857 continue;
833 858
834 // |last_sent_touchevent_| will be non-null as long as there is an 859 // |last_sent_touchevent_| will be non-null as long as there is an
835 // active touch sequence being forwarded to the renderer. 860 // active touch sequence being forwarded to the renderer.
(...skipping 25 matching lines...) Expand all
861 return ACK_WITH_NO_CONSUMER_EXISTS; 886 return ACK_WITH_NO_CONSUMER_EXISTS;
862 } 887 }
863 888
864 void TouchEventQueue::UpdateTouchConsumerStates(const WebTouchEvent& event, 889 void TouchEventQueue::UpdateTouchConsumerStates(const WebTouchEvent& event,
865 InputEventAckState ack_result) { 890 InputEventAckState ack_result) {
866 if (event.type == WebInputEvent::TouchStart) { 891 if (event.type == WebInputEvent::TouchStart) {
867 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 892 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
868 send_touch_events_async_ = false; 893 send_touch_events_async_ = false;
869 has_handler_for_current_sequence_ |= 894 has_handler_for_current_sequence_ |=
870 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; 895 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
896
897 if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
898 if (timeout_handler_ && timeout_handler_->HasTimeoutEvent())
899 LogSequenceHandlerType(UNKNOWN_BECAUSE_TIMEOUT);
900 else if (!has_handlers_)
901 LogSequenceHandlerType(NO_HANDLERS_FOR_PAGE);
902 else if (!has_handler_for_current_sequence_)
903 LogSequenceHandlerType(NO_HANDLER_FOR_SEQUENCE);
904 else if (!has_move_handlers_)
905 LogSequenceHandlerType(HAS_HANDLER_BUT_NO_MOVE_HANDLERS_FOR_PAGE);
906 else
907 LogSequenceHandlerType(HAS_HANDLER);
908 }
871 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { 909 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) {
872 has_handler_for_current_sequence_ = false; 910 has_handler_for_current_sequence_ = false;
873 } 911 }
874 } 912 }
875 913
876 } // namespace content 914 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698