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 { | |
tdresser
2017/04/13 18:13:35
Should this move to another file? Or the anonymous
Navid Zolghadr
2017/04/18 14:47:41
This wasn't quite possible. At least I couldn't ge
tdresser
2017/04/18 15:20:26
Acknowledged.
| |
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 if (config.touch_ack_timeout_supported) { | 121 if (config.touch_ack_timeout_supported) { |
64 timeout_handler_.reset( | 122 timeout_handler_.reset( |
65 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, | 123 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, |
66 config.mobile_touch_ack_timeout_delay)); | 124 config.mobile_touch_ack_timeout_delay)); |
67 } | 125 } |
68 } | 126 } |
69 | 127 |
70 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} | 128 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} |
71 | 129 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 | 171 |
114 void PassthroughTouchEventQueue::ProcessTouchAck( | 172 void PassthroughTouchEventQueue::ProcessTouchAck( |
115 InputEventAckState ack_result, | 173 InputEventAckState ack_result, |
116 const LatencyInfo& latency_info, | 174 const LatencyInfo& latency_info, |
117 const uint32_t unique_touch_event_id) { | 175 const uint32_t unique_touch_event_id) { |
118 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); | 176 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); |
119 if (timeout_handler_ && | 177 if (timeout_handler_ && |
120 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) | 178 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) |
121 return; | 179 return; |
122 | 180 |
181 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); | |
182 | |
123 auto touch_event_iter = outstanding_touches_.begin(); | 183 auto touch_event_iter = outstanding_touches_.begin(); |
124 while (touch_event_iter != outstanding_touches_.end()) { | 184 while (touch_event_iter != outstanding_touches_.end()) { |
125 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) | 185 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) |
126 break; | 186 break; |
127 ++touch_event_iter; | 187 ++touch_event_iter; |
128 } | 188 } |
129 | 189 |
130 if (touch_event_iter == outstanding_touches_.end()) | 190 if (touch_event_iter == outstanding_touches_.end()) |
131 return; | 191 return; |
132 | 192 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 drop_remaining_touches_in_sequence_ = false; | 350 drop_remaining_touches_in_sequence_ = false; |
291 if (!has_handlers_) { | 351 if (!has_handlers_) { |
292 drop_remaining_touches_in_sequence_ = true; | 352 drop_remaining_touches_in_sequence_ = true; |
293 return ACK_WITH_NO_CONSUMER_EXISTS; | 353 return ACK_WITH_NO_CONSUMER_EXISTS; |
294 } | 354 } |
295 } | 355 } |
296 | 356 |
297 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) | 357 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) |
298 return ACK_WITH_NO_CONSUMER_EXISTS; | 358 return ACK_WITH_NO_CONSUMER_EXISTS; |
299 | 359 |
360 if (touchmove_slop_suppressor_->FilterEvent(event)) | |
361 return ACK_WITH_NOT_CONSUMED; | |
362 | |
300 if (drop_remaining_touches_in_sequence_ && | 363 if (drop_remaining_touches_in_sequence_ && |
301 event.GetType() != WebInputEvent::kTouchCancel) { | 364 event.GetType() != WebInputEvent::kTouchCancel) { |
302 return ACK_WITH_NO_CONSUMER_EXISTS; | 365 return ACK_WITH_NO_CONSUMER_EXISTS; |
303 } | 366 } |
304 | 367 |
305 if (event.GetType() == WebInputEvent::kTouchStart) { | 368 if (event.GetType() == WebInputEvent::kTouchStart) { |
306 return (has_handlers_ || maybe_has_handler_for_current_sequence_) | 369 return (has_handlers_ || maybe_has_handler_for_current_sequence_) |
307 ? FORWARD_TO_RENDERER | 370 ? FORWARD_TO_RENDERER |
308 : ACK_WITH_NO_CONSUMER_EXISTS; | 371 : ACK_WITH_NO_CONSUMER_EXISTS; |
309 } | 372 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
374 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { | 437 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { |
375 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); | 438 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); |
376 } | 439 } |
377 | 440 |
378 const TouchEventWithLatencyInfo& | 441 const TouchEventWithLatencyInfo& |
379 PassthroughTouchEventQueue::GetLatestEventForTesting() const { | 442 PassthroughTouchEventQueue::GetLatestEventForTesting() const { |
380 return *outstanding_touches_.rbegin(); | 443 return *outstanding_touches_.rbegin(); |
381 } | 444 } |
382 | 445 |
383 } // namespace content | 446 } // namespace content |
OLD | NEW |