| 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 | |
| 31 // Compare all properties of touch points to determine the state. | 27 // Compare all properties of touch points to determine the state. |
| 32 bool HasPointChanged(const WebTouchPoint& point_1, | 28 bool HasPointChanged(const WebTouchPoint& point_1, |
| 33 const WebTouchPoint& point_2) { | 29 const WebTouchPoint& point_2) { |
| 34 DCHECK_EQ(point_1.id, point_2.id); | 30 DCHECK_EQ(point_1.id, point_2.id); |
| 35 if (point_1.screen_position != point_2.screen_position || | 31 if (point_1.screen_position != point_2.screen_position || |
| 36 point_1.position != point_2.position || | 32 point_1.position != point_2.position || |
| 37 point_1.radius_x != point_2.radius_x || | 33 point_1.radius_x != point_2.radius_x || |
| 38 point_1.radius_y != point_2.radius_y || | 34 point_1.radius_y != point_2.radius_y || |
| 39 point_1.rotation_angle != point_2.rotation_angle || | 35 point_1.rotation_angle != point_2.rotation_angle || |
| 40 point_1.force != point_2.force || point_1.tilt_x != point_2.tilt_x || | 36 point_1.force != point_2.force || point_1.tilt_x != point_2.tilt_x || |
| 41 point_1.tilt_y != point_2.tilt_y) { | 37 point_1.tilt_y != point_2.tilt_y) { |
| 42 return true; | 38 return true; |
| 43 } | 39 } |
| 44 return false; | 40 return false; |
| 45 } | 41 } |
| 46 | 42 |
| 47 } // namespace | 43 } // namespace |
| 48 | 44 |
| 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 | |
| 102 PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: | 45 PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: |
| 103 TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event) | 46 TouchEventWithLatencyInfoAndAckState(const TouchEventWithLatencyInfo& event) |
| 104 : TouchEventWithLatencyInfo(event), | 47 : TouchEventWithLatencyInfo(event), |
| 105 ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} | 48 ack_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {} |
| 106 | 49 |
| 107 bool PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: | 50 bool PassthroughTouchEventQueue::TouchEventWithLatencyInfoAndAckState:: |
| 108 operator<(const TouchEventWithLatencyInfoAndAckState& other) const { | 51 operator<(const TouchEventWithLatencyInfoAndAckState& other) const { |
| 109 return event.unique_touch_event_id < other.event.unique_touch_event_id; | 52 return event.unique_touch_event_id < other.event.unique_touch_event_id; |
| 110 } | 53 } |
| 111 | 54 |
| 112 PassthroughTouchEventQueue::PassthroughTouchEventQueue( | 55 PassthroughTouchEventQueue::PassthroughTouchEventQueue( |
| 113 TouchEventQueueClient* client, | 56 TouchEventQueueClient* client, |
| 114 const Config& config) | 57 const Config& config) |
| 115 : client_(client), | 58 : client_(client), |
| 116 has_handlers_(true), | 59 has_handlers_(true), |
| 117 maybe_has_handler_for_current_sequence_(false), | 60 maybe_has_handler_for_current_sequence_(false), |
| 118 drop_remaining_touches_in_sequence_(false), | 61 drop_remaining_touches_in_sequence_(false), |
| 119 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), | |
| 120 send_touch_events_async_(false) { | 62 send_touch_events_async_(false) { |
| 121 if (config.touch_ack_timeout_supported) { | 63 if (config.touch_ack_timeout_supported) { |
| 122 timeout_handler_.reset( | 64 timeout_handler_.reset( |
| 123 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, | 65 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, |
| 124 config.mobile_touch_ack_timeout_delay)); | 66 config.mobile_touch_ack_timeout_delay)); |
| 125 } | 67 } |
| 126 } | 68 } |
| 127 | 69 |
| 128 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} | 70 PassthroughTouchEventQueue::~PassthroughTouchEventQueue() {} |
| 129 | 71 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 | 113 |
| 172 void PassthroughTouchEventQueue::ProcessTouchAck( | 114 void PassthroughTouchEventQueue::ProcessTouchAck( |
| 173 InputEventAckState ack_result, | 115 InputEventAckState ack_result, |
| 174 const LatencyInfo& latency_info, | 116 const LatencyInfo& latency_info, |
| 175 const uint32_t unique_touch_event_id) { | 117 const uint32_t unique_touch_event_id) { |
| 176 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); | 118 TRACE_EVENT0("input", "PassthroughTouchEventQueue::ProcessTouchAck"); |
| 177 if (timeout_handler_ && | 119 if (timeout_handler_ && |
| 178 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) | 120 timeout_handler_->ConfirmTouchEvent(unique_touch_event_id, ack_result)) |
| 179 return; | 121 return; |
| 180 | 122 |
| 181 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); | |
| 182 | |
| 183 auto touch_event_iter = outstanding_touches_.begin(); | 123 auto touch_event_iter = outstanding_touches_.begin(); |
| 184 while (touch_event_iter != outstanding_touches_.end()) { | 124 while (touch_event_iter != outstanding_touches_.end()) { |
| 185 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) | 125 if (unique_touch_event_id == touch_event_iter->event.unique_touch_event_id) |
| 186 break; | 126 break; |
| 187 ++touch_event_iter; | 127 ++touch_event_iter; |
| 188 } | 128 } |
| 189 | 129 |
| 190 if (touch_event_iter == outstanding_touches_.end()) | 130 if (touch_event_iter == outstanding_touches_.end()) |
| 191 return; | 131 return; |
| 192 | 132 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 drop_remaining_touches_in_sequence_ = false; | 290 drop_remaining_touches_in_sequence_ = false; |
| 351 if (!has_handlers_) { | 291 if (!has_handlers_) { |
| 352 drop_remaining_touches_in_sequence_ = true; | 292 drop_remaining_touches_in_sequence_ = true; |
| 353 return ACK_WITH_NO_CONSUMER_EXISTS; | 293 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 354 } | 294 } |
| 355 } | 295 } |
| 356 | 296 |
| 357 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) | 297 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) |
| 358 return ACK_WITH_NO_CONSUMER_EXISTS; | 298 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 359 | 299 |
| 360 if (touchmove_slop_suppressor_->FilterEvent(event)) | |
| 361 return ACK_WITH_NOT_CONSUMED; | |
| 362 | |
| 363 if (drop_remaining_touches_in_sequence_ && | 300 if (drop_remaining_touches_in_sequence_ && |
| 364 event.GetType() != WebInputEvent::kTouchCancel) { | 301 event.GetType() != WebInputEvent::kTouchCancel) { |
| 365 return ACK_WITH_NO_CONSUMER_EXISTS; | 302 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 366 } | 303 } |
| 367 | 304 |
| 368 if (event.GetType() == WebInputEvent::kTouchStart) { | 305 if (event.GetType() == WebInputEvent::kTouchStart) { |
| 369 return (has_handlers_ || maybe_has_handler_for_current_sequence_) | 306 return (has_handlers_ || maybe_has_handler_for_current_sequence_) |
| 370 ? FORWARD_TO_RENDERER | 307 ? FORWARD_TO_RENDERER |
| 371 : ACK_WITH_NO_CONSUMER_EXISTS; | 308 : ACK_WITH_NO_CONSUMER_EXISTS; |
| 372 } | 309 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 437 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { | 374 bool PassthroughTouchEventQueue::IsTimeoutRunningForTesting() const { |
| 438 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); | 375 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); |
| 439 } | 376 } |
| 440 | 377 |
| 441 const TouchEventWithLatencyInfo& | 378 const TouchEventWithLatencyInfo& |
| 442 PassthroughTouchEventQueue::GetLatestEventForTesting() const { | 379 PassthroughTouchEventQueue::GetLatestEventForTesting() const { |
| 443 return *outstanding_touches_.rbegin(); | 380 return *outstanding_touches_.rbegin(); |
| 444 } | 381 } |
| 445 | 382 |
| 446 } // namespace content | 383 } // namespace content |
| OLD | NEW |