diff options
author | jdduke <jdduke@chromium.org> | 2015-06-25 16:13:18 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-25 23:14:03 +0000 |
commit | c05612bf6588fd75450b28d1e01e12493efbd409 (patch) | |
tree | 9ac680c39e3688d07dea3a236f18f127b7d283e2 | |
parent | 6a91472770fa114eaa33ce9703884a82abd32d13 (diff) | |
download | chromium_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.cc | 26 | ||||
-rw-r--r-- | content/renderer/render_widget.h | 7 | ||||
-rw-r--r-- | content/renderer/render_widget_unittest.cc | 83 |
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, ¶ms); + 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, ¶ms); + 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 |