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/input_router_impl.h" | 5 #include "content/browser/renderer_host/input/input_router_impl.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 InputAckHandler* ack_handler, | 136 InputAckHandler* ack_handler, |
| 137 int routing_id) | 137 int routing_id) |
| 138 : sender_(sender), | 138 : sender_(sender), |
| 139 client_(client), | 139 client_(client), |
| 140 ack_handler_(ack_handler), | 140 ack_handler_(ack_handler), |
| 141 routing_id_(routing_id), | 141 routing_id_(routing_id), |
| 142 select_range_pending_(false), | 142 select_range_pending_(false), |
| 143 move_caret_pending_(false), | 143 move_caret_pending_(false), |
| 144 mouse_move_pending_(false), | 144 mouse_move_pending_(false), |
| 145 mouse_wheel_pending_(false), | 145 mouse_wheel_pending_(false), |
| 146 pending_touchpad_pinch_(false), | |
| 147 current_wheel_event_is_for_pinch_(false), | |
| 146 touch_ack_timeout_supported_(false), | 148 touch_ack_timeout_supported_(false), |
| 147 current_view_flags_(0), | 149 current_view_flags_(0), |
| 148 current_ack_source_(ACK_SOURCE_NONE), | 150 current_ack_source_(ACK_SOURCE_NONE), |
| 149 flush_requested_(false), | 151 flush_requested_(false), |
| 150 touch_event_queue_(this, | 152 touch_event_queue_(this, |
| 151 GetTouchScrollingMode(), | 153 GetTouchScrollingMode(), |
| 152 GetTouchMoveSlopSuppressionLengthDips()), | 154 GetTouchMoveSlopSuppressionLengthDips()), |
| 153 gesture_event_queue_(this, this) { | 155 gesture_event_queue_(this, this) { |
| 154 DCHECK(sender); | 156 DCHECK(sender); |
| 155 DCHECK(client); | 157 DCHECK(client); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 if (mouse_event.event.type == WebInputEvent::MouseUp && | 201 if (mouse_event.event.type == WebInputEvent::MouseUp && |
| 200 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 202 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
| 201 ShouldSuppressMouseUp()) | 203 ShouldSuppressMouseUp()) |
| 202 return; | 204 return; |
| 203 | 205 |
| 204 SendMouseEventImmediately(mouse_event); | 206 SendMouseEventImmediately(mouse_event); |
| 205 } | 207 } |
| 206 | 208 |
| 207 void InputRouterImpl::SendWheelEvent( | 209 void InputRouterImpl::SendWheelEvent( |
| 208 const MouseWheelEventWithLatencyInfo& wheel_event) { | 210 const MouseWheelEventWithLatencyInfo& wheel_event) { |
| 209 // If there's already a mouse wheel event waiting to be sent to the renderer, | |
| 210 // add the new deltas to that event. Not doing so (e.g., by dropping the old | |
| 211 // event, as for mouse moves) results in very slow scrolling on the Mac (on | |
| 212 // which many, very small wheel events are sent). | |
| 213 if (mouse_wheel_pending_) { | 211 if (mouse_wheel_pending_) { |
| 212 // If the provided event is for touchpad pinch, we don't want to coalesce | |
| 213 // it in with other wheel events as that would make the ACK handling | |
|
jdduke (slow)
2014/05/01 15:44:47
I'm starting to think maintaining separate Touchpa
jdduke (slow)
2014/05/01 16:26:01
This is very much a future thing :)
Rick Byers
2014/05/01 17:34:57
Agreed. The gesture streams are as distinct as mo
| |
| 214 // difficult and could require coalescing correspending GesturePinchUpdate | |
| 215 // events in the GestureEventQueue. Do nothing for now, we'll send | |
| 216 // wheel_event_for_pending_pinch_ when the ACK for this wheel event | |
| 217 // arrives. | |
| 218 if (pending_touchpad_pinch_) { | |
| 219 DCHECK(!current_wheel_event_is_for_pinch_); | |
| 220 DCHECK(wheel_event.latency.trace_id == | |
| 221 wheel_event_for_pending_pinch_.latency.trace_id); | |
| 222 return; | |
| 223 } | |
| 224 | |
| 225 // If there's already a mouse wheel event waiting to be sent to the | |
| 226 // renderer, | |
| 227 // add the new deltas to that event. Not doing so (e.g., by dropping the old | |
| 228 // event, as for mouse moves) results in very slow scrolling on the Mac (on | |
| 229 // which many, very small wheel events are sent). | |
| 214 if (coalesced_mouse_wheel_events_.empty() || | 230 if (coalesced_mouse_wheel_events_.empty() || |
| 215 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { | 231 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { |
| 216 coalesced_mouse_wheel_events_.push_back(wheel_event); | 232 coalesced_mouse_wheel_events_.push_back(wheel_event); |
| 217 } else { | 233 } else { |
| 218 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); | 234 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); |
| 219 } | 235 } |
| 220 return; | 236 return; |
| 221 } | 237 } |
| 238 | |
| 222 mouse_wheel_pending_ = true; | 239 mouse_wheel_pending_ = true; |
| 223 current_wheel_event_ = wheel_event; | 240 current_wheel_event_ = wheel_event; |
| 224 | 241 |
| 225 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | 242 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
| 226 coalesced_mouse_wheel_events_.size()); | 243 coalesced_mouse_wheel_events_.size()); |
| 227 | 244 |
| 228 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); | 245 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); |
| 229 } | 246 } |
| 230 | 247 |
| 231 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, | 248 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 419 | 436 |
| 420 // Any input event cancels a pending mouse move event. | 437 // Any input event cancels a pending mouse move event. |
| 421 next_mouse_move_.reset(); | 438 next_mouse_move_.reset(); |
| 422 | 439 |
| 423 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); | 440 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); |
| 424 } | 441 } |
| 425 | 442 |
| 426 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, | 443 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, |
| 427 const ui::LatencyInfo& latency_info, | 444 const ui::LatencyInfo& latency_info, |
| 428 bool is_keyboard_shortcut) { | 445 bool is_keyboard_shortcut) { |
| 429 // Trackpad pinch gestures are not yet handled by the renderer. | 446 if (input_event.type == WebInputEvent::GesturePinchUpdate) { |
|
jdduke (slow)
2014/05/01 15:44:47
Can you explain to me why it's important for the v
jdduke (slow)
2014/05/01 16:26:01
As per offline discussion, nevermind this comment.
| |
| 430 // TODO(rbyers): Send mousewheel for trackpad pinch - crbug.com/289887. | 447 const WebGestureEvent& pinch_event = |
| 431 if (input_event.type == WebInputEvent::GesturePinchUpdate && | 448 static_cast<const WebGestureEvent&>(input_event); |
| 432 static_cast<const WebGestureEvent&>(input_event).sourceDevice == | 449 if (pinch_event.sourceDevice == WebGestureEvent::Touchpad) { |
| 433 WebGestureEvent::Touchpad) { | 450 SendSyntheticWheelEventForPinch(pinch_event, latency_info); |
| 434 ProcessInputEventAck(input_event.type, | 451 return; |
| 435 INPUT_EVENT_ACK_STATE_NOT_CONSUMED, | 452 } |
| 436 latency_info, | |
| 437 ACK_SOURCE_NONE); | |
| 438 return; | |
| 439 } | 453 } |
| 440 | 454 |
| 441 if (OfferToOverscrollController(input_event, latency_info)) | 455 if (OfferToOverscrollController(input_event, latency_info)) |
| 442 return; | 456 return; |
| 443 | 457 |
| 444 if (OfferToClient(input_event, latency_info)) | 458 if (OfferToClient(input_event, latency_info)) |
| 445 return; | 459 return; |
| 446 | 460 |
| 447 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); | 461 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); |
| 448 | 462 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 526 // affect event timing or in-flight event count metrics. | 540 // affect event timing or in-flight event count metrics. |
| 527 if (!WebInputEventTraits::IgnoresAckDisposition(input_event.type)) { | 541 if (!WebInputEventTraits::IgnoresAckDisposition(input_event.type)) { |
| 528 input_event_start_time_ = TimeTicks::Now(); | 542 input_event_start_time_ = TimeTicks::Now(); |
| 529 client_->IncrementInFlightEventCount(); | 543 client_->IncrementInFlightEventCount(); |
| 530 } | 544 } |
| 531 return true; | 545 return true; |
| 532 } | 546 } |
| 533 return false; | 547 return false; |
| 534 } | 548 } |
| 535 | 549 |
| 550 void InputRouterImpl::SendSyntheticWheelEventForPinch( | |
| 551 const blink::WebGestureEvent& pinch_event, | |
| 552 const ui::LatencyInfo& latency_info) { | |
| 553 // We match IE and Firefox behavior on Windows by sending fake wheel events | |
| 554 // with the ctrl modifier set when we see trackpad pinch gestures. Ideally | |
| 555 // we'd someday get a standard 'pinch' event and send that instead. | |
| 556 DCHECK(!pending_touchpad_pinch_); | |
| 557 DCHECK(!current_wheel_event_is_for_pinch_); | |
| 558 WebMouseWheelEvent wheelEvent; | |
| 559 wheelEvent.type = WebInputEvent::MouseWheel; | |
| 560 wheelEvent.timeStampSeconds = pinch_event.timeStampSeconds; | |
| 561 wheelEvent.modifiers = pinch_event.modifiers | WebInputEvent::ControlKey; | |
| 562 wheelEvent.deltaX = 0; | |
| 563 wheelEvent.deltaY = pinch_event.data.pinchUpdate.scale - 1; | |
| 564 wheelEvent.hasPreciseScrollingDeltas = true; | |
| 565 wheelEvent.wheelTicksX = 0; | |
| 566 wheelEvent.wheelTicksY = pinch_event.data.pinchUpdate.scale > 0 ? 1 : -1; | |
| 567 | |
| 568 SendWheelEvent(MouseWheelEventWithLatencyInfo(wheelEvent, latency_info)); | |
| 569 } | |
| 570 | |
| 536 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, | 571 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, |
| 537 InputEventAckState ack_result, | 572 InputEventAckState ack_result, |
| 538 const ui::LatencyInfo& latency_info) { | 573 const ui::LatencyInfo& latency_info) { |
| 539 // A synthetic ack will already have been sent for this event, and it should | 574 // A synthetic ack will already have been sent for this event, and it should |
| 540 // not affect event timing or in-flight count metrics. | 575 // not affect event timing or in-flight count metrics. |
| 541 if (WebInputEventTraits::IgnoresAckDisposition(event_type)) | 576 if (WebInputEventTraits::IgnoresAckDisposition(event_type)) |
| 542 return; | 577 return; |
| 543 | 578 |
| 544 client_->DecrementInFlightEventCount(); | 579 client_->DecrementInFlightEventCount(); |
| 545 | 580 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 663 if (next_mouse_move_) { | 698 if (next_mouse_move_) { |
| 664 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 699 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); |
| 665 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 700 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
| 666 = next_mouse_move_.Pass(); | 701 = next_mouse_move_.Pass(); |
| 667 SendMouseEvent(*next_mouse_move); | 702 SendMouseEvent(*next_mouse_move); |
| 668 } | 703 } |
| 669 } | 704 } |
| 670 | 705 |
| 671 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, | 706 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
| 672 const ui::LatencyInfo& latency) { | 707 const ui::LatencyInfo& latency) { |
| 708 DCHECK(mouse_wheel_pending_); | |
| 673 ProcessAckForOverscroll(current_wheel_event_.event, ack_result); | 709 ProcessAckForOverscroll(current_wheel_event_.event, ack_result); |
| 674 | 710 |
| 675 // TODO(miletus): Add renderer side latency to each uncoalesced mouse | 711 // TODO(miletus): Add renderer side latency to each uncoalesced mouse |
| 676 // wheel event and add terminal component to each of them. | 712 // wheel event and add terminal component to each of them. |
| 677 current_wheel_event_.latency.AddNewLatencyFrom(latency); | 713 current_wheel_event_.latency.AddNewLatencyFrom(latency); |
| 678 // Process the unhandled wheel event here before calling SendWheelEvent() | 714 |
| 679 // since it will mutate current_wheel_event_. | 715 if (current_wheel_event_is_for_pinch_) { |
| 680 ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); | 716 DCHECK(pending_touchpad_pinch_); |
| 717 DCHECK(current_wheel_event_.latency.trace_id == | |
| 718 wheel_event_for_pending_pinch_.latency.trace_id); | |
| 719 | |
| 720 // Ack the GesturePinchUpdate event that generated this wheel event. | |
| 721 ProcessInputEventAck(WebInputEvent::GesturePinchUpdate, | |
| 722 ack_result, | |
| 723 current_wheel_event_.latency, | |
| 724 ACK_SOURCE_NONE); | |
| 725 current_wheel_event_is_for_pinch_ = false; | |
| 726 pending_touchpad_pinch_ = false; | |
| 727 } else { | |
| 728 // Process the unhandled wheel event here before calling SendWheelEvent() | |
| 729 // since it will mutate current_wheel_event_. | |
| 730 ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); | |
| 731 } | |
| 681 mouse_wheel_pending_ = false; | 732 mouse_wheel_pending_ = false; |
| 682 | 733 |
| 683 // Now send the next (coalesced) mouse wheel event. | 734 // Send the next (coalesced or synthetic) mouse wheel event. |
| 684 if (!coalesced_mouse_wheel_events_.empty()) { | 735 if (pending_touchpad_pinch_) { |
| 736 DCHECK(!current_wheel_event_is_for_pinch_); | |
| 737 current_wheel_event_is_for_pinch_ = true; | |
| 738 SendWheelEvent(wheel_event_for_pending_pinch_); | |
| 739 } else if (!coalesced_mouse_wheel_events_.empty()) { | |
| 685 MouseWheelEventWithLatencyInfo next_wheel_event = | 740 MouseWheelEventWithLatencyInfo next_wheel_event = |
| 686 coalesced_mouse_wheel_events_.front(); | 741 coalesced_mouse_wheel_events_.front(); |
| 687 coalesced_mouse_wheel_events_.pop_front(); | 742 coalesced_mouse_wheel_events_.pop_front(); |
| 688 SendWheelEvent(next_wheel_event); | 743 SendWheelEvent(next_wheel_event); |
| 689 } | 744 } |
| 690 } | 745 } |
| 691 | 746 |
| 692 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, | 747 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, |
| 693 InputEventAckState ack_result, | 748 InputEventAckState ack_result, |
| 694 const ui::LatencyInfo& latency) { | 749 const ui::LatencyInfo& latency) { |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 849 select_range_pending_ || | 904 select_range_pending_ || |
| 850 move_caret_pending_; | 905 move_caret_pending_; |
| 851 } | 906 } |
| 852 | 907 |
| 853 bool InputRouterImpl::IsInOverscrollGesture() const { | 908 bool InputRouterImpl::IsInOverscrollGesture() const { |
| 854 OverscrollController* controller = client_->GetOverscrollController(); | 909 OverscrollController* controller = client_->GetOverscrollController(); |
| 855 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 910 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
| 856 } | 911 } |
| 857 | 912 |
| 858 } // namespace content | 913 } // namespace content |
| OLD | NEW |