| 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 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 350 // Note that this will be empty if no coalescing has occurred. | 350 // Note that this will be empty if no coalescing has occurred. |
| 351 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 351 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| 352 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; | 352 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; |
| 353 | 353 |
| 354 bool suppress_client_ack_; | 354 bool suppress_client_ack_; |
| 355 | 355 |
| 356 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); | 356 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
| 357 }; | 357 }; |
| 358 | 358 |
| 359 TouchEventQueue::Config::Config() | 359 TouchEventQueue::Config::Config() |
| 360 : touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), | 360 : touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), |
| 361 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), | |
| 362 touch_ack_timeout_supported(false) { | 361 touch_ack_timeout_supported(false) { |
| 363 } | 362 } |
| 364 | 363 |
| 365 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, | 364 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, |
| 366 const Config& config) | 365 const Config& config) |
| 367 : client_(client), | 366 : client_(client), |
| 368 dispatching_touch_ack_(NULL), | 367 dispatching_touch_ack_(NULL), |
| 369 dispatching_touch_(false), | 368 dispatching_touch_(false), |
| 370 has_handlers_(true), | 369 has_handlers_(true), |
| 371 drop_remaining_touches_in_sequence_(false), | 370 drop_remaining_touches_in_sequence_(false), |
| 372 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), | 371 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), |
| 373 send_touch_events_async_(false), | 372 send_touch_events_async_(false), |
| 374 last_sent_touch_timestamp_sec_(0), | 373 last_sent_touch_timestamp_sec_(0) { |
| 375 touch_scrolling_mode_(config.touch_scrolling_mode) { | |
| 376 DCHECK(client); | 374 DCHECK(client); |
| 377 if (config.touch_ack_timeout_supported) { | 375 if (config.touch_ack_timeout_supported) { |
| 378 timeout_handler_.reset( | 376 timeout_handler_.reset( |
| 379 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); | 377 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); |
| 380 } | 378 } |
| 381 } | 379 } |
| 382 | 380 |
| 383 TouchEventQueue::~TouchEventQueue() { | 381 TouchEventQueue::~TouchEventQueue() { |
| 384 if (!touch_queue_.empty()) | 382 if (!touch_queue_.empty()) |
| 385 STLDeleteElements(&touch_queue_); | 383 STLDeleteElements(&touch_queue_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 532 } |
| 535 | 533 |
| 536 void TouchEventQueue::OnGestureScrollEvent( | 534 void TouchEventQueue::OnGestureScrollEvent( |
| 537 const GestureEventWithLatencyInfo& gesture_event) { | 535 const GestureEventWithLatencyInfo& gesture_event) { |
| 538 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { | 536 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { |
| 539 if (!touch_consumer_states_.is_empty() && | 537 if (!touch_consumer_states_.is_empty() && |
| 540 !drop_remaining_touches_in_sequence_) { | 538 !drop_remaining_touches_in_sequence_) { |
| 541 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) | 539 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) |
| 542 << "A touch handler should be offered a touchmove before scrolling."; | 540 << "A touch handler should be offered a touchmove before scrolling."; |
| 543 } | 541 } |
| 544 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE && | 542 if (!drop_remaining_touches_in_sequence_ && |
| 545 !drop_remaining_touches_in_sequence_ && | |
| 546 touch_consumer_states_.is_empty()) { | 543 touch_consumer_states_.is_empty()) { |
| 547 // If no touch points have a consumer, prevent all subsequent touch events | 544 // If no touch points have a consumer, prevent all subsequent touch events |
| 548 // received during the scroll from reaching the renderer. This ensures | 545 // received during the scroll from reaching the renderer. This ensures |
| 549 // that the first touchstart the renderer sees in any given sequence can | 546 // that the first touchstart the renderer sees in any given sequence can |
| 550 // always be preventDefault'ed (cancelable == true). | 547 // always be preventDefault'ed (cancelable == true). |
| 551 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. | 548 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. |
| 552 drop_remaining_touches_in_sequence_ = true; | 549 drop_remaining_touches_in_sequence_ = true; |
| 553 } | 550 } |
| 554 | 551 |
| 555 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | 552 pending_async_touchmove_.reset(); |
| 556 pending_async_touchmove_.reset(); | |
| 557 | 553 |
| 558 return; | 554 return; |
| 559 } | 555 } |
| 560 | 556 |
| 561 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollUpdate) | 557 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollUpdate) |
| 562 return; | |
| 563 | |
| 564 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | |
| 565 send_touch_events_async_ = true; | 558 send_touch_events_async_ = true; |
| 566 | |
| 567 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) | |
| 568 return; | |
| 569 | |
| 570 // We assume that scroll events are generated synchronously from | |
| 571 // dispatching a touch event ack. This allows us to generate a synthetic | |
| 572 // cancel event that has the same touch ids as the touch event that | |
| 573 // is being acked. Otherwise, we don't perform the touch-cancel optimization. | |
| 574 if (!dispatching_touch_ack_) | |
| 575 return; | |
| 576 | |
| 577 if (drop_remaining_touches_in_sequence_) | |
| 578 return; | |
| 579 | |
| 580 drop_remaining_touches_in_sequence_ = true; | |
| 581 | |
| 582 // Fake a TouchCancel to cancel the touch points of the touch event | |
| 583 // that is currently being acked. | |
| 584 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we | |
| 585 // are in the scope of PopTouchEventToClient() and that no touch event | |
| 586 // in the queue is waiting for ack from renderer. So we can just insert | |
| 587 // the touch cancel at the beginning of the queue. | |
| 588 touch_queue_.push_front(new CoalescedWebTouchEvent( | |
| 589 ObtainCancelEventForTouchEvent( | |
| 590 dispatching_touch_ack_->coalesced_event()), true)); | |
| 591 } | 559 } |
| 592 | 560 |
| 593 void TouchEventQueue::OnGestureEventAck( | 561 void TouchEventQueue::OnGestureEventAck( |
| 594 const GestureEventWithLatencyInfo& event, | 562 const GestureEventWithLatencyInfo& event, |
| 595 InputEventAckState ack_result) { | 563 InputEventAckState ack_result) { |
| 596 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | |
| 597 return; | |
| 598 | |
| 599 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate) | |
| 600 return; | |
| 601 | |
| 602 // Throttle sending touchmove events as long as the scroll events are handled. | 564 // Throttle sending touchmove events as long as the scroll events are handled. |
| 603 // Note that there's no guarantee that this ACK is for the most recent | 565 // Note that there's no guarantee that this ACK is for the most recent |
| 604 // gesture event (or even part of the current sequence). Worst case, the | 566 // gesture event (or even part of the current sequence). Worst case, the |
| 605 // delay in updating the absorption state will result in minor UI glitches. | 567 // delay in updating the absorption state will result in minor UI glitches. |
| 606 // A valid |pending_async_touchmove_| will be flushed when the next event is | 568 // A valid |pending_async_touchmove_| will be flushed when the next event is |
| 607 // forwarded. | 569 // forwarded. |
| 608 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); | 570 if (event.event.type == blink::WebInputEvent::GestureScrollUpdate) |
| 571 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); |
| 609 } | 572 } |
| 610 | 573 |
| 611 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { | 574 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { |
| 612 DCHECK(!dispatching_touch_ack_); | 575 DCHECK(!dispatching_touch_ack_); |
| 613 DCHECK(!dispatching_touch_); | 576 DCHECK(!dispatching_touch_); |
| 614 has_handlers_ = has_handlers; | 577 has_handlers_ = has_handlers; |
| 615 } | 578 } |
| 616 | 579 |
| 617 bool TouchEventQueue::IsPendingAckTouchStart() const { | 580 bool TouchEventQueue::IsPendingAckTouchStart() const { |
| 618 DCHECK(!dispatching_touch_ack_); | 581 DCHECK(!dispatching_touch_ack_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 767 if (event.type == WebInputEvent::TouchEnd || | 730 if (event.type == WebInputEvent::TouchEnd || |
| 768 event.type == WebInputEvent::TouchCancel) { | 731 event.type == WebInputEvent::TouchCancel) { |
| 769 // The points have been released. Erase the ACK states. | 732 // The points have been released. Erase the ACK states. |
| 770 for (unsigned i = 0; i < event.touchesLength; ++i) { | 733 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 771 const WebTouchPoint& point = event.touches[i]; | 734 const WebTouchPoint& point = event.touches[i]; |
| 772 if (point.state == WebTouchPoint::StateReleased || | 735 if (point.state == WebTouchPoint::StateReleased || |
| 773 point.state == WebTouchPoint::StateCancelled) | 736 point.state == WebTouchPoint::StateCancelled) |
| 774 touch_consumer_states_.clear_bit(point.id); | 737 touch_consumer_states_.clear_bit(point.id); |
| 775 } | 738 } |
| 776 } else if (event.type == WebInputEvent::TouchStart) { | 739 } else if (event.type == WebInputEvent::TouchStart) { |
| 777 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE && | 740 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 778 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { | |
| 779 send_touch_events_async_ = false; | 741 send_touch_events_async_ = false; |
| 780 } | 742 |
| 781 for (unsigned i = 0; i < event.touchesLength; ++i) { | 743 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 782 const WebTouchPoint& point = event.touches[i]; | 744 const WebTouchPoint& point = event.touches[i]; |
| 783 if (point.state == WebTouchPoint::StatePressed) { | 745 if (point.state == WebTouchPoint::StatePressed) { |
| 784 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 746 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 785 touch_consumer_states_.mark_bit(point.id); | 747 touch_consumer_states_.mark_bit(point.id); |
| 786 else | 748 else |
| 787 touch_consumer_states_.clear_bit(point.id); | 749 touch_consumer_states_.clear_bit(point.id); |
| 788 } | 750 } |
| 789 } | 751 } |
| 790 } | 752 } |
| 791 } | 753 } |
| 792 | 754 |
| 793 } // namespace content | 755 } // namespace content |
| OLD | NEW |