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 |