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

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: Fix windows build and tweaks Created 6 years, 7 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
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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698