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

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: Fixing 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 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);
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) {
jdduke (slow) 2015/05/08 21:30:48 Hmm, synthetic means fake, so I think this should
lanwei 2015/05/11 19:27:56 Done.
368 ProcessInputEventAck(input_event.type, 371 ProcessInputEventAck(
369 INPUT_EVENT_ACK_STATE_IGNORED, 372 input_event.type, INPUT_EVENT_ACK_STATE_IGNORED, latency_info,
370 latency_info, 373 WebInputEventTraits::GetUniqueTouchEventId(input_event),
371 IGNORING_DISPOSITION); 374 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(
jdduke (slow) 2015/05/08 21:30:48 You can remove this unused variable.
lanwei 2015/05/11 19:27:55 Done.
390 input_event.type, filter_ack, latency_info,
391 WebInputEventTraits::GetUniqueTouchEventId(input_event));
392 ProcessInputEventAck(
393 input_event.type, filter_ack, latency_info,
394 WebInputEventTraits::GetUniqueTouchEventId(input_event), CLIENT);
387 // WARNING: |this| may be deleted at this point. 395 // WARNING: |this| may be deleted at this point.
388 consumed = true; 396 consumed = true;
389 break; 397 break;
398 }
390 case INPUT_EVENT_ACK_STATE_UNKNOWN: 399 case INPUT_EVENT_ACK_STATE_UNKNOWN:
391 // Simply drop the event. 400 // Simply drop the event.
392 consumed = true; 401 consumed = true;
393 break; 402 break;
394 default: 403 default:
395 break; 404 break;
396 } 405 }
397 406
398 return consumed; 407 return consumed;
399 } 408 }
400 409
401 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, 410 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
402 const ui::LatencyInfo& latency_info, 411 const ui::LatencyInfo& latency_info,
403 bool is_keyboard_shortcut) { 412 bool is_keyboard_shortcut) {
404 if (Send(new InputMsg_HandleInputEvent( 413 if (Send(new InputMsg_HandleInputEvent(
405 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) { 414 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) {
406 // Ack messages for ignored ack event types should never be sent by the 415 // Ack messages for ignored ack event types should never be sent by the
407 // renderer. Consequently, such event types should not affect event time 416 // renderer. Consequently, such event types should not affect event time
408 // or in-flight event count metrics. 417 // or in-flight event count metrics.
409 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { 418 if (WebInputEventTraits::WillReceiveAckFromRenderer(input_event)) {
410 input_event_start_time_ = TimeTicks::Now(); 419 input_event_start_time_ = TimeTicks::Now();
411 client_->IncrementInFlightEventCount(); 420 client_->IncrementInFlightEventCount();
412 } 421 }
413 return true; 422 return true;
414 } 423 }
415 return false; 424 return false;
416 } 425 }
417 426
418 void InputRouterImpl::OnInputEventAck( 427 void InputRouterImpl::OnInputEventAck(const InputEventAck& ack) {
419 const InputHostMsg_HandleInputEvent_ACK_Params& ack) {
420 client_->DecrementInFlightEventCount(); 428 client_->DecrementInFlightEventCount();
421
422 // Log the time delta for processing an input event. 429 // Log the time delta for processing an input event.
423 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; 430 TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
424 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); 431 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
425 432
426 if (ack.overscroll) { 433 if (ack.overscroll) {
427 DCHECK(ack.type == WebInputEvent::MouseWheel || 434 DCHECK(ack.type == WebInputEvent::MouseWheel ||
428 ack.type == WebInputEvent::GestureScrollUpdate); 435 ack.type == WebInputEvent::GestureScrollUpdate);
429 OnDidOverscroll(*ack.overscroll); 436 OnDidOverscroll(*ack.overscroll);
430 } 437 }
431 438
432 ProcessInputEventAck(ack.type, ack.state, ack.latency, RENDERER); 439 ProcessInputEventAck(ack.type, ack.state, ack.latency,
433 // WARNING: |this| may be deleted at this point. 440 ack.unique_touch_event_id, RENDERER);
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 } 441 }
448 442
449 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) { 443 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) {
450 client_->DidOverscroll(params); 444 client_->DidOverscroll(params);
451 } 445 }
452 446
453 void InputRouterImpl::OnMsgMoveCaretAck() { 447 void InputRouterImpl::OnMsgMoveCaretAck() {
454 move_caret_pending_ = false; 448 move_caret_pending_ = false;
455 if (next_move_caret_) 449 if (next_move_caret_)
456 SendMoveCaret(next_move_caret_.Pass()); 450 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. 489 // TOUCH_ACTION_NONE should disable the touch ack timeout.
496 UpdateTouchAckTimeoutEnabled(); 490 UpdateTouchAckTimeoutEnabled();
497 } 491 }
498 492
499 void InputRouterImpl::OnDidStopFlinging() { 493 void InputRouterImpl::OnDidStopFlinging() {
500 // TODO(jdduke): Track fling status to allow flush notifications after a fling 494 // TODO(jdduke): Track fling status to allow flush notifications after a fling
501 // has terminated, crbug.com/483037. 495 // has terminated, crbug.com/483037.
502 client_->DidStopFlinging(); 496 client_->DidStopFlinging();
503 } 497 }
504 498
505 void InputRouterImpl::ProcessInputEventAck( 499 void InputRouterImpl::ProcessInputEventAck(WebInputEvent::Type event_type,
506 WebInputEvent::Type event_type, 500 InputEventAckState ack_result,
507 InputEventAckState ack_result, 501 const ui::LatencyInfo& latency_info,
508 const ui::LatencyInfo& latency_info, 502 uint32 unique_touch_event_id,
509 AckSource ack_source) { 503 AckSource ack_source) {
510 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck", 504 TRACE_EVENT2("input", "InputRouterImpl::ProcessInputEventAck",
511 "type", WebInputEventTraits::GetName(event_type), 505 "type", WebInputEventTraits::GetName(event_type),
512 "ack", GetEventAckName(ack_result)); 506 "ack", GetEventAckName(ack_result));
513 507
514 // Note: The keyboard ack must be treated carefully, as it may result in 508 // Note: The keyboard ack must be treated carefully, as it may result in
515 // synchronous destruction of |this|. Handling immediately guards against 509 // synchronous destruction of |this|. Handling immediately guards against
516 // future references to |this|, as with |auto_reset_current_ack_source| below. 510 // future references to |this|, as with |auto_reset_current_ack_source| below.
517 if (WebInputEvent::isKeyboardEventType(event_type)) { 511 if (WebInputEvent::isKeyboardEventType(event_type)) {
518 ProcessKeyboardAck(event_type, ack_result); 512 ProcessKeyboardAck(event_type, ack_result);
519 // WARNING: |this| may be deleted at this point. 513 // WARNING: |this| may be deleted at this point.
520 return; 514 return;
521 } 515 }
522 516
523 base::AutoReset<AckSource> auto_reset_current_ack_source( 517 base::AutoReset<AckSource> auto_reset_current_ack_source(
524 &current_ack_source_, ack_source); 518 &current_ack_source_, ack_source);
525 519
526 if (WebInputEvent::isMouseEventType(event_type)) { 520 if (WebInputEvent::isMouseEventType(event_type)) {
527 ProcessMouseAck(event_type, ack_result); 521 ProcessMouseAck(event_type, ack_result);
528 } else if (event_type == WebInputEvent::MouseWheel) { 522 } else if (event_type == WebInputEvent::MouseWheel) {
529 ProcessWheelAck(ack_result, latency_info); 523 ProcessWheelAck(ack_result, latency_info);
530 } else if (WebInputEvent::isTouchEventType(event_type)) { 524 } else if (WebInputEvent::isTouchEventType(event_type)) {
531 ProcessTouchAck(ack_result, latency_info); 525 ProcessTouchAck(ack_result, latency_info, unique_touch_event_id);
532 } else if (WebInputEvent::isGestureEventType(event_type)) { 526 } else if (WebInputEvent::isGestureEventType(event_type)) {
533 ProcessGestureAck(event_type, ack_result, latency_info); 527 ProcessGestureAck(event_type, ack_result, latency_info);
534 } else if (event_type != WebInputEvent::Undefined) { 528 } else if (event_type != WebInputEvent::Undefined) {
535 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); 529 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE);
536 } 530 }
537 531
538 SignalFlushedIfNecessary(); 532 SignalFlushedIfNecessary();
539 } 533 }
540 534
541 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type, 535 void InputRouterImpl::ProcessKeyboardAck(blink::WebInputEvent::Type type,
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 } 594 }
601 } 595 }
602 596
603 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, 597 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type,
604 InputEventAckState ack_result, 598 InputEventAckState ack_result,
605 const ui::LatencyInfo& latency) { 599 const ui::LatencyInfo& latency) {
606 // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate. 600 // |gesture_event_queue_| will forward to OnGestureEventAck when appropriate.
607 gesture_event_queue_.ProcessGestureAck(ack_result, type, latency); 601 gesture_event_queue_.ProcessGestureAck(ack_result, type, latency);
608 } 602 }
609 603
610 void InputRouterImpl::ProcessTouchAck( 604 void InputRouterImpl::ProcessTouchAck(InputEventAckState ack_result,
611 InputEventAckState ack_result, 605 const ui::LatencyInfo& latency,
612 const ui::LatencyInfo& latency) { 606 uint32 unique_touch_event_id) {
613 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate. 607 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate.
614 touch_event_queue_.ProcessTouchAck(ack_result, latency); 608 touch_event_queue_.ProcessTouchAck(ack_result, latency,
609 unique_touch_event_id);
615 } 610 }
616 611
617 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() { 612 void InputRouterImpl::UpdateTouchAckTimeoutEnabled() {
618 // Mobile sites tend to be well-behaved with respect to touch handling, so 613 // Mobile sites tend to be well-behaved with respect to touch handling, so
619 // they have less need for the touch timeout fallback. 614 // they have less need for the touch timeout fallback.
620 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0; 615 const bool fixed_page_scale = (current_view_flags_ & FIXED_PAGE_SCALE) != 0;
621 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0; 616 const bool mobile_viewport = (current_view_flags_ & MOBILE_VIEWPORT) != 0;
622 617
623 // TOUCH_ACTION_NONE will prevent scrolling, in which case the timeout serves 618 // 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 619 // little purpose. It's also a strong signal that touch handling is critical
(...skipping 12 matching lines...) Expand all
637 return; 632 return;
638 633
639 if (HasPendingEvents()) 634 if (HasPendingEvents())
640 return; 635 return;
641 636
642 flush_requested_ = false; 637 flush_requested_ = false;
643 client_->DidFlush(); 638 client_->DidFlush();
644 } 639 }
645 640
646 } // namespace content 641 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698