Chromium Code Reviews| 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/immediate_input_router.h" | 5 #include "content/browser/renderer_host/input/immediate_input_router.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "content/browser/renderer_host/input/gesture_event_filter.h" | 9 #include "content/browser/renderer_host/input/gesture_event_filter.h" |
| 10 #include "content/browser/renderer_host/input/input_ack_handler.h" | 10 #include "content/browser/renderer_host/input/input_ack_handler.h" |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 IPC_MESSAGE_UNHANDLED(handled = false) | 299 IPC_MESSAGE_UNHANDLED(handled = false) |
| 300 IPC_END_MESSAGE_MAP() | 300 IPC_END_MESSAGE_MAP() |
| 301 | 301 |
| 302 if (!message_is_ok) | 302 if (!message_is_ok) |
| 303 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 303 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
| 304 | 304 |
| 305 return handled; | 305 return handled; |
| 306 } | 306 } |
| 307 | 307 |
| 308 void ImmediateInputRouter::OnTouchEventAck( | 308 void ImmediateInputRouter::OnTouchEventAck( |
| 309 const TouchEventWithLatencyInfo& event, | 309 const WebKit::WebTouchEvent& event, |
| 310 InputEventAckState ack_result) { | 310 InputEventAckState ack_result, |
| 311 ack_handler_->OnTouchEventAck(event, ack_result); | 311 ui::LatencyInfo* latency) { |
| 312 ack_handler_->OnTouchEventAck(event, ack_result, latency); | |
| 312 } | 313 } |
| 313 | 314 |
| 314 bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) { | 315 bool ImmediateInputRouter::SendSelectRange(scoped_ptr<IPC::Message> message) { |
| 315 DCHECK(message->type() == InputMsg_SelectRange::ID); | 316 DCHECK(message->type() == InputMsg_SelectRange::ID); |
| 316 if (select_range_pending_) { | 317 if (select_range_pending_) { |
| 317 next_selection_range_ = message.Pass(); | 318 next_selection_range_ = message.Pass(); |
| 318 return true; | 319 return true; |
| 319 } | 320 } |
| 320 | 321 |
| 321 select_range_pending_ = true; | 322 select_range_pending_ = true; |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 351 const WebInputEvent& input_event, | 352 const WebInputEvent& input_event, |
| 352 const ui::LatencyInfo& latency_info, | 353 const ui::LatencyInfo& latency_info, |
| 353 bool is_keyboard_shortcut) { | 354 bool is_keyboard_shortcut) { |
| 354 TRACE_EVENT0("input", "ImmediateInputRouter::FilterAndSendWebInputEvent"); | 355 TRACE_EVENT0("input", "ImmediateInputRouter::FilterAndSendWebInputEvent"); |
| 355 | 356 |
| 356 if (!process_->HasConnection()) | 357 if (!process_->HasConnection()) |
| 357 return; | 358 return; |
| 358 | 359 |
| 359 DCHECK(!process_->IgnoreInputEvents()); | 360 DCHECK(!process_->IgnoreInputEvents()); |
| 360 | 361 |
| 362 ui::LatencyInfo renderer_latency; | |
| 361 // Perform optional, synchronous event handling, sending ACK messages for | 363 // Perform optional, synchronous event handling, sending ACK messages for |
| 362 // processed events, or proceeding as usual. | 364 // processed events, or proceeding as usual. |
| 363 InputEventAckState filter_ack = client_->FilterInputEvent(input_event, | 365 InputEventAckState filter_ack = client_->FilterInputEvent(input_event, |
| 364 latency_info); | 366 latency_info); |
| 365 switch (filter_ack) { | 367 switch (filter_ack) { |
| 366 // Send the ACK and early exit. | 368 // Send the ACK and early exit. |
| 367 case INPUT_EVENT_ACK_STATE_CONSUMED: | 369 case INPUT_EVENT_ACK_STATE_CONSUMED: |
| 368 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: | 370 case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: |
| 369 next_mouse_move_.reset(); | 371 next_mouse_move_.reset(); |
| 370 ProcessInputEventAck(input_event.type, filter_ack, latency_info); | 372 ProcessInputEventAck(input_event.type, filter_ack, &renderer_latency); |
| 371 // WARNING: |this| may be deleted at this point. | 373 // WARNING: |this| may be deleted at this point. |
| 372 return; | 374 return; |
| 373 | 375 |
| 374 case INPUT_EVENT_ACK_STATE_UNKNOWN: { | 376 case INPUT_EVENT_ACK_STATE_UNKNOWN: { |
| 375 if (input_event.type == WebKit::WebInputEvent::MouseMove) { | 377 if (input_event.type == WebKit::WebInputEvent::MouseMove) { |
| 376 // Since this mouse-move event has been consumed, there will be no ACKs. | 378 // Since this mouse-move event has been consumed, there will be no ACKs. |
| 377 // So reset the state here so that future mouse-move events do reach the | 379 // So reset the state here so that future mouse-move events do reach the |
| 378 // renderer. | 380 // renderer. |
| 379 mouse_move_pending_ = false; | 381 mouse_move_pending_ = false; |
| 380 } else if (input_event.type == WebKit::WebInputEvent::MouseWheel) { | 382 } else if (input_event.type == WebKit::WebInputEvent::MouseWheel) { |
| 381 // Reset the wheel-event state when appropriate. | 383 // Reset the wheel-event state when appropriate. |
| 382 mouse_wheel_pending_ = false; | 384 mouse_wheel_pending_ = false; |
| 383 } else if (WebInputEvent::isGestureEventType(input_event.type) && | 385 } else if (WebInputEvent::isGestureEventType(input_event.type) && |
| 384 gesture_event_filter_->HasQueuedGestureEvents()) { | 386 gesture_event_filter_->HasQueuedGestureEvents()) { |
| 385 // If the gesture-event filter has queued gesture events, that implies | 387 // If the gesture-event filter has queued gesture events, that implies |
| 386 // it's awaiting an ack for the event. Since the event is being dropped, | 388 // it's awaiting an ack for the event. Since the event is being dropped, |
| 387 // it is never sent to the renderer, and so it won't receive any ACKs. | 389 // it is never sent to the renderer, and so it won't receive any ACKs. |
| 388 // So send the ACK to the gesture event filter immediately, and mark it | 390 // So send the ACK to the gesture event filter immediately, and mark it |
| 389 // as having been processed. | 391 // as having been processed. |
| 390 gesture_event_filter_->ProcessGestureAck(true, input_event.type); | 392 gesture_event_filter_->ProcessGestureAck(true, input_event.type); |
| 391 } else if (WebInputEvent::isTouchEventType(input_event.type)) { | 393 } else if (WebInputEvent::isTouchEventType(input_event.type)) { |
| 392 // During an overscroll gesture initiated by touch-scrolling, the | 394 // During an overscroll gesture initiated by touch-scrolling, the |
| 393 // touch-events do not reset or contribute to the overscroll gesture. | 395 // touch-events do not reset or contribute to the overscroll gesture. |
| 394 // However, the touch-events are not sent to the renderer. So send an | 396 // However, the touch-events are not sent to the renderer. So send an |
| 395 // ACK to the touch-event queue immediately. Mark the event as not | 397 // ACK to the touch-event queue immediately. Mark the event as not |
| 396 // processed, to make sure that the touch-scroll gesture that initiated | 398 // processed, to make sure that the touch-scroll gesture that initiated |
| 397 // the overscroll is updated properly. | 399 // the overscroll is updated properly. |
| 398 touch_event_queue_->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, | 400 touch_event_queue_->ProcessTouchAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, |
| 399 latency_info); | 401 &renderer_latency); |
| 400 } | 402 } |
| 401 return; | 403 return; |
| 402 } | 404 } |
| 403 | 405 |
| 404 // Proceed as normal. | 406 // Proceed as normal. |
| 405 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: | 407 case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: |
| 406 break; | 408 break; |
| 407 } | 409 } |
| 408 | 410 |
| 409 // Transmit any pending wheel events on a non-wheel event. This ensures that | 411 // Transmit any pending wheel events on a non-wheel event. This ensures that |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 420 | 422 |
| 421 SendWebInputEvent(input_event, latency_info, is_keyboard_shortcut); | 423 SendWebInputEvent(input_event, latency_info, is_keyboard_shortcut); |
| 422 | 424 |
| 423 // Any input event cancels a pending mouse move event. | 425 // Any input event cancels a pending mouse move event. |
| 424 next_mouse_move_.reset(); | 426 next_mouse_move_.reset(); |
| 425 } | 427 } |
| 426 | 428 |
| 427 void ImmediateInputRouter::OnInputEventAck( | 429 void ImmediateInputRouter::OnInputEventAck( |
| 428 WebInputEvent::Type event_type, | 430 WebInputEvent::Type event_type, |
| 429 InputEventAckState ack_result, | 431 InputEventAckState ack_result, |
| 430 const ui::LatencyInfo& latency_info) { | 432 ui::LatencyInfo latency_info) { |
| 431 // Log the time delta for processing an input event. | 433 // Log the time delta for processing an input event. |
| 432 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 434 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
| 433 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); | 435 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); |
| 434 | 436 |
| 435 client_->DecrementInFlightEventCount(); | 437 client_->DecrementInFlightEventCount(); |
| 436 | 438 |
| 437 ProcessInputEventAck(event_type, ack_result, latency_info); | 439 ProcessInputEventAck(event_type, ack_result, &latency_info); |
| 438 } | 440 } |
| 439 | 441 |
| 440 void ImmediateInputRouter::OnMsgMoveCaretAck() { | 442 void ImmediateInputRouter::OnMsgMoveCaretAck() { |
| 441 move_caret_pending_ = false; | 443 move_caret_pending_ = false; |
| 442 if (next_move_caret_) | 444 if (next_move_caret_) |
| 443 SendMoveCaret(next_move_caret_.Pass()); | 445 SendMoveCaret(next_move_caret_.Pass()); |
| 444 } | 446 } |
| 445 | 447 |
| 446 void ImmediateInputRouter::OnSelectRangeAck() { | 448 void ImmediateInputRouter::OnSelectRangeAck() { |
| 447 select_range_pending_ = false; | 449 select_range_pending_ = false; |
| 448 if (next_selection_range_) | 450 if (next_selection_range_) |
| 449 SendSelectRange(next_selection_range_.Pass()); | 451 SendSelectRange(next_selection_range_.Pass()); |
| 450 } | 452 } |
| 451 | 453 |
| 452 void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { | 454 void ImmediateInputRouter::OnHasTouchEventHandlers(bool has_handlers) { |
| 453 if (has_touch_handler_ == has_handlers) | 455 if (has_touch_handler_ == has_handlers) |
| 454 return; | 456 return; |
| 455 has_touch_handler_ = has_handlers; | 457 has_touch_handler_ = has_handlers; |
| 456 if (!has_handlers) | 458 if (!has_handlers) |
| 457 touch_event_queue_->FlushQueue(); | 459 touch_event_queue_->FlushQueue(); |
| 458 client_->OnHasTouchEventHandlers(has_handlers); | 460 client_->OnHasTouchEventHandlers(has_handlers); |
| 459 } | 461 } |
| 460 | 462 |
| 461 void ImmediateInputRouter::ProcessInputEventAck( | 463 void ImmediateInputRouter::ProcessInputEventAck( |
| 462 WebInputEvent::Type event_type, | 464 WebInputEvent::Type event_type, |
| 463 InputEventAckState ack_result, | 465 InputEventAckState ack_result, |
| 464 const ui::LatencyInfo& latency_info) { | 466 ui::LatencyInfo* latency_info) { |
| 465 TRACE_EVENT1("input", "ImmediateInputRouter::ProcessInputEventAck", | 467 TRACE_EVENT1("input", "ImmediateInputRouter::ProcessInputEventAck", |
| 466 "ack", GetEventAckName(ack_result)); | 468 "ack", GetEventAckName(ack_result)); |
| 467 | 469 |
| 468 int type = static_cast<int>(event_type); | 470 int type = static_cast<int>(event_type); |
| 469 if (type < WebInputEvent::Undefined) { | 471 if (type < WebInputEvent::Undefined) { |
| 470 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); | 472 ack_handler_->OnUnexpectedEventAck(InputAckHandler::BAD_ACK_MESSAGE); |
| 471 } else if (type == WebInputEvent::MouseMove) { | 473 } else if (type == WebInputEvent::MouseMove) { |
| 472 mouse_move_pending_ = false; | 474 mouse_move_pending_ = false; |
| 473 | 475 |
| 474 // now, we can send the next mouse move event | 476 // now, we can send the next mouse move event |
| 475 if (next_mouse_move_) { | 477 if (next_mouse_move_) { |
| 476 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 478 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); |
| 477 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 479 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
| 478 = next_mouse_move_.Pass(); | 480 = next_mouse_move_.Pass(); |
| 479 SendMouseEvent(*next_mouse_move); | 481 SendMouseEvent(*next_mouse_move); |
| 480 } | 482 } |
| 481 } else if (WebInputEvent::isKeyboardEventType(type)) { | 483 } else if (WebInputEvent::isKeyboardEventType(type)) { |
| 482 ProcessKeyboardAck(type, ack_result); | 484 ProcessKeyboardAck(type, ack_result); |
| 483 } else if (type == WebInputEvent::MouseWheel) { | 485 } else if (type == WebInputEvent::MouseWheel) { |
| 484 ProcessWheelAck(ack_result); | 486 ProcessWheelAck(ack_result, latency_info); |
| 485 } else if (WebInputEvent::isTouchEventType(type)) { | 487 } else if (WebInputEvent::isTouchEventType(type)) { |
| 486 ProcessTouchAck(ack_result, latency_info); | 488 ProcessTouchAck(ack_result, latency_info); |
| 487 } else if (WebInputEvent::isGestureEventType(type)) { | 489 } else if (WebInputEvent::isGestureEventType(type)) { |
| 488 ProcessGestureAck(type, ack_result); | 490 ProcessGestureAck(type, ack_result, latency_info); |
| 489 } | 491 } |
| 490 | 492 |
| 491 // WARNING: |this| may be deleted at this point. | 493 // WARNING: |this| may be deleted at this point. |
| 492 | 494 |
| 493 // This is used only for testing, and the other end does not use the | 495 // This is used only for testing, and the other end does not use the |
| 494 // source object. On linux, specifying | 496 // source object. On linux, specifying |
| 495 // Source<RenderWidgetHost> results in a very strange | 497 // Source<RenderWidgetHost> results in a very strange |
| 496 // runtime error in the epilogue of the enclosing | 498 // runtime error in the epilogue of the enclosing |
| 497 // (ProcessInputEventAck) method, but not on other platforms; using | 499 // (ProcessInputEventAck) method, but not on other platforms; using |
| 498 // 'void' instead is just as safe (since NotificationSource | 500 // 'void' instead is just as safe (since NotificationSource |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 517 NativeWebKeyboardEvent front_item = key_queue_.front(); | 519 NativeWebKeyboardEvent front_item = key_queue_.front(); |
| 518 key_queue_.pop_front(); | 520 key_queue_.pop_front(); |
| 519 | 521 |
| 520 ack_handler_->OnKeyboardEventAck(front_item, ack_result); | 522 ack_handler_->OnKeyboardEventAck(front_item, ack_result); |
| 521 // WARNING: This ImmediateInputRouter can be deallocated at this point | 523 // WARNING: This ImmediateInputRouter can be deallocated at this point |
| 522 // (i.e. in the case of Ctrl+W, where the call to | 524 // (i.e. in the case of Ctrl+W, where the call to |
| 523 // HandleKeyboardEvent destroys this ImmediateInputRouter). | 525 // HandleKeyboardEvent destroys this ImmediateInputRouter). |
| 524 } | 526 } |
| 525 } | 527 } |
| 526 | 528 |
| 527 void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result) { | 529 void ImmediateInputRouter::ProcessWheelAck(InputEventAckState ack_result, |
| 530 ui::LatencyInfo* latency) { | |
| 528 mouse_wheel_pending_ = false; | 531 mouse_wheel_pending_ = false; |
| 529 | 532 |
| 530 // Process the unhandled wheel event here before calling | 533 // Process the unhandled wheel event here before calling |
| 531 // ForwardWheelEventWithLatencyInfo() since it will mutate | 534 // ForwardWheelEventWithLatencyInfo() since it will mutate |
| 532 // current_wheel_event_. | 535 // current_wheel_event_. |
| 533 ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result); | 536 ack_handler_->OnWheelEventAck(current_wheel_event_.event, |
| 537 ack_result, | |
|
jdduke (slow)
2013/10/04 02:22:19
Are we not using the current_wheel_event_.latency
Yufeng Shen (Slow to review)
2013/10/04 18:03:03
Ideally I would like to have each uncoalesced mous
| |
| 538 latency); | |
| 534 | 539 |
| 535 // Now send the next (coalesced) mouse wheel event. | 540 // Now send the next (coalesced) mouse wheel event. |
| 536 if (!coalesced_mouse_wheel_events_.empty()) { | 541 if (!coalesced_mouse_wheel_events_.empty()) { |
| 537 MouseWheelEventWithLatencyInfo next_wheel_event = | 542 MouseWheelEventWithLatencyInfo next_wheel_event = |
| 538 coalesced_mouse_wheel_events_.front(); | 543 coalesced_mouse_wheel_events_.front(); |
| 539 coalesced_mouse_wheel_events_.pop_front(); | 544 coalesced_mouse_wheel_events_.pop_front(); |
| 540 SendWheelEvent(next_wheel_event); | 545 SendWheelEvent(next_wheel_event); |
| 541 } | 546 } |
| 542 } | 547 } |
| 543 | 548 |
| 544 void ImmediateInputRouter::ProcessGestureAck(int type, | 549 void ImmediateInputRouter::ProcessGestureAck(int type, |
| 545 InputEventAckState ack_result) { | 550 InputEventAckState ack_result, |
| 551 ui::LatencyInfo* latency) { | |
| 546 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result); | 552 const bool processed = (INPUT_EVENT_ACK_STATE_CONSUMED == ack_result); |
| 547 ack_handler_->OnGestureEventAck( | 553 ack_handler_->OnGestureEventAck( |
| 548 gesture_event_filter_->GetGestureEventAwaitingAck(), ack_result); | 554 gesture_event_filter_->GetGestureEventAwaitingAck(), ack_result, latency); |
| 549 gesture_event_filter_->ProcessGestureAck(processed, type); | 555 gesture_event_filter_->ProcessGestureAck(processed, type); |
| 550 } | 556 } |
| 551 | 557 |
| 552 void ImmediateInputRouter::ProcessTouchAck( | 558 void ImmediateInputRouter::ProcessTouchAck( |
| 553 InputEventAckState ack_result, | 559 InputEventAckState ack_result, |
| 554 const ui::LatencyInfo& latency_info) { | 560 ui::LatencyInfo* latency_info) { |
| 555 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate. | 561 // |touch_event_queue_| will forward to OnTouchEventAck when appropriate. |
| 556 touch_event_queue_->ProcessTouchAck(ack_result, latency_info); | 562 touch_event_queue_->ProcessTouchAck(ack_result, latency_info); |
| 557 } | 563 } |
| 558 | 564 |
| 559 void ImmediateInputRouter::HandleGestureScroll( | 565 void ImmediateInputRouter::HandleGestureScroll( |
| 560 const GestureEventWithLatencyInfo& gesture_event) { | 566 const GestureEventWithLatencyInfo& gesture_event) { |
| 561 if (!enable_no_touch_to_renderer_while_scrolling_) | 567 if (!enable_no_touch_to_renderer_while_scrolling_) |
| 562 return; | 568 return; |
| 563 | 569 |
| 564 // Once scrolling is started stop forwarding touch move events to renderer. | 570 // Once scrolling is started stop forwarding touch move events to renderer. |
| 565 if (gesture_event.event.type == WebInputEvent::GestureScrollBegin) | 571 if (gesture_event.event.type == WebInputEvent::GestureScrollBegin) |
| 566 touch_event_queue_->set_no_touch_move_to_renderer(true); | 572 touch_event_queue_->set_no_touch_move_to_renderer(true); |
| 567 | 573 |
| 568 if (gesture_event.event.type == WebInputEvent::GestureScrollEnd || | 574 if (gesture_event.event.type == WebInputEvent::GestureScrollEnd || |
| 569 gesture_event.event.type == WebInputEvent::GestureFlingStart) { | 575 gesture_event.event.type == WebInputEvent::GestureFlingStart) { |
| 570 touch_event_queue_->set_no_touch_move_to_renderer(false); | 576 touch_event_queue_->set_no_touch_move_to_renderer(false); |
| 571 } | 577 } |
| 572 } | 578 } |
| 573 | 579 |
| 574 } // namespace content | 580 } // namespace content |
| OLD | NEW |