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

Side by Side Diff: content/browser/renderer_host/input/input_router_impl.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: Change the unittests Created 5 years, 7 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/input_router_impl.h" 5 #include "content/browser/renderer_host/input/input_router_impl.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 const ui::LatencyInfo& latency_info, 351 const ui::LatencyInfo& latency_info,
352 bool is_keyboard_shortcut) { 352 bool is_keyboard_shortcut) {
353 output_stream_validator_.Validate(input_event); 353 output_stream_validator_.Validate(input_event);
354 354
355 if (OfferToClient(input_event, latency_info)) 355 if (OfferToClient(input_event, latency_info))
356 return; 356 return;
357 357
358 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); 358 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut);
359 359
360 // Touch events should always indicate in the event whether they are 360 // Touch events should always indicate in the event whether they are
361 // cancelable (respect ACK disposition) or not. 361 // cancelable (respect ACK disposition) or not except touchmove.
362 bool ignores_ack = WebInputEventTraits::IgnoresAckDisposition(input_event); 362 bool needs_synthetic_ack =
363 if (WebInputEvent::isTouchEventType(input_event.type)) { 363 !WebInputEventTraits::WillReceiveAckFromRenderer(input_event);
364
365 if (WebInputEvent::isTouchEventType(input_event.type) &&
366 input_event.type != WebInputEvent::TouchMove) {
364 const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event); 367 const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event);
365 DCHECK_NE(ignores_ack, !!touch.cancelable); 368 DCHECK_EQ(needs_synthetic_ack, !touch.cancelable);
366 } 369 }
367 370
368 // If we don't care about the ack disposition, send the ack immediately. 371 // The synthetic acks are sent immediately.
369 if (ignores_ack) { 372 if (needs_synthetic_ack) {
370 ProcessInputEventAck(input_event.type, 373 ProcessInputEventAck(
371 INPUT_EVENT_ACK_STATE_IGNORED, 374 input_event.type, INPUT_EVENT_ACK_STATE_IGNORED, latency_info,
372 latency_info, 375 WebInputEventTraits::GetUniqueTouchEventId(input_event),
373 IGNORING_DISPOSITION); 376 IGNORING_DISPOSITION);
374 } 377 }
375 } 378 }
376 379
377 bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event, 380 bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event,
378 const ui::LatencyInfo& latency_info) { 381 const ui::LatencyInfo& latency_info) {
379 bool consumed = false; 382 bool consumed = false;
380 383
381 InputEventAckState filter_ack = 384 InputEventAckState filter_ack =
382 client_->FilterInputEvent(input_event, latency_info); 385 client_->FilterInputEvent(input_event, latency_info);
383 switch (filter_ack) { 386 switch (filter_ack) {
384 case INPUT_EVENT_ACK_STATE_CONSUMED: 387 case INPUT_EVENT_ACK_STATE_CONSUMED:
385 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: 388 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
386 // Send the ACK and early exit. 389 // Send the ACK and early exit.
387 next_mouse_move_.reset(); 390 next_mouse_move_.reset();
388 ProcessInputEventAck(input_event.type, filter_ack, latency_info, CLIENT); 391 ProcessInputEventAck(
392 input_event.type, filter_ack, latency_info,
393 WebInputEventTraits::GetUniqueTouchEventId(input_event), CLIENT);
389 // WARNING: |this| may be deleted at this point. 394 // WARNING: |this| may be deleted at this point.
390 consumed = true; 395 consumed = true;
391 break; 396 break;
392 case INPUT_EVENT_ACK_STATE_UNKNOWN: 397 case INPUT_EVENT_ACK_STATE_UNKNOWN:
393 // Simply drop the event. 398 // Simply drop the event.
394 consumed = true; 399 consumed = true;
395 break; 400 break;
396 default: 401 default:
397 break; 402 break;
398 } 403 }
399 404
400 return consumed; 405 return consumed;
401 } 406 }
402 407
403 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, 408 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
404 const ui::LatencyInfo& latency_info, 409 const ui::LatencyInfo& latency_info,
405 bool is_keyboard_shortcut) { 410 bool is_keyboard_shortcut) {
406 if (Send(new InputMsg_HandleInputEvent( 411 if (Send(new InputMsg_HandleInputEvent(
407 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) { 412 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) {
408 // Ack messages for ignored ack event types should never be sent by the 413 // Ack messages for ignored ack event types should never be sent by the
409 // renderer. Consequently, such event types should not affect event time 414 // renderer. Consequently, such event types should not affect event time
410 // or in-flight event count metrics. 415 // or in-flight event count metrics.
411 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { 416 if (WebInputEventTraits::WillReceiveAckFromRenderer(input_event)) {
412 input_event_start_time_ = TimeTicks::Now(); 417 input_event_start_time_ = TimeTicks::Now();
413 client_->IncrementInFlightEventCount(); 418 client_->IncrementInFlightEventCount();
414 } 419 }
415 return true; 420 return true;
416 } 421 }
417 return false; 422 return false;
418 } 423 }
419 424
420 void InputRouterImpl::OnInputEventAck( 425 void InputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
421 const InputHostMsg_HandleInputEvent_ACK_Params& ack) {
422 client_->DecrementInFlightEventCount(); 426 client_->DecrementInFlightEventCount();
423
424 // Log the time delta for processing an input event. 427 // Log the time delta for processing an input event.
425 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; 428 TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
426 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); 429 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
427 430
428 if (ack.overscroll) { 431 if (ack.overscroll) {
429 DCHECK(ack.type == WebInputEvent::MouseWheel || 432 DCHECK(ack.type == WebInputEvent::MouseWheel ||
430 ack.type == WebInputEvent::GestureScrollUpdate); 433 ack.type == WebInputEvent::GestureScrollUpdate);
431 OnDidOverscroll(*ack.overscroll); 434 OnDidOverscroll(*ack.overscroll);
432 } 435 }
433 436
434 ProcessInputEventAck(ack.type, ack.state, ack.latency, RENDERER); 437 ProcessInputEventAck(ack.type, ack.state, ack.latency,
435 // WARNING: |this| may be deleted at this point. 438 ack.unique_touch_event_id, RENDERER);
436
437 // This is used only for testing, and the other end does not use the
438 // source object. On linux, specifying
439 // Source<RenderWidgetHost> results in a very strange
440 // runtime error in the epilogue of the enclosing
441 // (ProcessInputEventAck) method, but not on other platforms; using
442 // 'void' instead is just as safe (since NotificationSource
443 // is not actually typesafe) and avoids this error.
444 int type = static_cast<int>(ack.type);
445 NotificationService::current()->Notify(
446 NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
447 Source<void>(this),
448 Details<int>(&type));
449 } 439 }
450 440
451 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) { 441 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) {
452 client_->DidOverscroll(params); 442 client_->DidOverscroll(params);
453 } 443 }
454 444
455 void InputRouterImpl::OnMsgMoveCaretAck() { 445 void InputRouterImpl::OnMsgMoveCaretAck() {
456 move_caret_pending_ = false; 446 move_caret_pending_ = false;
457 if (next_move_caret_) 447 if (next_move_caret_)
458 SendMoveCaret(next_move_caret_.Pass()); 448 SendMoveCaret(next_move_caret_.Pass());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 DCHECK_GT(active_renderer_fling_count_, 0); 492 DCHECK_GT(active_renderer_fling_count_, 0);
503 // Note that we're only guaranteed to get a fling end notification from the 493 // Note that we're only guaranteed to get a fling end notification from the
504 // renderer, not from any other consumers. Consequently, the GestureEventQueue 494 // renderer, not from any other consumers. Consequently, the GestureEventQueue
505 // cannot use this bookkeeping for logic like tap suppression. 495 // cannot use this bookkeeping for logic like tap suppression.
506 --active_renderer_fling_count_; 496 --active_renderer_fling_count_;
507 SignalFlushedIfNecessary(); 497 SignalFlushedIfNecessary();
508 498
509 client_->DidStopFlinging(); 499 client_->DidStopFlinging();
510 } 500 }
511 501
512 void InputRouterImpl::ProcessInputEventAck( 502 void InputRouterImpl::ProcessInputEventAck(WebInputEvent::Type event_type,
513 WebInputEvent::Type event_type, 503 InputEventAckState ack_result,
514 InputEventAckState ack_result, 504 const ui::LatencyInfo& latency_info,
515 const ui::LatencyInfo& latency_info, 505 uint32 unique_touch_event_id,
516 AckSource ack_source) { 506 AckSource ack_source) {
517 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", 507 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck",
518 "type", WebInputEventTraits::GetName(event_type), 508 "type", WebInputEventTraits::GetName(event_type),
519 "ack", GetEventAckName(ack_result)); 509 "ack", GetEventAckName(ack_result));
520 510
521 // Note: The keyboard ack must be treated carefully, as it may result in 511 // Note: The keyboard ack must be treated carefully, as it may result in
522 // synchronous destruction of |this|. Handling immediately guards against 512 // synchronous destruction of |this|. Handling immediately guards against
523 // future references to |this|, as with |auto_reset_current_ack_source| below. 513 // future references to |this|, as with |auto_reset_current_ack_source| below.
524 if (WebInputEvent::isKeyboardEventType(event_type)) { 514 if (WebInputEvent::isKeyboardEventType(event_type)) {
525 ProcessKeyboardAck(event_type, ack_result); 515 ProcessKeyboardAck(event_type, ack_result);
526 // WARNING: |this| may be deleted at this point. 516 // WARNING: |this| may be deleted at this point.
527 return; 517 return;
528 } 518 }
529 519
530 base::AutoReset<AckSource> auto_reset_current_ack_source( 520 base::AutoReset<AckSource> auto_reset_current_ack_source(
531 &current_ack_source_, ack_source); 521 &current_ack_source_, ack_source);
532 522
533 if (WebInputEvent::isMouseEventType(event_type)) { 523 if (WebInputEvent::isMouseEventType(event_type)) {
534 ProcessMouseAck(event_type, ack_result); 524 ProcessMouseAck(event_type, ack_result);
535 } else if (event_type == WebInputEvent::MouseWheel) { 525 } else if (event_type == WebInputEvent::MouseWheel) {
536 ProcessWheelAck(ack_result, latency_info); 526 ProcessWheelAck(ack_result, latency_info);
537 } else if (WebInputEvent::isTouchEventType(event_type)) { 527 } else if (WebInputEvent::isTouchEventType(event_type)) {
538 ProcessTouchAck(ack_result, latency_info); 528 ProcessTouchAck(ack_result, latency_info, unique_touch_event_id);
539 } else if (WebInputEvent::isGestureEventType(event_type)) { 529 } else if (WebInputEvent::isGestureEventType(event_type)) {
540 ProcessGestureAck(event_type, ack_result, latency_info); 530 ProcessGestureAck(event_type, ack_result, latency_info);
541 } else if (event_type != WebInputEvent::Undefined) { 531 } else if (event_type != WebInputEvent::Undefined) {
542 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); 532 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
543 } 533 }
544 534
545 SignalFlushedIfNecessary(); 535 SignalFlushedIfNecessary();
546 } 536 }
547 537
548 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, 538 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (type == blink::WebInputEvent::GestureFlingStart && 603 if (type == blink::WebInputEvent::GestureFlingStart &&
614 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED && 604 ack_result == INPUT_EVENT_ACK_STATE_CONSUMED &&
615 current_ack_source_ == RENDERER) { 605 current_ack_source_ == RENDERER) {
616 ++active_renderer_fling_count_; 606 ++active_renderer_fling_count_;
617 } 607 }
618 608
619 // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate. 609 // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate.
620 gesture_event_queue_.ProcessGestureAck(ack_result, type, latency); 610 gesture_event_queue_.ProcessGestureAck(ack_result, type, latency);
621 } 611 }
622 612
623 void InputRouterImpl::ProcessTouchAck( 613 void InputRouterImpl::ProcessTouchAck(InputEventAckState ack_result,
624 InputEventAckState ack_result, 614 const ui::LatencyInfo& latency,
625 const ui::LatencyInfo& latency) { 615 uint32 unique_touch_event_id) {
626 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate. 616 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
627 touch_event_queue_.ProcessTouchAck(ack_result, latency); 617 touch_event_queue_.ProcessTouchAck(ack_result, latency,
618 unique_touch_event_id);
628 } 619 }
629 620
630 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { 621 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() {
631 // Mobile sites tend to be well-behaved with respect to touch handling, so 622 // Mobile sites tend to be well-behaved with respect to touch handling, so
632 // they have less need for the touch timeout fallback. 623 // they have less need for the touch timeout fallback.
633 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; 624 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0;
634 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; 625 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0;
635 626
636 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves 627 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves
637 // little purpose. It's also a strong signal that touch handling is critical 628 // little purpose. It's also a strong signal that touch handling is critical
(...skipping 12 matching lines...) Expand all
650 return; 641 return;
651 642
652 if (HasPendingEvents()) 643 if (HasPendingEvents())
653 return; 644 return;
654 645
655 flush_requested_ = false; 646 flush_requested_ = false;
656 client_->DidFlush(); 647 client_->DidFlush();
657 } 648 }
658 649
659 } // namespace content 650 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698