summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorlanwei <lanwei@chromium.org>2014-12-22 14:36:59 -0800
committerCommit bot <commit-bot@chromium.org>2014-12-22 22:37:58 +0000
commitb3361bcdd3766a67c702c19781154c895fee75ca (patch)
tree5a3573c8490deaa93d1ef67169e2cdf7cfe1d43d /content
parentd355ff75f2eb9129cb06e160c5beb1590d7d0ee3 (diff)
downloadchromium_src-b3361bcdd3766a67c702c19781154c895fee75ca.zip
chromium_src-b3361bcdd3766a67c702c19781154c895fee75ca.tar.gz
chromium_src-b3361bcdd3766a67c702c19781154c895fee75ca.tar.bz2
Explicitly suppress scrolling for wheel events that will trigger zooming
We added a flag in Blink to decide if Ctrl-wheel-scroll should scroll or zoom, and now we use this flag in chromium code. This patch is part of a series: patch #1: https://codereview.chromium.org/759073002 patch #2: This CL patch #3: https://codereview.chromium.org/768443002 BUG=397027, 378755 Review URL: https://codereview.chromium.org/739013008 Cr-Commit-Position: refs/heads/master@{#309472}
Diffstat (limited to 'content')
-rw-r--r--content/browser/renderer_host/input/input_router_impl.cc13
-rw-r--r--content/browser/renderer_host/input/input_router_impl_unittest.cc40
-rw-r--r--content/browser/renderer_host/render_widget_host_view_aura_unittest.cc80
-rw-r--r--content/browser/renderer_host/web_input_event_aura.cc13
-rw-r--r--content/browser/web_contents/web_contents_impl.cc11
-rw-r--r--content/browser/web_contents/web_contents_impl_unittest.cc10
-rw-r--r--content/common/input/synthetic_web_input_event_builders.cc1
-rw-r--r--content/common/input/web_input_event_traits.cc8
-rw-r--r--content/common/input/web_input_event_traits_unittest.cc36
-rw-r--r--content/renderer/input/input_handler_proxy.cc6
-rw-r--r--content/renderer/input/input_handler_proxy_unittest.cc4
-rw-r--r--content/shell/renderer/test_runner/event_sender.cc25
12 files changed, 198 insertions, 49 deletions
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index 9113bee..b802aed 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -136,11 +136,14 @@ void InputRouterImpl::SendWheelEvent(const QueuedWheelEvent& wheel_event) {
// 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.
+ // expects one ACK for each. But such events always have canScroll==false
+ // and hasPreciseDeltas=true, which should never happen for a real wheel
+ // event and so coalescing shouldn't occur. Note that the
+ // GestureEventQueue ensures we only ever have a single pinch event queued
+ // here.
if (coalesced_mouse_wheel_events_.empty() ||
- wheel_event.synthesized_from_pinch ||
+ wheel_event.synthesized_from_pinch !=
+ coalesced_mouse_wheel_events_.back().synthesized_from_pinch ||
!coalesced_mouse_wheel_events_.back().event.CanCoalesceWith(
wheel_event.event)) {
coalesced_mouse_wheel_events_.push_back(wheel_event);
@@ -458,7 +461,7 @@ void InputRouterImpl::SendSyntheticWheelEventForPinch(
wheelEvent.wheelTicksX = 0;
wheelEvent.wheelTicksY =
pinch_event.event.data.pinchUpdate.scale > 1 ? 1 : -1;
-
+ wheelEvent.canScroll = false;
SendWheelEvent(QueuedWheelEvent(
MouseWheelEventWithLatencyInfo(wheelEvent, pinch_event.latency), true));
}
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 3fa0b93..147f975 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -1631,6 +1631,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
EXPECT_TRUE(wheel_event->hasPreciseScrollingDeltas);
EXPECT_EQ(1, wheel_event->wheelTicksY);
EXPECT_EQ(0, wheel_event->wheelTicksX);
+ EXPECT_FALSE(wheel_event->canScroll);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Indicate that the wheel event was unhandled.
@@ -1653,6 +1654,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchUpdate) {
EXPECT_FLOAT_EQ(PinchScaleToWheelDelta(0.3f), wheel_event->deltaY);
EXPECT_TRUE(wheel_event->hasPreciseScrollingDeltas);
EXPECT_EQ(-1, wheel_event->wheelTicksY);
+ EXPECT_FALSE(wheel_event->canScroll);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Indicate that the wheel event was handled this time.
@@ -1732,8 +1734,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
// Note that in practice interleaving pinch and wheel events should be rare
// (eg. requires the use of a mouse and trackpad at the same time).
- // Use the control modifier to match the synthetic wheel events so that
- // they're elligble for coalescing.
+ // Synthetic wheel and real wheel events can never be coalesced together.
int mod = WebInputEvent::ControlKey;
// Event 1: sent directly.
@@ -1744,7 +1745,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
SimulateWheelEvent(0, -10, mod, true);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- // Event 3: enqueued in InputRouter, not coalesced into #2.
+ // Event 3: enqueued in InputRouter, not coalesced into #2 because of
+ // synthesized_from_pinch.
SimulateGesturePinchUpdateEvent(
1.5f, 20, 25, 0, blink::WebGestureDeviceTouchpad);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
@@ -1754,10 +1756,15 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
1.2f, 20, 25, 0, blink::WebGestureDeviceTouchpad);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
- // Event 5: coalesced into wheel event for #3.
+ // Event 5: enqueued in InputRouter, not coalesced into #3 because of
+ // synthesized_from_pinch.
SimulateWheelEvent(2, 0, mod, true);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ // Event 6: coalesced into #5.
+ SimulateWheelEvent(0, 3, mod, true);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
// Send ack for #1.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
@@ -1774,6 +1781,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
EXPECT_EQ(0, wheel_event->deltaX);
EXPECT_EQ(-10, wheel_event->deltaY);
EXPECT_EQ(mod, wheel_event->modifiers);
+ EXPECT_TRUE(wheel_event->canScroll);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Send ack for #2.
@@ -1782,22 +1790,41 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::MouseWheel, ack_handler_->ack_event_type());
- // Verify we sent #3 (with #5 coalesced in).
+ // Verify we sent #3.
ASSERT_EQ(1U, process_->sink().message_count());
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
ASSERT_EQ(WebInputEvent::MouseWheel, input_event->type);
wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
- EXPECT_EQ(2, wheel_event->deltaX);
+ EXPECT_EQ(0, wheel_event->deltaX);
EXPECT_EQ(PinchScaleToWheelDelta(1.5f), wheel_event->deltaY);
EXPECT_EQ(mod, wheel_event->modifiers);
+ EXPECT_FALSE(wheel_event->canScroll);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
// Send ack for #3.
SendInputEventACK(WebInputEvent::MouseWheel,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(WebInputEvent::GesturePinchUpdate, ack_handler_->ack_event_type());
+ // Verify we sent #5 with #6 coalesced into it.
+ ASSERT_EQ(1U, process_->sink().message_count());
+ input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
+ ASSERT_EQ(WebInputEvent::MouseWheel, input_event->type);
+ wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
+ EXPECT_EQ(2, wheel_event->deltaX);
+ EXPECT_EQ(3, wheel_event->deltaY);
+ EXPECT_EQ(mod, wheel_event->modifiers);
+ EXPECT_TRUE(wheel_event->canScroll);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Send ack for #5.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(WebInputEvent::MouseWheel, ack_handler_->ack_event_type());
+
// Verify we sent #4.
ASSERT_EQ(1U, process_->sink().message_count());
input_event = GetInputEventFromMessage(*process_->sink().GetMessageAt(0));
@@ -1806,6 +1833,7 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndWheel) {
EXPECT_EQ(0, wheel_event->deltaX);
EXPECT_FLOAT_EQ(PinchScaleToWheelDelta(1.2f), wheel_event->deltaY);
EXPECT_EQ(mod, wheel_event->modifiers);
+ EXPECT_FALSE(wheel_event->canScroll);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// Send ack for #4.
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 13d986b..9bdfbcc 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -308,6 +308,15 @@ class MockWindowObserver : public aura::WindowObserver {
MOCK_METHOD2(OnDelegatedFrameDamage, void(aura::Window*, const gfx::Rect&));
};
+const WebInputEvent* GetInputEventFromMessage(const IPC::Message& message) {
+ PickleIterator iter(message);
+ const char* data;
+ int data_length;
+ if (!iter.ReadData(&data, &data_length))
+ return NULL;
+ return reinterpret_cast<const WebInputEvent*>(data);
+}
+
} // namespace
class RenderWidgetHostViewAuraTest : public testing::Test {
@@ -388,6 +397,15 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
RendererFrameManager::GetInstance()->OnMemoryPressure(level);
}
+ void SendInputEventACK(WebInputEvent::Type type,
+ InputEventAckState ack_result) {
+ InputHostMsg_HandleInputEvent_ACK_Params ack;
+ ack.type = type;
+ ack.state = ack_result;
+ InputHostMsg_HandleInputEvent_ACK response(0, ack);
+ widget_host_->OnMessageReceived(response);
+ }
+
protected:
// If true, then calls RWH::Shutdown() instead of deleting RWH.
bool widget_host_uses_shutdown_to_destroy_;
@@ -580,15 +598,6 @@ class RenderWidgetHostViewAuraOverscrollTest
velocityX, velocityY, sourceDevice));
}
- void SendInputEventACK(WebInputEvent::Type type,
- InputEventAckState ack_result) {
- InputHostMsg_HandleInputEvent_ACK_Params ack;
- ack.type = type;
- ack.state = ack_result;
- InputHostMsg_HandleInputEvent_ACK response(0, ack);
- widget_host_->OnMessageReceived(response);
- }
-
bool ScrollStateIsContentScrolling() const {
return scroll_state() == OverscrollController::STATE_CONTENT_SCROLLING;
}
@@ -3071,4 +3080,57 @@ TEST_F(RenderWidgetHostViewAuraTest, KeyEvent) {
}
}
+TEST_F(RenderWidgetHostViewAuraTest, SetCanScrollForWebMouseWheelEvent) {
+ view_->InitAsChild(NULL);
+ view_->Show();
+
+ sink_->ClearMessages();
+
+ // Simulates the mouse wheel event with ctrl modifier applied.
+ ui::MouseWheelEvent event(gfx::Vector2d(1, 1),
+ gfx::Point(), gfx::Point(),
+ ui::EF_CONTROL_DOWN, 0);
+ view_->OnMouseEvent(&event);
+
+ const WebInputEvent* input_event =
+ GetInputEventFromMessage(*sink_->GetMessageAt(0));
+ const WebMouseWheelEvent* wheel_event =
+ static_cast<const WebMouseWheelEvent*>(input_event);
+ // Check if the canScroll set to false when ctrl-scroll is generated from
+ // mouse wheel event.
+ EXPECT_FALSE(wheel_event->canScroll);
+ sink_->ClearMessages();
+
+ // Ack'ing the outstanding event should flush the pending event queue.
+ SendInputEventACK(blink::WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Simulates the mouse wheel event with no modifier applied.
+ event = ui::MouseWheelEvent(gfx::Vector2d(1, 1), gfx::Point(), gfx::Point(),
+ ui::EF_NONE, 0);
+
+ view_->OnMouseEvent(&event);
+
+ input_event = GetInputEventFromMessage(*sink_->GetMessageAt(0));
+ wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
+ // Check if the canScroll set to true when no modifier is applied to the
+ // mouse wheel event.
+ EXPECT_TRUE(wheel_event->canScroll);
+ sink_->ClearMessages();
+
+ SendInputEventACK(blink::WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ // Simulates the scroll event with ctrl modifier applied.
+ ui::ScrollEvent scroll(ui::ET_SCROLL, gfx::Point(2, 2), ui::EventTimeForNow(),
+ ui::EF_CONTROL_DOWN, 0, 5, 0, 5, 2);
+ view_->OnScrollEvent(&scroll);
+
+ input_event = GetInputEventFromMessage(*sink_->GetMessageAt(0));
+ wheel_event = static_cast<const WebMouseWheelEvent*>(input_event);
+ // Check if the canScroll set to true when ctrl-touchpad-scroll is generated
+ // from scroll event.
+ EXPECT_TRUE(wheel_event->canScroll);
+}
+
} // namespace content
diff --git a/content/browser/renderer_host/web_input_event_aura.cc b/content/browser/renderer_host/web_input_event_aura.cc
index c4a766a..76bdbf1 100644
--- a/content/browser/renderer_host/web_input_event_aura.cc
+++ b/content/browser/renderer_host/web_input_event_aura.cc
@@ -193,14 +193,23 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
webkit_event.globalX = root_point.x();
webkit_event.globalY = root_point.y();
+ // Scroll events generated from the mouse wheel when the control key is held
+ // don't trigger scrolling. Instead, they may cause zooming.
+ bool from_mouse_wheel = !webkit_event.hasPreciseScrollingDeltas;
+ if ((webkit_event.modifiers & blink::WebInputEvent::ControlKey) &&
+ from_mouse_wheel) {
+ webkit_event.canScroll = false;
+ }
+
return webkit_event;
}
blink::WebMouseWheelEvent MakeWebMouseWheelEvent(const ui::ScrollEvent& event) {
#if defined(OS_WIN)
// Construct an untranslated event from the platform event data.
- blink::WebMouseWheelEvent webkit_event =
- MakeUntranslatedWebMouseWheelEventFromNativeEvent(event.native_event());
+ blink::WebMouseWheelEvent webkit_event = event.native_event().message ?
+ MakeUntranslatedWebMouseWheelEventFromNativeEvent(event.native_event()) :
+ MakeWebMouseWheelEventFromAuraEvent(event);
#else
blink::WebMouseWheelEvent webkit_event =
MakeWebMouseWheelEventFromAuraEvent(event);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 7151e15..44f103c 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1333,18 +1333,15 @@ void WebContentsImpl::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
bool WebContentsImpl::HandleWheelEvent(
const blink::WebMouseWheelEvent& event) {
#if !defined(OS_MACOSX)
- // On platforms other than Mac, control+mousewheel changes zoom. On Mac, this
- // isn't done for two reasons:
+ // On platforms other than Mac, control+mousewheel may change zoom. On Mac,
+ // this isn't done for two reasons:
// -the OS already has a gesture to do this through pinch-zoom
// -if a user starts an inertial scroll, let's go, and presses control
// (i.e. control+tab) then the OS's buffered scroll events will come in
// with control key set which isn't what the user wants
- if (delegate_ &&
- event.wheelTicksY &&
+ if (delegate_ && event.wheelTicksY &&
(event.modifiers & blink::WebInputEvent::ControlKey) &&
- // Avoid adjusting the zoom in response to two-finger-scrolling touchpad
- // gestures, which are regrettably easy to trigger accidentally.
- !event.hasPreciseScrollingDeltas) {
+ !event.canScroll) {
delegate_->ContentsZoomChange(event.wheelTicksY > 0);
return true;
}
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index ba1a8f0..12d04ee 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -2476,15 +2476,18 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) {
EXPECT_FALSE(contents()->HandleWheelEvent(event));
EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
- modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
+ modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey |
+ WebInputEvent::ControlKey;
event = SyntheticWebMouseWheelEventBuilder::Build(0, 1, modifiers, false);
EXPECT_FALSE(contents()->HandleWheelEvent(event));
EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
- // But whenever the ctrl modifier is applied, they can increase/decrease zoom.
- // Except on MacOS where we never want to adjust zoom with mousewheel.
+ // But whenever the ctrl modifier is applied with canScroll=false, they can
+ // increase/decrease zoom. Except on MacOS where we never want to adjust zoom
+ // with mousewheel.
modifiers = WebInputEvent::ControlKey;
event = SyntheticWebMouseWheelEventBuilder::Build(0, 1, modifiers, false);
+ event.canScroll = false;
bool handled = contents()->HandleWheelEvent(event);
#if defined(OS_MACOSX)
EXPECT_FALSE(handled);
@@ -2498,6 +2501,7 @@ TEST_F(WebContentsImplTest, HandleWheelEvent) {
modifiers = WebInputEvent::ControlKey | WebInputEvent::ShiftKey |
WebInputEvent::AltKey;
event = SyntheticWebMouseWheelEventBuilder::Build(2, -5, modifiers, false);
+ event.canScroll = false;
handled = contents()->HandleWheelEvent(event);
#if defined(OS_MACOSX)
EXPECT_FALSE(handled);
diff --git a/content/common/input/synthetic_web_input_event_builders.cc b/content/common/input/synthetic_web_input_event_builders.cc
index ab2968a..3efbbb7 100644
--- a/content/common/input/synthetic_web_input_event_builders.cc
+++ b/content/common/input/synthetic_web_input_event_builders.cc
@@ -68,6 +68,7 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float dx,
result.wheelTicksY = dy > 0.0f ? 1.0f : -1.0f;
result.modifiers = modifiers;
result.hasPreciseScrollingDeltas = precise;
+ result.canScroll = true;
return result;
}
diff --git a/content/common/input/web_input_event_traits.cc b/content/common/input/web_input_event_traits.cc
index 4e9c754..9466a17 100644
--- a/content/common/input/web_input_event_traits.cc
+++ b/content/common/input/web_input_event_traits.cc
@@ -58,7 +58,7 @@ void ApppendEventDetails(const WebMouseWheelEvent& event, std::string* result) {
StringAppendF(result,
"{\n Delta: (%f, %f)\n WheelTicks: (%f, %f)\n Accel: (%f, %f)\n"
" ScrollByPage: %d\n HasPreciseScrollingDeltas: %d\n"
- " Phase: (%d, %d)\n CanRubberband: (%d, %d)\n}",
+ " Phase: (%d, %d)\n CanRubberband: (%d, %d)\n CanScroll: %d\n}",
event.deltaX,
event.deltaY,
event.wheelTicksX,
@@ -70,7 +70,8 @@ void ApppendEventDetails(const WebMouseWheelEvent& event, std::string* result) {
event.phase,
event.momentumPhase,
event.canRubberbandLeft,
- event.canRubberbandRight);
+ event.canRubberbandRight,
+ event.canScroll);
}
void ApppendEventDetails(const WebGestureEvent& event, std::string* result) {
@@ -149,7 +150,8 @@ bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce,
event.phase == event_to_coalesce.phase &&
event.momentumPhase == event_to_coalesce.momentumPhase &&
event.hasPreciseScrollingDeltas ==
- event_to_coalesce.hasPreciseScrollingDeltas;
+ event_to_coalesce.hasPreciseScrollingDeltas &&
+ event.canScroll == event_to_coalesce.canScroll;
}
float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) {
diff --git a/content/common/input/web_input_event_traits_unittest.cc b/content/common/input/web_input_event_traits_unittest.cc
index 7a7cb7f..d4bbeba 100644
--- a/content/common/input/web_input_event_traits_unittest.cc
+++ b/content/common/input/web_input_event_traits_unittest.cc
@@ -51,6 +51,17 @@ class WebInputEventTraitsTest : public testing::Test {
event.y = y;
return event;
}
+
+ static WebMouseWheelEvent CreateMouseWheel(float deltaX,
+ float deltaY,
+ bool canScroll) {
+ WebMouseWheelEvent event;
+ event.type = WebInputEvent::MouseWheel;
+ event.deltaX = deltaX;
+ event.deltaY = deltaY;
+ event.canScroll = canScroll;
+ return event;
+ }
};
TEST_F(WebInputEventTraitsTest, TouchEventCoalescing) {
@@ -162,6 +173,31 @@ TEST_F(WebInputEventTraitsTest, PinchEventCoalescing) {
EXPECT_EQ(numeric_limits<float>::max(), pinch1.data.pinchUpdate.scale);
}
+TEST_F(WebInputEventTraitsTest, WebMouseWheelEventCoalescing) {
+ WebMouseWheelEvent mouseWheel0 =
+ CreateMouseWheel(1, 1, true);
+ WebMouseWheelEvent mouseWheel1 =
+ CreateMouseWheel(2, 2, true);
+
+ // WebMouseWheelEvent objects with same values except different deltaX and
+ // deltaY should coalesce.
+ EXPECT_TRUE(WebInputEventTraits::CanCoalesce(mouseWheel0, mouseWheel1));
+
+ mouseWheel0 = CreateMouseWheel(1, 1, true);
+ mouseWheel1 = CreateMouseWheel(1, 1, false);
+
+ // WebMouseWheelEvent objects with different canScroll values should not
+ // coalesce.
+ EXPECT_FALSE(WebInputEventTraits::CanCoalesce(mouseWheel0, mouseWheel1));
+
+ // WebMouseWheelEvent objects with different modifiers should not coalesce.
+ mouseWheel0 = CreateMouseWheel(1, 1, true);
+ mouseWheel1 = CreateMouseWheel(1, 1, true);
+ mouseWheel0.modifiers = blink::WebInputEvent::ControlKey;
+ mouseWheel1.modifiers = blink::WebInputEvent::ShiftKey;
+ EXPECT_FALSE(WebInputEventTraits::CanCoalesce(mouseWheel0, mouseWheel1));
+}
+
// Very basic smoke test to ensure stringification doesn't explode.
TEST_F(WebInputEventTraitsTest, ToString) {
WebKeyboardEvent key;
diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc
index 3edb957..602f113 100644
--- a/content/renderer/input/input_handler_proxy.cc
+++ b/content/renderer/input/input_handler_proxy.cc
@@ -324,9 +324,9 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
// TODO(jamesr): We don't properly handle scroll by page in the compositor
// thread, so punt it to the main thread. http://crbug.com/236639
result = DID_NOT_HANDLE;
- } else if (wheel_event.modifiers & WebInputEvent::ControlKey) {
- // Wheel events involving the control key never trigger scrolling, only
- // event handlers. Forward to the main thread.
+ } else if (!wheel_event.canScroll) {
+ // Wheel events with |canScroll| == false will not trigger scrolling,
+ // only event handlers. Forward to the main thread.
result = DID_NOT_HANDLE;
} else if (smooth_scroll_enabled_) {
cc::InputHandler::ScrollStatus scroll_status =
diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc
index cb85701..ad715ac 100644
--- a/content/renderer/input/input_handler_proxy_unittest.cc
+++ b/content/renderer/input/input_handler_proxy_unittest.cc
@@ -288,12 +288,12 @@ TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) {
testing::Mock::VerifyAndClearExpectations(&mock_client_);
}
-TEST_F(InputHandlerProxyTest, MouseWheelWithCtrl) {
+TEST_F(InputHandlerProxyTest, MouseWheelWithCtrlNotScroll) {
expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
WebMouseWheelEvent wheel;
wheel.type = WebInputEvent::MouseWheel;
wheel.modifiers = WebInputEvent::ControlKey;
-
+ wheel.canScroll = false;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
testing::Mock::VerifyAndClearExpectations(&mock_client_);
}
diff --git a/content/shell/renderer/test_runner/event_sender.cc b/content/shell/renderer/test_runner/event_sender.cc
index b22fe72..8971ab6 100644
--- a/content/shell/renderer/test_runner/event_sender.cc
+++ b/content/shell/renderer/test_runner/event_sender.cc
@@ -2207,14 +2207,21 @@ void EventSender::InitMouseWheelEvent(gin::Arguments* args,
bool paged = false;
bool has_precise_scrolling_deltas = false;
int modifiers = 0;
- if (!args->PeekNext().IsEmpty()) {
- args->GetNext(&paged);
- if (!args->PeekNext().IsEmpty()) {
- args->GetNext(&has_precise_scrolling_deltas);
- if (!args->PeekNext().IsEmpty())
- modifiers = GetKeyModifiersFromV8(args->PeekNext());
- }
- }
+ bool can_scroll = true;
+ if (args->PeekNext().IsEmpty())
+ return;
+ args->GetNext(&paged);
+ if (args->PeekNext().IsEmpty())
+ return;
+ args->GetNext(&has_precise_scrolling_deltas);
+ if (args->PeekNext().IsEmpty())
+ return;
+ v8::Handle<v8::Value> value;
+ args->GetNext(&value);
+ modifiers = GetKeyModifiersFromV8(value);
+ if (args->PeekNext().IsEmpty())
+ return;
+ args->GetNext(&can_scroll);
InitMouseEvent(WebInputEvent::MouseWheel,
pressed_button_,
@@ -2229,7 +2236,7 @@ void EventSender::InitMouseWheelEvent(gin::Arguments* args,
event->deltaY = event->wheelTicksY;
event->scrollByPage = paged;
event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
-
+ event->canScroll = can_scroll;
if (continuous) {
event->wheelTicksX /= kScrollbarPixelsPerTick;
event->wheelTicksY /= kScrollbarPixelsPerTick;