| Index: content/renderer/gpu/renderer_event_packet.cc
|
| diff --git a/content/renderer/gpu/renderer_event_packet.cc b/content/renderer/gpu/renderer_event_packet.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..29d9be24fedbf2c5a7ce6cd6c49f731a4648ec12
|
| --- /dev/null
|
| +++ b/content/renderer/gpu/renderer_event_packet.cc
|
| @@ -0,0 +1,136 @@
|
| +// Copyright (c) 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/renderer/gpu/renderer_event_packet.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"
|
| +
|
| +namespace content {
|
| +namespace {
|
| +
|
| +class RendererInputEvent {
|
| + public:
|
| + // |event| should outlive the created RendererInputEvent.
|
| + explicit RendererInputEvent(const InputEvent* event) : event_(event) {
|
| + DCHECK(event_);
|
| + }
|
| +
|
| + InputEventDisposition Dispatch(RendererEventPacket::Dispatcher* dispatcher,
|
| + int routing_id) {
|
| + DCHECK(dispatcher);
|
| + const InputEvent::Payload* payload = event_->payload();
|
| +
|
| + if (payload->GetType() == InputEvent::Payload::IPC_MESSAGE) {
|
| + return dispatcher->Dispatch(
|
| + *IPCInputEventPayload::Cast(payload)->message);
|
| + }
|
| +
|
| + if (payload->GetType() == InputEvent::Payload::WEB_INPUT_EVENT) {
|
| + const WebInputEventPayload* web_payload =
|
| + WebInputEventPayload::Cast(payload);
|
| + return dispatcher->Dispatch(routing_id,
|
| + web_payload->web_event(),
|
| + web_payload->latency_info(),
|
| + web_payload->is_keyboard_shortcut());
|
| + }
|
| +
|
| + NOTREACHED() << "Invalid InputEvent type.";
|
| + return INPUT_EVENT_UNHANDLED;
|
| + }
|
| +
|
| + bool CanCreateFollowupEvents() const {
|
| + const InputEvent::Payload* payload = event_->payload();
|
| + return payload->GetType() == InputEvent::Payload::WEB_INPUT_EVENT &&
|
| + WebInputEventPayload::Cast(payload)->CanCreateFollowupEvents();
|
| + }
|
| +
|
| + bool CanDeliverOnThread(RendererEventPacket::DispatchThreadType thread_type) {
|
| + switch (thread_type) {
|
| + case RendererEventPacket::THREAD_MAIN:
|
| + return true;
|
| + case RendererEventPacket::THREAD_IMPL:
|
| + return event_->payload()->GetType() ==
|
| + InputEvent::Payload::WEB_INPUT_EVENT;
|
| + }
|
| + NOTREACHED() << "Invalid dispatch thread type.";
|
| + return false;
|
| + }
|
| +
|
| +private:
|
| + const InputEvent* event_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(RendererInputEvent);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +RendererEventPacket::RendererEventPacket(
|
| + const EventPacket* packet,
|
| + const InputEventDispositions& dispositions)
|
| + : packet_(packet),
|
| + dispositions_(dispositions) {
|
| + DCHECK(packet_);
|
| + DCHECK_LE(dispositions_.size(), packet_->size());
|
| + dispositions_.resize(packet_->size(), INPUT_EVENT_UNHANDLED);
|
| +}
|
| +
|
| +RendererEventPacket::~RendererEventPacket() {}
|
| +
|
| +scoped_ptr<IPC::Message> RendererEventPacket::DispatchWith(
|
| + Dispatcher* dispatcher,
|
| + DispatchThreadType thread_type,
|
| + int routing_id) {
|
| + DCHECK(dispatcher);
|
| + DCHECK_EQ(dispositions_.size(), packet_->size());
|
| + const EventPacket::InputEvents& events = packet_->events();
|
| + for (size_t i = 0; i < events.size(); ++i) {
|
| + RendererInputEvent event(events[i]);
|
| +
|
| + // Ignore previously handled events.
|
| + InputEventDisposition old_disposition = dispositions_[i];
|
| + if (old_disposition != INPUT_EVENT_UNHANDLED &&
|
| + (thread_type == THREAD_IMPL ||
|
| + old_disposition != INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN))
|
| + continue;
|
| +
|
| + InputEventDisposition disposition = event.Dispatch(dispatcher, routing_id);
|
| + dispositions_[i] = disposition;
|
| +
|
| + if (disposition == INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN) {
|
| + DCHECK_EQ(THREAD_IMPL, thread_type);
|
| + // Bounce subsequent events to main. Events that should be offered to the
|
| + // impl thread will prevent further delivery.
|
| + bool can_continue_delivery = true;
|
| + while (++i < events.size()) {
|
| + RendererInputEvent current_event(events[i]);
|
| + if (current_event.CanDeliverOnThread(thread_type))
|
| + can_continue_delivery = false;
|
| + dispositions_[i] = can_continue_delivery
|
| + ? INPUT_EVENT_IMPL_THREAD_BOUNCE_TO_MAIN
|
| + : INPUT_EVENT_COULD_NOT_DELIVER;
|
| + }
|
| + return scoped_ptr<IPC::Message>(
|
| + new InputMsg_HandleEventPacket(routing_id, *packet_, dispositions_));
|
| + }
|
| +
|
| + // Unconsumed events that create followup will prevent further delivery.
|
| + bool event_consumed =
|
| + disposition == INPUT_EVENT_IMPL_THREAD_CONSUMED ||
|
| + disposition == INPUT_EVENT_MAIN_THREAD_CONSUMED ||
|
| + disposition == INPUT_EVENT_MAIN_THREAD_PREVENT_DEFAULTED;
|
| + if (!event_consumed && event.CanCreateFollowupEvents()) {
|
| + while (++i < events.size())
|
| + dispositions_[i] = INPUT_EVENT_COULD_NOT_DELIVER;
|
| + }
|
| + }
|
| +
|
| + return scoped_ptr<IPC::Message>(new InputHostMsg_HandleEventPacket_ACK(
|
| + routing_id, packet_->id(), dispositions_));
|
| +}
|
| +
|
| +} // namespace content
|
|
|