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 |