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

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

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

Powered by Google App Engine
This is Rietveld 408576698