| 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 |