summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjdduke <jdduke@chromium.org>2015-06-25 16:13:18 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-25 23:14:03 +0000
commitc05612bf6588fd75450b28d1e01e12493efbd409 (patch)
tree9ac680c39e3688d07dea3a236f18f127b7d283e2
parent6a91472770fa114eaa33ce9703884a82abd32d13 (diff)
downloadchromium_src-c05612bf6588fd75450b28d1e01e12493efbd409.zip
chromium_src-c05612bf6588fd75450b28d1e01e12493efbd409.tar.gz
chromium_src-c05612bf6588fd75450b28d1e01e12493efbd409.tar.bz2
Bundle main thread overscroll data with event ack messages
Currently, every main thread overscroll event will trigger an overscroll IPC notification. However, most such events occur in the context of handling input events. For such cases, bundle the overscroll data with the event ack. BUG=442859,502146 Review URL: https://codereview.chromium.org/1209043002 Cr-Commit-Position: refs/heads/master@{#336293}
-rw-r--r--content/renderer/render_widget.cc26
-rw-r--r--content/renderer/render_widget.h7
-rw-r--r--content/renderer/render_widget_unittest.cc83
3 files changed, 105 insertions, 11 deletions
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index d1faa54..de16016 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -491,6 +491,7 @@ RenderWidget::RenderWidget(blink::WebPopupType popup_type,
display_mode_(blink::WebDisplayModeUndefined),
has_focus_(false),
handling_input_event_(false),
+ handling_event_overscroll_(nullptr),
handling_ime_event_(false),
handling_event_type_(WebInputEvent::Undefined),
ignore_ack_for_mouse_move_from_debugger_(false),
@@ -1067,12 +1068,20 @@ void RenderWidget::OnSwapBuffersComplete() {
void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut) {
- base::AutoReset<bool> handling_input_event_resetter(
- &handling_input_event_, true);
if (!input_event)
return;
+ base::AutoReset<bool> handling_input_event_resetter(&handling_input_event_,
+ true);
base::AutoReset<WebInputEvent::Type> handling_event_type_resetter(
&handling_event_type_, input_event->type);
+
+ // Calls into |didOverscroll()| while handling this event will populate
+ // |event_overscroll|, which in turn will be bundled with the event ack.
+ scoped_ptr<DidOverscrollParams> event_overscroll;
+ base::AutoReset<scoped_ptr<DidOverscrollParams>*>
+ handling_event_overscroll_resetter(&handling_event_overscroll_,
+ &event_overscroll);
+
#if defined(OS_ANDROID)
// On Android, when a key is pressed or sent from the Keyboard using IME,
// |AdapterInputConnection| generates input key events to make sure all JS
@@ -1226,6 +1235,7 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
if (WebInputEventTraits::WillReceiveAckFromRenderer(*input_event) &&
!no_ack) {
InputEventAck ack(input_event->type, ack_result, swap_latency_info,
+ event_overscroll.Pass(),
WebInputEventTraits::GetUniqueTouchEventId(*input_event));
scoped_ptr<IPC::Message> response(
new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
@@ -1251,6 +1261,8 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
} else {
Send(response.release());
}
+ } else {
+ DCHECK(!event_overscroll) << "Unexpected overscroll for un-acked event";
}
if (!no_ack && RenderThreadImpl::current()) {
RenderThreadImpl::current()
@@ -2221,8 +2233,6 @@ void RenderWidget::didOverscroll(
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity) {
DidOverscrollParams params;
- // TODO(jdduke): Consider bundling the overscroll with the input event ack to
- // save an IPC.
params.accumulated_overscroll = gfx::Vector2dF(
accumulatedRootOverScroll.width, accumulatedRootOverScroll.height);
params.latest_overscroll_delta =
@@ -2232,6 +2242,14 @@ void RenderWidget::didOverscroll(
params.current_fling_velocity =
gfx::Vector2dF(-velocity.width, -velocity.height);
params.causal_event_viewport_point = gfx::PointF(position.x, position.y);
+
+ // If we're currently handling an event, stash the overscroll data such that
+ // it can be bundled in the event ack.
+ if (handling_event_overscroll_) {
+ handling_event_overscroll_->reset(new DidOverscrollParams(params));
+ return;
+ }
+
Send(new InputHostMsg_DidOverscroll(routing_id_, params));
}
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 5d58a87..92a0f38 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -87,6 +87,7 @@ class RenderWidgetCompositor;
class RenderWidgetTest;
class ResizingModeSelector;
struct ContextMenuParams;
+struct DidOverscrollParams;
struct WebPluginGeometry;
// RenderWidget provides a communication bridge between a WebWidget and
@@ -678,6 +679,12 @@ class CONTENT_EXPORT RenderWidget
// Are we currently handling an input event?
bool handling_input_event_;
+ // Used to intercept overscroll notifications while an event is being
+ // handled. If the event causes overscroll, the overscroll metadata can be
+ // bundled in the event ack, saving an IPC. Note that we must continue
+ // supporting overscroll IPC notifications due to fling animation updates.
+ scoped_ptr<DidOverscrollParams>* handling_event_overscroll_;
+
// Are we currently handling an ime event?
bool handling_ime_event_;
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index d9b919a..508ebc1 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -29,14 +29,15 @@ class RenderWidgetUnittest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
};
-class TouchableRenderWidget : public RenderWidget {
+class InteractiveRenderWidget : public RenderWidget {
public:
- TouchableRenderWidget()
+ InteractiveRenderWidget()
: RenderWidget(blink::WebPopupTypeNone,
blink::WebScreenInfo(),
false,
false,
- false) {}
+ false),
+ always_overscroll_(false) {}
void SetTouchRegion(const std::vector<gfx::Rect>& rects) {
rects_ = rects;
@@ -46,10 +47,14 @@ class TouchableRenderWidget : public RenderWidget {
OnHandleInputEvent(&event, ui::LatencyInfo(), false);
}
+ void set_always_overscroll(bool overscroll) {
+ always_overscroll_ = overscroll;
+ }
+
IPC::TestSink* sink() { return &sink_; }
protected:
- ~TouchableRenderWidget() override {}
+ ~InteractiveRenderWidget() override {}
// Overridden from RenderWidget:
bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
@@ -61,6 +66,22 @@ class TouchableRenderWidget : public RenderWidget {
return false;
}
+ bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override {
+ if (always_overscroll_ &&
+ event.type == blink::WebInputEvent::GestureScrollUpdate) {
+ didOverscroll(blink::WebFloatSize(event.data.scrollUpdate.deltaX,
+ event.data.scrollUpdate.deltaY),
+ blink::WebFloatSize(event.data.scrollUpdate.deltaX,
+ event.data.scrollUpdate.deltaY),
+ blink::WebFloatPoint(event.x, event.y),
+ blink::WebFloatSize(event.data.scrollUpdate.velocityX,
+ event.data.scrollUpdate.velocityY));
+ return true;
+ }
+
+ return false;
+ }
+
bool Send(IPC::Message* msg) override {
sink_.OnMessageReceived(*msg);
delete msg;
@@ -70,12 +91,13 @@ class TouchableRenderWidget : public RenderWidget {
private:
std::vector<gfx::Rect> rects_;
IPC::TestSink sink_;
+ bool always_overscroll_;
- DISALLOW_COPY_AND_ASSIGN(TouchableRenderWidget);
+ DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
};
TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
- scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget();
+ scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
SyntheticWebTouchEvent touch;
touch.PressPoint(10, 10);
@@ -109,7 +131,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
}
TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
- scoped_refptr<TouchableRenderWidget> widget = new TouchableRenderWidget();
+ scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
std::vector<gfx::Rect> rects;
rects.push_back(gfx::Rect(0, 0, 20, 20));
rects.push_back(gfx::Rect(25, 0, 10, 10));
@@ -143,4 +165,51 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
widget->sink()->ClearMessages();
}
+TEST_F(RenderWidgetUnittest, EventOverscroll) {
+ scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
+ widget->set_always_overscroll(true);
+
+ blink::WebGestureEvent scroll;
+ scroll.type = blink::WebInputEvent::GestureScrollUpdate;
+ scroll.x = -10;
+ scroll.data.scrollUpdate.deltaY = 10;
+ widget->SendInputEvent(scroll);
+
+ // Overscroll notifications received while handling an input event should
+ // be bundled with the event ack IPC.
+ ASSERT_EQ(1u, widget->sink()->message_count());
+ const IPC::Message* message = widget->sink()->GetMessageAt(0);
+ ASSERT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
+ InputHostMsg_HandleInputEvent_ACK::Param params;
+ InputHostMsg_HandleInputEvent_ACK::Read(message, &params);
+ const InputEventAck& ack = base::get<0>(params);
+ ASSERT_EQ(ack.type, scroll.type);
+ ASSERT_TRUE(ack.overscroll);
+ EXPECT_EQ(gfx::Vector2dF(0, 10), ack.overscroll->accumulated_overscroll);
+ EXPECT_EQ(gfx::Vector2dF(0, 10), ack.overscroll->latest_overscroll_delta);
+ EXPECT_EQ(gfx::Vector2dF(), ack.overscroll->current_fling_velocity);
+ EXPECT_EQ(gfx::PointF(-10, 0), ack.overscroll->causal_event_viewport_point);
+ widget->sink()->ClearMessages();
+}
+
+TEST_F(RenderWidgetUnittest, FlingOverscroll) {
+ scoped_refptr<InteractiveRenderWidget> widget = new InteractiveRenderWidget();
+
+ // Overscroll notifications received outside of handling an input event should
+ // be sent as a separate IPC.
+ widget->didOverscroll(blink::WebFloatSize(10, 5), blink::WebFloatSize(5, 5),
+ blink::WebFloatPoint(1, 1), blink::WebFloatSize(10, 5));
+ ASSERT_EQ(1u, widget->sink()->message_count());
+ const IPC::Message* message = widget->sink()->GetMessageAt(0);
+ ASSERT_EQ(InputHostMsg_DidOverscroll::ID, message->type());
+ InputHostMsg_DidOverscroll::Param params;
+ InputHostMsg_DidOverscroll::Read(message, &params);
+ const DidOverscrollParams& overscroll = base::get<0>(params);
+ EXPECT_EQ(gfx::Vector2dF(10, 5), overscroll.latest_overscroll_delta);
+ EXPECT_EQ(gfx::Vector2dF(5, 5), overscroll.accumulated_overscroll);
+ EXPECT_EQ(gfx::PointF(1, 1), overscroll.causal_event_viewport_point);
+ EXPECT_EQ(gfx::Vector2dF(-10, -5), overscroll.current_fling_velocity);
+ widget->sink()->ClearMessages();
+}
+
} // namespace content