Bundle DidOverscrollParams with the input event ack
Currently, overscroll notifications are always sent as a separate IPC message, regardless of the causal event. Instead, bundle the overscroll metadata with the event ack if the event caused the overscroll, saving an IPC message in the most common overscroll case. BUG=328503 Review URL: https://codereview.chromium.org/281723010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271541 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
content
browser
renderer_host
input
input_router_client.hinput_router_impl.ccinput_router_impl.hinput_router_impl_perftest.ccinput_router_impl_unittest.ccmock_input_router_client.ccmock_input_router_client.htouch_input_browsertest.cc
render_widget_host_impl.ccrender_widget_host_impl.hrender_widget_host_unittest.ccrender_widget_host_view_android.ccrender_widget_host_view_android.hrender_widget_host_view_base.hrender_widget_host_view_mac_unittest.mmcommon
content_common.gypirenderer
ipc
@ -18,6 +18,7 @@ struct LatencyInfo;
|
||||
namespace content {
|
||||
|
||||
class OverscrollController;
|
||||
struct DidOverscrollParams;
|
||||
|
||||
class CONTENT_EXPORT InputRouterClient {
|
||||
public:
|
||||
@ -56,6 +57,8 @@ class CONTENT_EXPORT InputRouterClient {
|
||||
// of the call to Flush. The call will typically be asynchronous with
|
||||
// respect to the call to |Flush| on the InputRouter.
|
||||
virtual void DidFlush() = 0;
|
||||
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) = 0;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -270,6 +270,7 @@ bool InputRouterImpl::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(InputRouterImpl, message)
|
||||
IPC_MESSAGE_HANDLER(InputHostMsg_HandleInputEvent_ACK, OnInputEventAck)
|
||||
IPC_MESSAGE_HANDLER(InputHostMsg_DidOverscroll, OnDidOverscroll)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_MoveCaret_ACK, OnMsgMoveCaretAck)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectRange_ACK, OnSelectRangeAck)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_HasTouchEventHandlers,
|
||||
@ -486,16 +487,21 @@ void InputRouterImpl::SendSyntheticWheelEventForPinch(
|
||||
MouseWheelEventWithLatencyInfo(wheelEvent, pinch_event.latency), true));
|
||||
}
|
||||
|
||||
void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type,
|
||||
InputEventAckState ack_result,
|
||||
const ui::LatencyInfo& latency_info) {
|
||||
void InputRouterImpl::OnInputEventAck(
|
||||
const InputHostMsg_HandleInputEvent_ACK_Params& ack) {
|
||||
client_->DecrementInFlightEventCount();
|
||||
|
||||
// Log the time delta for processing an input event.
|
||||
TimeDelta delta = TimeTicks::Now() - input_event_start_time_;
|
||||
UMA_HISTOGRAM_TIMES("MPArch.IIR_InputEventDelta", delta);
|
||||
|
||||
ProcessInputEventAck(event_type, ack_result, latency_info, RENDERER);
|
||||
if (ack.overscroll) {
|
||||
DCHECK(ack.type == WebInputEvent::MouseWheel ||
|
||||
ack.type == WebInputEvent::GestureScrollUpdate);
|
||||
OnDidOverscroll(*ack.overscroll);
|
||||
}
|
||||
|
||||
ProcessInputEventAck(ack.type, ack.state, ack.latency, RENDERER);
|
||||
// WARNING: |this| may be deleted at this point.
|
||||
|
||||
// This is used only for testing, and the other end does not use the
|
||||
@ -505,13 +511,17 @@ void InputRouterImpl::OnInputEventAck(WebInputEvent::Type event_type,
|
||||
// (ProcessInputEventAck) method, but not on other platforms; using
|
||||
// 'void' instead is just as safe (since NotificationSource
|
||||
// is not actually typesafe) and avoids this error.
|
||||
int type = static_cast<int>(event_type);
|
||||
int type = static_cast<int>(ack.type);
|
||||
NotificationService::current()->Notify(
|
||||
NOTIFICATION_RENDER_WIDGET_HOST_DID_RECEIVE_INPUT_EVENT_ACK,
|
||||
Source<void>(this),
|
||||
Details<int>(&type));
|
||||
}
|
||||
|
||||
void InputRouterImpl::OnDidOverscroll(const DidOverscrollParams& params) {
|
||||
client_->DidOverscroll(params);
|
||||
}
|
||||
|
||||
void InputRouterImpl::OnMsgMoveCaretAck() {
|
||||
move_caret_pending_ = false;
|
||||
if (next_move_caret_)
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "content/common/input/input_event_stream_validator.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.h"
|
||||
|
||||
struct InputHostMsg_HandleInputEvent_ACK_Params;
|
||||
|
||||
namespace IPC {
|
||||
class Sender;
|
||||
}
|
||||
@ -32,6 +34,7 @@ class InputAckHandler;
|
||||
class InputRouterClient;
|
||||
class OverscrollController;
|
||||
class RenderWidgetHostImpl;
|
||||
struct DidOverscrollParams;
|
||||
|
||||
// A default implementation for browser input event routing.
|
||||
class CONTENT_EXPORT InputRouterImpl
|
||||
@ -146,9 +149,8 @@ private:
|
||||
const GestureEventWithLatencyInfo& pinch_event);
|
||||
|
||||
// IPC message handlers
|
||||
void OnInputEventAck(blink::WebInputEvent::Type event_type,
|
||||
InputEventAckState ack_result,
|
||||
const ui::LatencyInfo& latency_info);
|
||||
void OnInputEventAck(const InputHostMsg_HandleInputEvent_ACK_Params& ack);
|
||||
void OnDidOverscroll(const DidOverscrollParams& params);
|
||||
void OnMsgMoveCaretAck();
|
||||
void OnSelectRangeAck();
|
||||
void OnHasTouchEventHandlers(bool has_handlers);
|
||||
|
@ -82,6 +82,7 @@ class NullInputRouterClient : public InputRouterClient {
|
||||
}
|
||||
virtual void DidFlush() OVERRIDE {}
|
||||
virtual void SetNeedsFlush() OVERRIDE {}
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE {}
|
||||
};
|
||||
|
||||
class NullIPCSender : public IPC::Sender {
|
||||
@ -237,8 +238,10 @@ class InputRouterImplPerfTest : public testing::Test {
|
||||
InputEventAckState ack_result) {
|
||||
if (WebInputEventTraits::IgnoresAckDisposition(event))
|
||||
return;
|
||||
InputHostMsg_HandleInputEvent_ACK response(
|
||||
0, event.type, ack_result, ui::LatencyInfo());
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = event.type;
|
||||
ack.state = ack_result;
|
||||
InputHostMsg_HandleInputEvent_ACK response(0, ack);
|
||||
input_router_->OnMessageReceived(response);
|
||||
}
|
||||
|
||||
|
@ -293,10 +293,10 @@ class InputRouterImplTest : public testing::Test {
|
||||
|
||||
void SendInputEventACK(blink::WebInputEvent::Type type,
|
||||
InputEventAckState ack_result) {
|
||||
scoped_ptr<IPC::Message> response(
|
||||
new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
|
||||
ui::LatencyInfo()));
|
||||
input_router_->OnMessageReceived(*response);
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = type;
|
||||
ack.state = ack_result;
|
||||
input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
|
||||
}
|
||||
|
||||
InputRouterImpl* input_router() const {
|
||||
@ -1653,4 +1653,42 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
|
||||
EXPECT_EQ(0, client_->in_flight_event_count());
|
||||
}
|
||||
|
||||
// Test proper routing of overscroll notifications received either from
|
||||
// event acks or from |DidOverscroll| IPC messages.
|
||||
TEST_F(InputRouterImplTest, OverscrollDispatch) {
|
||||
DidOverscrollParams overscroll;
|
||||
overscroll.accumulated_overscroll = gfx::Vector2dF(-14, 14);
|
||||
overscroll.latest_overscroll_delta = gfx::Vector2dF(-7, 0);
|
||||
overscroll.current_fling_velocity = gfx::Vector2dF(-1, 0);
|
||||
|
||||
input_router_->OnMessageReceived(InputHostMsg_DidOverscroll(0, overscroll));
|
||||
DidOverscrollParams client_overscroll = client_->GetAndResetOverscroll();
|
||||
EXPECT_EQ(overscroll.accumulated_overscroll,
|
||||
client_overscroll.accumulated_overscroll);
|
||||
EXPECT_EQ(overscroll.latest_overscroll_delta,
|
||||
client_overscroll.latest_overscroll_delta);
|
||||
EXPECT_EQ(overscroll.current_fling_velocity,
|
||||
client_overscroll.current_fling_velocity);
|
||||
|
||||
DidOverscrollParams wheel_overscroll;
|
||||
wheel_overscroll.accumulated_overscroll = gfx::Vector2dF(7, -7);
|
||||
wheel_overscroll.latest_overscroll_delta = gfx::Vector2dF(3, 0);
|
||||
wheel_overscroll.current_fling_velocity = gfx::Vector2dF(1, 0);
|
||||
|
||||
SimulateWheelEvent(3, 0, 0, false);
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = WebInputEvent::MouseWheel;
|
||||
ack.state = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
|
||||
ack.overscroll.reset(new DidOverscrollParams(wheel_overscroll));
|
||||
input_router_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
|
||||
|
||||
client_overscroll = client_->GetAndResetOverscroll();
|
||||
EXPECT_EQ(wheel_overscroll.accumulated_overscroll,
|
||||
client_overscroll.accumulated_overscroll);
|
||||
EXPECT_EQ(wheel_overscroll.latest_overscroll_delta,
|
||||
client_overscroll.latest_overscroll_delta);
|
||||
EXPECT_EQ(wheel_overscroll.current_fling_velocity,
|
||||
client_overscroll.current_fling_velocity);
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -50,6 +50,22 @@ void MockInputRouterClient::OnHasTouchEventHandlers(
|
||||
has_touch_handler_ = has_handlers;
|
||||
}
|
||||
|
||||
OverscrollController* MockInputRouterClient::GetOverscrollController() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MockInputRouterClient::DidFlush() {
|
||||
++did_flush_called_count_;
|
||||
}
|
||||
|
||||
void MockInputRouterClient::DidOverscroll(const DidOverscrollParams& params) {
|
||||
overscroll_ = params;
|
||||
}
|
||||
|
||||
void MockInputRouterClient::SetNeedsFlush() {
|
||||
set_needs_flush_called_ = true;
|
||||
}
|
||||
|
||||
bool MockInputRouterClient::GetAndResetFilterEventCalled() {
|
||||
bool filter_input_event_called = filter_input_event_called_;
|
||||
filter_input_event_called_ = false;
|
||||
@ -62,16 +78,10 @@ size_t MockInputRouterClient::GetAndResetDidFlushCount() {
|
||||
return did_flush_called_count;
|
||||
}
|
||||
|
||||
OverscrollController* MockInputRouterClient::GetOverscrollController() const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MockInputRouterClient::DidFlush() {
|
||||
++did_flush_called_count_;
|
||||
}
|
||||
|
||||
void MockInputRouterClient::SetNeedsFlush() {
|
||||
set_needs_flush_called_ = true;
|
||||
DidOverscrollParams MockInputRouterClient::GetAndResetOverscroll() {
|
||||
DidOverscrollParams overscroll;
|
||||
std::swap(overscroll_, overscroll);
|
||||
return overscroll;
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "content/browser/renderer_host/input/input_router_client.h"
|
||||
#include "content/common/input/did_overscroll_params.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
@ -27,10 +28,12 @@ class MockInputRouterClient : public InputRouterClient {
|
||||
virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
|
||||
virtual OverscrollController* GetOverscrollController() const OVERRIDE;
|
||||
virtual void DidFlush() OVERRIDE;
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
|
||||
virtual void SetNeedsFlush() OVERRIDE;
|
||||
|
||||
bool GetAndResetFilterEventCalled();
|
||||
size_t GetAndResetDidFlushCount();
|
||||
DidOverscrollParams GetAndResetOverscroll();
|
||||
|
||||
void set_input_router(InputRouter* input_router) {
|
||||
input_router_ = input_router;
|
||||
@ -59,6 +62,8 @@ class MockInputRouterClient : public InputRouterClient {
|
||||
|
||||
size_t did_flush_called_count_;
|
||||
bool set_needs_flush_called_;
|
||||
|
||||
DidOverscrollParams overscroll_;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -112,8 +112,8 @@ class InputEventMessageFilter : public BrowserMessageFilter {
|
||||
if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
|
||||
InputHostMsg_HandleInputEvent_ACK::Param params;
|
||||
InputHostMsg_HandleInputEvent_ACK::Read(&message, ¶ms);
|
||||
WebInputEvent::Type type = params.a;
|
||||
InputEventAckState ack = params.b;
|
||||
WebInputEvent::Type type = params.a.type;
|
||||
InputEventAckState ack = params.a.state;
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(&InputEventMessageFilter::ReceivedEventAck,
|
||||
this, type, ack));
|
||||
|
@ -1828,6 +1828,11 @@ void RenderWidgetHostImpl::DidFlush() {
|
||||
view_->OnDidFlushInput();
|
||||
}
|
||||
|
||||
void RenderWidgetHostImpl::DidOverscroll(const DidOverscrollParams& params) {
|
||||
if (view_)
|
||||
view_->DidOverscroll(params);
|
||||
}
|
||||
|
||||
void RenderWidgetHostImpl::OnKeyboardEventAck(
|
||||
const NativeWebKeyboardEvent& event,
|
||||
InputEventAckState ack_result) {
|
||||
|
@ -685,6 +685,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
|
||||
virtual void OnHasTouchEventHandlers(bool has_handlers) OVERRIDE;
|
||||
virtual OverscrollController* GetOverscrollController() const OVERRIDE;
|
||||
virtual void DidFlush() OVERRIDE;
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
|
||||
|
||||
// InputAckHandler
|
||||
virtual void OnKeyboardEventAck(const NativeWebKeyboardEvent& event,
|
||||
|
@ -638,10 +638,10 @@ class RenderWidgetHostTest : public testing::Test {
|
||||
|
||||
void SendInputEventACK(WebInputEvent::Type type,
|
||||
InputEventAckState ack_result) {
|
||||
scoped_ptr<IPC::Message> response(
|
||||
new InputHostMsg_HandleInputEvent_ACK(0, type, ack_result,
|
||||
ui::LatencyInfo()));
|
||||
host_->OnMessageReceived(*response);
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = type;
|
||||
ack.state = ack_result;
|
||||
host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack));
|
||||
}
|
||||
|
||||
double GetNextSimulatedEventTimeSeconds() {
|
||||
|
@ -216,7 +216,6 @@ bool RenderWidgetHostViewAndroid::OnMessageReceived(
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_StartContentIntent, OnStartContentIntent)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeBodyBackgroundColor,
|
||||
OnDidChangeBodyBackgroundColor)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnDidOverscroll)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_SetNeedsBeginFrame,
|
||||
OnSetNeedsBeginFrame)
|
||||
IPC_MESSAGE_HANDLER(ViewHostMsg_TextInputStateChanged,
|
||||
@ -518,25 +517,6 @@ void RenderWidgetHostViewAndroid::OnDidChangeBodyBackgroundColor(
|
||||
content_view_core_->OnBackgroundColorChanged(color);
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::OnDidOverscroll(
|
||||
const DidOverscrollParams& params) {
|
||||
if (!content_view_core_ || !layer_ || !is_showing_)
|
||||
return;
|
||||
|
||||
const float device_scale_factor = content_view_core_->GetDpiScale();
|
||||
if (overscroll_effect_->OnOverscrolled(
|
||||
content_view_core_->GetLayer(),
|
||||
base::TimeTicks::Now(),
|
||||
gfx::ScaleVector2d(params.accumulated_overscroll,
|
||||
device_scale_factor),
|
||||
gfx::ScaleVector2d(params.latest_overscroll_delta,
|
||||
device_scale_factor),
|
||||
gfx::ScaleVector2d(params.current_fling_velocity,
|
||||
device_scale_factor))) {
|
||||
SetNeedsAnimate();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::OnSetNeedsBeginFrame(bool enabled) {
|
||||
if (enabled == needs_begin_frame_)
|
||||
return;
|
||||
@ -1242,6 +1222,25 @@ SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
|
||||
return cached_background_color_;
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::DidOverscroll(
|
||||
const DidOverscrollParams& params) {
|
||||
if (!content_view_core_ || !layer_ || !is_showing_)
|
||||
return;
|
||||
|
||||
const float device_scale_factor = content_view_core_->GetDpiScale();
|
||||
if (overscroll_effect_->OnOverscrolled(
|
||||
content_view_core_->GetLayer(),
|
||||
base::TimeTicks::Now(),
|
||||
gfx::ScaleVector2d(params.accumulated_overscroll,
|
||||
device_scale_factor),
|
||||
gfx::ScaleVector2d(params.latest_overscroll_delta,
|
||||
device_scale_factor),
|
||||
gfx::ScaleVector2d(params.current_fling_velocity,
|
||||
device_scale_factor))) {
|
||||
SetNeedsAnimate();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewAndroid::DidStopFlinging() {
|
||||
if (content_view_core_)
|
||||
content_view_core_->DidStopFlinging();
|
||||
|
@ -158,6 +158,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
|
||||
virtual void OnSwapCompositorFrame(
|
||||
uint32 output_surface_id,
|
||||
scoped_ptr<cc::CompositorFrame> frame) OVERRIDE;
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE;
|
||||
virtual void DidStopFlinging() OVERRIDE;
|
||||
virtual void ShowDisambiguationPopup(const gfx::Rect& target_rect,
|
||||
const SkBitmap& zoomed_bitmap) OVERRIDE;
|
||||
@ -199,7 +200,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
|
||||
|
||||
void OnTextInputStateChanged(const ViewHostMsg_TextInputState_Params& params);
|
||||
void OnDidChangeBodyBackgroundColor(SkColor color);
|
||||
void OnDidOverscroll(const DidOverscrollParams& params);
|
||||
void OnStartContentIntent(const GURL& content_url);
|
||||
void OnSetNeedsBeginFrame(bool enabled);
|
||||
void OnSmartClipDataExtracted(const base::string16& result);
|
||||
|
@ -53,8 +53,9 @@ class BrowserAccessibilityManager;
|
||||
class SyntheticGesture;
|
||||
class SyntheticGestureTarget;
|
||||
class WebCursor;
|
||||
struct WebPluginGeometry;
|
||||
struct DidOverscrollParams;
|
||||
struct NativeWebKeyboardEvent;
|
||||
struct WebPluginGeometry;
|
||||
|
||||
// Basic implementation shared by concrete RenderWidgetHostView subclasses.
|
||||
class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
|
||||
@ -171,6 +172,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
|
||||
virtual void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
|
||||
InputEventAckState ack_result) {}
|
||||
|
||||
virtual void DidOverscroll(const DidOverscrollParams& params) {}
|
||||
|
||||
virtual void DidStopFlinging() {}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -717,9 +717,11 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
|
||||
ASSERT_EQ(1U, process_host->sink().message_count());
|
||||
|
||||
// Send an ACK for the first wheel event, so that the queue will be flushed.
|
||||
scoped_ptr<IPC::Message> response(new InputHostMsg_HandleInputEvent_ACK(
|
||||
0, blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED,
|
||||
ui::LatencyInfo()));
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = blink::WebInputEvent::MouseWheel;
|
||||
ack.state = INPUT_EVENT_ACK_STATE_CONSUMED;
|
||||
scoped_ptr<IPC::Message> response(
|
||||
new InputHostMsg_HandleInputEvent_ACK(0, ack));
|
||||
host->OnMessageReceived(*response);
|
||||
|
||||
// Post the NSEventPhaseEnded wheel event to NSApp and check whether the
|
||||
@ -761,9 +763,11 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
|
||||
process_host->sink().ClearMessages();
|
||||
|
||||
// Indicate that the wheel event was unhandled.
|
||||
scoped_ptr<IPC::Message> response1(new InputHostMsg_HandleInputEvent_ACK(0,
|
||||
blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
|
||||
ui::LatencyInfo()));
|
||||
InputHostMsg_HandleInputEvent_ACK_Params unhandled_ack;
|
||||
unhandled_ack.type = blink::WebInputEvent::MouseWheel;
|
||||
unhandled_ack.state = INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
|
||||
scoped_ptr<IPC::Message> response1(
|
||||
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
|
||||
host->OnMessageReceived(*response1);
|
||||
|
||||
// Check that the view delegate got an unhandled wheel event.
|
||||
@ -776,9 +780,8 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
|
||||
ASSERT_EQ(1U, process_host->sink().message_count());
|
||||
|
||||
// Indicate that the wheel event was also unhandled.
|
||||
scoped_ptr<IPC::Message> response2(new InputHostMsg_HandleInputEvent_ACK(0,
|
||||
blink::WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
|
||||
ui::LatencyInfo()));
|
||||
scoped_ptr<IPC::Message> response2(
|
||||
new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
|
||||
host->OnMessageReceived(*response2);
|
||||
|
||||
// Check that the view delegate ignored the empty unhandled wheel event.
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "content/common/content_export.h"
|
||||
#include "content/common/content_param_traits.h"
|
||||
#include "content/common/edit_command.h"
|
||||
#include "content/common/input/did_overscroll_params.h"
|
||||
#include "content/common/input/input_event.h"
|
||||
#include "content/common/input/input_event_ack_state.h"
|
||||
#include "content/common/input/input_param_traits.h"
|
||||
@ -25,6 +26,7 @@
|
||||
#include "ui/events/latency_info.h"
|
||||
#include "ui/gfx/point.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
#include "ui/gfx/vector2d_f.h"
|
||||
|
||||
#undef IPC_MESSAGE_EXPORT
|
||||
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
|
||||
@ -51,6 +53,12 @@ IPC_ENUM_TRAITS_VALIDATE(content::TouchAction, (
|
||||
(!(value & content::TOUCH_ACTION_PINCH_ZOOM) ||
|
||||
(value == content::TOUCH_ACTION_MANIPULATION))))
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(content::DidOverscrollParams)
|
||||
IPC_STRUCT_TRAITS_MEMBER(accumulated_overscroll)
|
||||
IPC_STRUCT_TRAITS_MEMBER(latest_overscroll_delta)
|
||||
IPC_STRUCT_TRAITS_MEMBER(current_fling_velocity)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
|
||||
IPC_STRUCT_TRAITS_MEMBER(name)
|
||||
IPC_STRUCT_TRAITS_MEMBER(value)
|
||||
@ -88,6 +96,14 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticTapGestureParams)
|
||||
IPC_STRUCT_TRAITS_MEMBER(duration_ms)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_BEGIN(InputHostMsg_HandleInputEvent_ACK_Params)
|
||||
IPC_STRUCT_MEMBER(blink::WebInputEvent::Type, type)
|
||||
IPC_STRUCT_MEMBER(content::InputEventAckState, state)
|
||||
IPC_STRUCT_MEMBER(ui::LatencyInfo, latency)
|
||||
// TODO(jdduke): Use Optional<T> type to avoid heap alloc, crbug.com/375002.
|
||||
IPC_STRUCT_MEMBER(scoped_ptr<content::DidOverscrollParams>, overscroll)
|
||||
IPC_STRUCT_END()
|
||||
|
||||
// Sends an input event to the render widget.
|
||||
IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
|
||||
IPC::WebInputEventPointer /* event */,
|
||||
@ -177,10 +193,8 @@ IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted);
|
||||
// Messages sent from the renderer to the browser.
|
||||
|
||||
// Acknowledges receipt of a InputMsg_HandleInputEvent message.
|
||||
IPC_MESSAGE_ROUTED3(InputHostMsg_HandleInputEvent_ACK,
|
||||
blink::WebInputEvent::Type,
|
||||
content::InputEventAckState /* ack_result */,
|
||||
ui::LatencyInfo /* latency_info */)
|
||||
IPC_MESSAGE_ROUTED1(InputHostMsg_HandleInputEvent_ACK,
|
||||
InputHostMsg_HandleInputEvent_ACK_Params)
|
||||
|
||||
IPC_MESSAGE_ROUTED1(InputHostMsg_QueueSyntheticGesture,
|
||||
content::SyntheticGesturePacket)
|
||||
@ -189,6 +203,11 @@ IPC_MESSAGE_ROUTED1(InputHostMsg_QueueSyntheticGesture,
|
||||
IPC_MESSAGE_ROUTED1(InputHostMsg_SetTouchAction,
|
||||
content::TouchAction /* touch_action */)
|
||||
|
||||
// Sent by the compositor when input scroll events are dropped due to bounds
|
||||
// restrictions on the root scroll offset.
|
||||
IPC_MESSAGE_ROUTED1(InputHostMsg_DidOverscroll,
|
||||
content::DidOverscrollParams /* params */)
|
||||
|
||||
// Adding a new message? Stick to the sort order above: first platform
|
||||
// independent InputMsg, then ifdefs for platform specific InputMsg, then
|
||||
// platform independent InputHostMsg, then ifdefs for platform specific
|
||||
|
@ -14,8 +14,6 @@
|
||||
#include "content/common/content_export.h"
|
||||
#include "content/common/content_param_traits.h"
|
||||
#include "content/common/cookie_data.h"
|
||||
#include "content/common/input/did_overscroll_params.h"
|
||||
#include "content/common/input/input_event_ack_state.h"
|
||||
#include "content/common/navigation_gesture.h"
|
||||
#include "content/common/pepper_renderer_instance_data.h"
|
||||
#include "content/common/view_message_enums.h"
|
||||
@ -154,12 +152,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::DateTimeSuggestion)
|
||||
IPC_STRUCT_TRAITS_MEMBER(label)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(content::DidOverscrollParams)
|
||||
IPC_STRUCT_TRAITS_MEMBER(accumulated_overscroll)
|
||||
IPC_STRUCT_TRAITS_MEMBER(latest_overscroll_delta)
|
||||
IPC_STRUCT_TRAITS_MEMBER(current_fling_velocity)
|
||||
IPC_STRUCT_TRAITS_END()
|
||||
|
||||
IPC_STRUCT_TRAITS_BEGIN(content::FaviconURL)
|
||||
IPC_STRUCT_TRAITS_MEMBER(icon_url)
|
||||
IPC_STRUCT_TRAITS_MEMBER(icon_type)
|
||||
@ -1504,11 +1496,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_SwapCompositorFrame,
|
||||
uint32 /* output_surface_id */,
|
||||
cc::CompositorFrame /* frame */)
|
||||
|
||||
// Sent by the compositor when input scroll events are dropped due to bounds
|
||||
// restricions on the root scroll offset.
|
||||
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidOverscroll,
|
||||
content::DidOverscrollParams /* params */)
|
||||
|
||||
// Sent by the compositor when a flinging animation is stopped.
|
||||
IPC_MESSAGE_ROUTED0(ViewHostMsg_DidStopFlinging)
|
||||
|
||||
|
@ -305,7 +305,6 @@
|
||||
'common/input/gesture_event_stream_validator.h',
|
||||
'common/input/input_event.cc',
|
||||
'common/input/input_event.h',
|
||||
'common/input/input_event_ack_state.h',
|
||||
'common/input/input_event_stream_validator.cc',
|
||||
'common/input/input_event_stream_validator.h',
|
||||
'common/input/input_param_traits.cc',
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "content/renderer/input/input_event_filter.h"
|
||||
|
||||
#include "base/auto_reset.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/debug/trace_event.h"
|
||||
@ -45,7 +46,8 @@ InputEventFilter::InputEventFilter(
|
||||
main_listener_(main_listener),
|
||||
sender_(NULL),
|
||||
target_loop_(target_loop),
|
||||
overscroll_notifications_enabled_(false) {
|
||||
overscroll_notifications_enabled_(false),
|
||||
current_overscroll_params_(NULL) {
|
||||
DCHECK(target_loop_.get());
|
||||
overscroll_notifications_enabled_ =
|
||||
CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
@ -73,11 +75,18 @@ void InputEventFilter::DidOverscroll(int routing_id,
|
||||
if (!overscroll_notifications_enabled_)
|
||||
return;
|
||||
|
||||
SendMessage(ViewHostMsg_DidOverscroll(routing_id, params));
|
||||
if (current_overscroll_params_) {
|
||||
current_overscroll_params_->reset(new DidOverscrollParams(params));
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessage(scoped_ptr<IPC::Message>(
|
||||
new InputHostMsg_DidOverscroll(routing_id, params)));
|
||||
}
|
||||
|
||||
void InputEventFilter::DidStopFlinging(int routing_id) {
|
||||
SendMessage(ViewHostMsg_DidStopFlinging(routing_id));
|
||||
SendMessage(
|
||||
scoped_ptr<IPC::Message>(new ViewHostMsg_DidStopFlinging(routing_id)));
|
||||
}
|
||||
|
||||
void InputEventFilter::OnFilterAdded(IPC::Channel* channel) {
|
||||
@ -121,6 +130,7 @@ bool InputEventFilter::OnMessageReceived(const IPC::Message& message) {
|
||||
}
|
||||
|
||||
InputEventFilter::~InputEventFilter() {
|
||||
DCHECK(!current_overscroll_params_);
|
||||
}
|
||||
|
||||
void InputEventFilter::ForwardToMainListener(const IPC::Message& message) {
|
||||
@ -154,9 +164,17 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
|
||||
bool is_keyboard_shortcut = params.c;
|
||||
DCHECK(event);
|
||||
|
||||
InputEventAckState ack = handler_.Run(routing_id, event, &latency_info);
|
||||
// Intercept |DidOverscroll| notifications, bundling any triggered overscroll
|
||||
// response with the input event ack.
|
||||
scoped_ptr<DidOverscrollParams> overscroll_params;
|
||||
base::AutoReset<scoped_ptr<DidOverscrollParams>*>
|
||||
auto_reset_current_overscroll_params(¤t_overscroll_params_,
|
||||
&overscroll_params);
|
||||
|
||||
if (ack == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
|
||||
InputEventAckState ack_state = handler_.Run(routing_id, event, &latency_info);
|
||||
|
||||
if (ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
|
||||
DCHECK(!overscroll_params);
|
||||
TRACE_EVENT_INSTANT0(
|
||||
"input",
|
||||
"InputEventFilter::ForwardToHandler::ForwardToMainListener",
|
||||
@ -170,33 +188,34 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WebInputEventTraits::IgnoresAckDisposition(*event))
|
||||
SendACK(event->type, ack, latency_info, routing_id);
|
||||
if (WebInputEventTraits::IgnoresAckDisposition(*event))
|
||||
return;
|
||||
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = event->type;
|
||||
ack.state = ack_state;
|
||||
ack.latency = latency_info;
|
||||
ack.overscroll = overscroll_params.Pass();
|
||||
SendMessage(scoped_ptr<IPC::Message>(
|
||||
new InputHostMsg_HandleInputEvent_ACK(routing_id, ack)));
|
||||
}
|
||||
|
||||
void InputEventFilter::SendACK(blink::WebInputEvent::Type type,
|
||||
InputEventAckState ack_result,
|
||||
const ui::LatencyInfo& latency_info,
|
||||
int routing_id) {
|
||||
SendMessage(InputHostMsg_HandleInputEvent_ACK(
|
||||
routing_id, type, ack_result, latency_info));
|
||||
}
|
||||
|
||||
void InputEventFilter::SendMessage(const IPC::Message& message) {
|
||||
void InputEventFilter::SendMessage(scoped_ptr<IPC::Message> message) {
|
||||
DCHECK(target_loop_->BelongsToCurrentThread());
|
||||
|
||||
io_loop_->PostTask(
|
||||
FROM_HERE,
|
||||
base::Bind(&InputEventFilter::SendMessageOnIOThread, this, message));
|
||||
io_loop_->PostTask(FROM_HERE,
|
||||
base::Bind(&InputEventFilter::SendMessageOnIOThread,
|
||||
this,
|
||||
base::Passed(&message)));
|
||||
}
|
||||
|
||||
void InputEventFilter::SendMessageOnIOThread(const IPC::Message& message) {
|
||||
void InputEventFilter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
|
||||
DCHECK(io_loop_->BelongsToCurrentThread());
|
||||
|
||||
if (!sender_)
|
||||
return; // Filter was removed.
|
||||
|
||||
sender_->Send(new IPC::Message(message));
|
||||
sender_->Send(message.release());
|
||||
}
|
||||
|
||||
} // namespace content
|
||||
|
@ -70,12 +70,8 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
|
||||
|
||||
void ForwardToMainListener(const IPC::Message& message);
|
||||
void ForwardToHandler(const IPC::Message& message);
|
||||
void SendACK(blink::WebInputEvent::Type type,
|
||||
InputEventAckState ack_result,
|
||||
const ui::LatencyInfo& latency_info,
|
||||
int routing_id);
|
||||
void SendMessage(const IPC::Message& message);
|
||||
void SendMessageOnIOThread(const IPC::Message& message);
|
||||
void SendMessage(scoped_ptr<IPC::Message> message);
|
||||
void SendMessageOnIOThread(scoped_ptr<IPC::Message> message);
|
||||
|
||||
scoped_refptr<base::MessageLoopProxy> main_loop_;
|
||||
IPC::Listener* main_listener_;
|
||||
@ -96,6 +92,12 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
|
||||
|
||||
// Specifies whether overscroll notifications are forwarded to the host.
|
||||
bool overscroll_notifications_enabled_;
|
||||
|
||||
// Used to intercept overscroll notifications while an event is being
|
||||
// dispatched. 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>* current_overscroll_params_;
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
|
@ -180,8 +180,8 @@ TEST_F(InputEventFilterTest, Basic) {
|
||||
|
||||
InputHostMsg_HandleInputEvent_ACK::Param params;
|
||||
EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms));
|
||||
WebInputEvent::Type event_type = params.a;
|
||||
InputEventAckState ack_result = params.b;
|
||||
WebInputEvent::Type event_type = params.a.type;
|
||||
InputEventAckState ack_result = params.a.state;
|
||||
|
||||
EXPECT_EQ(kEvents[i].type, event_type);
|
||||
EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
|
||||
@ -232,8 +232,8 @@ TEST_F(InputEventFilterTest, Basic) {
|
||||
|
||||
InputHostMsg_HandleInputEvent_ACK::Param params;
|
||||
EXPECT_TRUE(InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms));
|
||||
WebInputEvent::Type event_type = params.a;
|
||||
InputEventAckState ack_result = params.b;
|
||||
WebInputEvent::Type event_type = params.a.type;
|
||||
InputEventAckState ack_result = params.a.state;
|
||||
EXPECT_EQ(kEvents[i].type, event_type);
|
||||
EXPECT_EQ(ack_result, INPUT_EVENT_ACK_STATE_CONSUMED);
|
||||
}
|
||||
|
@ -1054,11 +1054,12 @@ void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
|
||||
TRACE_EVENT_SYNTHETIC_DELAY_END("blink.HandleInputEvent");
|
||||
|
||||
if (!WebInputEventTraits::IgnoresAckDisposition(*input_event)) {
|
||||
InputHostMsg_HandleInputEvent_ACK_Params ack;
|
||||
ack.type = input_event->type;
|
||||
ack.state = ack_result;
|
||||
ack.latency = swap_latency_info;
|
||||
scoped_ptr<IPC::Message> response(
|
||||
new InputHostMsg_HandleInputEvent_ACK(routing_id_,
|
||||
input_event->type,
|
||||
ack_result,
|
||||
swap_latency_info));
|
||||
new InputHostMsg_HandleInputEvent_ACK(routing_id_, ack));
|
||||
if (rate_limiting_wanted && event_type_can_be_rate_limited &&
|
||||
frame_pending && !is_hidden_) {
|
||||
// We want to rate limit the input events in this case, so we'll wait for
|
||||
|
@ -89,7 +89,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
|
||||
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
|
||||
InputHostMsg_HandleInputEvent_ACK::Param params;
|
||||
InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms);
|
||||
InputEventAckState ack_state = params.b;
|
||||
InputEventAckState ack_state = params.a.state;
|
||||
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
|
||||
widget->sink()->ClearMessages();
|
||||
|
||||
@ -103,7 +103,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
|
||||
message = widget->sink()->GetMessageAt(0);
|
||||
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
|
||||
InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms);
|
||||
ack_state = params.b;
|
||||
ack_state = params.a.state;
|
||||
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
|
||||
widget->sink()->ClearMessages();
|
||||
}
|
||||
@ -127,7 +127,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
|
||||
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
|
||||
InputHostMsg_HandleInputEvent_ACK::Param params;
|
||||
InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms);
|
||||
InputEventAckState ack_state = params.b;
|
||||
InputEventAckState ack_state = params.a.state;
|
||||
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, ack_state);
|
||||
widget->sink()->ClearMessages();
|
||||
|
||||
@ -138,7 +138,7 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
|
||||
message = widget->sink()->GetMessageAt(0);
|
||||
EXPECT_EQ(InputHostMsg_HandleInputEvent_ACK::ID, message->type());
|
||||
InputHostMsg_HandleInputEvent_ACK::Read(message, ¶ms);
|
||||
ack_state = params.b;
|
||||
ack_state = params.a.state;
|
||||
EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_state);
|
||||
widget->sink()->ClearMessages();
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "base/containers/small_map.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/format_macros.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/scoped_vector.h"
|
||||
#include "base/strings/string16.h"
|
||||
#include "base/strings/string_util.h"
|
||||
@ -706,6 +707,40 @@ struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
|
||||
}
|
||||
};
|
||||
|
||||
template <class P>
|
||||
struct ParamTraits<scoped_ptr<P> > {
|
||||
typedef scoped_ptr<P> param_type;
|
||||
static void Write(Message* m, const param_type& p) {
|
||||
bool valid = !!p;
|
||||
WriteParam(m, valid);
|
||||
if (valid)
|
||||
WriteParam(m, *p);
|
||||
}
|
||||
static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
|
||||
bool valid = false;
|
||||
if (!ReadParam(m, iter, &valid))
|
||||
return false;
|
||||
|
||||
if (!valid) {
|
||||
r->reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
param_type temp(new P());
|
||||
if (!ReadParam(m, iter, temp.get()))
|
||||
return false;
|
||||
|
||||
r->swap(temp);
|
||||
return true;
|
||||
}
|
||||
static void Log(const param_type& p, std::string* l) {
|
||||
if (p)
|
||||
LogParam(*p, l);
|
||||
else
|
||||
l->append("NULL");
|
||||
}
|
||||
};
|
||||
|
||||
// IPC types ParamTraits -------------------------------------------------------
|
||||
|
||||
// A ChannelHandle is basically a platform-inspecific wrapper around the
|
||||
|
Reference in New Issue
Block a user