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 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, | 365 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, |
| 366 const Config& config) | 366 const Config& config) |
| 367 : client_(client), | 367 : client_(client), |
| 368 dispatching_touch_ack_(false), | 368 dispatching_touch_ack_(false), |
| 369 dispatching_touch_(false), | 369 dispatching_touch_(false), |
| 370 has_handlers_(true), | 370 has_handlers_(true), |
| 371 has_handler_for_current_sequence_(false), | 371 has_handler_for_current_sequence_(false), |
| 372 drop_remaining_touches_in_sequence_(false), | 372 drop_remaining_touches_in_sequence_(false), |
| 373 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), | 373 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor), |
| 374 send_touch_events_async_(false), | 374 send_touch_events_async_(false), |
| 375 sent_uncancelable_touch_move_count_(0), | |
| 375 last_sent_touch_timestamp_sec_(0) { | 376 last_sent_touch_timestamp_sec_(0) { |
| 376 DCHECK(client); | 377 DCHECK(client); |
| 377 if (config.touch_ack_timeout_supported) { | 378 if (config.touch_ack_timeout_supported) { |
| 378 timeout_handler_.reset( | 379 timeout_handler_.reset( |
| 379 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); | 380 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay)); |
| 380 } | 381 } |
| 381 } | 382 } |
| 382 | 383 |
| 383 TouchEventQueue::~TouchEventQueue() { | 384 TouchEventQueue::~TouchEventQueue() { |
| 384 if (!touch_queue_.empty()) | 385 if (!touch_queue_.empty()) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 DCHECK(!dispatching_touch_ack_); | 427 DCHECK(!dispatching_touch_ack_); |
| 427 dispatching_touch_ = false; | 428 dispatching_touch_ = false; |
| 428 | 429 |
| 429 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) | 430 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result)) |
| 430 return; | 431 return; |
| 431 | 432 |
| 432 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); | 433 touchmove_slop_suppressor_->ConfirmTouchEvent(ack_result); |
| 433 | 434 |
| 434 if (touch_queue_.empty()) | 435 if (touch_queue_.empty()) |
| 435 return; | 436 return; |
| 436 | |
|
tdresser
2015/03/26 15:25:28
Put back whitespace.
lanwei
2015/03/27 04:39:41
Done.
| |
| 437 PopTouchEventToClient(ack_result, latency_info); | 437 PopTouchEventToClient(ack_result, latency_info); |
| 438 TryForwardNextEventToRenderer(); | 438 TryForwardNextEventToRenderer(); |
| 439 } | 439 } |
| 440 | 440 |
| 441 void TouchEventQueue::ProcessUncancelableTouchMoveAck() { | |
| 442 TRACE_EVENT0("input", "TouchEventQueue::ProcessUncancelableTouchMoveAck"); | |
| 443 | |
| 444 DCHECK(!dispatching_touch_ack_); | |
| 445 dispatching_touch_ = false; | |
| 446 | |
| 447 // Decrease the count once we receive the ack back from render for | |
| 448 // uncancelable touchmoves. | |
| 449 --sent_uncancelable_touch_move_count_; | |
| 450 | |
| 451 // Send the next pending async touch move once we receive the ack. | |
| 452 if (pending_async_touchmove_) { | |
|
tdresser
2015/03/26 15:25:28
Shouldn't we only dispatch the pending async touch
lanwei
2015/03/27 04:39:41
Done.
| |
| 453 TouchEventWithLatencyInfo touch = *pending_async_touchmove_; | |
| 454 touch.event.cancelable = !send_touch_events_async_; | |
| 455 pending_async_touchmove_.reset(); | |
| 456 if (!touch.event.cancelable) | |
| 457 ++sent_uncancelable_touch_move_count_; | |
| 458 touch_queue_.push_front(new CoalescedWebTouchEvent(touch, true)); | |
| 459 SendTouchEventImmediately(&touch); | |
| 460 } | |
| 461 } | |
| 462 | |
| 441 void TouchEventQueue::TryForwardNextEventToRenderer() { | 463 void TouchEventQueue::TryForwardNextEventToRenderer() { |
| 442 DCHECK(!dispatching_touch_ack_); | 464 DCHECK(!dispatching_touch_ack_); |
| 443 // If there are queued touch events, then try to forward them to the renderer | 465 // 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. | 466 // immediately, or ACK the events back to the client if appropriate. |
| 445 while (!touch_queue_.empty()) { | 467 while (!touch_queue_.empty()) { |
| 446 PreFilterResult filter_result = | 468 PreFilterResult filter_result = |
| 447 FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event); | 469 FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event); |
| 448 switch (filter_result) { | 470 switch (filter_result) { |
| 449 case ACK_WITH_NO_CONSUMER_EXISTS: | 471 case ACK_WITH_NO_CONSUMER_EXISTS: |
| 450 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); | 472 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); |
| 451 break; | 473 break; |
| 452 case ACK_WITH_NOT_CONSUMED: | 474 case ACK_WITH_NOT_CONSUMED: |
| 453 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | 475 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| 454 break; | 476 break; |
| 455 case FORWARD_TO_RENDERER: | 477 case FORWARD_TO_RENDERER: |
| 456 ForwardNextEventToRenderer(); | 478 ForwardNextEventToRenderer(); |
| 457 return; | 479 return; |
| 458 } | 480 } |
| 459 } | 481 } |
| 460 } | 482 } |
| 461 | 483 |
| 462 void TouchEventQueue::ForwardNextEventToRenderer() { | 484 void TouchEventQueue::ForwardNextEventToRenderer() { |
| 463 TRACE_EVENT0("input", "TouchEventQueue::ForwardNextEventToRenderer"); | 485 TRACE_EVENT0("input", "TouchEventQueue::ForwardNextEventToRenderer"); |
| 464 | 486 |
| 465 DCHECK(!empty()); | 487 DCHECK(!empty()); |
| 466 DCHECK(!dispatching_touch_); | 488 DCHECK(!dispatching_touch_); |
| 467 TouchEventWithLatencyInfo touch = touch_queue_.front()->coalesced_event(); | 489 TouchEventWithLatencyInfo touch = touch_queue_.front()->coalesced_event(); |
| 468 | |
|
tdresser
2015/03/26 15:25:28
Put back whitespace.
lanwei
2015/03/27 04:39:41
Done.
| |
| 469 if (send_touch_events_async_ && | 490 if (send_touch_events_async_ && |
| 470 touch.event.type == WebInputEvent::TouchMove) { | 491 touch.event.type == WebInputEvent::TouchMove) { |
| 471 // Throttling touchmove's in a continuous touchmove stream while scrolling | 492 // Throttling touchmove's in a continuous touchmove stream while scrolling |
| 472 // reduces the risk of jank. However, it's still important that the web | 493 // 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, | 494 // application be sent touches at key points in the gesture stream, |
| 474 // e.g., when the application slop region is exceeded or touchmove | 495 // e.g., when the application slop region is exceeded or touchmove |
| 475 // coalescing fails because of different modifiers. | 496 // coalescing fails because of different modifiers. |
| 476 bool send_touchmove_now = size() > 1; | 497 bool send_touchmove_now = size() > 1; |
| 477 send_touchmove_now |= pending_async_touchmove_ && | 498 send_touchmove_now |= pending_async_touchmove_ && |
| 478 !pending_async_touchmove_->CanCoalesceWith(touch); | 499 !pending_async_touchmove_->CanCoalesceWith(touch); |
| 479 send_touchmove_now |= | 500 send_touchmove_now |= |
| 480 touch.event.timeStampSeconds >= | 501 touch.event.timeStampSeconds >= |
| 481 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec; | 502 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec; |
| 482 | 503 |
| 483 if (!send_touchmove_now) { | 504 if (!send_touchmove_now || sent_uncancelable_touch_move_count_ > 0) { |
| 484 if (!pending_async_touchmove_) { | 505 if (!pending_async_touchmove_) { |
| 485 pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch)); | 506 pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch)); |
| 486 } else { | 507 } else { |
| 487 DCHECK(pending_async_touchmove_->CanCoalesceWith(touch)); | 508 DCHECK(pending_async_touchmove_->CanCoalesceWith(touch)); |
| 488 pending_async_touchmove_->CoalesceWith(touch); | 509 pending_async_touchmove_->CoalesceWith(touch); |
| 489 } | 510 } |
| 490 DCHECK_EQ(1U, size()); | 511 DCHECK_EQ(1U, size()); |
| 491 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | 512 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| 492 // It's possible (though unlikely) that ack'ing the current touch will | 513 // It's possible (though unlikely) that ack'ing the current touch will |
| 493 // trigger the queueing of another touch event (e.g., a touchcancel). As | 514 // trigger the queueing of another touch event (e.g., a touchcancel). As |
| 494 // forwarding of the queued event will be deferred while the ack is being | 515 // forwarding of the queued event will be deferred while the ack is being |
| 495 // dispatched (see |OnTouchEvent()|), try forwarding it now. | 516 // dispatched (see |OnTouchEvent()|), try forwarding it now. |
| 496 TryForwardNextEventToRenderer(); | 517 TryForwardNextEventToRenderer(); |
| 497 return; | 518 return; |
| 498 } | 519 } |
| 499 } | 520 } |
| 500 | 521 |
| 501 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds; | 522 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds; |
| 502 | |
| 503 // Flush any pending async touch move. If it can be combined with the current | 523 // Flush any pending async touch move. If it can be combined with the current |
| 504 // (touchmove) event, great, otherwise send it immediately but separately. Its | 524 // (touchmove) event, great, otherwise send it immediately but separately. Its |
| 505 // ack will trigger forwarding of the original |touch| event. | 525 // ack will trigger forwarding of the original |touch| event. |
| 506 if (pending_async_touchmove_) { | 526 if (pending_async_touchmove_) { |
| 507 if (pending_async_touchmove_->CanCoalesceWith(touch)) { | 527 if (pending_async_touchmove_->CanCoalesceWith(touch)) { |
| 508 pending_async_touchmove_->CoalesceWith(touch); | 528 pending_async_touchmove_->CoalesceWith(touch); |
| 509 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; | 529 pending_async_touchmove_->event.cancelable = !send_touch_events_async_; |
| 510 touch = *pending_async_touchmove_; | 530 touch = *pending_async_touchmove_; |
| 511 pending_async_touchmove_.reset(); | 531 pending_async_touchmove_.reset(); |
| 512 } else { | 532 } else { |
| 533 // Once we flush the pending async touch move, we ignore all the acks | |
| 534 // from the uncancelable touch moves that we sent out and wait for acks | |
| 535 // back. | |
| 536 ++sent_uncancelable_touch_move_count_; | |
|
tdresser
2015/03/26 15:25:28
Could we increase the count inside SendTouchEventI
lanwei
2015/03/27 04:39:41
Done.
| |
| 513 scoped_ptr<TouchEventWithLatencyInfo> async_move = | 537 scoped_ptr<TouchEventWithLatencyInfo> async_move = |
| 514 pending_async_touchmove_.Pass(); | 538 pending_async_touchmove_.Pass(); |
| 515 async_move->event.cancelable = false; | 539 async_move->event.cancelable = false; |
| 516 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); | 540 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 |
| 528 // A synchronous ack will reset |dispatching_touch_|, in which case | 552 // A synchronous ack will reset |dispatching_touch_|, in which case |
| 529 // the touch timeout should not be started. | 553 // the touch timeout should not be started. |
| 530 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); | 554 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
| 555 | |
| 556 // We increase the count when we send out a uncancelable touch move. | |
| 557 if (touch.event.type == WebInputEvent::TouchMove && !touch.event.cancelable) { | |
| 558 ++sent_uncancelable_touch_move_count_; | |
| 559 } | |
| 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) { |
| 538 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { | 567 if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) { |
| 539 if (has_handler_for_current_sequence_ && | 568 if (has_handler_for_current_sequence_ && |
| 540 !drop_remaining_touches_in_sequence_) { | 569 !drop_remaining_touches_in_sequence_) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 750 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) | 779 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| 751 send_touch_events_async_ = false; | 780 send_touch_events_async_ = false; |
| 752 has_handler_for_current_sequence_ |= | 781 has_handler_for_current_sequence_ |= |
| 753 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; | 782 ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; |
| 754 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { | 783 } else if (WebTouchEventTraits::IsTouchSequenceEnd(event)) { |
| 755 has_handler_for_current_sequence_ = false; | 784 has_handler_for_current_sequence_ = false; |
| 756 } | 785 } |
| 757 } | 786 } |
| 758 | 787 |
| 759 } // namespace content | 788 } // namespace content |
| OLD | NEW |