Chromium Code Reviews| 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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 // Note that this will be empty if no coalescing has occurred. | 336 // Note that this will be empty if no coalescing has occurred. |
| 337 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; | 337 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| 338 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; | 338 WebTouchEventWithLatencyList uncoaleseced_events_to_ack_; |
| 339 | 339 |
| 340 bool suppress_client_ack_; | 340 bool suppress_client_ack_; |
| 341 | 341 |
| 342 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); | 342 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
| 343 }; | 343 }; |
| 344 | 344 |
| 345 TouchEventQueue::Config::Config() | 345 TouchEventQueue::Config::Config() |
| 346 : touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT), | 346 : touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), |
| 347 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)), | |
| 348 touch_ack_timeout_supported(false) { | 347 touch_ack_timeout_supported(false) { |
| 349 } | 348 } |
| 350 | 349 |
| 351 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, | 350 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, |
| 352 const Config& config) | 351 const Config& config) |
| 353 : client_(client), | 352 : client_(client), |
| 354 dispatching_touch_ack_(NULL), | 353 dispatching_touch_ack_(NULL), |
| 355 dispatching_touch_(false), | 354 dispatching_touch_(false), |
| 356 has_handlers_(true), | 355 has_handlers_(true), |
| 357 drop_remaining_touches_in_sequence_(false), | 356 drop_remaining_touches_in_sequence_(false), |
| 358 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), | 357 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), |
| 359 send_touch_events_async_(false), | 358 send_touch_events_async_(false), |
| 360 last_sent_touch_timestamp_sec_(0), | 359 last_sent_touch_timestamp_sec_(0) { |
| 361 touch_scrolling_mode_(config.touch_scrolling_mode) { | |
| 362 DCHECK(client); | 360 DCHECK(client); |
| 363 if (config.touch_ack_timeout_supported) { | 361 if (config.touch_ack_timeout_supported) { |
| 364 timeout_handler_.reset( | 362 timeout_handler_.reset( |
| 365 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); | 363 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); |
| 366 } | 364 } |
| 367 } | 365 } |
| 368 | 366 |
| 369 TouchEventQueue::~TouchEventQueue() { | 367 TouchEventQueue::~TouchEventQueue() { |
| 370 if (!touch_queue_.empty()) | 368 if (!touch_queue_.empty()) |
| 371 STLDeleteElements(&touch_queue_); | 369 STLDeleteElements(&touch_queue_); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 } | 518 } |
| 521 | 519 |
| 522 void TouchEventQueue::OnGestureScrollEvent( | 520 void TouchEventQueue::OnGestureScrollEvent( |
| 523 const GestureEventWithLatencyInfo& gesture_event) { | 521 const GestureEventWithLatencyInfo& gesture_event) { |
| 524 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { | 522 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { |
| 525 if (!touch_consumer_states_.is_empty() && | 523 if (!touch_consumer_states_.is_empty() && |
| 526 !drop_remaining_touches_in_sequence_) { | 524 !drop_remaining_touches_in_sequence_) { |
| 527 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) | 525 DCHECK(!touchmove_slop_suppressor_->suppressing_touchmoves()) |
| 528 << "A touch handler should be offered a touchmove before scrolling."; | 526 << "A touch handler should be offered a touchmove before scrolling."; |
| 529 } | 527 } |
| 530 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE && | 528 if (!drop_remaining_touches_in_sequence_ && |
| 531 !drop_remaining_touches_in_sequence_ && | |
| 532 touch_consumer_states_.is_empty()) { | 529 touch_consumer_states_.is_empty()) { |
| 533 // If no touch points have a consumer, prevent all subsequent touch events | 530 // If no touch points have a consumer, prevent all subsequent touch events |
| 534 // received during the scroll from reaching the renderer. This ensures | 531 // received during the scroll from reaching the renderer. This ensures |
| 535 // that the first touchstart the renderer sees in any given sequence can | 532 // that the first touchstart the renderer sees in any given sequence can |
| 536 // always be preventDefault'ed (cancelable == true). | 533 // always be preventDefault'ed (cancelable == true). |
| 537 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. | 534 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. |
| 538 drop_remaining_touches_in_sequence_ = true; | 535 drop_remaining_touches_in_sequence_ = true; |
| 539 } | 536 } |
| 540 | 537 |
| 541 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | 538 pending_async_touchmove_.reset(); |
| 542 pending_async_touchmove_.reset(); | |
| 543 | 539 |
| 544 return; | 540 return; |
| 545 } | 541 } |
| 546 | 542 |
| 547 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollUpdate) | 543 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollUpdate) |
|
jdduke (slow)
2015/01/30 00:12:56
I guess we might as well consolidate this if with
lanwei
2015/02/03 20:44:32
Done.
| |
| 548 return; | 544 return; |
| 549 | 545 |
| 550 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | 546 send_touch_events_async_ = true; |
| 551 send_touch_events_async_ = true; | |
| 552 | |
| 553 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) | |
| 554 return; | |
| 555 | |
| 556 // We assume that scroll events are generated synchronously from | |
| 557 // dispatching a touch event ack. This allows us to generate a synthetic | |
| 558 // cancel event that has the same touch ids as the touch event that | |
| 559 // is being acked. Otherwise, we don't perform the touch-cancel optimization. | |
| 560 if (!dispatching_touch_ack_) | |
| 561 return; | |
| 562 | |
| 563 if (drop_remaining_touches_in_sequence_) | |
| 564 return; | |
| 565 | |
| 566 drop_remaining_touches_in_sequence_ = true; | |
| 567 | |
| 568 // Fake a TouchCancel to cancel the touch points of the touch event | |
| 569 // that is currently being acked. | |
| 570 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we | |
| 571 // are in the scope of PopTouchEventToClient() and that no touch event | |
| 572 // in the queue is waiting for ack from renderer. So we can just insert | |
| 573 // the touch cancel at the beginning of the queue. | |
| 574 touch_queue_.push_front(new CoalescedWebTouchEvent( | |
| 575 ObtainCancelEventForTouchEvent( | |
| 576 dispatching_touch_ack_->coalesced_event()), true)); | |
| 577 } | 547 } |
| 578 | 548 |
| 579 void TouchEventQueue::OnGestureEventAck( | 549 void TouchEventQueue::OnGestureEventAck( |
| 580 const GestureEventWithLatencyInfo& event, | 550 const GestureEventWithLatencyInfo& event, |
| 581 InputEventAckState ack_result) { | 551 InputEventAckState ack_result) { |
| 582 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) | |
| 583 return; | |
| 584 | |
| 585 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate) | 552 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate) |
| 586 return; | 553 return; |
| 587 | 554 |
| 588 // Throttle sending touchmove events as long as the scroll events are handled. | 555 // Throttle sending touchmove events as long as the scroll events are handled. |
| 589 // Note that there's no guarantee that this ACK is for the most recent | 556 // Note that there's no guarantee that this ACK is for the most recent |
| 590 // gesture event (or even part of the current sequence). Worst case, the | 557 // gesture event (or even part of the current sequence). Worst case, the |
| 591 // delay in updating the absorption state will result in minor UI glitches. | 558 // delay in updating the absorption state will result in minor UI glitches. |
| 592 // A valid |pending_async_touchmove_| will be flushed when the next event is | 559 // A valid |pending_async_touchmove_| will be flushed when the next event is |
| 593 // forwarded. | 560 // forwarded. |
| 594 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); | 561 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 725 if (event.type == WebInputEvent::TouchEnd || | 692 if (event.type == WebInputEvent::TouchEnd || |
| 726 event.type == WebInputEvent::TouchCancel) { | 693 event.type == WebInputEvent::TouchCancel) { |
| 727 // The points have been released. Erase the ACK states. | 694 // The points have been released. Erase the ACK states. |
| 728 for (unsigned i = 0; i < event.touchesLength; ++i) { | 695 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 729 const WebTouchPoint& point = event.touches[i]; | 696 const WebTouchPoint& point = event.touches[i]; |
| 730 if (point.state == WebTouchPoint::StateReleased || | 697 if (point.state == WebTouchPoint::StateReleased || |
| 731 point.state == WebTouchPoint::StateCancelled) | 698 point.state == WebTouchPoint::StateCancelled) |
| 732 touch_consumer_states_.clear_bit(point.id); | 699 touch_consumer_states_.clear_bit(point.id); |
| 733 } | 700 } |
| 734 } else if (event.type == WebInputEvent::TouchStart) { | 701 } else if (event.type == WebInputEvent::TouchStart) { |
| 735 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE && | 702 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { |
|
jdduke (slow)
2015/01/30 00:12:56
Nit: Looks like we can remove this one-line if bra
lanwei
2015/02/03 20:44:32
Done.
| |
| 736 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) { | |
| 737 send_touch_events_async_ = false; | 703 send_touch_events_async_ = false; |
| 738 } | 704 } |
| 739 for (unsigned i = 0; i < event.touchesLength; ++i) { | 705 for (unsigned i = 0; i < event.touchesLength; ++i) { |
| 740 const WebTouchPoint& point = event.touches[i]; | 706 const WebTouchPoint& point = event.touches[i]; |
| 741 if (point.state == WebTouchPoint::StatePressed) { | 707 if (point.state == WebTouchPoint::StatePressed) { |
| 742 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) | 708 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) |
| 743 touch_consumer_states_.mark_bit(point.id); | 709 touch_consumer_states_.mark_bit(point.id); |
| 744 else | 710 else |
| 745 touch_consumer_states_.clear_bit(point.id); | 711 touch_consumer_states_.clear_bit(point.id); |
| 746 } | 712 } |
| 747 } | 713 } |
| 748 } | 714 } |
| 749 } | 715 } |
| 750 | 716 |
| 751 } // namespace content | 717 } // namespace content |
| OLD | NEW |