| 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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 // The synthetic acks are sent immediately. |
| 367 if (ignores_ack) { | 370 if (needs_synthetic_ack) { |
| 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 ProcessInputEventAck( |
| 390 input_event.type, filter_ack, latency_info, |
| 391 WebInputEventTraits::GetUniqueTouchEventId(input_event), CLIENT); |
| 387 // WARNING: |this| may be deleted at this point. | 392 // WARNING: |this| may be deleted at this point. |
| 388 consumed = true; | 393 consumed = true; |
| 389 break; | 394 break; |
| 390 case INPUT_EVENT_ACK_STATE_UNKNOWN: | 395 case INPUT_EVENT_ACK_STATE_UNKNOWN: |
| 391 // Simply drop the event. | 396 // Simply drop the event. |
| 392 consumed = true; | 397 consumed = true; |
| 393 break; | 398 break; |
| 394 default: | 399 default: |
| 395 break; | 400 break; |
| 396 } | 401 } |
| 397 | 402 |
| 398 return consumed; | 403 return consumed; |
| 399 } | 404 } |
| 400 | 405 |
| 401 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, | 406 bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, |
| 402 const ui::LatencyInfo& latency_info, | 407 const ui::LatencyInfo& latency_info, |
| 403 bool is_keyboard_shortcut) { | 408 bool is_keyboard_shortcut) { |
| 404 if (Send(new InputMsg_HandleInputEvent( | 409 if (Send(new InputMsg_HandleInputEvent( |
| 405 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) { | 410 routing_id(), &input_event, latency_info, is_keyboard_shortcut))) { |
| 406 // Ack messages for ignored ack event types should never be sent by the | 411 // Ack messages for ignored ack event types should never be sent by the |
| 407 // renderer. Consequently, such event types should not affect event time | 412 // renderer. Consequently, such event types should not affect event time |
| 408 // or in-flight event count metrics. | 413 // or in-flight event count metrics. |
| 409 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { | 414 if (WebInputEventTraits::WillReceiveAckFromRenderer(input_event)) { |
| 410 input_event_start_time_ = TimeTicks::Now(); | 415 input_event_start_time_ = TimeTicks::Now(); |
| 411 client_->IncrementInFlightEventCount(); | 416 client_->IncrementInFlightEventCount(); |
| 412 } | 417 } |
| 413 return true; | 418 return true; |
| 414 } | 419 } |
| 415 return false; | 420 return false; |
| 416 } | 421 } |
| 417 | 422 |
| 418 void InputRouterImpl::OnInputEventAck( | 423 void InputRouterImpl::OnInputEventAck(const InputEventAck& ack) { |
| 419 const InputHostMsg_HandleInputEvent_ACK_Params& ack) { | |
| 420 client_->DecrementInFlightEventCount(); | 424 client_->DecrementInFlightEventCount(); |
| 421 | |
| 422 // Log the time delta for processing an input event. | 425 // Log the time delta for processing an input event. |
| 423 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 426 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
| 424 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); | 427 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); |
| 425 | 428 |
| 426 if (ack.overscroll) { | 429 if (ack.overscroll) { |
| 427 DCHECK(ack.type == WebInputEvent::MouseWheel || | 430 DCHECK(ack.type == WebInputEvent::MouseWheel || |
| 428 ack.type == WebInputEvent::GestureScrollUpdate); | 431 ack.type == WebInputEvent::GestureScrollUpdate); |
| 429 OnDidOverscroll(*ack.overscroll); | 432 OnDidOverscroll(*ack.overscroll); |
| 430 } | 433 } |
| 431 | 434 |
| 432 ProcessInputEventAck(ack.type, ack.state, ack.latency, RENDERER); | 435 ProcessInputEventAck(ack.type, ack.state, ack.latency, |
| 433 // WARNING: |this| may be deleted at this point. | 436 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 } | 437 } |
| 448 | 438 |
| 449 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) { | 439 void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) { |
| 450 client_->DidOverscroll(params); | 440 client_->DidOverscroll(params); |
| 451 } | 441 } |
| 452 | 442 |
| 453 void InputRouterImpl::OnMsgMoveCaretAck() { | 443 void InputRouterImpl::OnMsgMoveCaretAck() { |
| 454 move_caret_pending_ = false; | 444 move_caret_pending_ = false; |
| 455 if (next_move_caret_) | 445 if (next_move_caret_) |
| 456 SendMoveCaret(next_move_caret_.Pass()); | 446 SendMoveCaret(next_move_caret_.Pass()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 // TOUCH_ACTION_NONE should disable the touch ack timeout. | 485 // TOUCH_ACTION_NONE should disable the touch ack timeout. |
| 496 UpdateTouchAckTimeoutEnabled(); | 486 UpdateTouchAckTimeoutEnabled(); |
| 497 } | 487 } |
| 498 | 488 |
| 499 void InputRouterImpl::OnDidStopFlinging() { | 489 void InputRouterImpl::OnDidStopFlinging() { |
| 500 // TODO(jdduke): Track fling status to allow flush notifications after a fling | 490 // TODO(jdduke): Track fling status to allow flush notifications after a fling |
| 501 // has terminated, crbug.com/483037. | 491 // has terminated, crbug.com/483037. |
| 502 client_->DidStopFlinging(); | 492 client_->DidStopFlinging(); |
| 503 } | 493 } |
| 504 | 494 |
| 505 void InputRouterImpl::ProcessInputEventAck( | 495 void InputRouterImpl::ProcessInputEventAck(WebInputEvent::Type event_type, |
| 506 WebInputEvent::Type event_type, | 496 InputEventAckState ack_result, |
| 507 InputEventAckState ack_result, | 497 const ui::LatencyInfo& latency_info, |
| 508 const ui::LatencyInfo& latency_info, | 498 uint32 unique_touch_event_id, |
| 509 AckSource ack_source) { | 499 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 ¤t_ack_source_, ack_source); | 514 ¤t_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, latency_info); |
| 530 } else if (WebInputEvent::isTouchEventType(event_type)) { | 520 } else if (WebInputEvent::isTouchEventType(event_type)) { |
| 531 ProcessTouchAck(ack_result, latency_info); | 521 ProcessTouchAck(ack_result, latency_info, 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, latency_info); |
| 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, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 uint32 unique_touch_event_id) { |
| 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 Loading... |
| 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 |
| OLD | NEW |