OLD | NEW |
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 Loading... |
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 Loading... |
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 ¤t_ack_source_, ack_source); | 521 ¤t_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 Loading... |
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 Loading... |
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 |
OLD | NEW |