| Index: content/browser/renderer_host/input/touch_event_queue.cc
|
| diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc
|
| index 187728134120ad9edc378fe6fb60347a9a123535..16d9e114ed871b7c25e33fed81538c19000b6805 100644
|
| --- a/content/browser/renderer_host/input/touch_event_queue.cc
|
| +++ b/content/browser/renderer_host/input/touch_event_queue.cc
|
| @@ -5,10 +5,12 @@
|
| #include "content/browser/renderer_host/input/touch_event_queue.h"
|
|
|
| #include "base/auto_reset.h"
|
| +#include "base/command_line.h"
|
| #include "base/debug/trace_event.h"
|
| #include "base/stl_util.h"
|
| #include "content/browser/renderer_host/input/timeout_monitor.h"
|
| #include "content/common/input/web_touch_event_traits.h"
|
| +#include "content/public/common/content_switches.h"
|
| #include "ui/gfx/geometry/point_f.h"
|
|
|
| using blink::WebInputEvent;
|
| @@ -32,6 +34,8 @@
|
| // slop determination when using fractional DIP coordinates (assuming the slop
|
| // region and DPI scale are reasonably proportioned).
|
| const float kSlopEpsilon = .05f;
|
| +
|
| +typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
|
|
|
| TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
|
| const TouchEventWithLatencyInfo& event_to_cancel) {
|
| @@ -69,9 +73,7 @@
|
| timeout_delay_(timeout_delay),
|
| pending_ack_state_(PENDING_ACK_NONE),
|
| timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
|
| - base::Unretained(this))) {
|
| - DCHECK(timeout_delay != base::TimeDelta());
|
| - }
|
| + base::Unretained(this))) {}
|
|
|
| ~TouchTimeoutHandler() {}
|
|
|
| @@ -195,42 +197,42 @@
|
| TouchMoveSlopSuppressor(double slop_suppression_length_dips)
|
| : slop_suppression_length_dips_squared_(slop_suppression_length_dips *
|
| slop_suppression_length_dips),
|
| - suppressing_touchmoves_(false) {}
|
| + suppressing_touch_moves_(false) {}
|
|
|
| bool FilterEvent(const WebTouchEvent& event) {
|
| if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
|
| touch_sequence_start_position_ =
|
| gfx::PointF(event.touches[0].position);
|
| - suppressing_touchmoves_ = slop_suppression_length_dips_squared_ != 0;
|
| + suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0;
|
| }
|
|
|
| if (event.type != WebInputEvent::TouchMove)
|
| return false;
|
|
|
| - if (suppressing_touchmoves_) {
|
| + if (suppressing_touch_moves_) {
|
| // Movement with a secondary pointer should terminate suppression.
|
| if (event.touchesLength > 1) {
|
| - suppressing_touchmoves_ = false;
|
| + suppressing_touch_moves_ = false;
|
| } else if (event.touchesLength == 1) {
|
| // Movement outside of the slop region should terminate suppression.
|
| gfx::PointF position(event.touches[0].position);
|
| if ((position - touch_sequence_start_position_).LengthSquared() >
|
| slop_suppression_length_dips_squared_)
|
| - suppressing_touchmoves_ = false;
|
| + suppressing_touch_moves_ = false;
|
| }
|
| }
|
| - return suppressing_touchmoves_;
|
| + return suppressing_touch_moves_;
|
| }
|
|
|
| void ConfirmTouchEvent(InputEventAckState ack_result) {
|
| if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
|
| - suppressing_touchmoves_ = false;
|
| + suppressing_touch_moves_ = false;
|
| }
|
|
|
| private:
|
| double slop_suppression_length_dips_squared_;
|
| gfx::PointF touch_sequence_start_position_;
|
| - bool suppressing_touchmoves_;
|
| + bool suppressing_touch_moves_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor);
|
| };
|
| @@ -314,37 +316,26 @@
|
|
|
| // This is the list of the original events that were coalesced, each requiring
|
| // future ack dispatch to the client.
|
| - typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
|
| WebTouchEventWithLatencyList events_to_ack_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
|
| };
|
|
|
| -TouchEventQueue::Config::Config()
|
| - : touchmove_slop_suppression_length_dips(0),
|
| - touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT),
|
| - touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)),
|
| - touch_ack_timeout_supported(false) {
|
| -}
|
| -
|
| TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
|
| - const Config& config)
|
| + TouchScrollingMode mode,
|
| + double touchmove_suppression_length_dips)
|
| : client_(client),
|
| dispatching_touch_ack_(NULL),
|
| dispatching_touch_(false),
|
| touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
|
| - ack_timeout_enabled_(config.touch_ack_timeout_supported),
|
| + ack_timeout_enabled_(false),
|
| touchmove_slop_suppressor_(new TouchMoveSlopSuppressor(
|
| - config.touchmove_slop_suppression_length_dips + kSlopEpsilon)),
|
| + touchmove_suppression_length_dips + kSlopEpsilon)),
|
| send_touch_events_async_(false),
|
| - needs_async_touchmove_for_outer_slop_region_(false),
|
| + needs_async_touch_move_for_outer_slop_region_(false),
|
| last_sent_touch_timestamp_sec_(0),
|
| - touch_scrolling_mode_(config.touch_scrolling_mode) {
|
| + touch_scrolling_mode_(mode) {
|
| DCHECK(client);
|
| - if (ack_timeout_enabled_) {
|
| - timeout_handler_.reset(
|
| - new TouchTimeoutHandler(this, config.touch_ack_timeout_delay));
|
| - }
|
| }
|
|
|
| TouchEventQueue::~TouchEventQueue() {
|
| @@ -456,22 +447,22 @@
|
| // application be sent touches at key points in the gesture stream,
|
| // e.g., when the application slop region is exceeded or touchmove
|
| // coalescing fails because of different modifiers.
|
| - const bool send_touchmove_now =
|
| + const bool send_touch_move_now =
|
| size() > 1 ||
|
| (touch.event.timeStampSeconds >=
|
| last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec) ||
|
| - (needs_async_touchmove_for_outer_slop_region_ &&
|
| + (needs_async_touch_move_for_outer_slop_region_ &&
|
| OutsideApplicationSlopRegion(touch.event,
|
| touch_sequence_start_position_)) ||
|
| - (pending_async_touchmove_ &&
|
| - !pending_async_touchmove_->CanCoalesceWith(touch));
|
| -
|
| - if (!send_touchmove_now) {
|
| - if (!pending_async_touchmove_) {
|
| - pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch));
|
| + (pending_async_touch_move_ &&
|
| + !pending_async_touch_move_->CanCoalesceWith(touch));
|
| +
|
| + if (!send_touch_move_now) {
|
| + if (!pending_async_touch_move_) {
|
| + pending_async_touch_move_.reset(new TouchEventWithLatencyInfo(touch));
|
| } else {
|
| - DCHECK(pending_async_touchmove_->CanCoalesceWith(touch));
|
| - pending_async_touchmove_->CoalesceWith(touch);
|
| + DCHECK(pending_async_touch_move_->CanCoalesceWith(touch));
|
| + pending_async_touch_move_->CoalesceWith(touch);
|
| }
|
| DCHECK_EQ(1U, size());
|
| PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| @@ -489,14 +480,14 @@
|
| // Flush any pending async touch move. If it can be combined with the current
|
| // (touchmove) event, great, otherwise send it immediately but separately. Its
|
| // ack will trigger forwarding of the original |touch| event.
|
| - if (pending_async_touchmove_) {
|
| - if (pending_async_touchmove_->CanCoalesceWith(touch)) {
|
| - pending_async_touchmove_->CoalesceWith(touch);
|
| - pending_async_touchmove_->event.cancelable = !send_touch_events_async_;
|
| - touch = *pending_async_touchmove_.Pass();
|
| + if (pending_async_touch_move_) {
|
| + if (pending_async_touch_move_->CanCoalesceWith(touch)) {
|
| + pending_async_touch_move_->CoalesceWith(touch);
|
| + pending_async_touch_move_->event.cancelable = !send_touch_events_async_;
|
| + touch = *pending_async_touch_move_.Pass();
|
| } else {
|
| scoped_ptr<TouchEventWithLatencyInfo> async_move =
|
| - pending_async_touchmove_.Pass();
|
| + pending_async_touch_move_.Pass();
|
| async_move->event.cancelable = false;
|
| touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true));
|
| SendTouchEventImmediately(*async_move);
|
| @@ -543,9 +534,9 @@
|
| }
|
| }
|
|
|
| - pending_async_touchmove_.reset();
|
| + pending_async_touch_move_.reset();
|
| send_touch_events_async_ = true;
|
| - needs_async_touchmove_for_outer_slop_region_ = true;
|
| + needs_async_touch_move_for_outer_slop_region_ = true;
|
| return;
|
| }
|
|
|
| @@ -588,11 +579,11 @@
|
| // Note that there's no guarantee that this ACK is for the most recent
|
| // gesture event (or even part of the current sequence). Worst case, the
|
| // delay in updating the absorption state will result in minor UI glitches.
|
| - // A valid |pending_async_touchmove_| will be flushed when the next event is
|
| + // A valid |pending_async_touch_move_| will be flushed when the next event is
|
| // forwarded.
|
| send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
|
| if (!send_touch_events_async_)
|
| - needs_async_touchmove_for_outer_slop_region_ = false;
|
| + needs_async_touch_move_for_outer_slop_region_ = false;
|
| }
|
|
|
| void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
|
| @@ -610,7 +601,7 @@
|
| // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
|
| // state tracking (e.g., if the touch handler was removed mid-sequence).
|
| touch_filtering_state_ = DROP_ALL_TOUCHES;
|
| - pending_async_touchmove_.reset();
|
| + pending_async_touch_move_.reset();
|
| if (timeout_handler_)
|
| timeout_handler_->Reset();
|
| if (!touch_queue_.empty())
|
| @@ -630,30 +621,29 @@
|
| return (event.type == WebInputEvent::TouchStart);
|
| }
|
|
|
| -void TouchEventQueue::SetAckTimeoutEnabled(bool enabled) {
|
| - // The timeout handler is valid only if explicitly supported in the config.
|
| +void TouchEventQueue::SetAckTimeoutEnabled(bool enabled,
|
| + base::TimeDelta ack_timeout_delay) {
|
| + if (!enabled) {
|
| + ack_timeout_enabled_ = false;
|
| + if (touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT)
|
| + touch_filtering_state_ = FORWARD_ALL_TOUCHES;
|
| + // 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 (timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning())
|
| + timeout_handler_->Reset();
|
| + return;
|
| + }
|
| +
|
| + ack_timeout_enabled_ = true;
|
| if (!timeout_handler_)
|
| - return;
|
| -
|
| - if (ack_timeout_enabled_ == enabled)
|
| - return;
|
| -
|
| - ack_timeout_enabled_ = enabled;
|
| -
|
| - if (enabled)
|
| - return;
|
| -
|
| - if (touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT)
|
| - touch_filtering_state_ = FORWARD_ALL_TOUCHES;
|
| - // 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 (timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning())
|
| - timeout_handler_->Reset();
|
| + timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay));
|
| + else
|
| + timeout_handler_->set_timeout_delay(ack_timeout_delay);
|
| }
|
|
|
| bool TouchEventQueue::HasPendingAsyncTouchMoveForTesting() const {
|
| - return pending_async_touchmove_;
|
| + return pending_async_touch_move_;
|
| }
|
|
|
| bool TouchEventQueue::IsTimeoutRunningForTesting() const {
|
| @@ -668,7 +658,7 @@
|
| void TouchEventQueue::FlushQueue() {
|
| DCHECK(!dispatching_touch_ack_);
|
| DCHECK(!dispatching_touch_);
|
| - pending_async_touchmove_.reset();
|
| + pending_async_touch_move_.reset();
|
| if (touch_filtering_state_ != DROP_ALL_TOUCHES)
|
| touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
|
| while (!touch_queue_.empty())
|
| @@ -710,14 +700,14 @@
|
|
|
| void TouchEventQueue::SendTouchEventImmediately(
|
| const TouchEventWithLatencyInfo& touch) {
|
| - if (needs_async_touchmove_for_outer_slop_region_) {
|
| + if (needs_async_touch_move_for_outer_slop_region_) {
|
| // Any event other than a touchmove (e.g., touchcancel or secondary
|
| // touchstart) after a scroll has started will interrupt the need to send a
|
| // an outer slop-region exceeding touchmove.
|
| if (touch.event.type != WebInputEvent::TouchMove ||
|
| OutsideApplicationSlopRegion(touch.event,
|
| touch_sequence_start_position_))
|
| - needs_async_touchmove_for_outer_slop_region_ = false;
|
| + needs_async_touch_move_for_outer_slop_region_ = false;
|
| }
|
|
|
| client_->SendTouchEventImmediately(touch);
|
|
|