Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Side by Side Diff: content/browser/renderer_host/input/legacy_touch_event_queue.cc

Issue 2669663002: Move touch slop suppression to TouchEventManager (Closed)
Patch Set: slop regesion Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/legacy_touch_event_queue.h" 5 #include "content/browser/renderer_host/input/legacy_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"
(...skipping 10 matching lines...) Expand all
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 // Time interval at which touchmove events will be forwarded to the client while 27 // Time interval at which touchmove events will be forwarded to the client while
28 // scrolling is active and possible. 28 // scrolling is active and possible.
29 const double kAsyncTouchMoveIntervalSec = .2; 29 const double kAsyncTouchMoveIntervalSec = .2;
30 30
31 // A sanity check on touches received to ensure that touch movement outside
32 // the platform slop region will cause scrolling.
33 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.;
34
35 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( 31 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
36 const TouchEventWithLatencyInfo& event_to_cancel) { 32 const TouchEventWithLatencyInfo& event_to_cancel) {
37 TouchEventWithLatencyInfo event = event_to_cancel; 33 TouchEventWithLatencyInfo event = event_to_cancel;
38 WebTouchEventTraits::ResetTypeAndTouchStates( 34 WebTouchEventTraits::ResetTypeAndTouchStates(
39 WebInputEvent::TouchCancel, 35 WebInputEvent::TouchCancel,
40 // TODO(rbyers): Shouldn't we use a fresh timestamp? 36 // TODO(rbyers): Shouldn't we use a fresh timestamp?
41 event.event.timeStampSeconds(), &event.event); 37 event.event.timeStampSeconds(), &event.event);
42 return event; 38 return event;
43 } 39 }
44 40
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 TimeoutMonitor timeout_monitor_; 268 TimeoutMonitor timeout_monitor_;
273 269
274 bool enabled_; 270 bool enabled_;
275 bool enabled_for_current_sequence_; 271 bool enabled_for_current_sequence_;
276 272
277 // Bookkeeping to classify and log whether a touch sequence times out. 273 // Bookkeeping to classify and log whether a touch sequence times out.
278 bool sequence_awaiting_uma_update_; 274 bool sequence_awaiting_uma_update_;
279 bool sequence_using_mobile_timeout_; 275 bool sequence_using_mobile_timeout_;
280 }; 276 };
281 277
282 // Provides touchmove slop suppression for a touch sequence until a
283 // (unprevented) touch will trigger immediate scrolling.
284 class LegacyTouchEventQueue::TouchMoveSlopSuppressor {
285 public:
286 TouchMoveSlopSuppressor() : suppressing_touchmoves_(false) {}
287
288 bool FilterEvent(const WebTouchEvent& event) {
289 if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
290 suppressing_touchmoves_ = true;
291 touch_start_location_ = gfx::PointF(event.touches[0].position);
292 }
293
294 if (event.type() == WebInputEvent::TouchEnd ||
295 event.type() == WebInputEvent::TouchCancel)
296 suppressing_touchmoves_ = false;
297
298 if (event.type() != WebInputEvent::TouchMove)
299 return false;
300
301 if (suppressing_touchmoves_) {
302 if (event.touchesLength > 1) {
303 suppressing_touchmoves_ = false;
304 } else if (event.movedBeyondSlopRegion) {
305 suppressing_touchmoves_ = false;
306 } else {
307 // No sane slop region should be larger than 60 DIPs.
308 DCHECK_LT(
309 (gfx::PointF(event.touches[0].position) - touch_start_location_)
310 .LengthSquared(),
311 kMaxConceivablePlatformSlopRegionLengthDipsSquared);
312 }
313 }
314
315 return suppressing_touchmoves_;
316 }
317
318 void ConfirmTouchEvent(InputEventAckState ack_result) {
319 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
320 suppressing_touchmoves_ = false;
321 }
322
323 bool suppressing_touchmoves() const { return suppressing_touchmoves_; }
324
325 private:
326 bool suppressing_touchmoves_;
327
328 // Sanity check that the upstream touch provider is properly reporting whether
329 // the touch sequence will cause scrolling.
330 gfx::PointF touch_start_location_;
331
332 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor);
333 };
334
335 // This class represents a single coalesced touch event. However, it also keeps 278 // This class represents a single coalesced touch event. However, it also keeps
336 // track of all the original touch-events that were coalesced into a single 279 // track of all the original touch-events that were coalesced into a single
337 // event. The coalesced event is forwarded to the renderer, while the original 280 // event. The coalesced event is forwarded to the renderer, while the original
338 // touch-events are sent to the Client (on ACK for the coalesced event) so that 281 // touch-events are sent to the Client (on ACK for the coalesced event) so that
339 // the Client receives the event with their original timestamp. 282 // the Client receives the event with their original timestamp.
340 class CoalescedWebTouchEvent { 283 class CoalescedWebTouchEvent {
341 public: 284 public:
342 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, 285 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
343 bool suppress_client_ack) 286 bool suppress_client_ack)
344 : coalesced_event_(event), suppress_client_ack_(suppress_client_ack) { 287 : coalesced_event_(event), suppress_client_ack_(suppress_client_ack) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 }; 362 };
420 363
421 LegacyTouchEventQueue::LegacyTouchEventQueue(TouchEventQueueClient* client, 364 LegacyTouchEventQueue::LegacyTouchEventQueue(TouchEventQueueClient* client,
422 const Config& config) 365 const Config& config)
423 : client_(client), 366 : client_(client),
424 dispatching_touch_ack_(false), 367 dispatching_touch_ack_(false),
425 dispatching_touch_(false), 368 dispatching_touch_(false),
426 has_handlers_(true), 369 has_handlers_(true),
427 has_handler_for_current_sequence_(false), 370 has_handler_for_current_sequence_(false),
428 drop_remaining_touches_in_sequence_(false), 371 drop_remaining_touches_in_sequence_(false),
429 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor),
430 send_touch_events_async_(false), 372 send_touch_events_async_(false),
431 last_sent_touch_timestamp_sec_(0) { 373 last_sent_touch_timestamp_sec_(0) {
432 if (config.touch_ack_timeout_supported) { 374 if (config.touch_ack_timeout_supported) {
433 timeout_handler_.reset( 375 timeout_handler_.reset(
434 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay, 376 new TouchTimeoutHandler(this, config.desktop_touch_ack_timeout_delay,
435 config.mobile_touch_ack_timeout_delay)); 377 config.mobile_touch_ack_timeout_delay));
436 } 378 }
437 } 379 }
438 380
439 LegacyTouchEventQueue::~LegacyTouchEventQueue() {} 381 LegacyTouchEventQueue::~LegacyTouchEventQueue() {}
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 } 468 }
527 return; 469 return;
528 } 470 }
529 471
530 DCHECK(!dispatching_touch_ack_); 472 DCHECK(!dispatching_touch_ack_);
531 dispatching_touch_ = false; 473 dispatching_touch_ = false;
532 474
533 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) 475 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result))
534 return; 476 return;
535 477
536 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result);
537
538 if (touch_queue_.empty()) 478 if (touch_queue_.empty())
539 return; 479 return;
540 480
541 // We don't care about the ordering of the acks vs the ordering of the 481 // We don't care about the ordering of the acks vs the ordering of the
542 // dispatched events because we can receive the ack for event B before the ack 482 // dispatched events because we can receive the ack for event B before the ack
543 // for event A even though A was sent before B. This seems to be happening 483 // for event A even though A was sent before B. This seems to be happening
544 // when, for example, A is acked from renderer but B isn't, so the ack for B 484 // when, for example, A is acked from renderer but B isn't, so the ack for B
545 // is synthesized "locally" in InputRouter. 485 // is synthesized "locally" in InputRouter.
546 // 486 //
547 // TODO(crbug.com/600773): Bring the id checks back when dispatch triggering 487 // TODO(crbug.com/600773): Bring the id checks back when dispatch triggering
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 std::move(pending_async_touchmove_); 589 std::move(pending_async_touchmove_);
650 touch->event.dispatchType = WebInputEvent::EventNonBlocking; 590 touch->event.dispatchType = WebInputEvent::EventNonBlocking;
651 touch_queue_.push_front( 591 touch_queue_.push_front(
652 base::MakeUnique<CoalescedWebTouchEvent>(*touch, true)); 592 base::MakeUnique<CoalescedWebTouchEvent>(*touch, true));
653 SendTouchEventImmediately(touch.get()); 593 SendTouchEventImmediately(touch.get());
654 } 594 }
655 595
656 void LegacyTouchEventQueue::OnGestureScrollEvent( 596 void LegacyTouchEventQueue::OnGestureScrollEvent(
657 const GestureEventWithLatencyInfo& gesture_event) { 597 const GestureEventWithLatencyInfo& gesture_event) {
658 if (gesture_event.event.type() == blink::WebInputEvent::GestureScrollBegin) { 598 if (gesture_event.event.type() == blink::WebInputEvent::GestureScrollBegin) {
659 if (has_handler_for_current_sequence_ &&
660 !drop_remaining_touches_in_sequence_) {
661 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves())
662 << "A touch handler should be offered a touchmove before scrolling.";
663 }
664
665 pending_async_touchmove_.reset(); 599 pending_async_touchmove_.reset();
666 600
667 return; 601 return;
668 } 602 }
669 603
670 if (gesture_event.event.type() == blink::WebInputEvent::GestureScrollUpdate && 604 if (gesture_event.event.type() == blink::WebInputEvent::GestureScrollUpdate &&
671 gesture_event.event.resendingPluginId == -1) { 605 gesture_event.event.resendingPluginId == -1) {
672 send_touch_events_async_ = true; 606 send_touch_events_async_ = true;
673 } 607 }
674 } 608 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 drop_remaining_touches_in_sequence_ = false; 798 drop_remaining_touches_in_sequence_ = false;
865 if (!has_handlers_) { 799 if (!has_handlers_) {
866 drop_remaining_touches_in_sequence_ = true; 800 drop_remaining_touches_in_sequence_ = true;
867 return ACK_WITH_NO_CONSUMER_EXISTS; 801 return ACK_WITH_NO_CONSUMER_EXISTS;
868 } 802 }
869 } 803 }
870 804
871 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) 805 if (timeout_handler_ && timeout_handler_->FilterEvent(event))
872 return ACK_WITH_NO_CONSUMER_EXISTS; 806 return ACK_WITH_NO_CONSUMER_EXISTS;
873 807
874 if (touchmove_slop_suppressor_->FilterEvent(event))
875 return ACK_WITH_NOT_CONSUMED;
876
877 if (drop_remaining_touches_in_sequence_ && 808 if (drop_remaining_touches_in_sequence_ &&
878 event.type() != WebInputEvent::TouchCancel) { 809 event.type() != WebInputEvent::TouchCancel) {
879 return ACK_WITH_NO_CONSUMER_EXISTS; 810 return ACK_WITH_NO_CONSUMER_EXISTS;
880 } 811 }
881 812
882 if (event.type() == WebInputEvent::TouchStart) { 813 if (event.type() == WebInputEvent::TouchStart) {
883 return (has_handlers_ || has_handler_for_current_sequence_) 814 return (has_handlers_ || has_handler_for_current_sequence_)
884 ? FORWARD_TO_RENDERER 815 ? FORWARD_TO_RENDERER
885 : ACK_WITH_NO_CONSUMER_EXISTS; 816 : ACK_WITH_NO_CONSUMER_EXISTS;
886 } 817 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 860 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
930 send_touch_events_async_ = false; 861 send_touch_events_async_ = false;
931 has_handler_for_current_sequence_ |= 862 has_handler_for_current_sequence_ |=
932 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; 863 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
933 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { 864 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) {
934 has_handler_for_current_sequence_ = false; 865 has_handler_for_current_sequence_ = false;
935 } 866 }
936 } 867 }
937 868
938 } // namespace content 869 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698