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

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

Issue 1800143002: Notify Blink about start of gesture scroll through a queued event. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 8 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/touch_event_queue.h" 5 #include "content/browser/renderer_host/input/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 ui::LatencyInfo; 21 using ui::LatencyInfo;
22 22
23 namespace content { 23 namespace content {
24 namespace { 24 namespace {
25 25
26 // Time interval at which touchmove events will be forwarded to the client while 26 // Time interval at which touchmove events will be forwarded to the client while
27 // scrolling is active and possible. 27 // scrolling is active and possible.
28 const double kAsyncTouchMoveIntervalSec = .2; 28 const double kAsyncTouchMoveIntervalSec = .2;
29 29
30 // A sanity check on touches received to ensure that touch movement outside 30 // A sanity check on touches received to ensure that touch movement outside
31 // the platform slop region will cause scrolling, as indicated by the event's 31 // the platform slop region will cause scrolling.
32 // |causesScrollingIfUncanceled| bit.
33 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.; 32 const double kMaxConceivablePlatformSlopRegionLengthDipsSquared = 60. * 60.;
34 33
35 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( 34 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
36 const TouchEventWithLatencyInfo& event_to_cancel) { 35 const TouchEventWithLatencyInfo& event_to_cancel) {
37 TouchEventWithLatencyInfo event = event_to_cancel; 36 TouchEventWithLatencyInfo event = event_to_cancel;
38 WebTouchEventTraits::ResetTypeAndTouchStates( 37 WebTouchEventTraits::ResetTypeAndTouchStates(
39 WebInputEvent::TouchCancel, 38 WebInputEvent::TouchCancel,
40 // TODO(rbyers): Shouldn't we use a fresh timestamp? 39 // TODO(rbyers): Shouldn't we use a fresh timestamp?
41 event.event.timeStampSeconds, 40 event.event.timeStampSeconds,
42 &event.event); 41 &event.event);
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
484 // If the last queued touch-event was a touch-move, and the current event is 483 // If the last queued touch-event was a touch-move, and the current event is
485 // also a touch-move, then the events can be coalesced into a single event. 484 // also a touch-move, then the events can be coalesced into a single event.
486 if (touch_queue_.size() > 1) { 485 if (touch_queue_.size() > 1) {
487 CoalescedWebTouchEvent* last_event = touch_queue_.back(); 486 CoalescedWebTouchEvent* last_event = touch_queue_.back();
488 if (last_event->CoalesceEventIfPossible(event)) 487 if (last_event->CoalesceEventIfPossible(event))
489 return; 488 return;
490 } 489 }
491 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); 490 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
492 } 491 }
493 492
493 void TouchEventQueue::PrependTouchScrollNotification() {
494 TRACE_EVENT0("input", "TouchEventQueue::PrependTouchScrollNotification");
495
496 // The queue should have an in-flight event when this method is called because
497 // this method is triggered by InputRouterImpl::SendGestureEvent, which is
498 // triggered by TouchEventQueue::AckTouchEventToClient, which has just
499 // received an ack for the in-flight event. We leave the head of the queue
500 // untouched since it is the in-flight event.
501 //
502 // However, for the (integration) tests in RenderWidgetHostTest that trigger
503 // this method indirectly, they push the TouchScrollStarted event into
504 // TouchEventQueue without any way to dispatch it. Below we added a check for
505 // non-empty queue to keep those tests as-is w/o exposing internals of this
506 // class all the way up.
507 if (!touch_queue_.empty()) {
508 TouchEventWithLatencyInfo touch;
509 touch.event.type = WebInputEvent::TouchScrollStarted;
510 touch.event.uniqueTouchEventId = 0;
511 touch.event.touchesLength = 0;
512
513 auto it = touch_queue_.begin();
514 DCHECK(it != touch_queue_.end());
515 touch_queue_.insert(++it, new CoalescedWebTouchEvent(touch, false));
516 }
517 }
518
494 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, 519 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
495 const LatencyInfo& latency_info, 520 const LatencyInfo& latency_info,
496 const uint32_t unique_touch_event_id) { 521 const uint32_t unique_touch_event_id) {
497 TRACE_EVENT0("input", "TouchEventQueue::ProcessTouchAck"); 522 TRACE_EVENT0("input", "TouchEventQueue::ProcessTouchAck");
498 523
499 // We receive an ack for async touchmove from render. 524 // We receive an ack for async touchmove from render.
500 if (!ack_pending_async_touchmove_ids_.empty() && 525 if (!ack_pending_async_touchmove_ids_.empty() &&
501 ack_pending_async_touchmove_ids_.front() == unique_touch_event_id) { 526 ack_pending_async_touchmove_ids_.front() == unique_touch_event_id) {
502 // Remove the first touchmove from the ack_pending_async_touchmove queue. 527 // Remove the first touchmove from the ack_pending_async_touchmove queue.
503 ack_pending_async_touchmove_ids_.pop_front(); 528 ack_pending_async_touchmove_ids_.pop_front();
(...skipping 14 matching lines...) Expand all
518 dispatching_touch_ = false; 543 dispatching_touch_ = false;
519 544
520 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) 545 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result))
521 return; 546 return;
522 547
523 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); 548 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result);
524 549
525 if (touch_queue_.empty()) 550 if (touch_queue_.empty())
526 return; 551 return;
527 552
528 DCHECK_EQ(touch_queue_.front()->coalesced_event().event.uniqueTouchEventId, 553 // We don't care about the ordering of the acks vs the ordering of the
529 unique_touch_event_id); 554 // dispatched events because we can receive the ack for event B before the ack
555 // for event A even though A was sent before B. This seems to be happening
556 // when, for example, A is acked from renderer but B isn't, so the ack for B
557 // is synthesized "locally" in InputRouter.
558 //
559 // TODO(crbug.com/600773): Bring the id checks back when dispatch triggering
560 // is sane.
530 561
531 PopTouchEventToClient(ack_result, latency_info); 562 PopTouchEventToClient(ack_result, latency_info);
532 TryForwardNextEventToRenderer(); 563 TryForwardNextEventToRenderer();
533 } 564 }
534 565
535 void TouchEventQueue::TryForwardNextEventToRenderer() { 566 void TouchEventQueue::TryForwardNextEventToRenderer() {
536 DCHECK(!dispatching_touch_ack_); 567 DCHECK(!dispatching_touch_ack_);
537 // If there are queued touch events, then try to forward them to the renderer 568 // If there are queued touch events, then try to forward them to the renderer
538 // immediately, or ACK the events back to the client if appropriate. 569 // immediately, or ACK the events back to the client if appropriate.
539 while (!touch_queue_.empty()) { 570 while (!touch_queue_.empty()) {
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 void TouchEventQueue::FlushQueue() { 743 void TouchEventQueue::FlushQueue() {
713 DCHECK(!dispatching_touch_ack_); 744 DCHECK(!dispatching_touch_ack_);
714 DCHECK(!dispatching_touch_); 745 DCHECK(!dispatching_touch_);
715 pending_async_touchmove_.reset(); 746 pending_async_touchmove_.reset();
716 drop_remaining_touches_in_sequence_ = true; 747 drop_remaining_touches_in_sequence_ = true;
717 while (!touch_queue_.empty()) 748 while (!touch_queue_.empty())
718 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); 749 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
719 } 750 }
720 751
721 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) { 752 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) {
722 AckTouchEventToClient(ack_result, PopTouchEvent(), nullptr); 753 AckTouchEventToClient(ack_result, nullptr);
723 } 754 }
724 755
725 void TouchEventQueue::PopTouchEventToClient( 756 void TouchEventQueue::PopTouchEventToClient(
726 InputEventAckState ack_result, 757 InputEventAckState ack_result,
727 const LatencyInfo& renderer_latency_info) { 758 const LatencyInfo& renderer_latency_info) {
728 AckTouchEventToClient(ack_result, PopTouchEvent(), &renderer_latency_info); 759 AckTouchEventToClient(ack_result, &renderer_latency_info);
729 } 760 }
730 761
731 void TouchEventQueue::AckTouchEventToClient( 762 void TouchEventQueue::AckTouchEventToClient(
732 InputEventAckState ack_result, 763 InputEventAckState ack_result,
733 std::unique_ptr<CoalescedWebTouchEvent> acked_event,
734 const ui::LatencyInfo* optional_latency_info) { 764 const ui::LatencyInfo* optional_latency_info) {
765 DCHECK(!dispatching_touch_ack_);
766 DCHECK(!touch_queue_.empty());
767 std::unique_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
735 DCHECK(acked_event); 768 DCHECK(acked_event);
736 DCHECK(!dispatching_touch_ack_); 769
737 UpdateTouchConsumerStates(acked_event->coalesced_event().event, ack_result); 770 UpdateTouchConsumerStates(acked_event->coalesced_event().event, ack_result);
738 771
739 // Note that acking the touch-event may result in multiple gestures being sent 772 // Note that acking the touch-event may result in multiple gestures being sent
740 // to the renderer, or touch-events being queued. 773 // to the renderer, or touch-events being queued.
741 base::AutoReset<bool> dispatching_touch_ack(&dispatching_touch_ack_, true); 774 base::AutoReset<bool> dispatching_touch_ack(&dispatching_touch_ack_, true);
742 acked_event->DispatchAckToClient(ack_result, optional_latency_info, client_);
743 }
744 775
745 std::unique_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { 776 // Skip ack for TouchScrollStarted since it was synthesized within the queue.
746 DCHECK(!touch_queue_.empty()); 777 if (acked_event->coalesced_event().event.type !=
747 std::unique_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); 778 WebInputEvent::TouchScrollStarted) {
779 acked_event->DispatchAckToClient(ack_result, optional_latency_info,
780 client_);
781 }
782
748 touch_queue_.pop_front(); 783 touch_queue_.pop_front();
749 return event;
750 } 784 }
751 785
752 void TouchEventQueue::SendTouchEventImmediately( 786 void TouchEventQueue::SendTouchEventImmediately(
753 TouchEventWithLatencyInfo* touch) { 787 TouchEventWithLatencyInfo* touch) {
788 // TODO(crbug.com/600773): Hack to avoid cyclic reentry to this method.
789 if (dispatching_touch_)
790 return;
791
754 // For touchmove events, compare touch points position from current event 792 // For touchmove events, compare touch points position from current event
755 // to last sent event and update touch points state. 793 // to last sent event and update touch points state.
756 if (touch->event.type == WebInputEvent::TouchMove) { 794 if (touch->event.type == WebInputEvent::TouchMove) {
757 CHECK(last_sent_touchevent_); 795 CHECK(last_sent_touchevent_);
758 for (unsigned int i = 0; i < last_sent_touchevent_->touchesLength; ++i) { 796 for (unsigned int i = 0; i < last_sent_touchevent_->touchesLength; ++i) {
759 const WebTouchPoint& last_touch_point = 797 const WebTouchPoint& last_touch_point =
760 last_sent_touchevent_->touches[i]; 798 last_sent_touchevent_->touches[i];
761 // Touches with same id may not have same index in Touches array. 799 // Touches with same id may not have same index in Touches array.
762 for (unsigned int j = 0; j < touch->event.touchesLength; ++j) { 800 for (unsigned int j = 0; j < touch->event.touchesLength; ++j) {
763 const WebTouchPoint& current_touchmove_point = touch->event.touches[j]; 801 const WebTouchPoint& current_touchmove_point = touch->event.touches[j];
764 if (current_touchmove_point.id != last_touch_point.id) 802 if (current_touchmove_point.id != last_touch_point.id)
765 continue; 803 continue;
766 804
767 if (!HasPointChanged(last_touch_point, current_touchmove_point)) 805 if (!HasPointChanged(last_touch_point, current_touchmove_point))
768 touch->event.touches[j].state = WebTouchPoint::StateStationary; 806 touch->event.touches[j].state = WebTouchPoint::StateStationary;
769 807
770 break; 808 break;
771 } 809 }
772 } 810 }
773 } 811 }
774 812
775 if (last_sent_touchevent_) 813 if (touch->event.type != WebInputEvent::TouchScrollStarted) {
776 *last_sent_touchevent_ = touch->event; 814 if (last_sent_touchevent_)
777 else 815 *last_sent_touchevent_ = touch->event;
778 last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); 816 else
817 last_sent_touchevent_.reset(new WebTouchEvent(touch->event));
818 }
779 819
780 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); 820 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
781 821
782 client_->SendTouchEventImmediately(*touch); 822 client_->SendTouchEventImmediately(*touch);
783 823
784 // A synchronous ack will reset |dispatching_touch_|, in which case the touch 824 // A synchronous ack will reset |dispatching_touch_|, in which case the touch
785 // timeout should not be started and the count also should not be increased. 825 // timeout should not be started and the count also should not be increased.
786 if (dispatching_touch_) { 826 if (dispatching_touch_) {
787 if (touch->event.type == WebInputEvent::TouchMove && 827 if (touch->event.type == WebInputEvent::TouchMove &&
788 !touch->event.cancelable) { 828 !touch->event.cancelable) {
789 // When we send out a uncancelable touch move, we increase the count and 829 // When we send out a uncancelable touch move, we increase the count and
790 // we do not process input event ack any more, we will just ack to client 830 // we do not process input event ack any more, we will just ack to client
791 // and wait for the ack from render. Also we will remove it from the front 831 // and wait for the ack from render. Also we will remove it from the front
792 // of the queue. 832 // of the queue.
793 ack_pending_async_touchmove_ids_.push_back( 833 ack_pending_async_touchmove_ids_.push_back(
794 touch->event.uniqueTouchEventId); 834 touch->event.uniqueTouchEventId);
795 dispatching_touch_ = false; 835 dispatching_touch_ = false;
796 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_IGNORED); 836 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_IGNORED);
797 TryForwardNextEventToRenderer(); 837 TryForwardNextEventToRenderer();
798 return; 838 return;
799 } 839 }
800 840
801 if (timeout_handler_) 841 if (timeout_handler_)
802 timeout_handler_->StartIfNecessary(*touch); 842 timeout_handler_->StartIfNecessary(*touch);
803 } 843 }
804 } 844 }
805 845
806 TouchEventQueue::PreFilterResult 846 TouchEventQueue::PreFilterResult
807 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { 847 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
848 if (event.type == WebInputEvent::TouchScrollStarted)
849 return FORWARD_TO_RENDERER;
850
808 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { 851 if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
809 has_handler_for_current_sequence_ = false; 852 has_handler_for_current_sequence_ = false;
810 send_touch_events_async_ = false; 853 send_touch_events_async_ = false;
811 pending_async_touchmove_.reset(); 854 pending_async_touchmove_.reset();
812 last_sent_touchevent_.reset(); 855 last_sent_touchevent_.reset();
813 856
814 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position); 857 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position);
815 drop_remaining_touches_in_sequence_ = false; 858 drop_remaining_touches_in_sequence_ = false;
816 if (!has_handlers_) { 859 if (!has_handlers_) {
817 drop_remaining_touches_in_sequence_ = true; 860 drop_remaining_touches_in_sequence_ = true;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 923 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
881 send_touch_events_async_ = false; 924 send_touch_events_async_ = false;
882 has_handler_for_current_sequence_ |= 925 has_handler_for_current_sequence_ |=
883 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; 926 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
884 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { 927 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) {
885 has_handler_for_current_sequence_ = false; 928 has_handler_for_current_sequence_ = false;
886 } 929 }
887 } 930 }
888 931
889 } // namespace content 932 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698