Commit 6e463eb8 authored by jdduke@chromium.org's avatar jdduke@chromium.org

Add InputEvent and EventPacket types for batched input delivery

With the BufferedInputRouter, browser input events will be batched into packets
before being sent to the renderer.  Add a common InputEvent type that provides
id'ed carriage of either WebInputEvents or general IPC input messages. Also add
a composite EventPacket type for batched InputEvent transport and dispatch.

BUG=245499

Review URL: https://chromiumcodereview.appspot.com/19624005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221905 0039d316-1c4b-4281-b951-d872f2087c98
parent 82a192c7
aelias@chromium.org
nduca@chromium.org
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/event_packet.h"
#include "content/common/input/input_event.h"
namespace content {
EventPacket::EventPacket() : id_(0) {}
EventPacket::~EventPacket() {}
bool EventPacket::Add(scoped_ptr<InputEvent> event) {
if (!event || !event->valid())
return false;
events_.push_back(event.release());
return true;
}
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_EVENT_PACKET_H_
#define CONTENT_COMMON_INPUT_EVENT_PACKET_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "content/common/content_export.h"
namespace content {
class InputEvent;
// An id'ed sequence of InputEvents.
class CONTENT_EXPORT EventPacket {
public:
typedef ScopedVector<InputEvent> InputEvents;
EventPacket();
~EventPacket();
// Only a non-NULL and valid |event| will be accepted and added to the packet.
// Returns true if |event| was added, and false otherwise.
bool Add(scoped_ptr<InputEvent> event);
void set_id(int64 id) { id_ = id; }
int64 id() const { return id_; }
// Accessor functions for convenience.
bool empty() const { return events_.empty(); }
size_t size() const { return events_.size(); }
InputEvents::const_iterator begin() const { return events_.end(); }
InputEvents::const_iterator end() const { return events_.end(); }
const InputEvents& events() const { return events_; }
protected:
int64 id_;
InputEvents events_;
private:
DISALLOW_COPY_AND_ASSIGN(EventPacket);
};
} // namespace content
#endif // CONTENT_COMMON_INPUT_EVENT_PACKET_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/input_event.h"
#include "base/logging.h"
namespace content {
InputEvent::InputEvent() : id_(0) {}
InputEvent::~InputEvent() {}
scoped_ptr<InputEvent> InputEvent::Create(int64 id,
scoped_ptr<Payload> payload) {
scoped_ptr<InputEvent> event(new InputEvent());
event->Initialize(id, payload.Pass());
return event.Pass();
}
bool InputEvent::Initialize(int64 id, scoped_ptr<Payload> payload) {
id_ = id;
payload_ = payload.Pass();
return valid();
}
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_INPUT_EVENT_H_
#define CONTENT_COMMON_INPUT_INPUT_EVENT_H_
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace content {
// An id'ed event that carries a specific input payload.
class CONTENT_EXPORT InputEvent {
public:
// Input data carried by the InputEvent.
class CONTENT_EXPORT Payload {
public:
enum Type {
IPC_MESSAGE,
WEB_INPUT_EVENT,
PAYLOAD_TYPE_MAX = WEB_INPUT_EVENT
};
virtual ~Payload() {}
virtual Type GetType() const = 0;
};
// A valid InputEvent has a non-zero |id| and a non-NULL |payload|.
static scoped_ptr<InputEvent> Create(int64 id, scoped_ptr<Payload> payload);
template <typename PayloadType>
static scoped_ptr<InputEvent> Create(int64 id,
scoped_ptr<PayloadType> payload) {
return Create(id, payload.template PassAs<Payload>());
}
InputEvent();
virtual ~InputEvent();
// Returns true if the initialized InputEvent is |valid()|, false otherwise.
bool Initialize(int64 id, scoped_ptr<Payload> payload);
int64 id() const { return id_; }
const Payload* payload() const { return payload_.get(); }
bool valid() const { return id() && payload(); }
protected:
InputEvent(int64 id, scoped_ptr<Payload> payload);
private:
int64 id_;
scoped_ptr<Payload> payload_;
DISALLOW_COPY_AND_ASSIGN(InputEvent);
};
} // namespace content
#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/input_event_disposition.h"
#include "base/logging.h"
namespace content {
InputEventDisposition ToDisposition(InputEventAckState ack_state,
bool main_thread,
bool prevent_default) {
if (main_thread) {
switch (ack_state) {
case INPUT_EVENT_ACK_STATE_CONSUMED:
return INPUT_EVENT_MAIN_THREAD_CONSUMED;
case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
return prevent_default ? INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED
: INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED;
case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
return INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS;
case INPUT_EVENT_ACK_STATE_UNKNOWN:
return INPUT_EVENT_UNHANDLED;
}
} else {
switch (ack_state) {
case INPUT_EVENT_ACK_STATE_CONSUMED:
return INPUT_EVENT_IMPL_THREAD_CONSUMED;
case INPUT_EVENT_ACK_STATE_NOT_CONSUMED:
return INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN;
case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS:
return INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS;
case INPUT_EVENT_ACK_STATE_UNKNOWN:
return INPUT_EVENT_UNHANDLED;
}
}
NOTREACHED();
return INPUT_EVENT_UNHANDLED;
}
InputEventAckState ToAckState(InputEventDisposition disposition) {
switch (disposition) {
case INPUT_EVENT_UNHANDLED:
return INPUT_EVENT_ACK_STATE_UNKNOWN;
case INPUT_EVENT_IMPL_THREAD_CONSUMED:
return INPUT_EVENT_ACK_STATE_CONSUMED;
case INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS:
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
case INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN:
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
case INPUT_EVENT_COULD_NOT_DELIVER:
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
case INPUT_EVENT_MAIN_THREAD_CONSUMED:
return INPUT_EVENT_ACK_STATE_CONSUMED;
case INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED:
return INPUT_EVENT_ACK_STATE_CONSUMED;
case INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED:
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
case INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS:
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
}
NOTREACHED();
return INPUT_EVENT_ACK_STATE_UNKNOWN;
}
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
#define CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
#include <vector>
#include "content/common/content_export.h"
#include "content/port/common/input_event_ack_state.h"
namespace content {
// Disposition of input events as they are handled and passed between the
// browser and renderer.
enum InputEventDisposition {
INPUT_EVENT_UNHANDLED,
INPUT_EVENT_COULD_NOT_DELIVER,
INPUT_EVENT_IMPL_THREAD_CONSUMED,
INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN,
INPUT_EVENT_IMPL_THREAD_NO_CONSUMER_EXISTS,
INPUT_EVENT_MAIN_THREAD_CONSUMED,
INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED,
INPUT_EVENT_MAIN_THREAD_NOT_PREVENT_DEFAULTED,
INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS,
INPUT_EVENT_DISPOSITION_MAX = INPUT_EVENT_MAIN_THREAD_NO_CONSUMER_EXISTS
};
typedef std::vector<InputEventDisposition> InputEventDispositions;
InputEventDisposition CONTENT_EXPORT ToDisposition(InputEventAckState ack,
bool main_thread,
bool prevent_default);
InputEventAckState CONTENT_EXPORT ToAckState(InputEventDisposition disposition);
} // namespace content
#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_DISPOSITION_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/input_param_traits.h"
#include "content/common/content_param_traits.h"
#include "content/common/input/input_event_disposition.h"
#include "content/common/input/ipc_input_event_payload.h"
#include "content/common/input/web_input_event_payload.h"
#include "content/common/input_messages.h"
namespace IPC {
namespace {
template <typename PayloadType>
scoped_ptr<content::InputEvent::Payload> ReadPayload(const Message* m,
PickleIterator* iter) {
scoped_ptr<PayloadType> event = PayloadType::Create();
if (!ReadParam(m, iter, event.get()))
return scoped_ptr<content::InputEvent::Payload>();
return event.template PassAs<content::InputEvent::Payload>();
}
} // namespace
void ParamTraits<content::EventPacket>::Write(Message* m, const param_type& p) {
WriteParam(m, p.id());
WriteParam(m, p.events());
}
bool ParamTraits<content::EventPacket>::Read(const Message* m,
PickleIterator* iter,
param_type* p) {
int64 id;
content::EventPacket::InputEvents events;
if (!ReadParam(m, iter, &id) ||
!ReadParam(m, iter, &events))
return false;
p->set_id(id);
bool events_added_successfully = true;
for (size_t i = 0; i < events.size(); ++i) {
// Take ownership of all events.
scoped_ptr<content::InputEvent> event(events[i]);
if (!events_added_successfully)
continue;
if (!p->Add(event.Pass()))
events_added_successfully = false;
}
events.weak_clear();
return events_added_successfully;
}
void ParamTraits<content::EventPacket>::Log(const param_type& p,
std::string* l) {
l->append("EventPacket((");
LogParam(p.id(), l);
l->append("), Events(");
LogParam(p.events(), l);
l->append("))");
}
void ParamTraits<content::InputEvent>::Write(Message* m, const param_type& p) {
WriteParam(m, p.id());
WriteParam(m, !!p.payload());
if (!p.valid())
return;
content::InputEvent::Payload::Type payload_type = p.payload()->GetType();
WriteParam(m, payload_type);
switch (payload_type) {
case content::InputEvent::Payload::IPC_MESSAGE:
WriteParam(m, *content::IPCInputEventPayload::Cast(p.payload()));
break;
case content::InputEvent::Payload::WEB_INPUT_EVENT:
WriteParam(m, *content::WebInputEventPayload::Cast(p.payload()));
break;
default:
break;
}
}
bool ParamTraits<content::InputEvent>::Read(const Message* m,
PickleIterator* iter,
param_type* p) {
int64 id;
bool has_payload = false;
content::InputEvent::Payload::Type payload_type;
if (!ReadParam(m, iter, &id) ||
!ReadParam(m, iter, &has_payload) ||
!id ||
!has_payload ||
!ReadParam(m, iter, &payload_type))
return false;
scoped_ptr<content::InputEvent::Payload> payload;
switch (payload_type) {
case content::InputEvent::Payload::IPC_MESSAGE:
payload = ReadPayload<content::IPCInputEventPayload>(m, iter);
break;
case content::InputEvent::Payload::WEB_INPUT_EVENT:
payload = ReadPayload<content::WebInputEventPayload>(m, iter);
break;
default:
NOTREACHED() << "Invalid InputEvent::Payload type.";
return false;
}
return p->Initialize(id, payload.Pass());
}
void ParamTraits<content::InputEvent>::Log(const param_type& p,
std::string* l) {
l->append("InputEvent((");
LogParam(p.id(), l);
l->append("), Payload (");
const content::InputEvent::Payload* payload = p.payload();
if (payload) {
switch (payload->GetType()) {
case content::InputEvent::Payload::IPC_MESSAGE:
LogParam(*content::IPCInputEventPayload::Cast(payload), l);
break;
case content::InputEvent::Payload::WEB_INPUT_EVENT:
LogParam(*content::WebInputEventPayload::Cast(payload), l);
break;
default:
NOTREACHED() << "Invalid InputEvent::Payload type.";
l->append("INVALID");
break;
}
} else {
l->append("NULL");
}
l->append("))");
}
void ParamTraits<content::WebInputEventPayload>::Write(Message* m,
const param_type& p) {
bool valid_web_event = !!p.web_event();
WriteParam(m, valid_web_event);
if (valid_web_event)
WriteParam(m, p.web_event());
WriteParam(m, p.latency_info());
WriteParam(m, p.is_keyboard_shortcut());
}
bool ParamTraits<content::WebInputEventPayload>::Read(const Message* m,
PickleIterator* iter,
param_type* p) {
bool valid_web_event;
WebInputEventPointer web_input_event_pointer;
ui::LatencyInfo latency_info;
bool is_keyboard_shortcut;
if (!ReadParam(m, iter, &valid_web_event) ||
!valid_web_event ||
!ReadParam(m, iter, &web_input_event_pointer) ||
!ReadParam(m, iter, &latency_info) ||
!ReadParam(m, iter, &is_keyboard_shortcut))
return false;
p->Initialize(*web_input_event_pointer, latency_info, is_keyboard_shortcut);
return true;
}
void ParamTraits<content::WebInputEventPayload>::Log(const param_type& p,
std::string* l) {
l->append("WebInputEventPayload(");
LogParam(p.web_event(), l);
l->append(", ");
LogParam(p.latency_info(), l);
l->append(", ");
LogParam(p.is_keyboard_shortcut(), l);
l->append(")");
}
} // namespace IPC
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file defines IPC::ParamTraits<> specializations for several
// input-related types that require manual serialiation code.
#ifndef CONTENT_COMMON_INPUT_INPUT_PARAM_TRAITS_H_
#define CONTENT_COMMON_INPUT_INPUT_PARAM_TRAITS_H_
#include "base/memory/scoped_ptr.h"
#include "content/common/content_param_traits_macros.h"
#include "content/common/input/event_packet.h"
#include "content/common/input/input_event.h"
#include "content/common/input/web_input_event_payload.h"
namespace IPC {
// TODO(jdduke): There should be a common copy of this utility somewhere...
// Move or remove appropriately.
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");
}
};
template <>
struct CONTENT_EXPORT ParamTraits<content::EventPacket> {
typedef content::EventPacket param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<content::InputEvent> {
typedef content::InputEvent param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<content::WebInputEventPayload> {
typedef content::WebInputEventPayload param_type;
static void Write(Message* m, const param_type& p);
static bool Read(const Message* m, PickleIterator* iter, param_type* r);
static void Log(const param_type& p, std::string* l);
};
} // namespace IPC
#endif // CONTENT_COMMON_INPUT_INPUT_PARAM_TRAITS_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/input_param_traits.h"
#include "content/common/input/event_packet.h"
#include "content/common/input/input_event.h"
#include "content/common/input/ipc_input_event_payload.h"
#include "content/common/input/web_input_event_payload.h"
#include "content/common/input_messages.h"
#include "ipc/ipc_message.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
namespace {
class InputParamTraitsTest : public testing::Test {
protected:
void Compare(const WebInputEventPayload* a, const WebInputEventPayload* b) {
EXPECT_EQ(!!a->web_event(), !!b->web_event());
if (a->web_event() && b->web_event()) {
const size_t a_size = a->web_event()->size;
ASSERT_EQ(a_size, b->web_event()->size);
EXPECT_EQ(0, memcmp(a->web_event(), b->web_event(), a_size));
}
EXPECT_EQ(a->latency_info().latency_components.size(),
b->latency_info().latency_components.size());
EXPECT_EQ(a->is_keyboard_shortcut(), b->is_keyboard_shortcut());
}
void Compare(const IPCInputEventPayload* a, const IPCInputEventPayload* b) {
EXPECT_EQ(!!a->message, !!b->message);
if (a->message && b->message) {
EXPECT_EQ(a->message->type(), b->message->type());
EXPECT_EQ(a->message->routing_id(), b->message->routing_id());
}
}
void Compare(const InputEvent::Payload* a, const InputEvent::Payload* b) {
ASSERT_EQ(!!a, !!b);
if (!a)
return;
switch (a->GetType()) {
case InputEvent::Payload::IPC_MESSAGE:
Compare(IPCInputEventPayload::Cast(a), IPCInputEventPayload::Cast(b));
break;
case InputEvent::Payload::WEB_INPUT_EVENT:
Compare(WebInputEventPayload::Cast(a), WebInputEventPayload::Cast(b));
default:
break;
}
}
void Compare(const InputEvent* a, const InputEvent* b) {
EXPECT_EQ(a->id(), b->id());
EXPECT_EQ(a->valid(), b->valid());
Compare(a->payload(), b->payload());
}
void Compare(const EventPacket* a, const EventPacket* b) {
EXPECT_EQ(a->id(), b->id());
ASSERT_EQ(a->size(), b->size());
for (size_t i = 0; i < a->size(); ++i)
Compare(a->events()[i], b->events()[i]);
}
void Verify(const EventPacket& packet_in) {
IPC::Message msg;
IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
EventPacket packet_out;
PickleIterator iter(msg);
EXPECT_TRUE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
Compare(&packet_in, &packet_out);
// Perform a sanity check that logging doesn't explode.
std::string packet_in_string;
IPC::ParamTraits<EventPacket>::Log(packet_in, &packet_in_string);
std::string packet_out_string;
IPC::ParamTraits<EventPacket>::Log(packet_out, &packet_out_string);
ASSERT_FALSE(packet_in_string.empty());
EXPECT_EQ(packet_in_string, packet_out_string);
}
};
TEST_F(InputParamTraitsTest, EventPacketEmpty) {
EventPacket packet_in;
IPC::Message msg;
IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
EventPacket packet_out;
PickleIterator iter(msg);
EXPECT_TRUE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
Compare(&packet_in, &packet_out);
}
TEST_F(InputParamTraitsTest, EventPacketUninitializedEvents) {
EventPacket packet_in;
packet_in.set_id(1);
packet_in.Add(InputEvent::Create(1, WebInputEventPayload::Create()));
packet_in.Add(InputEvent::Create(2, IPCInputEventPayload::Create()));
IPC::Message msg;
IPC::ParamTraits<EventPacket>::Write(&msg, packet_in);
EventPacket packet_out;
PickleIterator iter(msg);
EXPECT_FALSE(IPC::ParamTraits<EventPacket>::Read(&msg, &iter, &packet_out));
}
TEST_F(InputParamTraitsTest, EventPacketIPCEvents) {
EventPacket packet_in;
packet_in.set_id(1);
packet_in.Add(
InputEvent::Create(1,
IPCInputEventPayload::Create(
scoped_ptr<IPC::Message>(new InputMsg_Undo(1)))));
packet_in.Add(InputEvent::Create(
1,
IPCInputEventPayload::Create(
scoped_ptr<IPC::Message>(new InputMsg_SetFocus(2, true)))));
Verify(packet_in);
}
TEST_F(InputParamTraitsTest, EventPacketWebInputEvents) {
EventPacket packet_in;
packet_in.set_id(1);
ui::LatencyInfo latency;
int64 next_event_id = 1;
WebKit::WebKeyboardEvent key_event;
key_event.type = WebKit::WebInputEvent::RawKeyDown;
key_event.nativeKeyCode = 5;
packet_in.Add(InputEvent::Create(
++next_event_id, WebInputEventPayload::Create(key_event, latency, true)));
WebKit::WebMouseWheelEvent wheel_event;
wheel_event.type = WebKit::WebInputEvent::MouseWheel;
wheel_event.deltaX = 10;
latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_RWH_COMPONENT, 1, 1);
packet_in.Add(InputEvent::Create(
++next_event_id,
WebInputEventPayload::Create(wheel_event, latency, false)));
WebKit::WebMouseEvent mouse_event;
mouse_event.type = WebKit::WebInputEvent::MouseDown;
mouse_event.x = 10;
latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 2, 2);
packet_in.Add(InputEvent::Create(
++next_event_id,
WebInputEventPayload::Create(mouse_event, latency, false)));
WebKit::WebGestureEvent gesture_event;
gesture_event.type = WebKit::WebInputEvent::GestureScrollBegin;
gesture_event.x = -1;
packet_in.Add(InputEvent::Create(
++next_event_id,
WebInputEventPayload::Create(gesture_event, latency, false)));
WebKit::WebTouchEvent touch_event;
touch_event.type = WebKit::WebInputEvent::TouchStart;
touch_event.touchesLength = 1;
touch_event.touches[0].radiusX = 1;
packet_in.Add(InputEvent::Create(
++next_event_id,
WebInputEventPayload::Create(touch_event, latency, false)));
Verify(packet_in);
}
TEST_F(InputParamTraitsTest, EventPacketMixedEvents) {
EventPacket packet_in;
packet_in.set_id(1);
int64 next_event_id = 1;
// Add a mix of IPC and WebInputEvents.
packet_in.Add(
InputEvent::Create(++next_event_id,
IPCInputEventPayload::Create(
scoped_ptr<IPC::Message>(new InputMsg_Undo(1)))));
ui::LatencyInfo latency;
WebKit::WebKeyboardEvent key_event;
key_event.type = WebKit::WebInputEvent::RawKeyDown;
key_event.nativeKeyCode = 5;
packet_in.Add(InputEvent::Create(
++next_event_id, WebInputEventPayload::Create(key_event, latency, true)));
packet_in.Add(InputEvent::Create(
++next_event_id,
IPCInputEventPayload::Create(
scoped_ptr<IPC::Message>(new InputMsg_SetFocus(2, true)))));
WebKit::WebMouseWheelEvent wheel_event;
wheel_event.type = WebKit::WebInputEvent::MouseWheel;
wheel_event.deltaX = 10;
packet_in.Add(InputEvent::Create(
++next_event_id,
WebInputEventPayload::Create(wheel_event, latency, false)));
Verify(packet_in);
}
} // namespace
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/ipc_input_event_payload.h"
namespace content {
scoped_ptr<IPCInputEventPayload> IPCInputEventPayload::Create() {
return make_scoped_ptr(new IPCInputEventPayload());
}
scoped_ptr<IPCInputEventPayload> IPCInputEventPayload::Create(
scoped_ptr<IPC::Message> message) {
DCHECK(message);
scoped_ptr<IPCInputEventPayload> payload = Create();
payload->message = message.Pass();
return payload.Pass();
}
const IPCInputEventPayload* IPCInputEventPayload::Cast(const Payload* payload) {
DCHECK(payload);
DCHECK_EQ(IPC_MESSAGE, payload->GetType());
return static_cast<const IPCInputEventPayload*>(payload);
}
IPCInputEventPayload::IPCInputEventPayload() {}
IPCInputEventPayload::~IPCInputEventPayload() {}
InputEvent::Payload::Type IPCInputEventPayload::GetType() const {
return IPC_MESSAGE;
}
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
#define CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
#include "base/basictypes.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event.h"
#include "ipc/ipc_message.h"
namespace content {
// Wraps a generic IPC message of type InputMsg_*.
class CONTENT_EXPORT IPCInputEventPayload : public InputEvent::Payload {
public:
static scoped_ptr<IPCInputEventPayload> Create();
static scoped_ptr<IPCInputEventPayload> Create(
scoped_ptr<IPC::Message> message);
static const IPCInputEventPayload* Cast(const Payload* payload);
virtual ~IPCInputEventPayload();
// InputEvent::Payload
virtual Type GetType() const OVERRIDE;
scoped_ptr<IPC::Message> message;
protected:
IPCInputEventPayload();
private:
DISALLOW_COPY_AND_ASSIGN(IPCInputEventPayload);
};
} // namespace content
#endif // CONTENT_COMMON_INPUT_IPC_INPUT_EVENT_PAYLOAD_H_
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/input/web_input_event_payload.h"
#include "base/logging.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
namespace {
static WebInputEventPayload::ScopedWebInputEvent CloneWebInputEvent(
const WebKit::WebInputEvent& event) {
WebInputEventPayload::ScopedWebInputEvent clone;
if (WebKit::WebInputEvent::isMouseEventType(event.type))
clone.reset(new WebKit::WebMouseEvent());
else if (event.type == WebKit::WebInputEvent::MouseWheel)
clone.reset(new WebKit::WebMouseWheelEvent());
else if (WebKit::WebInputEvent::isKeyboardEventType(event.type))
clone.reset(new WebKit::WebKeyboardEvent());
else if (WebKit::WebInputEvent::isTouchEventType(event.type))
clone.reset(new WebKit::WebTouchEvent());
else if (WebKit::WebInputEvent::isGestureEventType(event.type))
clone.reset(new WebKit::WebGestureEvent());
else
NOTREACHED() << "Unknown webkit event type " << event.type;
if (!clone)
return clone.Pass();
DCHECK_EQ(event.size, clone->size);
memcpy(clone.get(), &event, event.size);
return clone.Pass();
}
} // namespace
WebInputEventPayload::WebInputEventDeleter::WebInputEventDeleter() {}
void WebInputEventPayload::WebInputEventDeleter::operator()(
WebKit::WebInputEvent* event) const {
if (!event)
return;
if (WebKit::WebInputEvent::isMouseEventType(event->type))
delete static_cast<WebKit::WebMouseEvent*>(event);
else if (event->type == WebKit::WebInputEvent::MouseWheel)
delete static_cast<WebKit::WebMouseWheelEvent*>(event);
else if (WebKit::WebInputEvent::isKeyboardEventType(event->type))
delete static_cast<WebKit::WebKeyboardEvent*>(event);
else if (WebKit::WebInputEvent::isTouchEventType(event->type))
delete static_cast<WebKit::WebTouchEvent*>(event);
else if (WebKit::WebInputEvent::isGestureEventType(event->type))
delete static_cast<WebKit::WebGestureEvent*>(event);
else
NOTREACHED() << "Unknown webkit event type " << event->type;
}
WebInputEventPayload::WebInputEventPayload() : is_keyboard_shortcut_(false) {}
WebInputEventPayload::~WebInputEventPayload() {}
scoped_ptr<WebInputEventPayload> WebInputEventPayload::Create() {
return make_scoped_ptr(new WebInputEventPayload());
}
scoped_ptr<WebInputEventPayload> WebInputEventPayload::Create(
const WebKit::WebInputEvent& event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut) {
scoped_ptr<WebInputEventPayload> payload = Create();
payload->Initialize(event, latency_info, is_keyboard_shortcut);
return payload.Pass();
}
const WebInputEventPayload* WebInputEventPayload::Cast(const Payload* payload) {
DCHECK(payload);
DCHECK_EQ(WEB_INPUT_EVENT, payload->GetType());
return static_cast<const WebInputEventPayload*>(payload);
}
InputEvent::Payload::Type WebInputEventPayload::GetType() const {
return WEB_INPUT_EVENT;
}
void WebInputEventPayload::Initialize(const WebKit::WebInputEvent& web_event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut) {
DCHECK(!web_event_) << "WebInputEventPayload already initialized";
web_event_ = CloneWebInputEvent(web_event);
latency_info_ = latency_info;
is_keyboard_shortcut_ = is_keyboard_shortcut;
}
bool WebInputEventPayload::CanCreateFollowupEvents() const {
return WebKit::WebInputEvent::isTouchEventType(web_event()->type);
}
} // namespace content
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
#define CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
#include "base/basictypes.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event.h"
#include "ui/base/latency_info.h"
namespace WebKit {
class WebInputEvent;
}
namespace content {
// Wraps a WebKit::WebInputEvent.
class CONTENT_EXPORT WebInputEventPayload : public InputEvent::Payload {
public:
static scoped_ptr<WebInputEventPayload> Create();
static scoped_ptr<WebInputEventPayload> Create(
const WebKit::WebInputEvent& event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut);
static const WebInputEventPayload* Cast(const Payload* payload);
virtual ~WebInputEventPayload();
// InputEvent::Payload
virtual Type GetType() const OVERRIDE;
void Initialize(const WebKit::WebInputEvent& event,
const ui::LatencyInfo& latency_info,
bool is_keyboard_shortcut);
// True for WebTouchEvents only.
bool CanCreateFollowupEvents() const;
const WebKit::WebInputEvent* web_event() const { return web_event_.get(); }
const ui::LatencyInfo& latency_info() const { return latency_info_; }
bool is_keyboard_shortcut() const { return is_keyboard_shortcut_; }
// WebKit::WebInputEvent does not provide a virtual destructor.
struct WebInputEventDeleter {
WebInputEventDeleter();
void operator()(WebKit::WebInputEvent* event) const;
};
typedef scoped_ptr<WebKit::WebInputEvent,
WebInputEventDeleter> ScopedWebInputEvent;
protected:
WebInputEventPayload();
private:
ScopedWebInputEvent web_event_;
ui::LatencyInfo latency_info_;
bool is_keyboard_shortcut_;
DISALLOW_COPY_AND_ASSIGN(WebInputEventPayload);
};
} // namespace content
#endif // CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_PAYLOAD_H_
...@@ -10,6 +10,11 @@ ...@@ -10,6 +10,11 @@
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/common/content_param_traits.h" #include "content/common/content_param_traits.h"
#include "content/common/edit_command.h" #include "content/common/edit_command.h"
#include "content/common/input/input_event.h"
#include "content/common/input/input_event_disposition.h"
#include "content/common/input/input_param_traits.h"
#include "content/common/input/ipc_input_event_payload.h"
#include "content/common/input/event_packet.h"
#include "content/port/common/input_event_ack_state.h" #include "content/port/common/input_event_ack_state.h"
#include "content/public/common/common_param_traits.h" #include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h" #include "ipc/ipc_message_macros.h"
...@@ -27,19 +32,33 @@ ...@@ -27,19 +32,33 @@
#define IPC_MESSAGE_START InputMsgStart #define IPC_MESSAGE_START InputMsgStart
IPC_ENUM_TRAITS(content::InputEventAckState) IPC_ENUM_TRAITS_MAX_VALUE(content::InputEvent::Payload::Type,
content::InputEvent::Payload::PAYLOAD_TYPE_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventAckState,
content::INPUT_EVENT_ACK_STATE_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventDisposition,
content::INPUT_EVENT_DISPOSITION_MAX)
IPC_STRUCT_TRAITS_BEGIN(content::EditCommand) IPC_STRUCT_TRAITS_BEGIN(content::EditCommand)
IPC_STRUCT_TRAITS_MEMBER(name) IPC_STRUCT_TRAITS_MEMBER(name)
IPC_STRUCT_TRAITS_MEMBER(value) IPC_STRUCT_TRAITS_MEMBER(value)
IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::IPCInputEventPayload)
IPC_STRUCT_TRAITS_MEMBER(message)
IPC_STRUCT_TRAITS_END()
// Sends an input event to the render widget. // Sends an input event to the render widget.
IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent, IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
IPC::WebInputEventPointer /* event */, IPC::WebInputEventPointer /* event */,
ui::LatencyInfo /* latency_info */, ui::LatencyInfo /* latency_info */,
bool /* is_keyboard_shortcut */) bool /* is_keyboard_shortcut */)
// Sends an event packet to the render widget.
IPC_MESSAGE_ROUTED2(InputMsg_HandleEventPacket,
content::EventPacket /* event_packet */,
content::InputEventDispositions /* dispositions */)
// Sends the cursor visibility state to the render widget. // Sends the cursor visibility state to the render widget.
IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange, IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
bool /* is_visible */) bool /* is_visible */)
...@@ -131,6 +150,10 @@ IPC_MESSAGE_ROUTED3(InputHostMsg_HandleInputEvent_ACK, ...@@ -131,6 +150,10 @@ IPC_MESSAGE_ROUTED3(InputHostMsg_HandleInputEvent_ACK,
content::InputEventAckState /* ack_result */, content::InputEventAckState /* ack_result */,
ui::LatencyInfo /* latency_info */) ui::LatencyInfo /* latency_info */)
IPC_MESSAGE_ROUTED2(InputHostMsg_HandleEventPacket_ACK,
int64 /* event_packet_id */,
content::InputEventDispositions /* dispositions */)
// Adding a new message? Stick to the sort order above: first platform // Adding a new message? Stick to the sort order above: first platform
// independent InputMsg, then ifdefs for platform specific InputMsg, then // independent InputMsg, then ifdefs for platform specific InputMsg, then
......
...@@ -258,6 +258,18 @@ ...@@ -258,6 +258,18 @@
'common/indexed_db/indexed_db_messages.h', 'common/indexed_db/indexed_db_messages.h',
'common/indexed_db/indexed_db_param_traits.cc', 'common/indexed_db/indexed_db_param_traits.cc',
'common/indexed_db/indexed_db_param_traits.h', 'common/indexed_db/indexed_db_param_traits.h',
'common/input/event_packet.cc',
'common/input/event_packet.h',
'common/input/ipc_input_event_payload.cc',
'common/input/ipc_input_event_payload.h',
'common/input/input_event.cc',
'common/input/input_event.h',
'common/input/input_event_disposition.cc',
'common/input/input_event_disposition.h',
'common/input/input_param_traits.cc',
'common/input/input_param_traits.h',
'common/input/web_input_event_payload.cc',
'common/input/web_input_event_payload.h',
'common/input_messages.h', 'common/input_messages.h',
'common/inter_process_time_ticks_converter.cc', 'common/inter_process_time_ticks_converter.cc',
'common/inter_process_time_ticks_converter.h', 'common/inter_process_time_ticks_converter.h',
......
...@@ -337,7 +337,6 @@ ...@@ -337,7 +337,6 @@
'browser/power_monitor_message_broadcaster_unittest.cc', 'browser/power_monitor_message_broadcaster_unittest.cc',
'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc', 'browser/renderer_host/compositing_iosurface_transformer_mac_unittest.cc',
'browser/renderer_host/gtk_key_bindings_handler_unittest.cc', 'browser/renderer_host/gtk_key_bindings_handler_unittest.cc',
'browser/renderer_host/input/immediate_input_router_unittest.cc',
'browser/renderer_host/media/audio_input_device_manager_unittest.cc', 'browser/renderer_host/media/audio_input_device_manager_unittest.cc',
'browser/renderer_host/media/audio_mirroring_manager_unittest.cc', 'browser/renderer_host/media/audio_mirroring_manager_unittest.cc',
'browser/renderer_host/media/audio_renderer_host_unittest.cc', 'browser/renderer_host/media/audio_renderer_host_unittest.cc',
...@@ -405,6 +404,7 @@ ...@@ -405,6 +404,7 @@
'common/dom_storage/dom_storage_map_unittest.cc', 'common/dom_storage/dom_storage_map_unittest.cc',
'common/gpu/gpu_memory_manager_unittest.cc', 'common/gpu/gpu_memory_manager_unittest.cc',
'common/indexed_db/indexed_db_key_unittest.cc', 'common/indexed_db/indexed_db_key_unittest.cc',
'common/input/input_param_traits_unittest.cc',
'common/inter_process_time_ticks_converter_unittest.cc', 'common/inter_process_time_ticks_converter_unittest.cc',
'common/mac/attributed_string_coder_unittest.mm', 'common/mac/attributed_string_coder_unittest.mm',
'common/mac/font_descriptor_unittest.mm', 'common/mac/font_descriptor_unittest.mm',
......
...@@ -13,6 +13,7 @@ enum InputEventAckState { ...@@ -13,6 +13,7 @@ enum InputEventAckState {
INPUT_EVENT_ACK_STATE_CONSUMED, INPUT_EVENT_ACK_STATE_CONSUMED,
INPUT_EVENT_ACK_STATE_NOT_CONSUMED, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
INPUT_EVENT_ACK_STATE_MAX = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
}; };
} // namespace content } // namespace content
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment