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

Side by Side Diff: content/renderer/input/main_thread_event_queue.cc

Issue 2765583002: Teach main thread event queue about closures. (Closed)
Patch Set: Remove two virtuals Created 3 years, 8 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/input/main_thread_event_queue.h" 5 #include "content/renderer/input/main_thread_event_queue.h"
6 6
7 #include "base/metrics/field_trial.h" 7 #include "base/metrics/field_trial.h"
8 #include "base/metrics/histogram_macros.h" 8 #include "base/metrics/histogram_macros.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "content/common/input/event_with_latency_info.h" 10 #include "content/common/input/event_with_latency_info.h"
11 #include "content/common/input_messages.h" 11 #include "content/common/input_messages.h"
12 12
13 namespace content { 13 namespace content {
14 14
15 namespace { 15 namespace {
16 16
17 const size_t kTenSeconds = 10 * 1000 * 1000;
18
19 class QueuedClosure : public MainThreadEventQueueTask {
20 public:
21 QueuedClosure(const base::Closure& closure) : closure_(closure) {}
22
23 ~QueuedClosure() override {}
24
25 CoalesceResult CoalesceWith(
26 const MainThreadEventQueueTask& other_task) override {
27 return other_task.IsWebInputEvent() ? CoalesceResult::KeepSearching
28 : CoalesceResult::CannotCoalesce;
29 }
30
31 bool IsWebInputEvent() const override { return false; }
32
33 void Dispatch(int routing_id, MainThreadEventQueueClient*) override {
34 closure_.Run();
35 }
36
37 void EventHandled(int routing_id,
38 blink::scheduler::RendererScheduler* renderer_scheduler,
39 MainThreadEventQueueClient* client,
40 blink::WebInputEvent::Type type,
41 blink::WebInputEventResult result,
42 InputEventAckState ack_result) override {}
43
44 private:
45 base::Closure closure_;
46 };
47
48 class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
49 public MainThreadEventQueueTask {
50 public:
51 QueuedWebInputEvent(ui::WebScopedInputEvent event,
52 const ui::LatencyInfo& latency,
53 InputEventDispatchType dispatch_type,
54 bool originally_cancelable)
55 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency),
56 dispatch_type_(dispatch_type),
57 non_blocking_coalesced_count_(0),
58 creation_timestamp_(base::TimeTicks::Now()),
59 last_coalesced_timestamp_(creation_timestamp_),
60 originally_cancelable_(originally_cancelable) {}
61
62 ~QueuedWebInputEvent() override {}
63
64 CoalesceResult CoalesceWith(
65 const MainThreadEventQueueTask& other_item) override {
66 if (!other_item.IsWebInputEvent())
67 return CoalesceResult::CannotCoalesce;
68
69 const QueuedWebInputEvent& other_event =
70 static_cast<const QueuedWebInputEvent&>(other_item);
71 if (!event().isSameEventClass(other_event.event()))
72 return CoalesceResult::KeepSearching;
73
74 if (!ScopedWebInputEventWithLatencyInfo::CanCoalesceWith(other_event))
75 return CoalesceResult::CannotCoalesce;
76
77 // If this event was blocking push the event id to the blocking
78 // list before updating the dispatch_type of this event.
79 if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) {
80 blocking_coalesced_event_ids_.push_back(
81 ui::WebInputEventTraits::GetUniqueTouchEventId(event()));
82 } else {
83 non_blocking_coalesced_count_++;
84 }
85 ScopedWebInputEventWithLatencyInfo::CoalesceWith(other_event);
86 last_coalesced_timestamp_ = base::TimeTicks::Now();
87
88 // The newest event (|other_item|) always wins when updating fields.
89 dispatch_type_ = other_event.dispatch_type_;
90 originally_cancelable_ = other_event.originally_cancelable_;
91
92 return CoalesceResult::Coalesced;
93 }
94
95 bool IsWebInputEvent() const override { return true; }
96
97 void Dispatch(int routing_id, MainThreadEventQueueClient* client) override {
98 // Report the coalesced count only for continuous events; otherwise
99 // the zero value would be dominated by non-continuous events.
100 base::TimeTicks now = base::TimeTicks::Now();
101 if (IsContinuousEvent()) {
102 UMA_HISTOGRAM_CUSTOM_COUNTS(
103 "Event.MainThreadEventQueue.Continuous.QueueingTime",
104 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50);
105
106 UMA_HISTOGRAM_CUSTOM_COUNTS(
107 "Event.MainThreadEventQueue.Continuous.FreshnessTime",
108 (now - lastCoalescedTimestamp()).InMicroseconds(), 1, kTenSeconds,
109 50);
110
111 UMA_HISTOGRAM_COUNTS_1000("Event.MainThreadEventQueue.CoalescedCount",
112 coalescedCount());
113 } else {
114 UMA_HISTOGRAM_CUSTOM_COUNTS(
115 "Event.MainThreadEventQueue.NonContinuous.QueueingTime",
116 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50);
117 }
118
119 InputEventDispatchType dispatch_type = dispatchType();
120 if (!blockingCoalescedEventIds().empty()) {
121 switch (dispatch_type) {
122 case DISPATCH_TYPE_BLOCKING:
123 dispatch_type = DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN;
124 break;
125 case DISPATCH_TYPE_NON_BLOCKING:
126 dispatch_type = DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN;
127 break;
128 default:
129 NOTREACHED();
130 }
131 }
132 client->HandleEventOnMainThread(routing_id, &coalesced_event(),
133 latencyInfo(), dispatch_type);
134 }
135
136 void EventHandled(int routing_id,
137 blink::scheduler::RendererScheduler* renderer_scheduler,
138 MainThreadEventQueueClient* client,
139 blink::WebInputEvent::Type type,
140 blink::WebInputEventResult result,
141 InputEventAckState ack_result) override {
142 for (const auto id : blockingCoalescedEventIds()) {
143 client->SendInputEventAck(routing_id, type, ack_result, id);
144 if (renderer_scheduler) {
145 renderer_scheduler->DidHandleInputEventOnMainThread(event(), result);
146 }
147 }
148 }
149
150 bool originallyCancelable() const { return originally_cancelable_; }
151
152 private:
153 const std::deque<uint32_t>& blockingCoalescedEventIds() const {
154 return blocking_coalesced_event_ids_;
155 }
156 InputEventDispatchType dispatchType() const { return dispatch_type_; }
157 base::TimeTicks creationTimestamp() const { return creation_timestamp_; }
158 base::TimeTicks lastCoalescedTimestamp() const {
159 return last_coalesced_timestamp_;
160 }
161
162 size_t coalescedCount() const {
163 return non_blocking_coalesced_count_ + blocking_coalesced_event_ids_.size();
164 }
165
166 bool IsContinuousEvent() const {
167 switch (event().type()) {
168 case blink::WebInputEvent::MouseMove:
169 case blink::WebInputEvent::MouseWheel:
170 case blink::WebInputEvent::TouchMove:
171 return true;
172 default:
173 return false;
174 }
175 }
176
177 InputEventDispatchType dispatch_type_;
178
179 // Contains the unique touch event ids to be acked. If
180 // the events are not TouchEvents the values will be 0. More importantly for
181 // those cases the deque ends up containing how many additional ACKs
182 // need to be sent.
183 std::deque<uint32_t> blocking_coalesced_event_ids_;
184 // Contains the number of non-blocking events coalesced.
185 size_t non_blocking_coalesced_count_;
186 base::TimeTicks creation_timestamp_;
187 base::TimeTicks last_coalesced_timestamp_;
188
189 // Whether the received event was originally cancelable or not. The compositor
190 // input handler can change the event based on presence of event handlers so
191 // this is the state at which the renderer received the event from the
192 // browser.
193 bool originally_cancelable_;
194 };
195
17 // Time interval at which touchmove events will be skipped during rAF signal. 196 // Time interval at which touchmove events will be skipped during rAF signal.
18 const base::TimeDelta kAsyncTouchMoveInterval = 197 const base::TimeDelta kAsyncTouchMoveInterval =
19 base::TimeDelta::FromMilliseconds(200); 198 base::TimeDelta::FromMilliseconds(200);
20 199
21 const size_t kTenSeconds = 10 * 1000 * 1000; 200 bool IsAsyncTouchMove(
22 201 const std::unique_ptr<MainThreadEventQueueTask>& queued_item) {
23 bool IsContinuousEvent(const std::unique_ptr<EventWithDispatchType>& event) { 202 if (!queued_item->IsWebInputEvent())
24 switch (event->event().type()) { 203 return false;
25 case blink::WebInputEvent::MouseMove: 204 const QueuedWebInputEvent* event =
26 case blink::WebInputEvent::MouseWheel: 205 static_cast<const QueuedWebInputEvent*>(queued_item.get());
27 case blink::WebInputEvent::TouchMove:
28 return true;
29 default:
30 return false;
31 }
32 }
33
34 bool IsAsyncTouchMove(const std::unique_ptr<EventWithDispatchType>& event) {
35 if (event->event().type() != blink::WebInputEvent::TouchMove) 206 if (event->event().type() != blink::WebInputEvent::TouchMove)
36 return false; 207 return false;
37 const blink::WebTouchEvent& touch_event = 208 const blink::WebTouchEvent& touch_event =
38 static_cast<const blink::WebTouchEvent&>(event->event()); 209 static_cast<const blink::WebTouchEvent&>(event->event());
39 return touch_event.movedBeyondSlopRegion && !event->originallyCancelable(); 210 return touch_event.movedBeyondSlopRegion && !event->originallyCancelable();
40 } 211 }
41 212
42 } // namespace 213 } // namespace
43 214
44 EventWithDispatchType::EventWithDispatchType(
45 ui::WebScopedInputEvent event,
46 const ui::LatencyInfo& latency,
47 InputEventDispatchType dispatch_type,
48 bool originally_cancelable)
49 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency),
50 dispatch_type_(dispatch_type),
51 non_blocking_coalesced_count_(0),
52 creation_timestamp_(base::TimeTicks::Now()),
53 last_coalesced_timestamp_(creation_timestamp_),
54 originally_cancelable_(originally_cancelable) {}
55
56 EventWithDispatchType::~EventWithDispatchType() {}
57
58 void EventWithDispatchType::CoalesceWith(const EventWithDispatchType& other) {
59 // If this event was blocking push the event id to the blocking
60 // list before updating the dispatch_type of this event.
61 if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) {
62 blocking_coalesced_event_ids_.push_back(
63 ui::WebInputEventTraits::GetUniqueTouchEventId(event()));
64 } else {
65 non_blocking_coalesced_count_++;
66 }
67 ScopedWebInputEventWithLatencyInfo::CoalesceWith(other);
68 dispatch_type_ = other.dispatch_type_;
69 last_coalesced_timestamp_ = base::TimeTicks::Now();
70 originally_cancelable_ = other.originally_cancelable_;
71 }
72
73 MainThreadEventQueue::SharedState::SharedState() 215 MainThreadEventQueue::SharedState::SharedState()
74 : sent_main_frame_request_(false) {} 216 : sent_main_frame_request_(false), sent_post_task_(false) {}
75 217
76 MainThreadEventQueue::SharedState::~SharedState() {} 218 MainThreadEventQueue::SharedState::~SharedState() {}
77 219
78 MainThreadEventQueue::MainThreadEventQueue( 220 MainThreadEventQueue::MainThreadEventQueue(
79 int routing_id, 221 int routing_id,
80 MainThreadEventQueueClient* client, 222 MainThreadEventQueueClient* client,
81 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, 223 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
82 blink::scheduler::RendererScheduler* renderer_scheduler) 224 blink::scheduler::RendererScheduler* renderer_scheduler)
83 : routing_id_(routing_id), 225 : routing_id_(routing_id),
84 client_(client), 226 client_(client),
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 // Adjust the |dispatchType| on the event since the compositor 331 // Adjust the |dispatchType| on the event since the compositor
190 // determined all event listeners are passive. 332 // determined all event listeners are passive.
191 wheel_event->dispatchType = 333 wheel_event->dispatchType =
192 blink::WebInputEvent::ListenersNonBlockingPassive; 334 blink::WebInputEvent::ListenersNonBlockingPassive;
193 } 335 }
194 } 336 }
195 337
196 InputEventDispatchType dispatch_type = 338 InputEventDispatchType dispatch_type =
197 non_blocking ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING; 339 non_blocking ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING;
198 340
199 std::unique_ptr<EventWithDispatchType> event_with_dispatch_type( 341 std::unique_ptr<QueuedWebInputEvent> event_with_dispatch_type(
200 new EventWithDispatchType(std::move(event), latency, dispatch_type, 342 new QueuedWebInputEvent(std::move(event), latency, dispatch_type,
201 originally_cancelable)); 343 originally_cancelable));
202 344
203 QueueEvent(std::move(event_with_dispatch_type)); 345 QueueEvent(std::move(event_with_dispatch_type));
204 346
205 // send an ack when we are non-blocking. 347 // send an ack when we are non-blocking.
206 return non_blocking; 348 return non_blocking;
207 } 349 }
208 350
351 void MainThreadEventQueue::QueueClosure(const base::Closure& closure) {
352 bool needs_post_task = false;
353 std::unique_ptr<QueuedClosure> item(new QueuedClosure(closure));
354 {
355 base::AutoLock lock(shared_state_lock_);
356 shared_state_.events_.Queue(std::move(item));
357 needs_post_task = !shared_state_.sent_post_task_;
358 shared_state_.sent_post_task_ = true;
359 }
360
361 if (needs_post_task)
362 PostTaskToMainThread();
363 }
364
209 void MainThreadEventQueue::DispatchInFlightEvent() { 365 void MainThreadEventQueue::DispatchInFlightEvent() {
210 if (in_flight_event_) { 366 if (in_flight_event_) {
211 // Report the coalesced count only for continuous events; otherwise 367 in_flight_event_->Dispatch(routing_id_, client_);
212 // the zero value would be dominated by non-continuous events. 368 in_flight_event_.reset();
213 base::TimeTicks now = base::TimeTicks::Now();
214 if (IsContinuousEvent(in_flight_event_)) {
215 UMA_HISTOGRAM_CUSTOM_COUNTS(
216 "Event.MainThreadEventQueue.Continuous.QueueingTime",
217 (now - in_flight_event_->creationTimestamp()).InMicroseconds(), 1,
218 kTenSeconds, 50);
219
220 UMA_HISTOGRAM_CUSTOM_COUNTS(
221 "Event.MainThreadEventQueue.Continuous.FreshnessTime",
222 (now - in_flight_event_->lastCoalescedTimestamp()).InMicroseconds(),
223 1, kTenSeconds, 50);
224
225 UMA_HISTOGRAM_COUNTS_1000("Event.MainThreadEventQueue.CoalescedCount",
226 in_flight_event_->coalescedCount());
227 } else {
228 UMA_HISTOGRAM_CUSTOM_COUNTS(
229 "Event.MainThreadEventQueue.NonContinuous.QueueingTime",
230 (now - in_flight_event_->creationTimestamp()).InMicroseconds(), 1,
231 kTenSeconds, 50);
232 }
233
234 InputEventDispatchType dispatch_type = in_flight_event_->dispatchType();
235 if (!in_flight_event_->blockingCoalescedEventIds().empty()) {
236 switch (dispatch_type) {
237 case DISPATCH_TYPE_BLOCKING:
238 dispatch_type = DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN;
239 break;
240 case DISPATCH_TYPE_NON_BLOCKING:
241 dispatch_type = DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN;
242 break;
243 default:
244 NOTREACHED();
245 }
246 }
247 client_->HandleEventOnMainThread(
248 routing_id_, &in_flight_event_->coalesced_event(),
249 in_flight_event_->latencyInfo(), dispatch_type);
250 } 369 }
251
252 in_flight_event_.reset();
253 } 370 }
254 371
255 void MainThreadEventQueue::PossiblyScheduleMainFrame() { 372 void MainThreadEventQueue::PossiblyScheduleMainFrame() {
256 if (IsRafAlignedInputDisabled()) 373 if (IsRafAlignedInputDisabled())
257 return; 374 return;
258 bool needs_main_frame = false; 375 bool needs_main_frame = false;
259 { 376 {
260 base::AutoLock lock(shared_state_lock_); 377 base::AutoLock lock(shared_state_lock_);
261 if (!shared_state_.sent_main_frame_request_ && 378 if (!shared_state_.sent_main_frame_request_ &&
262 !shared_state_.events_.empty() && 379 !shared_state_.events_.empty() &&
263 IsRafAlignedEvent(shared_state_.events_.front()->event())) { 380 IsRafAlignedEvent(shared_state_.events_.front())) {
264 needs_main_frame = !shared_state_.sent_main_frame_request_; 381 needs_main_frame = !shared_state_.sent_main_frame_request_;
265 shared_state_.sent_main_frame_request_ = false; 382 shared_state_.sent_main_frame_request_ = false;
266 } 383 }
267 } 384 }
268 if (needs_main_frame) 385 if (needs_main_frame)
269 client_->NeedsMainFrame(routing_id_); 386 client_->NeedsMainFrame(routing_id_);
270 } 387 }
271 388
272 void MainThreadEventQueue::DispatchSingleEvent() { 389 void MainThreadEventQueue::DispatchEvents() {
390 std::deque<std::unique_ptr<MainThreadEventQueueTask>> events_to_process;
273 { 391 {
274 base::AutoLock lock(shared_state_lock_); 392 base::AutoLock lock(shared_state_lock_);
275 if (shared_state_.events_.empty()) 393 shared_state_.sent_post_task_ = false;
276 return;
277 394
278 in_flight_event_ = shared_state_.events_.Pop(); 395 shared_state_.events_.swap(&events_to_process);
396
397 // Now take any raf aligned events that are at the tail of the queue
398 // and put them back.
399 while (!events_to_process.empty()) {
400 if (!IsRafAlignedEvent(events_to_process.back()))
401 break;
402 shared_state_.events_.emplace_front(std::move(events_to_process.back()));
403 events_to_process.pop_back();
404 }
279 } 405 }
280 DispatchInFlightEvent(); 406 while (!events_to_process.empty()) {
407 in_flight_event_ = std::move(events_to_process.front());
408 events_to_process.pop_front();
409 DispatchInFlightEvent();
410 }
281 PossiblyScheduleMainFrame(); 411 PossiblyScheduleMainFrame();
282 } 412 }
283 413
284 void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type, 414 void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type,
285 blink::WebInputEventResult result, 415 blink::WebInputEventResult result,
286 InputEventAckState ack_result) { 416 InputEventAckState ack_result) {
287 if (in_flight_event_) { 417 if (in_flight_event_) {
288 for (const auto id : in_flight_event_->blockingCoalescedEventIds()) { 418 in_flight_event_->EventHandled(routing_id_, renderer_scheduler_, client_,
289 client_->SendInputEventAck(routing_id_, type, ack_result, id); 419 type, result, ack_result);
290 if (renderer_scheduler_) {
291 renderer_scheduler_->DidHandleInputEventOnMainThread(
292 in_flight_event_->event(), result);
293 }
294 }
295 } 420 }
296 } 421 }
297 422
298 void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) { 423 void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) {
299 if (IsRafAlignedInputDisabled()) 424 if (IsRafAlignedInputDisabled())
300 return; 425 return;
301 426
302 std::deque<std::unique_ptr<EventWithDispatchType>> events_to_process; 427 std::deque<std::unique_ptr<MainThreadEventQueueTask>> events_to_process;
303 { 428 {
304 base::AutoLock lock(shared_state_lock_); 429 base::AutoLock lock(shared_state_lock_);
305 shared_state_.sent_main_frame_request_ = false; 430 shared_state_.sent_main_frame_request_ = false;
306 431
307 while (!shared_state_.events_.empty()) { 432 while (!shared_state_.events_.empty()) {
308 if (!IsRafAlignedEvent(shared_state_.events_.front()->event())) 433 if (IsRafAlignedEvent(shared_state_.events_.front())) {
309 break; 434 // Throttle touchmoves that are async.
310 435 if (handle_raf_aligned_touch_input_ &&
311 // Throttle touchmoves that are async. 436 IsAsyncTouchMove(shared_state_.events_.front())) {
312 if (handle_raf_aligned_touch_input_ && 437 if (shared_state_.events_.size() == 1 &&
313 IsAsyncTouchMove(shared_state_.events_.front())) { 438 frame_time < shared_state_.last_async_touch_move_timestamp_ +
314 if (shared_state_.events_.size() == 1 && 439 kAsyncTouchMoveInterval) {
315 frame_time < shared_state_.last_async_touch_move_timestamp_ + 440 break;
316 kAsyncTouchMoveInterval) { 441 }
317 break; 442 shared_state_.last_async_touch_move_timestamp_ = frame_time;
318 } 443 }
319 shared_state_.last_async_touch_move_timestamp_ = frame_time;
320 } 444 }
321 events_to_process.emplace_back(shared_state_.events_.Pop()); 445 events_to_process.emplace_back(shared_state_.events_.Pop());
322 } 446 }
323 } 447 }
324 448
325 while(!events_to_process.empty()) { 449 while(!events_to_process.empty()) {
326 in_flight_event_ = std::move(events_to_process.front()); 450 in_flight_event_ = std::move(events_to_process.front());
327 events_to_process.pop_front(); 451 events_to_process.pop_front();
328 DispatchInFlightEvent(); 452 DispatchInFlightEvent();
329 } 453 }
330 PossiblyScheduleMainFrame(); 454 PossiblyScheduleMainFrame();
331 } 455 }
332 456
333 void MainThreadEventQueue::SendEventNotificationToMainThread() { 457 void MainThreadEventQueue::PostTaskToMainThread() {
334 main_task_runner_->PostTask( 458 main_task_runner_->PostTask(
335 FROM_HERE, base::Bind(&MainThreadEventQueue::DispatchSingleEvent, this)); 459 FROM_HERE, base::Bind(&MainThreadEventQueue::DispatchEvents, this));
336 } 460 }
337 461
338 void MainThreadEventQueue::QueueEvent( 462 void MainThreadEventQueue::QueueEvent(
339 std::unique_ptr<EventWithDispatchType> event) { 463 std::unique_ptr<MainThreadEventQueueTask> event) {
340 bool is_raf_aligned = IsRafAlignedEvent(event->event()); 464 bool is_raf_aligned = IsRafAlignedEvent(event);
341 size_t send_notification_count = 0;
342 bool needs_main_frame = false; 465 bool needs_main_frame = false;
466 bool needs_post_task = false;
343 { 467 {
344 base::AutoLock lock(shared_state_lock_); 468 base::AutoLock lock(shared_state_lock_);
345 size_t size_before = shared_state_.events_.size(); 469 size_t size_before = shared_state_.events_.size();
346
347 // Stash if the tail of the queue was rAF aligned.
348 bool was_raf_aligned = false;
349 if (size_before > 0) {
350 was_raf_aligned =
351 IsRafAlignedEvent(shared_state_.events_.at(size_before - 1)->event());
352 }
353 shared_state_.events_.Queue(std::move(event)); 470 shared_state_.events_.Queue(std::move(event));
354 size_t size_after = shared_state_.events_.size(); 471 size_t size_after = shared_state_.events_.size();
355 472
356 if (size_before != size_after) { 473 if (size_before != size_after) {
357 if (IsRafAlignedInputDisabled()) { 474 if (!is_raf_aligned) {
358 send_notification_count = 1; 475 needs_post_task = !shared_state_.sent_post_task_;
359 } else if (!is_raf_aligned) { 476 shared_state_.sent_post_task_ = true;
360 send_notification_count = 1;
361 // If we had just enqueued a non-rAF input event we will send a series
362 // of normal post messages to ensure they are all handled right away.
363 for (size_t pos = size_after - 1; pos >= 1; --pos) {
364 if (IsRafAlignedEvent(shared_state_.events_.at(pos - 1)->event()))
365 send_notification_count++;
366 else
367 break;
368 }
369 } else { 477 } else {
370 needs_main_frame = !shared_state_.sent_main_frame_request_; 478 needs_main_frame = !shared_state_.sent_main_frame_request_;
371 shared_state_.sent_main_frame_request_ = true; 479 shared_state_.sent_main_frame_request_ = true;
372 } 480 }
373 } else if (size_before > 0) {
374 // The event was coalesced. The queue size didn't change but
375 // the rAF alignment of the event may have and we need to schedule
376 // a notification.
377 bool is_coalesced_raf_aligned =
378 IsRafAlignedEvent(shared_state_.events_.at(size_before - 1)->event());
379 if (was_raf_aligned != is_coalesced_raf_aligned)
380 send_notification_count = 1;
381 } 481 }
382 } 482 }
383 483
384 for (size_t i = 0; i < send_notification_count; ++i) 484 if (needs_post_task)
385 SendEventNotificationToMainThread(); 485 PostTaskToMainThread();
386 if (needs_main_frame) 486 if (needs_main_frame)
387 client_->NeedsMainFrame(routing_id_); 487 client_->NeedsMainFrame(routing_id_);
388 } 488 }
389 489
390 bool MainThreadEventQueue::IsRafAlignedInputDisabled() { 490 bool MainThreadEventQueue::IsRafAlignedInputDisabled() const {
391 return !handle_raf_aligned_mouse_input_ && !handle_raf_aligned_touch_input_; 491 return !handle_raf_aligned_mouse_input_ && !handle_raf_aligned_touch_input_;
392 } 492 }
393 493
394 bool MainThreadEventQueue::IsRafAlignedEvent( 494 bool MainThreadEventQueue::IsRafAlignedEvent(
395 const blink::WebInputEvent& event) { 495 const std::unique_ptr<MainThreadEventQueueTask>& item) const {
396 switch (event.type()) { 496 if (!item->IsWebInputEvent())
497 return false;
498 const QueuedWebInputEvent* event =
499 static_cast<const QueuedWebInputEvent*>(item.get());
500 switch (event->event().type()) {
397 case blink::WebInputEvent::MouseMove: 501 case blink::WebInputEvent::MouseMove:
398 case blink::WebInputEvent::MouseWheel: 502 case blink::WebInputEvent::MouseWheel:
399 return handle_raf_aligned_mouse_input_; 503 return handle_raf_aligned_mouse_input_;
400 case blink::WebInputEvent::TouchMove: 504 case blink::WebInputEvent::TouchMove:
401 return handle_raf_aligned_touch_input_; 505 return handle_raf_aligned_touch_input_;
402 default: 506 default:
403 return false; 507 return false;
404 } 508 }
405 } 509 }
406 510
407 } // namespace content 511 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698