Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: content/browser/renderer_host/input/touch_event_queue.cc

Issue 997283002: Coalesce async touch move events until the ack back from render (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698