| 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 3524b18250e1cb22162b755122230d8e5affd38d..5921521e8ce0b2115106fad05b9561420f0aba6f 100644
|
| --- a/content/browser/renderer_host/input/touch_event_queue.cc
|
| +++ b/content/browser/renderer_host/input/touch_event_queue.cc
|
| @@ -103,6 +103,11 @@ class TouchEventQueue::TouchTimeoutHandler {
|
| return timeout_monitor_.IsRunning();
|
| }
|
|
|
| + void Reset() {
|
| + pending_ack_state_ = PENDING_ACK_NONE;
|
| + timeout_monitor_.Stop();
|
| + }
|
| +
|
| private:
|
| enum PendingAckState {
|
| PENDING_ACK_NONE,
|
| @@ -236,7 +241,8 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
|
| : client_(client),
|
| dispatching_touch_ack_(NULL),
|
| dispatching_touch_(false),
|
| - no_touch_to_renderer_(false),
|
| + has_handlers_(false),
|
| + scroll_in_progress_(false),
|
| renderer_is_consuming_touch_gesture_(false),
|
| ack_timeout_enabled_(false) {
|
| DCHECK(client);
|
| @@ -248,6 +254,14 @@ TouchEventQueue::~TouchEventQueue() {
|
| }
|
|
|
| void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
|
| + // Optimization of the case without touch handlers. Removing this path
|
| + // yields identical results, but this avoids unnecessary allocations.
|
| + if (!has_handlers_) {
|
| + DCHECK(touch_queue_.empty());
|
| + client_->OnTouchEventAck(event, kDefaultNotForwardedAck);
|
| + return;
|
| + }
|
| +
|
| // If the queueing of |event| was triggered by an ack dispatch, defer
|
| // processing the event until the dispatch has finished.
|
| if (touch_queue_.empty() && !dispatching_touch_ack_) {
|
| @@ -296,8 +310,10 @@ void TouchEventQueue::TryForwardNextEventToRenderer() {
|
| while (!touch_queue_.empty()) {
|
| const TouchEventWithLatencyInfo& touch =
|
| touch_queue_.front()->coalesced_event();
|
| - if (IsNewTouchGesture(touch.event))
|
| + if (IsNewTouchGesture(touch.event)) {
|
| + touch_ack_states_.clear();
|
| renderer_is_consuming_touch_gesture_ = false;
|
| + }
|
| if (ShouldForwardToRenderer(touch.event)) {
|
| ForwardToRenderer(touch);
|
| break;
|
| @@ -330,9 +346,9 @@ void TouchEventQueue::OnGestureScrollEvent(
|
| // dispatching a touch event ack, so that we can fake a cancel
|
| // event that has the correct touch ids as the touch event that
|
| // is being acked. If not, we don't do the touch-cancel optimization.
|
| - if (no_touch_to_renderer_ || !dispatching_touch_ack_)
|
| + if (scroll_in_progress_ || !dispatching_touch_ack_)
|
| return;
|
| - no_touch_to_renderer_ = true;
|
| + scroll_in_progress_ = true;
|
|
|
| // If we have a timeout event, a cancel has already been dispatched
|
| // for the current touch stream.
|
| @@ -350,15 +366,34 @@ void TouchEventQueue::OnGestureScrollEvent(
|
| dispatching_touch_ack_->coalesced_event()), true));
|
| } else if (type == blink::WebInputEvent::GestureScrollEnd ||
|
| type == blink::WebInputEvent::GestureFlingStart) {
|
| - no_touch_to_renderer_ = false;
|
| + scroll_in_progress_ = false;
|
| }
|
| }
|
|
|
| -void TouchEventQueue::FlushQueue() {
|
| +void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
|
| DCHECK(!dispatching_touch_ack_);
|
| DCHECK(!dispatching_touch_);
|
| - while (!touch_queue_.empty())
|
| - PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
|
| + if (has_handlers_ == has_handlers)
|
| + return;
|
| +
|
| + has_handlers_ = has_handlers;
|
| +
|
| + if (!has_handlers_) {
|
| + // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
|
| + // state tracking.
|
| + if (timeout_handler_)
|
| + timeout_handler_->Reset();
|
| + if (!touch_queue_.empty())
|
| + ProcessTouchAck(kDefaultNotForwardedAck, ui::LatencyInfo());
|
| + // As there is no touch handler, ack'ing the event should flush the queue.
|
| + DCHECK(touch_queue_.empty());
|
| + } else {
|
| + DCHECK(touch_queue_.empty());
|
| + // Prevent a partial sequence from being sent to the renderer.
|
| + TouchPointAckStates::iterator ack_it = touch_ack_states_.begin();
|
| + for (; ack_it != touch_ack_states_.end(); ++ack_it)
|
| + ack_it->second = kDefaultNotForwardedAck;
|
| + }
|
| }
|
|
|
| bool TouchEventQueue::IsPendingAckTouchStart() const {
|
| @@ -398,6 +433,13 @@ TouchEventQueue::GetLatestEventForTesting() const {
|
| return touch_queue_.back()->coalesced_event();
|
| }
|
|
|
| +void TouchEventQueue::FlushQueue() {
|
| + DCHECK(!dispatching_touch_ack_);
|
| + DCHECK(!dispatching_touch_);
|
| + while (!touch_queue_.empty())
|
| + PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
|
| +}
|
| +
|
| void TouchEventQueue::PopTouchEventToClient(
|
| InputEventAckState ack_result,
|
| const ui::LatencyInfo& renderer_latency_info) {
|
| @@ -428,7 +470,10 @@ bool TouchEventQueue::ShouldForwardToRenderer(
|
| if (HasTimeoutEvent())
|
| return false;
|
|
|
| - if (no_touch_to_renderer_ &&
|
| + if (!has_handlers_)
|
| + return false;
|
| +
|
| + if (scroll_in_progress_ &&
|
| event.type != blink::WebInputEvent::TouchCancel)
|
| return false;
|
|
|
|
|