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