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/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 dispatching_touch_ = false; | 385 dispatching_touch_ = false; |
386 | 386 |
387 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) | 387 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) |
388 return; | 388 return; |
389 | 389 |
390 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); | 390 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); |
391 | 391 |
392 if (touch_queue_.empty()) | 392 if (touch_queue_.empty()) |
393 return; | 393 return; |
394 | 394 |
395 const WebTouchEvent& acked_event = | |
396 touch_queue_.front()->coalesced_event().event; | |
397 | |
398 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED && | 395 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED && |
399 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT) { | 396 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT) { |
400 touch_filtering_state_ = FORWARD_ALL_TOUCHES; | 397 touch_filtering_state_ = FORWARD_ALL_TOUCHES; |
401 } | 398 } |
402 | 399 |
403 if (ack_result == INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS && | |
404 touch_filtering_state_ != DROP_ALL_TOUCHES && | |
405 WebTouchEventTraits::IsTouchSequenceStart(acked_event)) { | |
406 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; | |
407 } | |
408 | |
409 PopTouchEventToClient(ack_result, latency_info); | 400 PopTouchEventToClient(ack_result, latency_info); |
410 TryForwardNextEventToRenderer(); | 401 TryForwardNextEventToRenderer(); |
411 } | 402 } |
412 | 403 |
413 void TouchEventQueue::TryForwardNextEventToRenderer() { | 404 void TouchEventQueue::TryForwardNextEventToRenderer() { |
414 DCHECK(!dispatching_touch_ack_); | 405 DCHECK(!dispatching_touch_ack_); |
415 // If there are queued touch events, then try to forward them to the renderer | 406 // If there are queued touch events, then try to forward them to the renderer |
416 // immediately, or ACK the events back to the client if appropriate. | 407 // immediately, or ACK the events back to the client if appropriate. |
417 while (!touch_queue_.empty()) { | 408 while (!touch_queue_.empty()) { |
418 PreFilterResult filter_result = | 409 PreFilterResult filter_result = |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 (pending_async_touch_move_ && | 457 (pending_async_touch_move_ && |
467 !pending_async_touch_move_->CanCoalesceWith(touch)); | 458 !pending_async_touch_move_->CanCoalesceWith(touch)); |
468 | 459 |
469 if (!send_touch_move_now) { | 460 if (!send_touch_move_now) { |
470 if (!pending_async_touch_move_) { | 461 if (!pending_async_touch_move_) { |
471 pending_async_touch_move_.reset(new TouchEventWithLatencyInfo(touch)); | 462 pending_async_touch_move_.reset(new TouchEventWithLatencyInfo(touch)); |
472 } else { | 463 } else { |
473 DCHECK(pending_async_touch_move_->CanCoalesceWith(touch)); | 464 DCHECK(pending_async_touch_move_->CanCoalesceWith(touch)); |
474 pending_async_touch_move_->CoalesceWith(touch); | 465 pending_async_touch_move_->CoalesceWith(touch); |
475 } | 466 } |
| 467 DCHECK_EQ(1U, size()); |
476 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | 468 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| 469 // It's possible (though unlikely) that ack'ing the current touch will |
| 470 // trigger the queueing of another touch event (e.g., a touchcancel). As |
| 471 // forwarding of the queued event will be deferred while the ack is being |
| 472 // dispatched (see |OnTouchEvent()|), try forwarding it now. |
| 473 TryForwardNextEventToRenderer(); |
477 return; | 474 return; |
478 } | 475 } |
479 } | 476 } |
480 | 477 |
481 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds; | 478 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds; |
482 | 479 |
483 // Flush any pending async touch move. If it can be combined with the current | 480 // Flush any pending async touch move. If it can be combined with the current |
484 // (touchmove) event, great, otherwise send it immediately but separately. Its | 481 // (touchmove) event, great, otherwise send it immediately but separately. Its |
485 // ack will trigger forwarding of the original |touch| event. | 482 // ack will trigger forwarding of the original |touch| event. |
486 if (pending_async_touch_move_) { | 483 if (pending_async_touch_move_) { |
(...skipping 28 matching lines...) Expand all Loading... |
515 timeout_handler_->Start(touch); | 512 timeout_handler_->Start(touch); |
516 } | 513 } |
517 } | 514 } |
518 | 515 |
519 void TouchEventQueue::OnGestureScrollEvent( | 516 void TouchEventQueue::OnGestureScrollEvent( |
520 const GestureEventWithLatencyInfo& gesture_event) { | 517 const GestureEventWithLatencyInfo& gesture_event) { |
521 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin) | 518 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin) |
522 return; | 519 return; |
523 | 520 |
524 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) { | 521 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) { |
| 522 if (touch_filtering_state_ != DROP_ALL_TOUCHES && |
| 523 touch_filtering_state_ != DROP_TOUCHES_IN_SEQUENCE) { |
| 524 // If no touch points have a consumer, prevent all subsequent touch events |
| 525 // received during the scroll from reaching the renderer. This ensures |
| 526 // that the first touchstart the renderer sees in any given sequence can |
| 527 // always be preventDefault'ed (cancelable == true). |
| 528 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. |
| 529 if (touch_ack_states_.empty() || |
| 530 AllTouchAckStatesHaveState( |
| 531 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) { |
| 532 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; |
| 533 return; |
| 534 } |
| 535 } |
| 536 |
525 pending_async_touch_move_.reset(); | 537 pending_async_touch_move_.reset(); |
526 send_touch_events_async_ = true; | 538 send_touch_events_async_ = true; |
527 needs_async_touch_move_for_outer_slop_region_ = true; | 539 needs_async_touch_move_for_outer_slop_region_ = true; |
528 return; | 540 return; |
529 } | 541 } |
530 | 542 |
531 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) | 543 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) |
532 return; | 544 return; |
533 | 545 |
534 // We assume that scroll events are generated synchronously from | 546 // We assume that scroll events are generated synchronously from |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 } | 769 } |
758 } else if (event.type == WebInputEvent::TouchStart) { | 770 } else if (event.type == WebInputEvent::TouchStart) { |
759 for (unsigned i = 0; i < event.touchesLength; ++i) { | 771 for (unsigned i = 0; i < event.touchesLength; ++i) { |
760 const WebTouchPoint& point = event.touches[i]; | 772 const WebTouchPoint& point = event.touches[i]; |
761 if (point.state == WebTouchPoint::StatePressed) | 773 if (point.state == WebTouchPoint::StatePressed) |
762 touch_ack_states_[point.id] = ack_result; | 774 touch_ack_states_[point.id] = ack_result; |
763 } | 775 } |
764 } | 776 } |
765 } | 777 } |
766 | 778 |
| 779 bool TouchEventQueue::AllTouchAckStatesHaveState( |
| 780 InputEventAckState ack_state) const { |
| 781 if (touch_ack_states_.empty()) |
| 782 return false; |
| 783 |
| 784 for (TouchPointAckStates::const_iterator iter = touch_ack_states_.begin(), |
| 785 end = touch_ack_states_.end(); |
| 786 iter != end; |
| 787 ++iter) { |
| 788 if (iter->second != ack_state) |
| 789 return false; |
| 790 } |
| 791 |
| 792 return true; |
| 793 } |
| 794 |
767 } // namespace content | 795 } // namespace content |
OLD | NEW |