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

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

Powered by Google App Engine
This is Rietveld 408576698