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 |