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

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

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

Powered by Google App Engine
This is Rietveld 408576698