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 |