Index: content/browser/renderer_host/input/legacy_touch_event_queue.cc |
diff --git a/content/browser/renderer_host/input/legacy_touch_event_queue.cc b/content/browser/renderer_host/input/legacy_touch_event_queue.cc |
index c723964708056c6dfb647694acefe174176fa002..9f685b8ce6fc82ca2bcc2cc3039a69c8719b5c55 100644 |
--- a/content/browser/renderer_host/input/legacy_touch_event_queue.cc |
+++ b/content/browser/renderer_host/input/legacy_touch_event_queue.cc |
@@ -11,7 +11,7 @@ |
#include "base/memory/ptr_util.h" |
#include "base/metrics/histogram_macros.h" |
#include "base/trace_event/trace_event.h" |
-#include "content/browser/renderer_host/input/timeout_monitor.h" |
+#include "content/browser/renderer_host/input/touch_timeout_handler.h" |
#include "content/common/input/web_touch_event_traits.h" |
#include "ui/events/base_event_utils.h" |
#include "ui/gfx/geometry/point_f.h" |
@@ -28,22 +28,6 @@ namespace { |
// scrolling is active and possible. |
const double kAsyncTouchMoveIntervalSec = .2; |
-TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( |
- const TouchEventWithLatencyInfo& event_to_cancel) { |
- TouchEventWithLatencyInfo event = event_to_cancel; |
- WebTouchEventTraits::ResetTypeAndTouchStates( |
- WebInputEvent::TouchCancel, |
- // TODO(rbyers): Shouldn't we use a fresh timestamp? |
- event.event.timeStampSeconds(), &event.event); |
- return event; |
-} |
- |
-bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) { |
- return (event.type() == WebInputEvent::TouchStart || |
- event.type() == WebInputEvent::TouchMove) && |
- event.dispatchType == WebInputEvent::Blocking; |
-} |
- |
// Compare all properties of touch points to determine the state. |
bool HasPointChanged(const WebTouchPoint& point_1, |
const WebTouchPoint& point_2) { |
@@ -62,219 +46,6 @@ bool HasPointChanged(const WebTouchPoint& point_1, |
} // namespace |
-// Cancels a touch sequence if a touchstart or touchmove ack response is |
-// sufficiently delayed. |
-class LegacyTouchEventQueue::TouchTimeoutHandler { |
- public: |
- TouchTimeoutHandler(LegacyTouchEventQueue* touch_queue, |
- base::TimeDelta desktop_timeout_delay, |
- base::TimeDelta mobile_timeout_delay) |
- : touch_queue_(touch_queue), |
- desktop_timeout_delay_(desktop_timeout_delay), |
- mobile_timeout_delay_(mobile_timeout_delay), |
- use_mobile_timeout_(false), |
- pending_ack_state_(PENDING_ACK_NONE), |
- timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut, |
- base::Unretained(this))), |
- enabled_(true), |
- enabled_for_current_sequence_(false), |
- sequence_awaiting_uma_update_(false), |
- sequence_using_mobile_timeout_(false) { |
- SetUseMobileTimeout(false); |
- } |
- |
- ~TouchTimeoutHandler() { LogSequenceEndForUMAIfNecessary(false); } |
- |
- void StartIfNecessary(const TouchEventWithLatencyInfo& event) { |
- if (pending_ack_state_ != PENDING_ACK_NONE) |
- return; |
- |
- if (!enabled_) |
- return; |
- |
- const base::TimeDelta timeout_delay = GetTimeoutDelay(); |
- if (timeout_delay.is_zero()) |
- return; |
- |
- if (!ShouldTouchTriggerTimeout(event.event)) |
- return; |
- |
- if (WebTouchEventTraits::IsTouchSequenceStart(event.event)) { |
- LogSequenceStartForUMA(); |
- enabled_for_current_sequence_ = true; |
- } |
- |
- if (!enabled_for_current_sequence_) |
- return; |
- |
- timeout_event_ = event; |
- timeout_monitor_.Restart(timeout_delay); |
- } |
- |
- bool ConfirmTouchEvent(InputEventAckState ack_result) { |
- switch (pending_ack_state_) { |
- case PENDING_ACK_NONE: |
- if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
- enabled_for_current_sequence_ = false; |
- timeout_monitor_.Stop(); |
- return false; |
- case PENDING_ACK_ORIGINAL_EVENT: |
- if (AckedTimeoutEventRequiresCancel(ack_result)) { |
- SetPendingAckState(PENDING_ACK_CANCEL_EVENT); |
- TouchEventWithLatencyInfo cancel_event = |
- ObtainCancelEventForTouchEvent(timeout_event_); |
- touch_queue_->SendTouchEventImmediately(&cancel_event); |
- } else { |
- SetPendingAckState(PENDING_ACK_NONE); |
- touch_queue_->UpdateTouchConsumerStates(timeout_event_.event, |
- ack_result); |
- } |
- return true; |
- case PENDING_ACK_CANCEL_EVENT: |
- SetPendingAckState(PENDING_ACK_NONE); |
- return true; |
- } |
- return false; |
- } |
- |
- bool FilterEvent(const WebTouchEvent& event) { |
- if (!HasTimeoutEvent()) |
- return false; |
- |
- if (WebTouchEventTraits::IsTouchSequenceStart(event)) { |
- // If a new sequence is observed while we're still waiting on the |
- // timed-out sequence response, also count the new sequence as timed-out. |
- LogSequenceStartForUMA(); |
- LogSequenceEndForUMAIfNecessary(true); |
- } |
- |
- return true; |
- } |
- |
- void SetEnabled(bool enabled) { |
- if (enabled_ == enabled) |
- return; |
- |
- enabled_ = enabled; |
- |
- if (enabled_) |
- return; |
- |
- enabled_for_current_sequence_ = false; |
- // Only reset the |timeout_handler_| if the timer is running and has not |
- // yet timed out. This ensures that an already timed out sequence is |
- // properly flushed by the handler. |
- if (IsTimeoutTimerRunning()) { |
- pending_ack_state_ = PENDING_ACK_NONE; |
- timeout_monitor_.Stop(); |
- } |
- } |
- |
- void SetUseMobileTimeout(bool use_mobile_timeout) { |
- use_mobile_timeout_ = use_mobile_timeout; |
- } |
- |
- bool IsTimeoutTimerRunning() const { return timeout_monitor_.IsRunning(); } |
- |
- bool IsEnabled() const { return enabled_ && !GetTimeoutDelay().is_zero(); } |
- |
- private: |
- enum PendingAckState { |
- PENDING_ACK_NONE, |
- PENDING_ACK_ORIGINAL_EVENT, |
- PENDING_ACK_CANCEL_EVENT, |
- }; |
- |
- void OnTimeOut() { |
- LogSequenceEndForUMAIfNecessary(true); |
- SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT); |
- touch_queue_->FlushQueue(); |
- } |
- |
- // Skip a cancel event if the timed-out event had no consumer and was the |
- // initial event in the gesture. |
- bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const { |
- DCHECK(HasTimeoutEvent()); |
- if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
- return true; |
- return !WebTouchEventTraits::IsTouchSequenceStart(timeout_event_.event); |
- } |
- |
- void SetPendingAckState(PendingAckState new_pending_ack_state) { |
- DCHECK_NE(pending_ack_state_, new_pending_ack_state); |
- switch (new_pending_ack_state) { |
- case PENDING_ACK_ORIGINAL_EVENT: |
- DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); |
- TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this); |
- break; |
- case PENDING_ACK_CANCEL_EVENT: |
- DCHECK_EQ(pending_ack_state_, PENDING_ACK_ORIGINAL_EVENT); |
- DCHECK(!timeout_monitor_.IsRunning()); |
- DCHECK(touch_queue_->empty()); |
- TRACE_EVENT_ASYNC_STEP_INTO0("input", "TouchEventTimeout", this, |
- "CancelEvent"); |
- break; |
- case PENDING_ACK_NONE: |
- DCHECK(!timeout_monitor_.IsRunning()); |
- DCHECK(touch_queue_->empty()); |
- TRACE_EVENT_ASYNC_END0("input", "TouchEventTimeout", this); |
- break; |
- } |
- pending_ack_state_ = new_pending_ack_state; |
- } |
- |
- void LogSequenceStartForUMA() { |
- // Always flush any unlogged entries before starting a new one. |
- LogSequenceEndForUMAIfNecessary(false); |
- sequence_awaiting_uma_update_ = true; |
- sequence_using_mobile_timeout_ = use_mobile_timeout_; |
- } |
- |
- void LogSequenceEndForUMAIfNecessary(bool timed_out) { |
- if (!sequence_awaiting_uma_update_) |
- return; |
- |
- sequence_awaiting_uma_update_ = false; |
- |
- if (sequence_using_mobile_timeout_) { |
- UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnMobileSite", timed_out); |
- } else { |
- UMA_HISTOGRAM_BOOLEAN("Event.Touch.TimedOutOnDesktopSite", timed_out); |
- } |
- } |
- |
- base::TimeDelta GetTimeoutDelay() const { |
- return use_mobile_timeout_ ? mobile_timeout_delay_ : desktop_timeout_delay_; |
- } |
- |
- bool HasTimeoutEvent() const { |
- return pending_ack_state_ != PENDING_ACK_NONE; |
- } |
- |
- LegacyTouchEventQueue* touch_queue_; |
- |
- // How long to wait on a touch ack before cancelling the touch sequence. |
- const base::TimeDelta desktop_timeout_delay_; |
- const base::TimeDelta mobile_timeout_delay_; |
- bool use_mobile_timeout_; |
- |
- // The touch event source for which we expect the next ack. |
- PendingAckState pending_ack_state_; |
- |
- // The event for which the ack timeout is triggered. |
- TouchEventWithLatencyInfo timeout_event_; |
- |
- // Provides timeout-based callback behavior. |
- TimeoutMonitor timeout_monitor_; |
- |
- bool enabled_; |
- bool enabled_for_current_sequence_; |
- |
- // Bookkeeping to classify and log whether a touch sequence times out. |
- bool sequence_awaiting_uma_update_; |
- bool sequence_using_mobile_timeout_; |
-}; |
- |
// This class represents a single coalesced touch event. However, it also keeps |
// track of all the original touch-events that were coalesced into a single |
// event. The coalesced event is forwarded to the renderer, while the original |
@@ -472,7 +243,8 @@ void LegacyTouchEventQueue::ProcessTouchAck( |
DCHECK(!dispatching_touch_ack_); |
dispatching_touch_ = false; |
- if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) |
+ if (timeout_handler_ && |
+ timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) |
return; |
if (touch_queue_.empty()) |
@@ -719,6 +491,16 @@ void LegacyTouchEventQueue::AckTouchEventToClient( |
touch_queue_.pop_front(); |
} |
+void LegacyTouchEventQueue::SendTouchCancelEventForTouchEvent( |
+ const TouchEventWithLatencyInfo& event_to_cancel) { |
+ TouchEventWithLatencyInfo event = event_to_cancel; |
+ WebTouchEventTraits::ResetTypeAndTouchStates( |
+ WebInputEvent::TouchCancel, |
+ // TODO(rbyers): Shouldn't we use a fresh timestamp? |
+ event.event.timeStampSeconds(), &event.event); |
+ SendTouchEventImmediately(&event); |
+} |
+ |
void LegacyTouchEventQueue::SendTouchEventImmediately( |
TouchEventWithLatencyInfo* touch) { |
// TODO(crbug.com/600773): Hack to avoid cyclic reentry to this method. |
@@ -794,7 +576,6 @@ LegacyTouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { |
pending_async_touchmove_.reset(); |
last_sent_touchevent_.reset(); |
- touch_sequence_start_position_ = gfx::PointF(event.touches[0].position); |
drop_remaining_touches_in_sequence_ = false; |
if (!has_handlers_) { |
drop_remaining_touches_in_sequence_ = true; |