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

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

Issue 788923002: Touch Events - changedTouches list includes non-changed touch points on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Added unit test for checking Pointer states when other than position changed. Created 5 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/touch_event_queue.h" 5 #include "content/browser/renderer_host/input/touch_event_queue.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "base/trace_event/trace_event.h" 9 #include "base/trace_event/trace_event.h"
10 #include "content/browser/renderer_host/input/timeout_monitor.h" 10 #include "content/browser/renderer_host/input/timeout_monitor.h"
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 event.type == WebInputEvent::TouchMove) && 49 event.type == WebInputEvent::TouchMove) &&
50 !WebInputEventTraits::IgnoresAckDisposition(event); 50 !WebInputEventTraits::IgnoresAckDisposition(event);
51 } 51 }
52 52
53 bool OutsideApplicationSlopRegion(const WebTouchEvent& event, 53 bool OutsideApplicationSlopRegion(const WebTouchEvent& event,
54 const gfx::PointF& anchor) { 54 const gfx::PointF& anchor) {
55 return (gfx::PointF(event.touches[0].position) - anchor).LengthSquared() > 55 return (gfx::PointF(event.touches[0].position) - anchor).LengthSquared() >
56 kApplicationSlopRegionLengthDipsSqared; 56 kApplicationSlopRegionLengthDipsSqared;
57 } 57 }
58 58
59 // Compare all properties of touch points to determine the state.
60 bool HasPointChanged(const WebTouchPoint& last_point,
61 const WebTouchPoint& current_point) {
62 if (last_point.position != current_point.position ||
63 last_point.radiusX != current_point.radiusX ||
64 last_point.radiusY != current_point.radiusY ||
65 last_point.rotationAngle != current_point.rotationAngle ||
66 last_point.force != current_point.force ||
67 last_point.screenPosition != current_point.screenPosition) {
jdduke (slow) 2015/01/29 16:53:19 Nit: Let's put the |screenPosition| comparison fir
USE s.singapati at gmail.com 2015/01/30 12:19:27 Done.
68 return true;
69 }
70 return false;
71 }
72
59 } // namespace 73 } // namespace
60 74
61 75
62 // Cancels a touch sequence if a touchstart or touchmove ack response is 76 // Cancels a touch sequence if a touchstart or touchmove ack response is
63 // sufficiently delayed. 77 // sufficiently delayed.
64 class TouchEventQueue::TouchTimeoutHandler { 78 class TouchEventQueue::TouchTimeoutHandler {
65 public: 79 public:
66 TouchTimeoutHandler(TouchEventQueue* touch_queue, 80 TouchTimeoutHandler(TouchEventQueue* touch_queue,
67 base::TimeDelta timeout_delay) 81 base::TimeDelta timeout_delay)
68 : touch_queue_(touch_queue), 82 : touch_queue_(touch_queue),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 case PENDING_ACK_NONE: 114 case PENDING_ACK_NONE:
101 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 115 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
102 enabled_for_current_sequence_ = false; 116 enabled_for_current_sequence_ = false;
103 timeout_monitor_.Stop(); 117 timeout_monitor_.Stop();
104 return false; 118 return false;
105 case PENDING_ACK_ORIGINAL_EVENT: 119 case PENDING_ACK_ORIGINAL_EVENT:
106 if (AckedTimeoutEventRequiresCancel(ack_result)) { 120 if (AckedTimeoutEventRequiresCancel(ack_result)) {
107 SetPendingAckState(PENDING_ACK_CANCEL_EVENT); 121 SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
108 TouchEventWithLatencyInfo cancel_event = 122 TouchEventWithLatencyInfo cancel_event =
109 ObtainCancelEventForTouchEvent(timeout_event_); 123 ObtainCancelEventForTouchEvent(timeout_event_);
110 touch_queue_->SendTouchEventImmediately(cancel_event); 124 touch_queue_->SendTouchEventImmediately(&cancel_event);
111 } else { 125 } else {
112 SetPendingAckState(PENDING_ACK_NONE); 126 SetPendingAckState(PENDING_ACK_NONE);
113 touch_queue_->UpdateTouchConsumerStates(timeout_event_.event, 127 touch_queue_->UpdateTouchConsumerStates(timeout_event_.event,
114 ack_result); 128 ack_result);
115 } 129 }
116 return true; 130 return true;
117 case PENDING_ACK_CANCEL_EVENT: 131 case PENDING_ACK_CANCEL_EVENT:
118 SetPendingAckState(PENDING_ACK_NONE); 132 SetPendingAckState(PENDING_ACK_NONE);
119 return true; 133 return true;
120 } 134 }
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 if (pending_async_touchmove_->CanCoalesceWith(touch)) { 522 if (pending_async_touchmove_->CanCoalesceWith(touch)) {
509 pending_async_touchmove_->CoalesceWith(touch); 523 pending_async_touchmove_->CoalesceWith(touch);
510 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; 524 pending_async_touchmove_->event.cancelable = !send_touch_events_async_;
511 touch = *pending_async_touchmove_; 525 touch = *pending_async_touchmove_;
512 pending_async_touchmove_.reset(); 526 pending_async_touchmove_.reset();
513 } else { 527 } else {
514 scoped_ptr<TouchEventWithLatencyInfo> async_move = 528 scoped_ptr<TouchEventWithLatencyInfo> async_move =
515 pending_async_touchmove_.Pass(); 529 pending_async_touchmove_.Pass();
516 async_move->event.cancelable = false; 530 async_move->event.cancelable = false;
517 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); 531 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true));
518 SendTouchEventImmediately(*async_move); 532 SendTouchEventImmediately(async_move.get());
519 return; 533 return;
520 } 534 }
521 } 535 }
522 536
523 // Note: Touchstart events are marked cancelable to allow transitions between 537 // Note: Touchstart events are marked cancelable to allow transitions between
524 // platform scrolling and JS pinching. Touchend events, however, remain 538 // platform scrolling and JS pinching. Touchend events, however, remain
525 // uncancelable, mitigating the risk of jank when transitioning to a fling. 539 // uncancelable, mitigating the risk of jank when transitioning to a fling.
526 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) 540 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart)
527 touch.event.cancelable = false; 541 touch.event.cancelable = false;
528 542
529 // A synchronous ack will reset |dispatching_touch_|, in which case 543 // A synchronous ack will reset |dispatching_touch_|, in which case
530 // the touch timeout should not be started. 544 // the touch timeout should not be started.
531 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); 545 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
532 SendTouchEventImmediately(touch); 546 SendTouchEventImmediately(&touch);
533 if (dispatching_touch_ && timeout_handler_) 547 if (dispatching_touch_ && timeout_handler_)
534 timeout_handler_->StartIfNecessary(touch); 548 timeout_handler_->StartIfNecessary(touch);
535 } 549 }
536 550
537 void TouchEventQueue::OnGestureScrollEvent( 551 void TouchEventQueue::OnGestureScrollEvent(
538 const GestureEventWithLatencyInfo& gesture_event) { 552 const GestureEventWithLatencyInfo& gesture_event) {
539 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { 553 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) {
540 if (!touch_consumer_states_.is_empty() && 554 if (!touch_consumer_states_.is_empty() &&
541 !drop_remaining_touches_in_sequence_) { 555 !drop_remaining_touches_in_sequence_) {
542 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) 556 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves())
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 } 700 }
687 701
688 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { 702 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() {
689 DCHECK(!touch_queue_.empty()); 703 DCHECK(!touch_queue_.empty());
690 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); 704 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front());
691 touch_queue_.pop_front(); 705 touch_queue_.pop_front();
692 return event.Pass(); 706 return event.Pass();
693 } 707 }
694 708
695 void TouchEventQueue::SendTouchEventImmediately( 709 void TouchEventQueue::SendTouchEventImmediately(
696 const TouchEventWithLatencyInfo& touch) { 710 TouchEventWithLatencyInfo* touch) {
697 if (needs_async_touchmove_for_outer_slop_region_) { 711 if (needs_async_touchmove_for_outer_slop_region_) {
698 // Any event other than a touchmove (e.g., touchcancel or secondary 712 // Any event other than a touchmove (e.g., touchcancel or secondary
699 // touchstart) after a scroll has started will interrupt the need to send a 713 // touchstart) after a scroll has started will interrupt the need to send a
700 // an outer slop-region exceeding touchmove. 714 // an outer slop-region exceeding touchmove.
701 if (touch.event.type != WebInputEvent::TouchMove || 715 if (touch->event.type != WebInputEvent::TouchMove ||
702 OutsideApplicationSlopRegion(touch.event, 716 OutsideApplicationSlopRegion(touch->event,
703 touch_sequence_start_position_)) 717 touch_sequence_start_position_))
704 needs_async_touchmove_for_outer_slop_region_ = false; 718 needs_async_touchmove_for_outer_slop_region_ = false;
705 } 719 }
706 720
707 client_->SendTouchEventImmediately(touch); 721 // For touchmove events, compare touch points position from current event
722 // to last sent event and update touch points state.
723 if (touch->event.type == WebInputEvent::TouchMove) {
724 CHECK(last_sent_touchevent_);
725 for (unsigned int i = 0; i < last_sent_touchevent_->touchesLength; ++i) {
726 const WebTouchPoint& last_touch_point =
727 last_sent_touchevent_->touches[i];
728 // Touches with same id may not have same index in Touches array.
729 for (unsigned int j = 0; j < touch->event.touchesLength; ++j) {
730 const WebTouchPoint& current_touchmove_point = touch->event.touches[j];
731 if (current_touchmove_point.id != last_touch_point.id)
732 continue;
733
734 if (!HasPointChanged(last_touch_point, current_touchmove_point))
735 touch->event.touches[j].state = WebTouchPoint::StateStationary;
736
737 break;
738 }
739 }
740 }
741
742 if (last_sent_touchevent_)
743 *last_sent_touchevent_ = touch->event;
744 else
745 last_sent_touchevent_.reset(new WebTouchEvent(touch->event));
746
747 client_->SendTouchEventImmediately(*touch);
708 } 748 }
709 749
710 TouchEventQueue::PreFilterResult 750 TouchEventQueue::PreFilterResult
711 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { 751 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
712 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) 752 if (timeout_handler_ && timeout_handler_->FilterEvent(event))
713 return ACK_WITH_NO_CONSUMER_EXISTS; 753 return ACK_WITH_NO_CONSUMER_EXISTS;
714 754
715 if (touchmove_slop_suppressor_->FilterEvent(event)) 755 if (touchmove_slop_suppressor_->FilterEvent(event))
716 return ACK_WITH_NOT_CONSUMED; 756 return ACK_WITH_NOT_CONSUMED;
717 757
718 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { 758 if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
719 touch_consumer_states_.clear(); 759 touch_consumer_states_.clear();
720 send_touch_events_async_ = false; 760 send_touch_events_async_ = false;
721 pending_async_touchmove_.reset(); 761 pending_async_touchmove_.reset();
762 last_sent_touchevent_.reset();
763
722 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position); 764 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position);
723 drop_remaining_touches_in_sequence_ = false; 765 drop_remaining_touches_in_sequence_ = false;
724 if (!has_handlers_) { 766 if (!has_handlers_) {
725 drop_remaining_touches_in_sequence_ = true; 767 drop_remaining_touches_in_sequence_ = true;
726 return ACK_WITH_NO_CONSUMER_EXISTS; 768 return ACK_WITH_NO_CONSUMER_EXISTS;
727 } 769 }
728 } 770 }
729 771
730 if (drop_remaining_touches_in_sequence_ && 772 if (drop_remaining_touches_in_sequence_ &&
731 event.type != WebInputEvent::TouchCancel) { 773 event.type != WebInputEvent::TouchCancel) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
771 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) 813 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
772 touch_consumer_states_.mark_bit(point.id); 814 touch_consumer_states_.mark_bit(point.id);
773 else 815 else
774 touch_consumer_states_.clear_bit(point.id); 816 touch_consumer_states_.clear_bit(point.id);
775 } 817 }
776 } 818 }
777 } 819 }
778 } 820 }
779 821
780 } // namespace content 822 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698