Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(488)

Side by Side Diff: content/browser/renderer_host/input/input_router_impl.cc

Issue 250923004: Synthesize ctrl-wheel events on touchpad pinch (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/input/input_router_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « content/browser/renderer_host/input/input_router_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698