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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 if (mouse_event.event.type == WebInputEvent::MouseUp && | 173 if (mouse_event.event.type == WebInputEvent::MouseUp && |
174 gesture_event_queue_.GetTouchpadTapSuppressionController()-> | 174 gesture_event_queue_.GetTouchpadTapSuppressionController()-> |
175 ShouldSuppressMouseUp()) | 175 ShouldSuppressMouseUp()) |
176 return; | 176 return; |
177 | 177 |
178 SendMouseEventImmediately(mouse_event); | 178 SendMouseEventImmediately(mouse_event); |
179 } | 179 } |
180 | 180 |
181 void InputRouterImpl::SendWheelEvent( | 181 void InputRouterImpl::SendWheelEvent( |
182 const MouseWheelEventWithLatencyInfo& wheel_event) { | 182 const MouseWheelEventWithLatencyInfo& wheel_event) { |
183 // If there's already a mouse wheel event waiting to be sent to the renderer, | 183 SendWheelEvent(QueuedWheelEvent(wheel_event, false)); |
184 // add the new deltas to that event. Not doing so (e.g., by dropping the old | 184 } |
185 // event, as for mouse moves) results in very slow scrolling on the Mac (on | 185 |
186 // which many, very small wheel events are sent). | 186 void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) { |
187 if (mouse_wheel_pending_) { | 187 if (mouse_wheel_pending_) { |
188 // If there's already a mouse wheel event waiting to be sent to the | |
189 // renderer, add the new deltas to that event. Not doing so (e.g., by | |
190 // dropping the old event, as for mouse moves) results in very slow | |
191 // scrolling on the Mac (on which many, very small wheel events are sent). | |
192 // Note that we can't coalesce wheel events for pinches because the GEQ | |
193 // expects one ACK for each (but it's fine to coalesce non-pinch wheels | |
194 // into a pinch one). Note that the GestureEventQueue ensures we only | |
195 // ever have a single pinch event queued here. | |
188 if (coalesced_mouse_wheel_events_.empty() || | 196 if (coalesced_mouse_wheel_events_.empty() || |
189 !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { | 197 wheel_event.synthesized_from_pinch || |
198 !coalesced_mouse_wheel_events_.back().event.CanCoalesceWith( | |
199 wheel_event.event)) { | |
190 coalesced_mouse_wheel_events_.push_back(wheel_event); | 200 coalesced_mouse_wheel_events_.push_back(wheel_event); |
191 } else { | 201 } else { |
192 coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event); | 202 coalesced_mouse_wheel_events_.back().event.CoalesceWith( |
203 wheel_event.event); | |
193 } | 204 } |
194 return; | 205 return; |
195 } | 206 } |
207 | |
196 mouse_wheel_pending_ = true; | 208 mouse_wheel_pending_ = true; |
197 current_wheel_event_ = wheel_event; | 209 current_wheel_event_ = wheel_event; |
198 | 210 |
199 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", | 211 HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", |
200 coalesced_mouse_wheel_events_.size()); | 212 coalesced_mouse_wheel_events_.size()); |
201 | 213 |
202 FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false); | 214 FilterAndSendWebInputEvent( |
215 wheel_event.event.event, wheel_event.event.latency, false); | |
203 } | 216 } |
204 | 217 |
205 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, | 218 void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event, |
206 const ui::LatencyInfo& latency_info, | 219 const ui::LatencyInfo& latency_info, |
207 bool is_keyboard_shortcut) { | 220 bool is_keyboard_shortcut) { |
208 // Put all WebKeyboardEvent objects in a queue since we can't trust the | 221 // Put all WebKeyboardEvent objects in a queue since we can't trust the |
209 // renderer and we need to give something to the HandleKeyboardEvent | 222 // renderer and we need to give something to the HandleKeyboardEvent |
210 // handler. | 223 // handler. |
211 key_queue_.push_back(key_event); | 224 key_queue_.push_back(key_event); |
212 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); | 225 HISTOGRAM_COUNTS_100("Renderer.KeyboardQueueSize", key_queue_.size()); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 | 384 |
372 void InputRouterImpl::FilterAndSendWebInputEvent( | 385 void InputRouterImpl::FilterAndSendWebInputEvent( |
373 const WebInputEvent& input_event, | 386 const WebInputEvent& input_event, |
374 const ui::LatencyInfo& latency_info, | 387 const ui::LatencyInfo& latency_info, |
375 bool is_keyboard_shortcut) { | 388 bool is_keyboard_shortcut) { |
376 TRACE_EVENT1("input", | 389 TRACE_EVENT1("input", |
377 "InputRouterImpl::FilterAndSendWebInputEvent", | 390 "InputRouterImpl::FilterAndSendWebInputEvent", |
378 "type", | 391 "type", |
379 WebInputEventTraits::GetName(input_event.type)); | 392 WebInputEventTraits::GetName(input_event.type)); |
380 | 393 |
381 // Transmit any pending wheel events on a non-wheel event. This ensures that | |
382 // final PhaseEnded wheel event is received, which is necessary to terminate | |
383 // rubber-banding, for example. | |
384 if (input_event.type != WebInputEvent::MouseWheel) { | |
385 WheelEventQueue mouse_wheel_events; | |
386 mouse_wheel_events.swap(coalesced_mouse_wheel_events_); | |
387 for (size_t i = 0; i < mouse_wheel_events.size(); ++i) { | |
388 OfferToHandlers(mouse_wheel_events[i].event, | |
389 mouse_wheel_events[i].latency, | |
390 false); | |
391 } | |
392 } | |
393 | |
394 // Any input event cancels a pending mouse move event. | 394 // Any input event cancels a pending mouse move event. |
395 next_mouse_move_.reset(); | 395 next_mouse_move_.reset(); |
396 | 396 |
397 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); | 397 OfferToHandlers(input_event, latency_info, is_keyboard_shortcut); |
398 } | 398 } |
399 | 399 |
400 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, | 400 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event, |
401 const ui::LatencyInfo& latency_info, | 401 const ui::LatencyInfo& latency_info, |
402 bool is_keyboard_shortcut) { | 402 bool is_keyboard_shortcut) { |
403 // Trackpad pinch gestures are not yet handled by the renderer. | 403 if (input_event.type == WebInputEvent::GesturePinchUpdate) { |
jdduke (slow)
2014/05/01 15:44:47
Can we move this to |SendGestureEventImmediately|.
Rick Byers
2014/05/01 17:34:57
With a bit of refactoring, yes. That's better - t
| |
404 // TODO(rbyers): Send mousewheel for trackpad pinch - crbug.com/289887. | 404 const WebGestureEvent& pinch_event = |
405 if (input_event.type == WebInputEvent::GesturePinchUpdate && | 405 static_cast<const WebGestureEvent&>(input_event); |
406 static_cast<const WebGestureEvent&>(input_event).sourceDevice == | 406 if (pinch_event.sourceDevice == WebGestureEvent::Touchpad) { |
407 WebGestureEvent::Touchpad) { | 407 SendSyntheticWheelEventForPinch(pinch_event, latency_info); |
408 ProcessInputEventAck(input_event.type, | 408 return; |
409 INPUT_EVENT_ACK_STATE_NOT_CONSUMED, | 409 } |
410 latency_info, | |
411 ACK_SOURCE_NONE); | |
412 return; | |
413 } | 410 } |
414 | 411 |
415 if (OfferToOverscrollController(input_event, latency_info)) | 412 if (OfferToOverscrollController(input_event, latency_info)) |
416 return; | 413 return; |
417 | 414 |
418 if (OfferToClient(input_event, latency_info)) | 415 if (OfferToClient(input_event, latency_info)) |
419 return; | 416 return; |
420 | 417 |
421 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); | 418 OfferToRenderer(input_event, latency_info, is_keyboard_shortcut); |
422 | 419 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 // or in-flight event count metrics. | 505 // or in-flight event count metrics. |
509 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { | 506 if (!WebInputEventTraits::IgnoresAckDisposition(input_event)) { |
510 input_event_start_time_ = TimeTicks::Now(); | 507 input_event_start_time_ = TimeTicks::Now(); |
511 client_->IncrementInFlightEventCount(); | 508 client_->IncrementInFlightEventCount(); |
512 } | 509 } |
513 return true; | 510 return true; |
514 } | 511 } |
515 return false; | 512 return false; |
516 } | 513 } |
517 | 514 |
515 void InputRouterImpl::SendSyntheticWheelEventForPinch( | |
516 const blink::WebGestureEvent& pinch_event, | |
517 const ui::LatencyInfo& latency_info) { | |
518 // We match typical trackpad behavior on Windows by sending fake wheel events | |
519 // with the ctrl modifier set when we see trackpad pinch gestures. Ideally | |
520 // we'd someday get a standard 'pinch' event and send that instead. | |
521 | |
522 WebMouseWheelEvent wheelEvent; | |
523 wheelEvent.type = WebInputEvent::MouseWheel; | |
524 wheelEvent.timeStampSeconds = pinch_event.timeStampSeconds; | |
525 wheelEvent.windowX = wheelEvent.x = pinch_event.x; | |
526 wheelEvent.windowY = wheelEvent.y = pinch_event.y; | |
527 wheelEvent.globalX = pinch_event.globalX; | |
528 wheelEvent.globalY = pinch_event.globalY; | |
529 wheelEvent.modifiers = pinch_event.modifiers | WebInputEvent::ControlKey; | |
530 wheelEvent.deltaX = 0; | |
531 // For maximum compatibility with wheels, deltaY here is a "magnification | |
532 // percentage". Note that wheel events in JS have the sign reversed. | |
533 wheelEvent.deltaY = 100.0f * (1.0f - pinch_event.data.pinchUpdate.scale); | |
jdduke (slow)
2014/05/01 15:44:47
Maybe DCHECK that the scale is positive? Is the ma
Rick Byers
2014/05/01 17:34:57
Done.
| |
534 wheelEvent.hasPreciseScrollingDeltas = true; | |
535 wheelEvent.wheelTicksX = 0; | |
536 wheelEvent.wheelTicksY = pinch_event.data.pinchUpdate.scale > 1 ? 1 : -1; | |
537 | |
538 SendWheelEvent(QueuedWheelEvent( | |
539 MouseWheelEventWithLatencyInfo(wheelEvent, latency_info), true)); | |
540 } | |
541 | |
518 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, | 542 void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, |
519 InputEventAckState ack_result, | 543 InputEventAckState ack_result, |
520 const ui::LatencyInfo& latency_info) { | 544 const ui::LatencyInfo& latency_info) { |
521 client_->DecrementInFlightEventCount(); | 545 client_->DecrementInFlightEventCount(); |
522 | 546 |
523 // Log the time delta for processing an input event. | 547 // Log the time delta for processing an input event. |
524 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; | 548 TimeDelta delta = TimeTicks::Now() - input_event_start_time_; |
525 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); | 549 UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta); |
526 | 550 |
527 ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER); | 551 ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
640 if (next_mouse_move_) { | 664 if (next_mouse_move_) { |
641 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); | 665 DCHECK(next_mouse_move_->event.type == WebInputEvent::MouseMove); |
642 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move | 666 scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move |
643 = next_mouse_move_.Pass(); | 667 = next_mouse_move_.Pass(); |
644 SendMouseEvent(*next_mouse_move); | 668 SendMouseEvent(*next_mouse_move); |
645 } | 669 } |
646 } | 670 } |
647 | 671 |
648 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, | 672 void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
649 const ui::LatencyInfo& latency) { | 673 const ui::LatencyInfo& latency) { |
650 ProcessAckForOverscroll(current_wheel_event_.event, ack_result); | |
651 | |
652 // TODO(miletus): Add renderer side latency to each uncoalesced mouse | 674 // TODO(miletus): Add renderer side latency to each uncoalesced mouse |
653 // wheel event and add terminal component to each of them. | 675 // wheel event and add terminal component to each of them. |
654 current_wheel_event_.latency.AddNewLatencyFrom(latency); | 676 current_wheel_event_.event.latency.AddNewLatencyFrom(latency); |
655 // Process the unhandled wheel event here before calling SendWheelEvent() | 677 |
656 // since it will mutate current_wheel_event_. | 678 if (current_wheel_event_.synthesized_from_pinch) { |
657 ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); | 679 // Ack the GesturePinchUpdate event that generated this wheel event. |
680 ProcessInputEventAck(WebInputEvent::GesturePinchUpdate, | |
681 ack_result, | |
682 current_wheel_event_.event.latency, | |
683 ACK_SOURCE_NONE); | |
jdduke (slow)
2014/05/01 15:44:47
ACK_SOURCE_NONE -> current_ack_source_
Rick Byers
2014/05/01 17:34:57
Done.
| |
684 } else { | |
685 // Process the unhandled wheel event here before calling SendWheelEvent() | |
686 // since it will mutate current_wheel_event_. | |
687 ProcessAckForOverscroll(current_wheel_event_.event.event, ack_result); | |
688 ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result); | |
689 } | |
658 mouse_wheel_pending_ = false; | 690 mouse_wheel_pending_ = false; |
jdduke (slow)
2014/05/01 15:44:47
Could you put a note that the order this bool is s
Rick Byers
2014/05/01 17:34:57
Done.
| |
659 | 691 |
660 // Now send the next (coalesced) mouse wheel event. | 692 // Send the next (coalesced or synthetic) mouse wheel event. |
661 if (!coalesced_mouse_wheel_events_.empty()) { | 693 if (!coalesced_mouse_wheel_events_.empty()) { |
662 MouseWheelEventWithLatencyInfo next_wheel_event = | 694 QueuedWheelEvent next_wheel_event = coalesced_mouse_wheel_events_.front(); |
663 coalesced_mouse_wheel_events_.front(); | |
664 coalesced_mouse_wheel_events_.pop_front(); | 695 coalesced_mouse_wheel_events_.pop_front(); |
665 SendWheelEvent(next_wheel_event); | 696 SendWheelEvent(next_wheel_event); |
666 } | 697 } |
667 } | 698 } |
668 | 699 |
669 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, | 700 void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type, |
670 InputEventAckState ack_result, | 701 InputEventAckState ack_result, |
671 const ui::LatencyInfo& latency) { | 702 const ui::LatencyInfo& latency) { |
672 // If |ack_result| originated from the overscroll controller, only | 703 // If |ack_result| originated from the overscroll controller, only |
673 // feed |gesture_event_queue_| the ack if it was expecting one. | 704 // feed |gesture_event_queue_| the ack if it was expecting one. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
745 mouse_wheel_pending_ || | 776 mouse_wheel_pending_ || |
746 select_range_pending_ || | 777 select_range_pending_ || |
747 move_caret_pending_; | 778 move_caret_pending_; |
748 } | 779 } |
749 | 780 |
750 bool InputRouterImpl::IsInOverscrollGesture() const { | 781 bool InputRouterImpl::IsInOverscrollGesture() const { |
751 OverscrollController* controller = client_->GetOverscrollController(); | 782 OverscrollController* controller = client_->GetOverscrollController(); |
752 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; | 783 return controller && controller->overscroll_mode() != OVERSCROLL_NONE; |
753 } | 784 } |
754 | 785 |
786 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent() { | |
jdduke (slow)
2014/05/01 15:44:47
synthesized_from_pinch(false)
Rick Byers
2014/05/01 17:34:57
Thanks! Done.
| |
787 } | |
788 | |
789 InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent( | |
790 const MouseWheelEventWithLatencyInfo& event, | |
791 bool synthesized_from_pinch) | |
792 : event(event), synthesized_from_pinch(synthesized_from_pinch) { | |
793 } | |
794 | |
795 InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() { | |
796 } | |
797 | |
755 } // namespace content | 798 } // namespace content |
OLD | NEW |