| OLD | NEW |
| 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/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 | 25 |
| 26 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( | 26 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( |
| 27 const TouchEventWithLatencyInfo& event_to_cancel) { | 27 const TouchEventWithLatencyInfo& event_to_cancel) { |
| 28 TouchEventWithLatencyInfo event = event_to_cancel; | 28 TouchEventWithLatencyInfo event = event_to_cancel; |
| 29 event.event.type = WebInputEvent::TouchCancel; | 29 event.event.type = WebInputEvent::TouchCancel; |
| 30 for (size_t i = 0; i < event.event.touchesLength; i++) | 30 for (size_t i = 0; i < event.event.touchesLength; i++) |
| 31 event.event.touches[i].state = WebTouchPoint::StateCancelled; | 31 event.event.touches[i].state = WebTouchPoint::StateCancelled; |
| 32 return event; | 32 return event; |
| 33 } | 33 } |
| 34 | 34 |
| 35 bool IsNewTouchSequence(const WebTouchEvent& event) { | |
| 36 if (event.type != WebInputEvent::TouchStart) | |
| 37 return false; | |
| 38 if (!event.touchesLength) | |
| 39 return false; | |
| 40 for (size_t i = 0; i < event.touchesLength; i++) { | |
| 41 if (event.touches[i].state != WebTouchPoint::StatePressed) | |
| 42 return false; | |
| 43 } | |
| 44 return true; | |
| 45 } | |
| 46 | |
| 47 bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) { | 35 bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) { |
| 48 return type == WebInputEvent::TouchStart || | 36 return type == WebInputEvent::TouchStart || |
| 49 type == WebInputEvent::TouchMove; | 37 type == WebInputEvent::TouchMove; |
| 50 } | 38 } |
| 51 | 39 |
| 52 } // namespace | 40 } // namespace |
| 53 | 41 |
| 54 | 42 |
| 55 // Cancels a touch sequence if a touchstart or touchmove ack response is | 43 // Cancels a touch sequence if a touchstart or touchmove ack response is |
| 56 // sufficiently delayed. | 44 // sufficiently delayed. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT); | 107 SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT); |
| 120 touch_queue_->FlushQueue(); | 108 touch_queue_->FlushQueue(); |
| 121 } | 109 } |
| 122 | 110 |
| 123 // Skip a cancel event if the timed-out event had no consumer and was the | 111 // Skip a cancel event if the timed-out event had no consumer and was the |
| 124 // initial event in the gesture. | 112 // initial event in the gesture. |
| 125 bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const { | 113 bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const { |
| 126 DCHECK(HasTimeoutEvent()); | 114 DCHECK(HasTimeoutEvent()); |
| 127 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 115 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 128 return true; | 116 return true; |
| 129 return !IsNewTouchSequence(timeout_event_.event); | 117 return !WebInputEventTraits::IsNewTouchSequence(timeout_event_.event); |
| 130 } | 118 } |
| 131 | 119 |
| 132 void SetPendingAckState(PendingAckState new_pending_ack_state) { | 120 void SetPendingAckState(PendingAckState new_pending_ack_state) { |
| 133 DCHECK_NE(pending_ack_state_, new_pending_ack_state); | 121 DCHECK_NE(pending_ack_state_, new_pending_ack_state); |
| 134 switch (new_pending_ack_state) { | 122 switch (new_pending_ack_state) { |
| 135 case PENDING_ACK_ORIGINAL_EVENT: | 123 case PENDING_ACK_ORIGINAL_EVENT: |
| 136 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); | 124 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); |
| 137 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this); | 125 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this); |
| 138 break; | 126 break; |
| 139 case PENDING_ACK_CANCEL_EVENT: | 127 case PENDING_ACK_CANCEL_EVENT: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 // Provides touchmove slop suppression for a single touch that remains within | 163 // Provides touchmove slop suppression for a single touch that remains within |
| 176 // a given slop region, unless the touchstart is preventDefault'ed. | 164 // a given slop region, unless the touchstart is preventDefault'ed. |
| 177 class TouchEventQueue::TouchMoveSlopSuppressor { | 165 class TouchEventQueue::TouchMoveSlopSuppressor { |
| 178 public: | 166 public: |
| 179 TouchMoveSlopSuppressor(double slop_suppression_length_dips) | 167 TouchMoveSlopSuppressor(double slop_suppression_length_dips) |
| 180 : slop_suppression_length_dips_squared_(slop_suppression_length_dips * | 168 : slop_suppression_length_dips_squared_(slop_suppression_length_dips * |
| 181 slop_suppression_length_dips), | 169 slop_suppression_length_dips), |
| 182 suppressing_touch_moves_(false) {} | 170 suppressing_touch_moves_(false) {} |
| 183 | 171 |
| 184 bool FilterEvent(const WebTouchEvent& event) { | 172 bool FilterEvent(const WebTouchEvent& event) { |
| 185 if (IsNewTouchSequence(event)) { | 173 if (WebInputEventTraits::IsNewTouchSequence(event)) { |
| 186 touch_sequence_start_position_ = | 174 touch_sequence_start_position_ = |
| 187 gfx::Point(event.touches[0].position); | 175 gfx::Point(event.touches[0].position); |
| 188 suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0; | 176 suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0; |
| 189 } | 177 } |
| 190 | 178 |
| 191 if (event.type != WebInputEvent::TouchMove) | 179 if (event.type != WebInputEvent::TouchMove) |
| 192 return false; | 180 return false; |
| 193 | 181 |
| 194 if (suppressing_touch_moves_) { | 182 if (suppressing_touch_moves_) { |
| 195 // Movement with a secondary pointer should terminate suppression. | 183 // Movement with a secondary pointer should terminate suppression. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { | 298 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { |
| 311 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); | 299 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); |
| 312 | 300 |
| 313 // If the queueing of |event| was triggered by an ack dispatch, defer | 301 // If the queueing of |event| was triggered by an ack dispatch, defer |
| 314 // processing the event until the dispatch has finished. | 302 // processing the event until the dispatch has finished. |
| 315 if (touch_queue_.empty() && !dispatching_touch_ack_) { | 303 if (touch_queue_.empty() && !dispatching_touch_ack_) { |
| 316 // Optimization of the case without touch handlers. Removing this path | 304 // Optimization of the case without touch handlers. Removing this path |
| 317 // yields identical results, but this avoids unnecessary allocations. | 305 // yields identical results, but this avoids unnecessary allocations. |
| 318 if (touch_filtering_state_ == DROP_ALL_TOUCHES || | 306 if (touch_filtering_state_ == DROP_ALL_TOUCHES || |
| 319 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && | 307 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && |
| 320 !IsNewTouchSequence(event.event))) { | 308 !WebInputEventTraits::IsNewTouchSequence(event.event))) { |
| 321 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); | 309 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); |
| 322 return; | 310 return; |
| 323 } | 311 } |
| 324 | 312 |
| 325 // There is no touch event in the queue. Forward it to the renderer | 313 // There is no touch event in the queue. Forward it to the renderer |
| 326 // immediately. | 314 // immediately. |
| 327 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); | 315 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); |
| 328 TryForwardNextEventToRenderer(); | 316 TryForwardNextEventToRenderer(); |
| 329 return; | 317 return; |
| 330 } | 318 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 } | 377 } |
| 390 } | 378 } |
| 391 | 379 |
| 392 void TouchEventQueue::ForwardToRenderer( | 380 void TouchEventQueue::ForwardToRenderer( |
| 393 const TouchEventWithLatencyInfo& touch) { | 381 const TouchEventWithLatencyInfo& touch) { |
| 394 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); | 382 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); |
| 395 | 383 |
| 396 DCHECK(!dispatching_touch_); | 384 DCHECK(!dispatching_touch_); |
| 397 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); | 385 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); |
| 398 | 386 |
| 399 if (IsNewTouchSequence(touch.event)) { | 387 if (WebInputEventTraits::IsNewTouchSequence(touch.event)) { |
| 400 touch_filtering_state_ = | 388 touch_filtering_state_ = |
| 401 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT | 389 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT |
| 402 : FORWARD_ALL_TOUCHES; | 390 : FORWARD_ALL_TOUCHES; |
| 403 touch_ack_states_.clear(); | 391 touch_ack_states_.clear(); |
| 404 absorbing_touch_moves_ = false; | 392 absorbing_touch_moves_ = false; |
| 405 } | 393 } |
| 406 | 394 |
| 407 // A synchronous ack will reset |dispatching_touch_|, in which case | 395 // A synchronous ack will reset |dispatching_touch_|, in which case |
| 408 // the touch timeout should not be started. | 396 // the touch timeout should not be started. |
| 409 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | 397 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 return ACK_WITH_NO_CONSUMER_EXISTS; | 551 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 564 | 552 |
| 565 if (touchmove_slop_suppressor_->FilterEvent(event)) | 553 if (touchmove_slop_suppressor_->FilterEvent(event)) |
| 566 return ACK_WITH_NOT_CONSUMED; | 554 return ACK_WITH_NOT_CONSUMED; |
| 567 | 555 |
| 568 if (touch_filtering_state_ == DROP_ALL_TOUCHES) | 556 if (touch_filtering_state_ == DROP_ALL_TOUCHES) |
| 569 return ACK_WITH_NO_CONSUMER_EXISTS; | 557 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 570 | 558 |
| 571 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && | 559 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && |
| 572 event.type != WebInputEvent::TouchCancel) { | 560 event.type != WebInputEvent::TouchCancel) { |
| 573 if (IsNewTouchSequence(event)) | 561 if (WebInputEventTraits::IsNewTouchSequence(event)) |
| 574 return FORWARD_TO_RENDERER; | 562 return FORWARD_TO_RENDERER; |
| 575 return ACK_WITH_NOT_CONSUMED; | 563 return ACK_WITH_NOT_CONSUMED; |
| 576 } | 564 } |
| 577 | 565 |
| 578 if (absorbing_touch_moves_ && event.type == WebInputEvent::TouchMove) | 566 if (absorbing_touch_moves_ && event.type == WebInputEvent::TouchMove) |
| 579 return ACK_WITH_NOT_CONSUMED; | 567 return ACK_WITH_NOT_CONSUMED; |
| 580 | 568 |
| 581 // Touch press events should always be forwarded to the renderer. | 569 // Touch press events should always be forwarded to the renderer. |
| 582 if (event.type == WebInputEvent::TouchStart) | 570 if (event.type == WebInputEvent::TouchStart) |
| 583 return FORWARD_TO_RENDERER; | 571 return FORWARD_TO_RENDERER; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 } else if (event.type == WebInputEvent::TouchStart) { | 605 } else if (event.type == WebInputEvent::TouchStart) { |
| 618 for (unsigned i = 0; i < event.touchesLength; ++i) { | 606 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 619 const WebTouchPoint& point = event.touches[i]; | 607 const WebTouchPoint& point = event.touches[i]; |
| 620 if (point.state == WebTouchPoint::StatePressed) | 608 if (point.state == WebTouchPoint::StatePressed) |
| 621 touch_ack_states_[point.id] = ack_result; | 609 touch_ack_states_[point.id] = ack_result; |
| 622 } | 610 } |
| 623 } | 611 } |
| 624 } | 612 } |
| 625 | 613 |
| 626 } // namespace content | 614 } // namespace content |
| OLD | NEW |