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

Side by Side Diff: content/browser/renderer_host/input/input_queue.cc

Issue 20356003: Provided batched input delivery with a BufferedInputRouter (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Refactoring 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/renderer_host/input/input_queue.h"
6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "content/browser/renderer_host/input/browser_input_event.h"
10 #include "content/browser/renderer_host/input/input_queue_client.h"
11 #include "content/common/input/event_packet.h"
12 #include "content/common/input/input_event.h"
13
14 namespace content {
15
16 // A specialized EventPacket with utility methods for dispatched event handling.
17 class InputQueue::BrowserEventPacket : public EventPacket {
18 public:
19 typedef ScopedVector<BrowserInputEvent> BrowserInputEvents;
20
21 BrowserEventPacket() : weak_factory_(this) {}
22 virtual ~BrowserEventPacket() {}
23
24 // Validate the response and signal dispatch to the processed events.
25 // Undelivered events will be re-enqueued, and any generated followup events
26 // will be inserted at the same relative order as their generating event.
27 AckResult ValidateAndDispatchAck(int64 packet_id,
28 const InputEventDispositions& dispositions) {
29 if (!Validate(packet_id, dispositions))
30 return ACK_INVALID;
31
32 // Empty the packet; events will be re-enqueued as necessary.
33 InputEvents dispatched_events;
34 events_.swap(dispatched_events);
35
36 // The packet could be deleted as a result of event dispatch; use a local
37 // weak ref to ensure proper shutdown.
38 base::WeakPtr<EventPacket> weak_ref_this = weak_factory_.GetWeakPtr();
39
40 BrowserInputEvents followup_events;
41 for (size_t i = 0; i < dispatched_events.size(); ++i) {
42 // Take ownership of the event.
43 scoped_ptr<BrowserInputEvent> event(
44 static_cast<BrowserInputEvent*>(dispatched_events[i]));
45 dispatched_events[i] = NULL;
46
47 // Re-enqueue undelivered events.
48 InputEventDisposition disposition = dispositions[i];
49 if (disposition == INPUT_EVENT_COULD_NOT_DELIVER) {
50 Add(event.PassAs<InputEvent>());
51 continue;
52 }
53
54 event->OnDispatched(disposition, &followup_events);
55
56 if (!weak_ref_this.get())
aelias_OOO_until_Jul13 2013/09/09 22:31:14 Please add a comment // TODO(jdduke): http://crbug
jdduke (slow) 2013/09/10 19:41:16 Done.
57 return ACK_SHUTDOWN;
58
59 AddAll(&followup_events);
60 }
61 return ACK_OK;
62 };
63
64 protected:
65 // Add and take ownership of events in |followup_events|.
66 void AddAll(BrowserInputEvents* followup_events) {
67 for (BrowserInputEvents::iterator iter = followup_events->begin();
68 iter != followup_events->end();
69 ++iter) {
70 Add(scoped_ptr<InputEvent>(*iter));
71 }
72 followup_events->weak_clear();
73 }
74
75 // Perform a sanity check of the ack against the current packet.
76 // |packet_id| should match that of this packet, and |dispositions| should
77 // be of size equal to the number of events in this packet.
78 bool Validate(int64 packet_id,
79 const InputEventDispositions& dispositions) const {
80 if (packet_id != id())
81 return false;
82
83 if (dispositions.size() != size())
84 return false;
85
86 return true;
87 }
88
89 private:
90 base::WeakPtrFactory<EventPacket> weak_factory_;
91 };
92
93 InputQueue::InputQueue(InputQueueClient* client)
94 : client_(client),
95 next_packet_id_(1),
96 flush_requested_(false),
97 in_flush_packet_(new BrowserEventPacket()),
98 pending_flush_packet_(new BrowserEventPacket()) {
99 DCHECK(client_);
100 }
101
102 InputQueue::~InputQueue() {}
103
104 void InputQueue::QueueEvent(scoped_ptr<BrowserInputEvent> event) {
105 DCHECK(event);
106 DCHECK(event->valid());
107 pending_flush_packet_->Add(event.PassAs<InputEvent>());
108 RequestFlushIfNecessary();
109 }
110
111 void InputQueue::BeginFlush() {
112 // Ignore repeated flush attempts.
113 if (!flush_requested_)
114 return;
115
116 DCHECK(!FlushInProgress());
117 DCHECK(!pending_flush_packet_->empty());
118
119 flush_requested_ = false;
120 in_flush_packet_.swap(pending_flush_packet_);
121 DeliverInFlushPacket();
122 }
123
124 InputQueue::AckResult InputQueue::OnEventPacketAck(
125 int64 packet_id, const InputEventDispositions& dispositions) {
126 if (!FlushInProgress())
127 return ACK_UNEXPECTED;
128
129 TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "AckPacket",
130 "id", packet_id);
131
132 AckResult ack_result =
133 in_flush_packet_->ValidateAndDispatchAck(packet_id, dispositions);
134
135 if (ack_result != ACK_OK)
136 return ack_result;
137
138 if (FlushInProgress()) {
139 DeliverInFlushPacket();
140 } else {
141 TRACE_EVENT_ASYNC_END0("input", "InputQueueFlush", this);
142 client_->DidFinishFlush();
143 RequestFlushIfNecessary();
144 }
145
146 return ACK_OK;
147 }
148
149 size_t InputQueue::QueuedEventCount() const {
150 return in_flush_packet_->size() + pending_flush_packet_->size();
151 }
152
153 void InputQueue::DeliverInFlushPacket() {
154 DCHECK(FlushInProgress());
155 TRACE_EVENT_ASYNC_STEP1("input", "InputQueueFlush", this, "DeliverPacket",
156 "id", next_packet_id_);
157 in_flush_packet_->set_id(next_packet_id_++);
158 client_->Deliver(*in_flush_packet_);
159 }
160
161 void InputQueue::RequestFlushIfNecessary() {
162 if (flush_requested_)
163 return;
164
165 // Defer flush requests until the current flush has finished.
166 if (FlushInProgress())
167 return;
168
169 // No additional events to flush.
170 if (pending_flush_packet_->empty())
171 return;
172
173 TRACE_EVENT_ASYNC_BEGIN0("input", "InputQueueFlush", this);
174 TRACE_EVENT_ASYNC_STEP0("input", "InputQueueFlush", this, "Request");
175 flush_requested_ = true;
176 client_->SetNeedsFlush();
177 }
178
179 bool InputQueue::FlushInProgress() const {
180 return !in_flush_packet_->empty();
181 }
182
183 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698