| OLD | NEW |
| 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 27 matching lines...) Expand all Loading... |
| 38 &event.event); | 38 &event.event); |
| 39 return event; | 39 return event; |
| 40 } | 40 } |
| 41 | 41 |
| 42 bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) { | 42 bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) { |
| 43 return (event.type == WebInputEvent::TouchStart || | 43 return (event.type == WebInputEvent::TouchStart || |
| 44 event.type == WebInputEvent::TouchMove) && | 44 event.type == WebInputEvent::TouchMove) && |
| 45 !WebInputEventTraits::IgnoresAckDisposition(event); | 45 !WebInputEventTraits::IgnoresAckDisposition(event); |
| 46 } | 46 } |
| 47 | 47 |
| 48 // Compare all properties of touch points to determine the state. |
| 49 bool HasPointChanged(const WebTouchPoint& last_point, |
| 50 const WebTouchPoint& current_point) { |
| 51 if (last_point.screenPosition != current_point.screenPosition || |
| 52 last_point.position != current_point.position || |
| 53 last_point.radiusX != current_point.radiusX || |
| 54 last_point.radiusY != current_point.radiusY || |
| 55 last_point.rotationAngle != current_point.rotationAngle || |
| 56 last_point.force != current_point.force) { |
| 57 return true; |
| 58 } |
| 59 return false; |
| 60 } |
| 61 |
| 48 } // namespace | 62 } // namespace |
| 49 | 63 |
| 50 | 64 |
| 51 // Cancels a touch sequence if a touchstart or touchmove ack response is | 65 // Cancels a touch sequence if a touchstart or touchmove ack response is |
| 52 // sufficiently delayed. | 66 // sufficiently delayed. |
| 53 class TouchEventQueue::TouchTimeoutHandler { | 67 class TouchEventQueue::TouchTimeoutHandler { |
| 54 public: | 68 public: |
| 55 TouchTimeoutHandler(TouchEventQueue* touch_queue, | 69 TouchTimeoutHandler(TouchEventQueue* touch_queue, |
| 56 base::TimeDelta timeout_delay) | 70 base::TimeDelta timeout_delay) |
| 57 : touch_queue_(touch_queue), | 71 : touch_queue_(touch_queue), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 case PENDING_ACK_NONE: | 103 case PENDING_ACK_NONE: |
| 90 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) | 104 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 91 enabled_for_current_sequence_ = false; | 105 enabled_for_current_sequence_ = false; |
| 92 timeout_monitor_.Stop(); | 106 timeout_monitor_.Stop(); |
| 93 return false; | 107 return false; |
| 94 case PENDING_ACK_ORIGINAL_EVENT: | 108 case PENDING_ACK_ORIGINAL_EVENT: |
| 95 if (AckedTimeoutEventRequiresCancel(ack_result)) { | 109 if (AckedTimeoutEventRequiresCancel(ack_result)) { |
| 96 SetPendingAckState(PENDING_ACK_CANCEL_EVENT); | 110 SetPendingAckState(PENDING_ACK_CANCEL_EVENT); |
| 97 TouchEventWithLatencyInfo cancel_event = | 111 TouchEventWithLatencyInfo cancel_event = |
| 98 ObtainCancelEventForTouchEvent(timeout_event_); | 112 ObtainCancelEventForTouchEvent(timeout_event_); |
| 99 touch_queue_->SendTouchEventImmediately(cancel_event); | 113 touch_queue_->SendTouchEventImmediately(&cancel_event); |
| 100 } else { | 114 } else { |
| 101 SetPendingAckState(PENDING_ACK_NONE); | 115 SetPendingAckState(PENDING_ACK_NONE); |
| 102 touch_queue_->UpdateTouchConsumerStates(timeout_event_.event, | 116 touch_queue_->UpdateTouchConsumerStates(timeout_event_.event, |
| 103 ack_result); | 117 ack_result); |
| 104 } | 118 } |
| 105 return true; | 119 return true; |
| 106 case PENDING_ACK_CANCEL_EVENT: | 120 case PENDING_ACK_CANCEL_EVENT: |
| 107 SetPendingAckState(PENDING_ACK_NONE); | 121 SetPendingAckState(PENDING_ACK_NONE); |
| 108 return true; | 122 return true; |
| 109 } | 123 } |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 if (pending_async_touchmove_->CanCoalesceWith(touch)) { | 507 if (pending_async_touchmove_->CanCoalesceWith(touch)) { |
| 494 pending_async_touchmove_->CoalesceWith(touch); | 508 pending_async_touchmove_->CoalesceWith(touch); |
| 495 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; | 509 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; |
| 496 touch = *pending_async_touchmove_; | 510 touch = *pending_async_touchmove_; |
| 497 pending_async_touchmove_.reset(); | 511 pending_async_touchmove_.reset(); |
| 498 } else { | 512 } else { |
| 499 scoped_ptr<TouchEventWithLatencyInfo> async_move = | 513 scoped_ptr<TouchEventWithLatencyInfo> async_move = |
| 500 pending_async_touchmove_.Pass(); | 514 pending_async_touchmove_.Pass(); |
| 501 async_move->event.cancelable = false; | 515 async_move->event.cancelable = false; |
| 502 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); | 516 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); |
| 503 SendTouchEventImmediately(*async_move); | 517 SendTouchEventImmediately(async_move.get()); |
| 504 return; | 518 return; |
| 505 } | 519 } |
| 506 } | 520 } |
| 507 | 521 |
| 508 // Note: Touchstart events are marked cancelable to allow transitions between | 522 // Note: Touchstart events are marked cancelable to allow transitions between |
| 509 // platform scrolling and JS pinching. Touchend events, however, remain | 523 // platform scrolling and JS pinching. Touchend events, however, remain |
| 510 // uncancelable, mitigating the risk of jank when transitioning to a fling. | 524 // uncancelable, mitigating the risk of jank when transitioning to a fling. |
| 511 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) | 525 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) |
| 512 touch.event.cancelable = false; | 526 touch.event.cancelable = false; |
| 513 | 527 |
| 514 // A synchronous ack will reset |dispatching_touch_|, in which case | 528 // A synchronous ack will reset |dispatching_touch_|, in which case |
| 515 // the touch timeout should not be started. | 529 // the touch timeout should not be started. |
| 516 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | 530 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
| 517 SendTouchEventImmediately(touch); | 531 SendTouchEventImmediately(&touch); |
| 518 if (dispatching_touch_ && timeout_handler_) | 532 if (dispatching_touch_ && timeout_handler_) |
| 519 timeout_handler_->StartIfNecessary(touch); | 533 timeout_handler_->StartIfNecessary(touch); |
| 520 } | 534 } |
| 521 | 535 |
| 522 void TouchEventQueue::OnGestureScrollEvent( | 536 void TouchEventQueue::OnGestureScrollEvent( |
| 523 const GestureEventWithLatencyInfo& gesture_event) { | 537 const GestureEventWithLatencyInfo& gesture_event) { |
| 524 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { | 538 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { |
| 525 if (!touch_consumer_states_.is_empty() && | 539 if (!touch_consumer_states_.is_empty() && |
| 526 !drop_remaining_touches_in_sequence_) { | 540 !drop_remaining_touches_in_sequence_) { |
| 527 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) | 541 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 } | 681 } |
| 668 | 682 |
| 669 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { | 683 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { |
| 670 DCHECK(!touch_queue_.empty()); | 684 DCHECK(!touch_queue_.empty()); |
| 671 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); | 685 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); |
| 672 touch_queue_.pop_front(); | 686 touch_queue_.pop_front(); |
| 673 return event.Pass(); | 687 return event.Pass(); |
| 674 } | 688 } |
| 675 | 689 |
| 676 void TouchEventQueue::SendTouchEventImmediately( | 690 void TouchEventQueue::SendTouchEventImmediately( |
| 677 const TouchEventWithLatencyInfo& touch) { | 691 TouchEventWithLatencyInfo* touch) { |
| 678 client_->SendTouchEventImmediately(touch); | 692 // For touchmove events, compare touch points position from current event |
| 693 // to last sent event and update touch points state. |
| 694 if (touch->event.type == WebInputEvent::TouchMove) { |
| 695 CHECK(last_sent_touchevent_); |
| 696 for (unsigned int i = 0; i < last_sent_touchevent_->touchesLength; ++i) { |
| 697 const WebTouchPoint& last_touch_point = |
| 698 last_sent_touchevent_->touches[i]; |
| 699 // Touches with same id may not have same index in Touches array. |
| 700 for (unsigned int j = 0; j < touch->event.touchesLength; ++j) { |
| 701 const WebTouchPoint& current_touchmove_point = touch->event.touches[j]; |
| 702 if (current_touchmove_point.id != last_touch_point.id) |
| 703 continue; |
| 704 |
| 705 if (!HasPointChanged(last_touch_point, current_touchmove_point)) |
| 706 touch->event.touches[j].state = WebTouchPoint::StateStationary; |
| 707 |
| 708 break; |
| 709 } |
| 710 } |
| 711 } |
| 712 |
| 713 if (last_sent_touchevent_) |
| 714 *last_sent_touchevent_ = touch->event; |
| 715 else |
| 716 last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); |
| 717 |
| 718 client_->SendTouchEventImmediately(*touch); |
| 679 } | 719 } |
| 680 | 720 |
| 681 TouchEventQueue::PreFilterResult | 721 TouchEventQueue::PreFilterResult |
| 682 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { | 722 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { |
| 683 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) | 723 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) |
| 684 return ACK_WITH_NO_CONSUMER_EXISTS; | 724 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 685 | 725 |
| 686 if (touchmove_slop_suppressor_->FilterEvent(event)) | 726 if (touchmove_slop_suppressor_->FilterEvent(event)) |
| 687 return ACK_WITH_NOT_CONSUMED; | 727 return ACK_WITH_NOT_CONSUMED; |
| 688 | 728 |
| 689 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { | 729 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { |
| 690 touch_consumer_states_.clear(); | 730 touch_consumer_states_.clear(); |
| 691 send_touch_events_async_ = false; | 731 send_touch_events_async_ = false; |
| 692 pending_async_touchmove_.reset(); | 732 pending_async_touchmove_.reset(); |
| 733 last_sent_touchevent_.reset(); |
| 734 |
| 693 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position); | 735 touch_sequence_start_position_ = gfx::PointF(event.touches[0].position); |
| 694 drop_remaining_touches_in_sequence_ = false; | 736 drop_remaining_touches_in_sequence_ = false; |
| 695 if (!has_handlers_) { | 737 if (!has_handlers_) { |
| 696 drop_remaining_touches_in_sequence_ = true; | 738 drop_remaining_touches_in_sequence_ = true; |
| 697 return ACK_WITH_NO_CONSUMER_EXISTS; | 739 return ACK_WITH_NO_CONSUMER_EXISTS; |
| 698 } | 740 } |
| 699 } | 741 } |
| 700 | 742 |
| 701 if (drop_remaining_touches_in_sequence_ && | 743 if (drop_remaining_touches_in_sequence_ && |
| 702 event.type != WebInputEvent::TouchCancel) { | 744 event.type != WebInputEvent::TouchCancel) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 784 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 743 touch_consumer_states_.mark_bit(point.id); | 785 touch_consumer_states_.mark_bit(point.id); |
| 744 else | 786 else |
| 745 touch_consumer_states_.clear_bit(point.id); | 787 touch_consumer_states_.clear_bit(point.id); |
| 746 } | 788 } |
| 747 } | 789 } |
| 748 } | 790 } |
| 749 } | 791 } |
| 750 | 792 |
| 751 } // namespace content | 793 } // namespace content |
| OLD | NEW |