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

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

Issue 2813683002: Allow MainThreadEventQueue to call the RenderWidget directly. (Closed)
Patch Set: Fix style nits 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 #include "content/renderer/render_widget.h"
12 13
13 namespace content { 14 namespace content {
14 15
15 namespace { 16 namespace {
16 17
17 const size_t kTenSeconds = 10 * 1000 * 1000; 18 const size_t kTenSeconds = 10 * 1000 * 1000;
18 19
19 class QueuedClosure : public MainThreadEventQueueTask { 20 class QueuedClosure : public MainThreadEventQueueTask {
20 public: 21 public:
21 QueuedClosure(const base::Closure& closure) : closure_(closure) {} 22 QueuedClosure(const base::Closure& closure) : closure_(closure) {}
22 23
23 ~QueuedClosure() override {} 24 ~QueuedClosure() override {}
24 25
25 FilterResult FilterNewEvent( 26 FilterResult FilterNewEvent(
26 const MainThreadEventQueueTask& other_task) override { 27 const MainThreadEventQueueTask& other_task) override {
27 return other_task.IsWebInputEvent() ? FilterResult::KeepIterating 28 return other_task.IsWebInputEvent() ? FilterResult::KeepIterating
28 : FilterResult::StopIterating; 29 : FilterResult::StopIterating;
29 } 30 }
30 31
31 bool IsWebInputEvent() const override { return false; } 32 bool IsWebInputEvent() const override { return false; }
32 33
33 void Dispatch(int routing_id, MainThreadEventQueueClient*) override { 34 void Dispatch(MainThreadEventQueue*) override { closure_.Run(); }
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 35
44 private: 36 private:
45 base::Closure closure_; 37 base::Closure closure_;
46 }; 38 };
47 39
40 // Time interval at which touchmove events during scroll will be skipped
41 // during rAF signal.
42 const base::TimeDelta kAsyncTouchMoveInterval =
43 base::TimeDelta::FromMilliseconds(200);
44
45 } // namespace
46
48 class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo, 47 class QueuedWebInputEvent : public ScopedWebInputEventWithLatencyInfo,
49 public MainThreadEventQueueTask { 48 public MainThreadEventQueueTask {
50 public: 49 public:
51 QueuedWebInputEvent(ui::WebScopedInputEvent event, 50 QueuedWebInputEvent(ui::WebScopedInputEvent event,
52 const ui::LatencyInfo& latency, 51 const ui::LatencyInfo& latency,
53 InputEventDispatchType dispatch_type, 52 InputEventDispatchType dispatch_type,
54 bool originally_cancelable) 53 bool originally_cancelable)
55 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency), 54 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency),
56 dispatch_type_(dispatch_type), 55 dispatch_type_(dispatch_type),
57 non_blocking_coalesced_count_(0), 56 non_blocking_coalesced_count_(0),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 last_coalesced_timestamp_ = base::TimeTicks::Now(); 90 last_coalesced_timestamp_ = base::TimeTicks::Now();
92 91
93 // The newest event (|other_item|) always wins when updating fields. 92 // The newest event (|other_item|) always wins when updating fields.
94 originally_cancelable_ = other_event.originally_cancelable_; 93 originally_cancelable_ = other_event.originally_cancelable_;
95 94
96 return FilterResult::CoalescedEvent; 95 return FilterResult::CoalescedEvent;
97 } 96 }
98 97
99 bool IsWebInputEvent() const override { return true; } 98 bool IsWebInputEvent() const override { return true; }
100 99
101 void Dispatch(int routing_id, MainThreadEventQueueClient* client) override { 100 void Dispatch(MainThreadEventQueue* queue) override {
102 // Report the coalesced count only for continuous events; otherwise 101 // Report the coalesced count only for continuous events; otherwise
103 // the zero value would be dominated by non-continuous events. 102 // the zero value would be dominated by non-continuous events.
104 base::TimeTicks now = base::TimeTicks::Now(); 103 base::TimeTicks now = base::TimeTicks::Now();
105 if (IsContinuousEvent()) { 104 if (IsContinuousEvent()) {
106 UMA_HISTOGRAM_CUSTOM_COUNTS( 105 UMA_HISTOGRAM_CUSTOM_COUNTS(
107 "Event.MainThreadEventQueue.Continuous.QueueingTime", 106 "Event.MainThreadEventQueue.Continuous.QueueingTime",
108 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50); 107 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50);
109 108
110 UMA_HISTOGRAM_CUSTOM_COUNTS( 109 UMA_HISTOGRAM_CUSTOM_COUNTS(
111 "Event.MainThreadEventQueue.Continuous.FreshnessTime", 110 "Event.MainThreadEventQueue.Continuous.FreshnessTime",
112 (now - lastCoalescedTimestamp()).InMicroseconds(), 1, kTenSeconds, 111 (now - lastCoalescedTimestamp()).InMicroseconds(), 1, kTenSeconds,
113 50); 112 50);
114 113
115 UMA_HISTOGRAM_COUNTS_1000("Event.MainThreadEventQueue.CoalescedCount", 114 UMA_HISTOGRAM_COUNTS_1000("Event.MainThreadEventQueue.CoalescedCount",
116 coalescedCount()); 115 coalescedCount());
117 } else { 116 } else {
118 UMA_HISTOGRAM_CUSTOM_COUNTS( 117 UMA_HISTOGRAM_CUSTOM_COUNTS(
119 "Event.MainThreadEventQueue.NonContinuous.QueueingTime", 118 "Event.MainThreadEventQueue.NonContinuous.QueueingTime",
120 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50); 119 (now - creationTimestamp()).InMicroseconds(), 1, kTenSeconds, 50);
121 } 120 }
122 121
123 InputEventDispatchType dispatch_type = dispatchType(); 122 InputEventAckState ack_result = queue->HandleEventOnMainThread(
124 if (!blockingCoalescedEventIds().empty()) { 123 coalesced_event(), latencyInfo(), dispatchType());
125 switch (dispatch_type) { 124 for (const auto id : blockingCoalescedEventIds())
126 case DISPATCH_TYPE_BLOCKING: 125 queue->SendInputEventAck(event(), ack_result, id);
127 dispatch_type = DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN;
128 break;
129 case DISPATCH_TYPE_NON_BLOCKING:
130 dispatch_type = DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN;
131 break;
132 default:
133 NOTREACHED();
134 }
135 }
136 client->HandleEventOnMainThread(routing_id, &coalesced_event(),
137 latencyInfo(), dispatch_type);
138 }
139
140 void EventHandled(int routing_id,
141 blink::scheduler::RendererScheduler* renderer_scheduler,
142 MainThreadEventQueueClient* client,
143 blink::WebInputEvent::Type type,
144 blink::WebInputEventResult result,
145 InputEventAckState ack_result) override {
146 for (const auto id : blockingCoalescedEventIds()) {
147 client->SendInputEventAck(routing_id, type, ack_result, id);
148 if (renderer_scheduler) {
149 renderer_scheduler->DidHandleInputEventOnMainThread(event(), result);
150 }
151 }
152 } 126 }
153 127
154 bool originallyCancelable() const { return originally_cancelable_; } 128 bool originallyCancelable() const { return originally_cancelable_; }
155 129
156 private: 130 private:
157 FilterResult HandleTouchScrollStartQueued() { 131 FilterResult HandleTouchScrollStartQueued() {
158 // A TouchScrollStart will queued after this touch move which will make all 132 // A TouchScrollStart will queued after this touch move which will make all
159 // previous touch moves that are queued uncancelable. 133 // previous touch moves that are queued uncancelable.
160 switch (event().GetType()) { 134 switch (event().GetType()) {
161 case blink::WebInputEvent::kTouchMove: { 135 case blink::WebInputEvent::kTouchMove: {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 base::TimeTicks creation_timestamp_; 186 base::TimeTicks creation_timestamp_;
213 base::TimeTicks last_coalesced_timestamp_; 187 base::TimeTicks last_coalesced_timestamp_;
214 188
215 // Whether the received event was originally cancelable or not. The compositor 189 // Whether the received event was originally cancelable or not. The compositor
216 // input handler can change the event based on presence of event handlers so 190 // input handler can change the event based on presence of event handlers so
217 // this is the state at which the renderer received the event from the 191 // this is the state at which the renderer received the event from the
218 // browser. 192 // browser.
219 bool originally_cancelable_; 193 bool originally_cancelable_;
220 }; 194 };
221 195
222 // Time interval at which touchmove events will be skipped during rAF signal.
223 const base::TimeDelta kAsyncTouchMoveInterval =
224 base::TimeDelta::FromMilliseconds(200);
225
226 bool IsAsyncTouchMove(
227 const std::unique_ptr<MainThreadEventQueueTask>& queued_item) {
228 if (!queued_item->IsWebInputEvent())
229 return false;
230 const QueuedWebInputEvent* event =
231 static_cast<const QueuedWebInputEvent*>(queued_item.get());
232 if (event->event().GetType() != blink::WebInputEvent::kTouchMove)
233 return false;
234 const blink::WebTouchEvent& touch_event =
235 static_cast<const blink::WebTouchEvent&>(event->event());
236 return touch_event.moved_beyond_slop_region && !event->originallyCancelable();
237 }
238
239 } // namespace
240
241 MainThreadEventQueue::SharedState::SharedState() 196 MainThreadEventQueue::SharedState::SharedState()
242 : sent_main_frame_request_(false), sent_post_task_(false) {} 197 : sent_main_frame_request_(false), sent_post_task_(false) {}
243 198
244 MainThreadEventQueue::SharedState::~SharedState() {} 199 MainThreadEventQueue::SharedState::~SharedState() {}
245 200
246 MainThreadEventQueue::MainThreadEventQueue( 201 MainThreadEventQueue::MainThreadEventQueue(
247 int routing_id,
248 MainThreadEventQueueClient* client, 202 MainThreadEventQueueClient* client,
249 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, 203 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
250 blink::scheduler::RendererScheduler* renderer_scheduler) 204 blink::scheduler::RendererScheduler* renderer_scheduler)
251 : routing_id_(routing_id), 205 : client_(client),
252 client_(client),
253 last_touch_start_forced_nonblocking_due_to_fling_(false), 206 last_touch_start_forced_nonblocking_due_to_fling_(false),
254 enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled( 207 enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled(
255 features::kPassiveEventListenersDueToFling)), 208 features::kPassiveEventListenersDueToFling)),
256 enable_non_blocking_due_to_main_thread_responsiveness_flag_( 209 enable_non_blocking_due_to_main_thread_responsiveness_flag_(
257 base::FeatureList::IsEnabled( 210 base::FeatureList::IsEnabled(
258 features::kMainThreadBusyScrollIntervention)), 211 features::kMainThreadBusyScrollIntervention)),
259 handle_raf_aligned_touch_input_( 212 handle_raf_aligned_touch_input_(
260 base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents)), 213 base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents)),
261 handle_raf_aligned_mouse_input_( 214 handle_raf_aligned_mouse_input_(
262 base::FeatureList::IsEnabled(features::kRafAlignedMouseInputEvents)), 215 base::FeatureList::IsEnabled(features::kRafAlignedMouseInputEvents)),
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 needs_post_task = !shared_state_.sent_post_task_; 336 needs_post_task = !shared_state_.sent_post_task_;
384 shared_state_.sent_post_task_ = true; 337 shared_state_.sent_post_task_ = true;
385 } 338 }
386 339
387 if (needs_post_task) 340 if (needs_post_task)
388 PostTaskToMainThread(); 341 PostTaskToMainThread();
389 } 342 }
390 343
391 void MainThreadEventQueue::DispatchInFlightEvent() { 344 void MainThreadEventQueue::DispatchInFlightEvent() {
392 if (in_flight_event_) { 345 if (in_flight_event_) {
393 in_flight_event_->Dispatch(routing_id_, client_); 346 in_flight_event_->Dispatch(this);
394 in_flight_event_.reset(); 347 in_flight_event_.reset();
395 } 348 }
396 } 349 }
397 350
398 void MainThreadEventQueue::PossiblyScheduleMainFrame() { 351 void MainThreadEventQueue::PossiblyScheduleMainFrame() {
399 if (IsRafAlignedInputDisabled()) 352 if (IsRafAlignedInputDisabled())
400 return; 353 return;
401 bool needs_main_frame = false; 354 bool needs_main_frame = false;
402 { 355 {
403 base::AutoLock lock(shared_state_lock_); 356 base::AutoLock lock(shared_state_lock_);
404 if (!shared_state_.sent_main_frame_request_ && 357 if (!shared_state_.sent_main_frame_request_ &&
405 !shared_state_.events_.empty() && 358 !shared_state_.events_.empty() &&
406 IsRafAlignedEvent(shared_state_.events_.front())) { 359 IsRafAlignedEvent(shared_state_.events_.front())) {
407 needs_main_frame = true; 360 needs_main_frame = true;
408 shared_state_.sent_main_frame_request_ = true; 361 shared_state_.sent_main_frame_request_ = true;
409 } 362 }
410 } 363 }
411 if (needs_main_frame) 364 if (needs_main_frame)
412 client_->NeedsMainFrame(routing_id_); 365 SetNeedsMainFrame();
413 } 366 }
414 367
415 void MainThreadEventQueue::DispatchEvents() { 368 void MainThreadEventQueue::DispatchEvents() {
416 size_t events_to_process; 369 size_t events_to_process;
417 370
418 // Record the queue size so that we only process 371 // Record the queue size so that we only process
419 // that maximum number of events. 372 // that maximum number of events.
420 { 373 {
421 base::AutoLock lock(shared_state_lock_); 374 base::AutoLock lock(shared_state_lock_);
422 shared_state_.sent_post_task_ = false; 375 shared_state_.sent_post_task_ = false;
(...skipping 13 matching lines...) Expand all
436 return; 389 return;
437 in_flight_event_ = shared_state_.events_.Pop(); 390 in_flight_event_ = shared_state_.events_.Pop();
438 } 391 }
439 392
440 // Dispatching the event is outside of critical section. 393 // Dispatching the event is outside of critical section.
441 DispatchInFlightEvent(); 394 DispatchInFlightEvent();
442 } 395 }
443 PossiblyScheduleMainFrame(); 396 PossiblyScheduleMainFrame();
444 } 397 }
445 398
446 void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type, 399 static bool IsAsyncTouchMove(
447 blink::WebInputEventResult result, 400 const std::unique_ptr<MainThreadEventQueueTask>& queued_item) {
448 InputEventAckState ack_result) { 401 if (!queued_item->IsWebInputEvent())
449 if (in_flight_event_) { 402 return false;
450 in_flight_event_->EventHandled(routing_id_, renderer_scheduler_, client_, 403 const QueuedWebInputEvent* event =
451 type, result, ack_result); 404 static_cast<const QueuedWebInputEvent*>(queued_item.get());
452 } 405 if (event->event().GetType() != blink::WebInputEvent::kTouchMove)
406 return false;
407 const blink::WebTouchEvent& touch_event =
408 static_cast<const blink::WebTouchEvent&>(event->event());
409 return touch_event.moved_beyond_slop_region && !event->originallyCancelable();
453 } 410 }
454 411
455 void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) { 412 void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) {
456 if (IsRafAlignedInputDisabled()) 413 if (IsRafAlignedInputDisabled())
457 return; 414 return;
458 415
459 size_t queue_size_at_start; 416 size_t queue_size_at_start;
460 417
461 // Record the queue size so that we only process 418 // Record the queue size so that we only process
462 // that maximum number of events. 419 // that maximum number of events.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
518 } else { 475 } else {
519 needs_main_frame = !shared_state_.sent_main_frame_request_; 476 needs_main_frame = !shared_state_.sent_main_frame_request_;
520 shared_state_.sent_main_frame_request_ = true; 477 shared_state_.sent_main_frame_request_ = true;
521 } 478 }
522 } 479 }
523 } 480 }
524 481
525 if (needs_post_task) 482 if (needs_post_task)
526 PostTaskToMainThread(); 483 PostTaskToMainThread();
527 if (needs_main_frame) 484 if (needs_main_frame)
528 client_->NeedsMainFrame(routing_id_); 485 SetNeedsMainFrame();
529 } 486 }
530 487
531 bool MainThreadEventQueue::IsRafAlignedInputDisabled() const { 488 bool MainThreadEventQueue::IsRafAlignedInputDisabled() const {
532 return !handle_raf_aligned_mouse_input_ && !handle_raf_aligned_touch_input_; 489 return !handle_raf_aligned_mouse_input_ && !handle_raf_aligned_touch_input_;
533 } 490 }
534 491
535 bool MainThreadEventQueue::IsRafAlignedEvent( 492 bool MainThreadEventQueue::IsRafAlignedEvent(
536 const std::unique_ptr<MainThreadEventQueueTask>& item) const { 493 const std::unique_ptr<MainThreadEventQueueTask>& item) const {
537 if (!item->IsWebInputEvent()) 494 if (!item->IsWebInputEvent())
538 return false; 495 return false;
539 const QueuedWebInputEvent* event = 496 const QueuedWebInputEvent* event =
540 static_cast<const QueuedWebInputEvent*>(item.get()); 497 static_cast<const QueuedWebInputEvent*>(item.get());
541 switch (event->event().GetType()) { 498 switch (event->event().GetType()) {
542 case blink::WebInputEvent::kMouseMove: 499 case blink::WebInputEvent::kMouseMove:
543 case blink::WebInputEvent::kMouseWheel: 500 case blink::WebInputEvent::kMouseWheel:
544 return handle_raf_aligned_mouse_input_; 501 return handle_raf_aligned_mouse_input_;
545 case blink::WebInputEvent::kTouchMove: 502 case blink::WebInputEvent::kTouchMove:
546 return handle_raf_aligned_touch_input_; 503 return handle_raf_aligned_touch_input_;
547 default: 504 default:
548 return false; 505 return false;
549 } 506 }
550 } 507 }
551 508
509 InputEventAckState MainThreadEventQueue::HandleEventOnMainThread(
510 const blink::WebCoalescedInputEvent& event,
511 const ui::LatencyInfo& latency,
512 InputEventDispatchType dispatch_type) {
513 if (client_)
514 return client_->HandleInputEvent(event, latency, dispatch_type);
515 return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
516 }
517
518 void MainThreadEventQueue::SendInputEventAck(const blink::WebInputEvent& event,
519 InputEventAckState ack_result,
520 uint32_t touch_event_id) {
521 DCHECK(main_task_runner_->BelongsToCurrentThread());
522 if (!client_)
523 return;
524 client_->SendInputEventAck(event.GetType(), ack_result, touch_event_id);
525 if (renderer_scheduler_) {
526 renderer_scheduler_->DidHandleInputEventOnMainThread(
527 event, ack_result == INPUT_EVENT_ACK_STATE_CONSUMED
528 ? blink::WebInputEventResult::kHandledApplication
529 : blink::WebInputEventResult::kNotHandled);
530 }
531 }
532
533 void MainThreadEventQueue::SetNeedsMainFrame() {
534 if (main_task_runner_->BelongsToCurrentThread()) {
535 if (client_)
536 client_->SetNeedsMainFrame();
537 return;
538 }
539
540 main_task_runner_->PostTask(
541 FROM_HERE, base::Bind(&MainThreadEventQueue::SetNeedsMainFrame, this));
542 }
543
544 void MainThreadEventQueue::ClearClient() {
545 DCHECK(main_task_runner_->BelongsToCurrentThread());
546 client_ = nullptr;
547 }
548
552 } // namespace content 549 } // 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