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 129f34698a3b97b521c3dbc4f61b1194154da54f..ee49300a57a3ffa3616c2dd31dff3b22de13c3ab 100644 |
--- a/content/browser/renderer_host/input/input_router_impl.cc |
+++ b/content/browser/renderer_host/input/input_router_impl.cc |
@@ -143,6 +143,8 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender, |
move_caret_pending_(false), |
mouse_move_pending_(false), |
mouse_wheel_pending_(false), |
+ pending_touchpad_pinch_(false), |
+ current_wheel_event_is_for_pinch_(false), |
touch_ack_timeout_supported_(false), |
current_view_flags_(0), |
current_ack_source_(ACK_SOURCE_NONE), |
@@ -206,11 +208,25 @@ 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). |
if (mouse_wheel_pending_) { |
+ // If the provided event is for touchpad pinch, we don't want to coalesce |
+ // 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
|
+ // difficult and could require coalescing correspending GesturePinchUpdate |
+ // events in the GestureEventQueue. Do nothing for now, we'll send |
+ // wheel_event_for_pending_pinch_ when the ACK for this wheel event |
+ // arrives. |
+ if (pending_touchpad_pinch_) { |
+ DCHECK(!current_wheel_event_is_for_pinch_); |
+ DCHECK(wheel_event.latency.trace_id == |
+ wheel_event_for_pending_pinch_.latency.trace_id); |
+ return; |
+ } |
+ |
+ // 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). |
if (coalesced_mouse_wheel_events_.empty() || |
!coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event)) { |
coalesced_mouse_wheel_events_.push_back(wheel_event); |
@@ -219,6 +235,7 @@ void InputRouterImpl::SendWheelEvent( |
} |
return; |
} |
+ |
mouse_wheel_pending_ = true; |
current_wheel_event_ = wheel_event; |
@@ -426,16 +443,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 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.
|
+ 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)) |
@@ -533,6 +547,27 @@ bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event, |
return false; |
} |
+void InputRouterImpl::SendSyntheticWheelEventForPinch( |
+ const blink::WebGestureEvent& pinch_event, |
+ const ui::LatencyInfo& latency_info) { |
+ // We match IE and Firefox 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. |
+ DCHECK(!pending_touchpad_pinch_); |
+ DCHECK(!current_wheel_event_is_for_pinch_); |
+ WebMouseWheelEvent wheelEvent; |
+ wheelEvent.type = WebInputEvent::MouseWheel; |
+ wheelEvent.timeStampSeconds = pinch_event.timeStampSeconds; |
+ wheelEvent.modifiers = pinch_event.modifiers | WebInputEvent::ControlKey; |
+ wheelEvent.deltaX = 0; |
+ wheelEvent.deltaY = pinch_event.data.pinchUpdate.scale - 1; |
+ wheelEvent.hasPreciseScrollingDeltas = true; |
+ wheelEvent.wheelTicksX = 0; |
+ wheelEvent.wheelTicksY = pinch_event.data.pinchUpdate.scale > 0 ? 1 : -1; |
+ |
+ SendWheelEvent(MouseWheelEventWithLatencyInfo(wheelEvent, latency_info)); |
+} |
+ |
void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type, |
InputEventAckState ack_result, |
const ui::LatencyInfo& latency_info) { |
@@ -670,18 +705,38 @@ void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type, |
void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result, |
const ui::LatencyInfo& latency) { |
+ DCHECK(mouse_wheel_pending_); |
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); |
+ |
+ if (current_wheel_event_is_for_pinch_) { |
+ DCHECK(pending_touchpad_pinch_); |
+ DCHECK(current_wheel_event_.latency.trace_id == |
+ wheel_event_for_pending_pinch_.latency.trace_id); |
+ |
+ // Ack the GesturePinchUpdate event that generated this wheel event. |
+ ProcessInputEventAck(WebInputEvent::GesturePinchUpdate, |
+ ack_result, |
+ current_wheel_event_.latency, |
+ ACK_SOURCE_NONE); |
+ current_wheel_event_is_for_pinch_ = false; |
+ pending_touchpad_pinch_ = false; |
+ } else { |
+ // Process the unhandled wheel event here before calling SendWheelEvent() |
+ // since it will mutate current_wheel_event_. |
+ ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result); |
+ } |
mouse_wheel_pending_ = false; |
- // Now send the next (coalesced) mouse wheel event. |
- if (!coalesced_mouse_wheel_events_.empty()) { |
+ // Send the next (coalesced or synthetic) mouse wheel event. |
+ if (pending_touchpad_pinch_) { |
+ DCHECK(!current_wheel_event_is_for_pinch_); |
+ current_wheel_event_is_for_pinch_ = true; |
+ SendWheelEvent(wheel_event_for_pending_pinch_); |
+ } else if (!coalesced_mouse_wheel_events_.empty()) { |
MouseWheelEventWithLatencyInfo next_wheel_event = |
coalesced_mouse_wheel_events_.front(); |
coalesced_mouse_wheel_events_.pop_front(); |