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

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

Powered by Google App Engine
This is Rietveld 408576698