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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/input_router_impl.cc
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 83f6fcb164f066646547a34903fa98d2e0f8e787..266fff74b704079046b0783cb6f4aeaefd8df788 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -180,26 +180,39 @@ void InputRouterImpl::SendMouseEvent(
void InputRouterImpl::SendWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) {
- // If there's already a mouse wheel event waiting to be sent to the renderer,
- // add the new deltas to that event. Not doing so (e.g., by dropping the old
- // event, as for mouse moves) results in very slow scrolling on the Mac (on
- // which many, very small wheel events are sent).
+ SendWheelEvent(QueuedWheelEvent(wheel_event, false));
+}
+
+void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) {
if (mouse_wheel_pending_) {
+ // If there's already a mouse wheel event waiting to be sent to the
+ // renderer, add the new deltas to that event. Not doing so (e.g., by
+ // dropping the old event, as for mouse moves) results in very slow
+ // scrolling on the Mac (on which many, very small wheel events are sent).
+ // Note that we can't coalesce wheel events for pinches because the GEQ
+ // expects one ACK for each (but it's fine to coalesce non-pinch wheels
+ // into a pinch one). Note that the GestureEventQueue ensures we only
+ // ever have a single pinch event queued here.
if (coalesced_mouse_wheel_events_.empty() ||
- !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) {
+ wheel_event.synthesized_from_pinch ||
+ !coalesced_mouse_wheel_events_.back().event.CanCoalesceWith(
+ wheel_event.event)) {
coalesced_mouse_wheel_events_.push_back(wheel_event);
} else {
- coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event);
+ coalesced_mouse_wheel_events_.back().event.CoalesceWith(
+ wheel_event.event);
}
return;
}
+
mouse_wheel_pending_ = true;
current_wheel_event_ = wheel_event;
HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
coalesced_mouse_wheel_events_.size());
- FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency, false);
+ FilterAndSendWebInputEvent(
+ wheel_event.event.event, wheel_event.event.latency, false);
}
void InputRouterImpl::SendKeyboardEvent(const NativeWebKeyboardEvent& key_event,
@@ -378,19 +391,6 @@ void InputRouterImpl::FilterAndSendWebInputEvent(
"type",
WebInputEventTraits::GetName(input_event.type));
- // Transmit any pending wheel events on a non-wheel event. This ensures that
- // final PhaseEnded wheel event is received, which is necessary to terminate
- // rubber-banding, for example.
- if (input_event.type != WebInputEvent::MouseWheel) {
- WheelEventQueue mouse_wheel_events;
- mouse_wheel_events.swap(coalesced_mouse_wheel_events_);
- for (size_t i = 0; i < mouse_wheel_events.size(); ++i) {
- OfferToHandlers(mouse_wheel_events[i].event,
- mouse_wheel_events[i].latency,
- false);
- }
- }
-
// Any input event cancels a pending mouse move event.
next_mouse_move_.reset();
@@ -400,16 +400,13 @@ void InputRouterImpl::FilterAndSendWebInputEvent(
void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut) {
- // Trackpad pinch gestures are not yet handled by the renderer.
- // TODO(rbyers): Send mousewheel for trackpad pinch - crbug.com/289887.
- if (input_event.type == WebInputEvent::GesturePinchUpdate &&
- static_cast<const WebGestureEvent&>(input_event).sourceDevice ==
- WebGestureEvent::Touchpad) {
- ProcessInputEventAck(input_event.type,
- INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
- latency_info,
- ACK_SOURCE_NONE);
- return;
+ 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
+ const WebGestureEvent& pinch_event =
+ static_cast<const WebGestureEvent&>(input_event);
+ if (pinch_event.sourceDevice == WebGestureEvent::Touchpad) {
+ SendSyntheticWheelEventForPinch(pinch_event, latency_info);
+ return;
+ }
}
if (OfferToOverscrollController(input_event, latency_info))
@@ -515,6 +512,33 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
return false;
}
+void InputRouterImpl::SendSyntheticWheelEventForPinch(
+ const blink::WebGestureEvent& pinch_event,
+ const ui::LatencyInfo& latency_info) {
+ // We match typical trackpad behavior on Windows by sending fake wheel events
+ // with the ctrl modifier set when we see trackpad pinch gestures. Ideally
+ // we'd someday get a standard 'pinch' event and send that instead.
+
+ WebMouseWheelEvent wheelEvent;
+ wheelEvent.type = WebInputEvent::MouseWheel;
+ wheelEvent.timeStampSeconds = pinch_event.timeStampSeconds;
+ wheelEvent.windowX = wheelEvent.x = pinch_event.x;
+ wheelEvent.windowY = wheelEvent.y = pinch_event.y;
+ wheelEvent.globalX = pinch_event.globalX;
+ wheelEvent.globalY = pinch_event.globalY;
+ wheelEvent.modifiers = pinch_event.modifiers | WebInputEvent::ControlKey;
+ wheelEvent.deltaX = 0;
+ // For maximum compatibility with wheels, deltaY here is a "magnification
+ // percentage". Note that wheel events in JS have the sign reversed.
+ 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.
+ wheelEvent.hasPreciseScrollingDeltas = true;
+ wheelEvent.wheelTicksX = 0;
+ wheelEvent.wheelTicksY = pinch_event.data.pinchUpdate.scale > 1 ? 1 : -1;
+
+ SendWheelEvent(QueuedWheelEvent(
+ MouseWheelEventWithLatencyInfo(wheelEvent, latency_info), true));
+}
+
void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type,
InputEventAckState ack_result,
const ui::LatencyInfo& latency_info) {
@@ -647,20 +671,27 @@ void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency) {
- ProcessAckForOverscroll(current_wheel_event_.event, ack_result);
-
// TODO(miletus): Add renderer side latency to each uncoalesced mouse
// wheel event and add terminal component to each of them.
- current_wheel_event_.latency.AddNewLatencyFrom(latency);
- // Process the unhandled wheel event here before calling SendWheelEvent()
- // since it will mutate current_wheel_event_.
- ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result);
+ current_wheel_event_.event.latency.AddNewLatencyFrom(latency);
+
+ if (current_wheel_event_.synthesized_from_pinch) {
+ // Ack the GesturePinchUpdate event that generated this wheel event.
+ ProcessInputEventAck(WebInputEvent::GesturePinchUpdate,
+ ack_result,
+ current_wheel_event_.event.latency,
+ 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.
+ } else {
+ // Process the unhandled wheel event here before calling SendWheelEvent()
+ // since it will mutate current_wheel_event_.
+ ProcessAckForOverscroll(current_wheel_event_.event.event, ack_result);
+ ack_handler_->OnWheelEventAck(current_wheel_event_.event, ack_result);
+ }
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.
- // Now send the next (coalesced) mouse wheel event.
+ // Send the next (coalesced or synthetic) mouse wheel event.
if (!coalesced_mouse_wheel_events_.empty()) {
- MouseWheelEventWithLatencyInfo next_wheel_event =
- coalesced_mouse_wheel_events_.front();
+ QueuedWheelEvent next_wheel_event = coalesced_mouse_wheel_events_.front();
coalesced_mouse_wheel_events_.pop_front();
SendWheelEvent(next_wheel_event);
}
@@ -752,4 +783,16 @@ bool InputRouterImpl::IsInOverscrollGesture() const {
return controller && controller->overscroll_mode() != OVERSCROLL_NONE;
}
+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.
+}
+
+InputRouterImpl::QueuedWheelEvent::QueuedWheelEvent(
+ const MouseWheelEventWithLatencyInfo& event,
+ bool synthesized_from_pinch)
+ : event(event), synthesized_from_pinch(synthesized_from_pinch) {
+}
+
+InputRouterImpl::QueuedWheelEvent::~QueuedWheelEvent() {
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698