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 23 matching lines...) Expand all Loading... | |
34 WebTouchEventTraits::ResetTypeAndTouchStates( | 34 WebTouchEventTraits::ResetTypeAndTouchStates( |
35 WebInputEvent::TouchCancel, | 35 WebInputEvent::TouchCancel, |
36 // TODO(rbyers): Shouldn't we use a fresh timestamp? | 36 // TODO(rbyers): Shouldn't we use a fresh timestamp? |
37 event.event.timeStampSeconds, | 37 event.event.timeStampSeconds, |
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) && event.cancelable; |
45 !WebInputEventTraits::IgnoresAckDisposition(event); | |
46 } | 45 } |
47 | 46 |
48 // Compare all properties of touch points to determine the state. | 47 // Compare all properties of touch points to determine the state. |
49 bool HasPointChanged(const WebTouchPoint& point_1, | 48 bool HasPointChanged(const WebTouchPoint& point_1, |
50 const WebTouchPoint& point_2) { | 49 const WebTouchPoint& point_2) { |
51 DCHECK_EQ(point_1.id, point_2.id); | 50 DCHECK_EQ(point_1.id, point_2.id); |
52 if (point_1.screenPosition != point_2.screenPosition || | 51 if (point_1.screenPosition != point_2.screenPosition || |
53 point_1.position != point_2.position || | 52 point_1.position != point_2.position || |
54 point_1.radiusX != point_2.radiusX || | 53 point_1.radiusX != point_2.radiusX || |
55 point_1.radiusY != point_2.radiusY || | 54 point_1.radiusY != point_2.radiusY || |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 | 430 |
432 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); | 431 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); |
433 | 432 |
434 if (touch_queue_.empty()) | 433 if (touch_queue_.empty()) |
435 return; | 434 return; |
436 | 435 |
437 PopTouchEventToClient(ack_result, latency_info); | 436 PopTouchEventToClient(ack_result, latency_info); |
438 TryForwardNextEventToRenderer(); | 437 TryForwardNextEventToRenderer(); |
439 } | 438 } |
440 | 439 |
440 void TouchEventQueue::ProcessUncancelableTouchMoveAck() { | |
441 TRACE_EVENT0("input", "TouchEventQueue::ProcessUncancelableTouchMoveAck"); | |
442 | |
443 DCHECK(!dispatching_touch_ack_); | |
444 dispatching_touch_ = false; | |
445 | |
446 // Remove it from the queue once we receive the ack back from render for | |
447 // uncancelable touchmoves. | |
448 DCHECK(!ack_pending_async_touchmove_.empty()); | |
449 ack_pending_async_touchmove_.pop_back(); | |
450 | |
451 // Send the next pending async touch move once we receive the ack. | |
452 if (pending_async_touchmove_ && ack_pending_async_touchmove_.empty()) { | |
453 TouchEventWithLatencyInfo touch = *pending_async_touchmove_; | |
454 | |
455 // Dispatch the next pending async touch move when time expires. | |
456 if (touch.event.timeStampSeconds >= | |
457 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec) { | |
458 touch.event.cancelable = false; | |
459 pending_async_touchmove_.reset(); | |
460 SendTouchEventImmediately(&touch); | |
461 } | |
462 } | |
463 } | |
464 | |
441 void TouchEventQueue::TryForwardNextEventToRenderer() { | 465 void TouchEventQueue::TryForwardNextEventToRenderer() { |
442 DCHECK(!dispatching_touch_ack_); | 466 DCHECK(!dispatching_touch_ack_); |
443 // If there are queued touch events, then try to forward them to the renderer | 467 // If there are queued touch events, then try to forward them to the renderer |
444 // immediately, or ACK the events back to the client if appropriate. | 468 // immediately, or ACK the events back to the client if appropriate. |
445 while (!touch_queue_.empty()) { | 469 while (!touch_queue_.empty()) { |
446 PreFilterResult filter_result = | 470 PreFilterResult filter_result = |
447 FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event); | 471 FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event); |
448 switch (filter_result) { | 472 switch (filter_result) { |
449 case ACK_WITH_NO_CONSUMER_EXISTS: | 473 case ACK_WITH_NO_CONSUMER_EXISTS: |
450 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); | 474 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); |
(...skipping 21 matching lines...) Expand all Loading... | |
472 // reduces the risk of jank. However, it's still important that the web | 496 // reduces the risk of jank. However, it's still important that the web |
473 // application be sent touches at key points in the gesture stream, | 497 // application be sent touches at key points in the gesture stream, |
474 // e.g., when the application slop region is exceeded or touchmove | 498 // e.g., when the application slop region is exceeded or touchmove |
475 // coalescing fails because of different modifiers. | 499 // coalescing fails because of different modifiers. |
476 bool send_touchmove_now = size() > 1; | 500 bool send_touchmove_now = size() > 1; |
477 send_touchmove_now |= pending_async_touchmove_ && | 501 send_touchmove_now |= pending_async_touchmove_ && |
478 !pending_async_touchmove_->CanCoalesceWith(touch); | 502 !pending_async_touchmove_->CanCoalesceWith(touch); |
479 send_touchmove_now |= | 503 send_touchmove_now |= |
480 touch.event.timeStampSeconds >= | 504 touch.event.timeStampSeconds >= |
481 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec; | 505 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec; |
506 send_touchmove_now &= ack_pending_async_touchmove_.empty(); | |
jdduke (slow)
2015/04/15 17:14:53
So, I think we have to send the touchmove if we ca
lanwei
2015/04/17 20:49:00
Done.
| |
482 | 507 |
483 if (!send_touchmove_now) { | 508 if (!send_touchmove_now) { |
484 if (!pending_async_touchmove_) { | 509 if (!pending_async_touchmove_) { |
485 pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch)); | 510 pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch)); |
486 } else { | 511 } else { |
487 DCHECK(pending_async_touchmove_->CanCoalesceWith(touch)); | 512 DCHECK(pending_async_touchmove_->CanCoalesceWith(touch)); |
488 pending_async_touchmove_->CoalesceWith(touch); | 513 pending_async_touchmove_->CoalesceWith(touch); |
489 } | 514 } |
490 DCHECK_EQ(1U, size()); | 515 DCHECK_EQ(1U, size()); |
491 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | 516 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
(...skipping 14 matching lines...) Expand all Loading... | |
506 if (pending_async_touchmove_) { | 531 if (pending_async_touchmove_) { |
507 if (pending_async_touchmove_->CanCoalesceWith(touch)) { | 532 if (pending_async_touchmove_->CanCoalesceWith(touch)) { |
508 pending_async_touchmove_->CoalesceWith(touch); | 533 pending_async_touchmove_->CoalesceWith(touch); |
509 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; | 534 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; |
510 touch = *pending_async_touchmove_; | 535 touch = *pending_async_touchmove_; |
511 pending_async_touchmove_.reset(); | 536 pending_async_touchmove_.reset(); |
512 } else { | 537 } else { |
513 scoped_ptr<TouchEventWithLatencyInfo> async_move = | 538 scoped_ptr<TouchEventWithLatencyInfo> async_move = |
514 pending_async_touchmove_.Pass(); | 539 pending_async_touchmove_.Pass(); |
515 async_move->event.cancelable = false; | 540 async_move->event.cancelable = false; |
516 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); | |
517 SendTouchEventImmediately(async_move.get()); | 541 SendTouchEventImmediately(async_move.get()); |
518 return; | 542 return; |
519 } | 543 } |
520 } | 544 } |
521 | 545 |
522 // Note: Touchstart events are marked cancelable to allow transitions between | 546 // Note: Touchstart events are marked cancelable to allow transitions between |
523 // platform scrolling and JS pinching. Touchend events, however, remain | 547 // platform scrolling and JS pinching. Touchend events, however, remain |
524 // uncancelable, mitigating the risk of jank when transitioning to a fling. | 548 // uncancelable, mitigating the risk of jank when transitioning to a fling. |
525 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) | 549 if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart) |
526 touch.event.cancelable = false; | 550 touch.event.cancelable = false; |
527 | 551 |
552 // For the async touchmove, when we dispatch it, we will remove it from the | |
553 // front of the queue and keep it in a separate queue. | |
554 if (touch.event.type == WebInputEvent::TouchMove && !touch.event.cancelable) { | |
555 PopTouchEvent(); | |
jdduke (slow)
2015/04/15 17:14:53
Why can't we move this code next to the other asyn
lanwei
2015/04/17 20:49:00
When pending_async_touchmove_ is not null and we h
| |
556 } | |
528 // A synchronous ack will reset |dispatching_touch_|, in which case | 557 // A synchronous ack will reset |dispatching_touch_|, in which case |
529 // the touch timeout should not be started. | 558 // the touch timeout should not be started. |
530 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | 559 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
531 SendTouchEventImmediately(&touch); | 560 SendTouchEventImmediately(&touch); |
532 if (dispatching_touch_ && timeout_handler_) | 561 if (dispatching_touch_ && timeout_handler_) |
533 timeout_handler_->StartIfNecessary(touch); | 562 timeout_handler_->StartIfNecessary(touch); |
534 } | 563 } |
535 | 564 |
536 void TouchEventQueue::OnGestureScrollEvent( | 565 void TouchEventQueue::OnGestureScrollEvent( |
537 const GestureEventWithLatencyInfo& gesture_event) { | 566 const GestureEventWithLatencyInfo& gesture_event) { |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
664 } | 693 } |
665 } | 694 } |
666 } | 695 } |
667 | 696 |
668 if (last_sent_touchevent_) | 697 if (last_sent_touchevent_) |
669 *last_sent_touchevent_ = touch->event; | 698 *last_sent_touchevent_ = touch->event; |
670 else | 699 else |
671 last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); | 700 last_sent_touchevent_.reset(new WebTouchEvent(touch->event)); |
672 | 701 |
673 client_->SendTouchEventImmediately(*touch); | 702 client_->SendTouchEventImmediately(*touch); |
703 | |
704 if (touch->event.type == WebInputEvent::TouchMove && | |
jdduke (slow)
2015/04/15 17:14:53
I think we may need a guard here in the event that
lanwei
2015/04/17 20:49:00
Done.
| |
705 !touch->event.cancelable) { | |
706 // We push it into the queue when we send out a uncancelable touch move. | |
707 // For the async touchmove, we do not process input event ack any more, we | |
708 // will ack to client and wait for the ack from render. | |
709 ack_pending_async_touchmove_.push_front(*touch); | |
jdduke (slow)
2015/04/15 17:14:53
A count should be sufficient.
lanwei
2015/04/17 20:49:00
Done.
| |
710 client_->OnTouchEventAck(*touch, INPUT_EVENT_ACK_STATE_IGNORED); | |
711 TryForwardNextEventToRenderer(); | |
712 } | |
674 } | 713 } |
675 | 714 |
676 TouchEventQueue::PreFilterResult | 715 TouchEventQueue::PreFilterResult |
677 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { | 716 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { |
678 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { | 717 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { |
679 has_handler_for_current_sequence_ = false; | 718 has_handler_for_current_sequence_ = false; |
680 send_touch_events_async_ = false; | 719 send_touch_events_async_ = false; |
681 pending_async_touchmove_.reset(); | 720 pending_async_touchmove_.reset(); |
682 last_sent_touchevent_.reset(); | 721 last_sent_touchevent_.reset(); |
683 | 722 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
750 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) | 789 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
751 send_touch_events_async_ = false; | 790 send_touch_events_async_ = false; |
752 has_handler_for_current_sequence_ |= | 791 has_handler_for_current_sequence_ |= |
753 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; | 792 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; |
754 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { | 793 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { |
755 has_handler_for_current_sequence_ = false; | 794 has_handler_for_current_sequence_ = false; |
756 } | 795 } |
757 } | 796 } |
758 | 797 |
759 } // namespace content | 798 } // namespace content |
OLD | NEW |