Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1365)

Unified Diff: content/browser/renderer_host/input/input_queue.cc

Issue 19220002: [WIP] BufferedInputRouter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix client assignment Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/browser/renderer_host/input/input_queue.cc
diff --git a/content/browser/renderer_host/input/input_queue.cc b/content/browser/renderer_host/input/input_queue.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9e7bf654df5671d736cdf907cf78c2d25524a76f
--- /dev/null
+++ b/content/browser/renderer_host/input/input_queue.cc
@@ -0,0 +1,183 @@
+// 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/browser/renderer_host/input/input_queue.h"
+
+#include "base/bind.h"
+#include "base/debug/trace_event.h"
+#include "content/browser/renderer_host/input/browser_input_event.h"
+#include "content/browser/renderer_host/input/input_queue_client.h"
+#include "content/common/input/event_packet.h"
+#include "content/common/input/input_event.h"
+
+namespace content {
+
+// A specialized EventPacket with utility methods for dispatched event handling.
+class InputQueue::BrowserEventPacket : public EventPacket {
+ public:
+ typedef ScopedVector<BrowserInputEvent> BrowserInputEvents;
+
+ BrowserEventPacket() : weak_factory_(this) {}
+ virtual ~BrowserEventPacket() {}
+
+ // Validate the response and signal dispatch to the processed events.
+ // Undelivered events will be re-enqueued, and any generated followup events
+ // will be inserted at the same relative order as their generating event.
+ AckResult ValidateAndDispatchAck(int64 packet_id,
+ const InputEventDispositions& dispositions) {
+ if (!Validate(packet_id, dispositions))
+ return ACK_INVALID;
+
+ // Empty the packet; events will be re-enqueued as necessary.
+ InputEvents dispatched_events;
+ events_.swap(dispatched_events);
+
+ // The packet could be deleted as a result of event dispatch; use a local
+ // weak ref to ensure proper shutdown.
+ base::WeakPtr<EventPacket> weak_ref_this = weak_factory_.GetWeakPtr();
+
+ BrowserInputEvents followup_events;
+ for (size_t i = 0; i < dispatched_events.size(); ++i) {
+ // Take ownership of the event.
+ scoped_ptr<BrowserInputEvent> event(
+ static_cast<BrowserInputEvent*>(dispatched_events[i]));
+ dispatched_events[i] = NULL;
+
+ // Re-enqueue undelivered events.
+ InputEventDisposition disposition = dispositions[i];
+ if (disposition == INPUT_EVENT_COULD_NOT_DELIVER) {
+ Add(event.PassAs<InputEvent>());
+ continue;
+ }
+
+ event->OnDispatched(disposition, &followup_events);
+
+ // TODO(jdduke): http://crbug.com/274029
+ if (!weak_ref_this.get())
+ return ACK_SHUTDOWN;
+
+ AddAll(&followup_events);
+ }
+ return ACK_OK;
+ }
+
+ protected:
+ // Add and take ownership of events in |followup_events|.
+ void AddAll(BrowserInputEvents* followup_events) {
+ for (BrowserInputEvents::iterator iter = followup_events->begin();
+ iter != followup_events->end();
+ ++iter) {
+ Add(scoped_ptr<InputEvent>(*iter));
+ }
+ followup_events->weak_clear();
+ }
+
+ // Perform a sanity check of the ack against the current packet.
+ // |packet_id| should match that of this packet, and |dispositions| should
+ // be of size equal to the number of events in this packet.
+ bool Validate(int64 packet_id,
+ const InputEventDispositions& dispositions) const {
+ if (packet_id != id())
+ return false;
+
+ if (dispositions.size() != size())
+ return false;
+
+ return true;
+ }
+
+ private:
+ base::WeakPtrFactory<EventPacket> weak_factory_;
+};
+
+InputQueue::InputQueue(InputQueueClient* client)
+ : client_(client),
+ next_packet_id_(1),
+ flush_requested_(false),
+ in_flush_packet_(new BrowserEventPacket()),
+ pending_flush_packet_(new BrowserEventPacket()) {
+ DCHECK(client_);
+}
+
+InputQueue::~InputQueue() {}
+
+void InputQueue::QueueEvent(scoped_ptr<BrowserInputEvent> event) {
+ DCHECK(event);
+ DCHECK(event->valid());
+ pending_flush_packet_->Add(event.PassAs<InputEvent>());
+ RequestFlushIfNecessary();
+}
+
+void InputQueue::BeginFlush() {
+ // Ignore repeated flush attempts.
+ if (!flush_requested_)
+ return;
+
+ DCHECK(!FlushInProgress());
+ DCHECK(!pending_flush_packet_->empty());
+
+ flush_requested_ = false;
+ in_flush_packet_.swap(pending_flush_packet_);
+ DeliverInFlushPacket();
+}
+
+InputQueue::AckResult InputQueue::OnEventPacketAck(
+ int64 packet_id,
+ const InputEventDispositions& dispositions) {
+ if (!FlushInProgress())
+ return ACK_UNEXPECTED;
+
+ TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "AckPacket",
+ "id", packet_id);
+
+ AckResult ack_result =
+ in_flush_packet_->ValidateAndDispatchAck(packet_id, dispositions);
+
+ if (ack_result != ACK_OK)
+ return ack_result;
+
+ if (FlushInProgress()) {
+ DeliverInFlushPacket();
+ } else {
+ TRACE_EVENT_ASYNC_END0("input", "InputQueueFlush", this);
+ client_->DidFinishFlush();
+ RequestFlushIfNecessary();
+ }
+
+ return ACK_OK;
+}
+
+size_t InputQueue::QueuedEventCount() const {
+ return in_flush_packet_->size() + pending_flush_packet_->size();
+}
+
+void InputQueue::DeliverInFlushPacket() {
+ DCHECK(FlushInProgress());
+ TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "DeliverPacket",
+ "id", next_packet_id_);
+ in_flush_packet_->set_id(next_packet_id_++);
+ client_->Deliver(*in_flush_packet_);
+}
+
+void InputQueue::RequestFlushIfNecessary() {
+ if (flush_requested_)
+ return;
+
+ // Defer flush requests until the current flush has finished.
+ if (FlushInProgress())
+ return;
+
+ // No additional events to flush.
+ if (pending_flush_packet_->empty())
+ return;
+
+ TRACE_EVENT_ASYNC_BEGIN0("input", "InputQueueFlush", this);
+ TRACE_EVENT_ASYNC_STEP0("input", "InputQueueFlush", this, "Request");
+ flush_requested_ = true;
+ client_->SetNeedsFlush();
+}
+
+bool InputQueue::FlushInProgress() const { return !in_flush_packet_->empty(); }
+
+} // namespace content
« no previous file with comments | « content/browser/renderer_host/input/input_queue.h ('k') | content/browser/renderer_host/input/input_queue_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698