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

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

Powered by Google App Engine
This is Rietveld 408576698