| 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" |
| 11 #include "content/browser/renderer_host/input/timeout_monitor.h" | 11 #include "content/browser/renderer_host/input/timeout_monitor.h" |
| 12 #include "content/common/input/web_input_event_traits.h" | 12 #include "content/browser/renderer_host/input/web_touch_event_traits.h" |
| 13 #include "content/public/common/content_switches.h" | 13 #include "content/public/common/content_switches.h" |
| 14 #include "ui/gfx/geometry/point_f.h" | 14 #include "ui/gfx/geometry/point_f.h" |
| 15 | 15 |
| 16 using blink::WebInputEvent; | 16 using blink::WebInputEvent; |
| 17 using blink::WebTouchEvent; | 17 using blink::WebTouchEvent; |
| 18 using blink::WebTouchPoint; | 18 using blink::WebTouchPoint; |
| 19 using ui::LatencyInfo; | 19 using ui::LatencyInfo; |
| 20 | 20 |
| 21 namespace content { | 21 namespace content { |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 24 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| 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 !WebTouchEventTraits::IsTouchSequenceStart(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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 class TouchEventQueue::TouchMoveSlopSuppressor { | 165 class TouchEventQueue::TouchMoveSlopSuppressor { |
| 178 public: | 166 public: |
| 179 // TODO(jdduke): Remove int cast on suppression length, crbug.com/336807. | 167 // TODO(jdduke): Remove int cast on suppression length, crbug.com/336807. |
| 180 TouchMoveSlopSuppressor(double slop_suppression_length_dips) | 168 TouchMoveSlopSuppressor(double slop_suppression_length_dips) |
| 181 : slop_suppression_length_dips_squared_( | 169 : slop_suppression_length_dips_squared_( |
| 182 static_cast<int>(slop_suppression_length_dips) * | 170 static_cast<int>(slop_suppression_length_dips) * |
| 183 static_cast<int>(slop_suppression_length_dips)), | 171 static_cast<int>(slop_suppression_length_dips)), |
| 184 suppressing_touch_moves_(false) {} | 172 suppressing_touch_moves_(false) {} |
| 185 | 173 |
| 186 bool FilterEvent(const WebTouchEvent& event) { | 174 bool FilterEvent(const WebTouchEvent& event) { |
| 187 if (IsNewTouchSequence(event)) { | 175 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { |
| 188 touch_sequence_start_position_ = | 176 touch_sequence_start_position_ = |
| 189 gfx::Point(event.touches[0].position); | 177 gfx::Point(event.touches[0].position); |
| 190 suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0; | 178 suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0; |
| 191 } | 179 } |
| 192 | 180 |
| 193 if (event.type != WebInputEvent::TouchMove) | 181 if (event.type != WebInputEvent::TouchMove) |
| 194 return false; | 182 return false; |
| 195 | 183 |
| 196 if (suppressing_touch_moves_) { | 184 if (suppressing_touch_moves_) { |
| 197 // Movement with a secondary pointer should terminate suppression. | 185 // Movement with a secondary pointer should terminate suppression. |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { | 302 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { |
| 315 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); | 303 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); |
| 316 | 304 |
| 317 // If the queueing of |event| was triggered by an ack dispatch, defer | 305 // If the queueing of |event| was triggered by an ack dispatch, defer |
| 318 // processing the event until the dispatch has finished. | 306 // processing the event until the dispatch has finished. |
| 319 if (touch_queue_.empty() && !dispatching_touch_ack_) { | 307 if (touch_queue_.empty() && !dispatching_touch_ack_) { |
| 320 // Optimization of the case without touch handlers. Removing this path | 308 // Optimization of the case without touch handlers. Removing this path |
| 321 // yields identical results, but this avoids unnecessary allocations. | 309 // yields identical results, but this avoids unnecessary allocations. |
| 322 if (touch_filtering_state_ == DROP_ALL_TOUCHES || | 310 if (touch_filtering_state_ == DROP_ALL_TOUCHES || |
| 323 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && | 311 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && |
| 324 !IsNewTouchSequence(event.event))) { | 312 !WebTouchEventTraits::IsTouchSequenceStart(event.event))) { |
| 325 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); | 313 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); |
| 326 return; | 314 return; |
| 327 } | 315 } |
| 328 | 316 |
| 329 // There is no touch event in the queue. Forward it to the renderer | 317 // There is no touch event in the queue. Forward it to the renderer |
| 330 // immediately. | 318 // immediately. |
| 331 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); | 319 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); |
| 332 TryForwardNextEventToRenderer(); | 320 TryForwardNextEventToRenderer(); |
| 333 return; | 321 return; |
| 334 } | 322 } |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 } | 381 } |
| 394 } | 382 } |
| 395 | 383 |
| 396 void TouchEventQueue::ForwardToRenderer( | 384 void TouchEventQueue::ForwardToRenderer( |
| 397 const TouchEventWithLatencyInfo& touch) { | 385 const TouchEventWithLatencyInfo& touch) { |
| 398 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); | 386 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); |
| 399 | 387 |
| 400 DCHECK(!dispatching_touch_); | 388 DCHECK(!dispatching_touch_); |
| 401 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); | 389 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); |
| 402 | 390 |
| 403 if (IsNewTouchSequence(touch.event)) { | 391 if (WebTouchEventTraits::IsTouchSequenceStart(touch.event)) { |
| 404 touch_filtering_state_ = | 392 touch_filtering_state_ = |
| 405 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT | 393 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT |
| 406 : FORWARD_ALL_TOUCHES; | 394 : FORWARD_ALL_TOUCHES; |
| 407 touch_ack_states_.clear(); | 395 touch_ack_states_.clear(); |
| 408 absorbing_touch_moves_ = false; | 396 absorbing_touch_moves_ = false; |
| 409 } | 397 } |
| 410 | 398 |
| 411 // A synchronous ack will reset |dispatching_touch_|, in which case | 399 // A synchronous ack will reset |dispatching_touch_|, in which case |
| 412 // the touch timeout should not be started. | 400 // the touch timeout should not be started. |
| 413 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | 401 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 return ACK_WITH_NO_CONSUMER_EXISTS; | 555 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 568 | 556 |
| 569 if (touchmove_slop_suppressor_->FilterEvent(event)) | 557 if (touchmove_slop_suppressor_->FilterEvent(event)) |
| 570 return ACK_WITH_NOT_CONSUMED; | 558 return ACK_WITH_NOT_CONSUMED; |
| 571 | 559 |
| 572 if (touch_filtering_state_ == DROP_ALL_TOUCHES) | 560 if (touch_filtering_state_ == DROP_ALL_TOUCHES) |
| 573 return ACK_WITH_NO_CONSUMER_EXISTS; | 561 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 574 | 562 |
| 575 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && | 563 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && |
| 576 event.type != WebInputEvent::TouchCancel) { | 564 event.type != WebInputEvent::TouchCancel) { |
| 577 if (IsNewTouchSequence(event)) | 565 if (WebTouchEventTraits::IsTouchSequenceStart(event)) |
| 578 return FORWARD_TO_RENDERER; | 566 return FORWARD_TO_RENDERER; |
| 579 return ACK_WITH_NOT_CONSUMED; | 567 return ACK_WITH_NOT_CONSUMED; |
| 580 } | 568 } |
| 581 | 569 |
| 582 if (absorbing_touch_moves_ && event.type == WebInputEvent::TouchMove) | 570 if (absorbing_touch_moves_ && event.type == WebInputEvent::TouchMove) |
| 583 return ACK_WITH_NOT_CONSUMED; | 571 return ACK_WITH_NOT_CONSUMED; |
| 584 | 572 |
| 585 // Touch press events should always be forwarded to the renderer. | 573 // Touch press events should always be forwarded to the renderer. |
| 586 if (event.type == WebInputEvent::TouchStart) | 574 if (event.type == WebInputEvent::TouchStart) |
| 587 return FORWARD_TO_RENDERER; | 575 return FORWARD_TO_RENDERER; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 } else if (event.type == WebInputEvent::TouchStart) { | 609 } else if (event.type == WebInputEvent::TouchStart) { |
| 622 for (unsigned i = 0; i < event.touchesLength; ++i) { | 610 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 623 const WebTouchPoint& point = event.touches[i]; | 611 const WebTouchPoint& point = event.touches[i]; |
| 624 if (point.state == WebTouchPoint::StatePressed) | 612 if (point.state == WebTouchPoint::StatePressed) |
| 625 touch_ack_states_[point.id] = ack_result; | 613 touch_ack_states_[point.id] = ack_result; |
| 626 } | 614 } |
| 627 } | 615 } |
| 628 } | 616 } |
| 629 | 617 |
| 630 } // namespace content | 618 } // namespace content |
| OLD | NEW |