OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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/passthrough_touch_event_queue.h" | 5 #include "content/browser/renderer_host/input/passthrough_touch_event_queue.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/memory/ptr_util.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
13 #include "base/trace_event/trace_event.h" | 13 #include "base/trace_event/trace_event.h" |
14 #include "content/browser/renderer_host/input/touch_timeout_handler.h" | 14 #include "content/browser/renderer_host/input/touch_timeout_handler.h" |
15 #include "content/common/input/web_touch_event_traits.h" | 15 #include "content/common/input/web_touch_event_traits.h" |
16 #include "ui/events/base_event_utils.h" | 16 #include "ui/events/base_event_utils.h" |
17 #include "ui/gfx/geometry/point_f.h" | 17 #include "ui/gfx/geometry/point_f.h" |
18 | 18 |
19 using blink::WebInputEvent; | 19 using blink::WebInputEvent; |
20 using blink::WebTouchEvent; | 20 using blink::WebTouchEvent; |
21 using blink::WebTouchPoint; | 21 using blink::WebTouchPoint; |
22 using ui::LatencyInfo; | 22 using ui::LatencyInfo; |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 namespace { | 25 namespace { |
26 | 26 |
| 27 // A sanity check on touches received to ensure that touch movement outside |
| 28 // the platform slop region will cause scrolling. |
| 29 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.; |
| 30 |
27 // Compare all properties of touch points to determine the state. | 31 // Compare all properties of touch points to determine the state. |
28 bool HasPointChanged(const WebTouchPoint& point_1, | 32 bool HasPointChanged(const WebTouchPoint& point_1, |
29 const WebTouchPoint& point_2) { | 33 const WebTouchPoint& point_2) { |
30 DCHECK_EQ(point_1.id, point_2.id); | 34 DCHECK_EQ(point_1.id, point_2.id); |
31 if (point_1.screen_position != point_2.screen_position || | 35 if (point_1.screen_position != point_2.screen_position || |
32 point_1.position != point_2.position || | 36 point_1.position != point_2.position || |
33 point_1.radius_x != point_2.radius_x || | 37 point_1.radius_x != point_2.radius_x || |
34 point_1.radius_y != point_2.radius_y || | 38 point_1.radius_y != point_2.radius_y || |
35 point_1.rotation_angle != point_2.rotation_angle || | 39 point_1.rotation_angle != point_2.rotation_angle || |
36 point_1.force != point_2.force || point_1.tilt_x != point_2.tilt_x || | 40 point_1.force != point_2.force || point_1.tilt_x != point_2.tilt_x || |
37 point_1.tilt_y != point_2.tilt_y) { | 41 point_1.tilt_y != point_2.tilt_y) { |
38 return true; | 42 return true; |
39 } | 43 } |
40 return false; | 44 return false; |
41 } | 45 } |
42 | 46 |
43 } // namespace | 47 } // namespace |
44 | 48 |
| 49 // Provides touchmove slop suppression for a touch sequence until a |
| 50 // (unprevented) touch will trigger immediate scrolling. |
| 51 class TouchMoveSlopSuppressor { |
| 52 public: |
| 53 TouchMoveSlopSuppressor() : suppressing_touchmoves_(false) {} |
| 54 |
| 55 bool FilterEvent(const WebTouchEvent& event) { |
| 56 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { |
| 57 suppressing_touchmoves_ = true; |
| 58 touch_start_location_ = gfx::PointF(event.touches[0].position); |
| 59 } |
| 60 |
| 61 if (event.GetType() == WebInputEvent::kTouchEnd || |
| 62 event.GetType() == WebInputEvent::kTouchCancel) |
| 63 suppressing_touchmoves_ = false; |
| 64 |
| 65 if (event.GetType() != WebInputEvent::kTouchMove) |
| 66 return false; |
| 67 |
| 68 if (suppressing_touchmoves_) { |
| 69 if (event.touches_length > 1) { |
| 70 suppressing_touchmoves_ = false; |
| 71 } else if (event.moved_beyond_slop_region) { |
| 72 suppressing_touchmoves_ = false; |
| 73 } else { |
| 74 // No sane slop region should be larger than 60 DIPs. |
| 75 DCHECK_LT( |
| 76 (gfx::PointF(event.touches[0].position) - touch_start_location_) |
| 77 .LengthSquared(), |
| 78 kMaxConceivablePlatformSlopRegionLengthDipsSquared); |
| 79 } |
| 80 } |
| 81 |
| 82 return suppressing_touchmoves_; |
| 83 } |
| 84 |
| 85 void ConfirmTouchEvent(InputEventAckState ack_result) { |
| 86 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 87 suppressing_touchmoves_ = false; |
| 88 } |
| 89 |
| 90 bool suppressing_touchmoves() const { return suppressing_touchmoves_; } |
| 91 |
| 92 private: |
| 93 bool suppressing_touchmoves_; |
| 94 |
| 95 // Sanity check that the upstream touch provider is properly reporting whether |
| 96 // the touch sequence will cause scrolling. |
| 97 gfx::PointF touch_start_location_; |
| 98 |
| 99 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); |
| 100 }; |
| 101 |
45 PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: | 102 PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: |
46 TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event) | 103 TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event) |
47 : TouchEventWithLatencyInfo(event), | 104 : TouchEventWithLatencyInfo(event), |
48 ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} | 105 ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} |
49 | 106 |
50 bool PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: | 107 bool PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: |
51 operator<(const TouchEventWithLatencyInfoAndAckState& other) const { | 108 operator<(const TouchEventWithLatencyInfoAndAckState& other) const { |
52 return event.unique_touch_event_id < other.event.unique_touch_event_id; | 109 return event.unique_touch_event_id < other.event.unique_touch_event_id; |
53 } | 110 } |
54 | 111 |
55 PassthroughTouchEventQueue::PassthroughTouchEventQueue( | 112 PassthroughTouchEventQueue::PassthroughTouchEventQueue( |
56 TouchEventQueueClient* client, | 113 TouchEventQueueClient* client, |
57 const Config& config) | 114 const Config& config) |
58 : client_(client), | 115 : client_(client), |
59 has_handlers_(true), | 116 has_handlers_(true), |
60 maybe_has_handler_for_current_sequence_(false), | 117 maybe_has_handler_for_current_sequence_(false), |
61 drop_remaining_touches_in_sequence_(false), | 118 drop_remaining_touches_in_sequence_(false), |
| 119 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), |
62 send_touch_events_async_(false), | 120 send_touch_events_async_(false), |
63 processing_acks_(false) { | 121 processing_acks_(false) { |
64 if (config.touch_ack_timeout_supported) { | 122 if (config.touch_ack_timeout_supported) { |
65 timeout_handler_.reset( | 123 timeout_handler_.reset( |
66 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, | 124 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, |
67 config.mobile_touch_ack_timeout_delay)); | 125 config.mobile_touch_ack_timeout_delay)); |
68 } | 126 } |
69 } | 127 } |
70 | 128 |
71 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} | 129 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 | 172 |
115 void PassthroughTouchEventQueue::ProcessTouchAck( | 173 void PassthroughTouchEventQueue::ProcessTouchAck( |
116 InputEventAckState ack_result, | 174 InputEventAckState ack_result, |
117 const LatencyInfo& latency_info, | 175 const LatencyInfo& latency_info, |
118 const uint32_t unique_touch_event_id) { | 176 const uint32_t unique_touch_event_id) { |
119 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); | 177 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); |
120 if (timeout_handler_ && | 178 if (timeout_handler_ && |
121 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) | 179 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) |
122 return; | 180 return; |
123 | 181 |
| 182 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); |
| 183 |
124 auto touch_event_iter = outstanding_touches_.begin(); | 184 auto touch_event_iter = outstanding_touches_.begin(); |
125 while (touch_event_iter != outstanding_touches_.end()) { | 185 while (touch_event_iter != outstanding_touches_.end()) { |
126 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) | 186 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) |
127 break; | 187 break; |
128 ++touch_event_iter; | 188 ++touch_event_iter; |
129 } | 189 } |
130 | 190 |
131 if (touch_event_iter == outstanding_touches_.end()) | 191 if (touch_event_iter == outstanding_touches_.end()) |
132 return; | 192 return; |
133 | 193 |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 drop_remaining_touches_in_sequence_ = false; | 356 drop_remaining_touches_in_sequence_ = false; |
297 if (!has_handlers_) { | 357 if (!has_handlers_) { |
298 drop_remaining_touches_in_sequence_ = true; | 358 drop_remaining_touches_in_sequence_ = true; |
299 return ACK_WITH_NO_CONSUMER_EXISTS; | 359 return ACK_WITH_NO_CONSUMER_EXISTS; |
300 } | 360 } |
301 } | 361 } |
302 | 362 |
303 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) | 363 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) |
304 return ACK_WITH_NO_CONSUMER_EXISTS; | 364 return ACK_WITH_NO_CONSUMER_EXISTS; |
305 | 365 |
| 366 if (touchmove_slop_suppressor_->FilterEvent(event)) |
| 367 return ACK_WITH_NOT_CONSUMED; |
| 368 |
306 if (drop_remaining_touches_in_sequence_ && | 369 if (drop_remaining_touches_in_sequence_ && |
307 event.GetType() != WebInputEvent::kTouchCancel) { | 370 event.GetType() != WebInputEvent::kTouchCancel) { |
308 return ACK_WITH_NO_CONSUMER_EXISTS; | 371 return ACK_WITH_NO_CONSUMER_EXISTS; |
309 } | 372 } |
310 | 373 |
311 if (event.GetType() == WebInputEvent::kTouchStart) { | 374 if (event.GetType() == WebInputEvent::kTouchStart) { |
312 return (has_handlers_ || maybe_has_handler_for_current_sequence_) | 375 return (has_handlers_ || maybe_has_handler_for_current_sequence_) |
313 ? FORWARD_TO_RENDERER | 376 ? FORWARD_TO_RENDERER |
314 : ACK_WITH_NO_CONSUMER_EXISTS; | 377 : ACK_WITH_NO_CONSUMER_EXISTS; |
315 } | 378 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
380 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { | 443 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { |
381 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); | 444 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); |
382 } | 445 } |
383 | 446 |
384 const TouchEventWithLatencyInfo& | 447 const TouchEventWithLatencyInfo& |
385 PassthroughTouchEventQueue::GetLatestEventForTesting() const { | 448 PassthroughTouchEventQueue::GetLatestEventForTesting() const { |
386 return *outstanding_touches_.rbegin(); | 449 return *outstanding_touches_.rbegin(); |
387 } | 450 } |
388 | 451 |
389 } // namespace content | 452 } // namespace content |
OLD | NEW |