Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/histogram_macros.h" | 7 #include "base/metrics/histogram_macros.h" |
| 8 #include "content/common/input/event_with_latency_info.h" | 8 #include "content/common/input/event_with_latency_info.h" |
| 9 #include "content/common/input_messages.h" | 9 #include "content/common/input_messages.h" |
| 10 | 10 |
| 11 namespace content { | 11 namespace content { |
| 12 | 12 |
| 13 namespace { | 13 namespace { |
| 14 | 14 |
| 15 const size_t kTenSeconds = 10 * 1000 * 1000; | 15 const size_t kTenSeconds = 10 * 1000 * 1000; |
| 16 | 16 |
| 17 bool isContinuousEvent(const std::unique_ptr<EventWithDispatchType>& event) { | 17 bool isPossiblyContinuousEvent( |
|
Charlie Reis
2016/10/25 16:58:46
Style nit: "Is" should be capitalized.
dtapuska
2016/10/26 02:34:52
Done.
| |
| 18 const std::unique_ptr<EventWithDispatchType>& event) { | |
| 18 switch (event->event().type) { | 19 switch (event->event().type) { |
| 19 case blink::WebInputEvent::MouseMove: | 20 case blink::WebInputEvent::MouseMove: |
| 20 case blink::WebInputEvent::MouseWheel: | 21 case blink::WebInputEvent::MouseWheel: |
| 21 return true; | 22 return true; |
| 22 case blink::WebInputEvent::TouchMove: | 23 case blink::WebInputEvent::TouchMove: |
| 23 // TouchMoves that are blocking end up blocking scroll. Do not treat | 24 // TouchMoves that are blocking end up blocking scroll. Do not treat |
| 24 // them as continuous events otherwise we will end up waiting up to an | 25 // them as continuous events otherwise we will end up waiting up to an |
| 25 // additional frame. | 26 // additional frame. |
| 26 return static_cast<const blink::WebTouchEvent&>(event->event()) | 27 return static_cast<const blink::WebTouchEvent&>(event->event()) |
| 27 .dispatchType != blink::WebInputEvent::Blocking; | 28 .dispatchType != blink::WebInputEvent::Blocking; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 int routing_id, | 66 int routing_id, |
| 66 MainThreadEventQueueClient* client, | 67 MainThreadEventQueueClient* client, |
| 67 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, | 68 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner, |
| 68 blink::scheduler::RendererScheduler* renderer_scheduler) | 69 blink::scheduler::RendererScheduler* renderer_scheduler) |
| 69 : routing_id_(routing_id), | 70 : routing_id_(routing_id), |
| 70 client_(client), | 71 client_(client), |
| 71 is_flinging_(false), | 72 is_flinging_(false), |
| 72 last_touch_start_forced_nonblocking_due_to_fling_(false), | 73 last_touch_start_forced_nonblocking_due_to_fling_(false), |
| 73 enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled( | 74 enable_fling_passive_listener_flag_(base::FeatureList::IsEnabled( |
| 74 features::kPassiveEventListenersDueToFling)), | 75 features::kPassiveEventListenersDueToFling)), |
| 75 handle_raf_aligned_input_( | 76 handle_raf_aligned_touch_input_( |
| 76 base::FeatureList::IsEnabled(features::kRafAlignedInputEvents)), | 77 base::FeatureList::IsEnabled(features::kRafAlignedTouchInputEvents)), |
| 78 handle_raf_aligned_mouse_input_( | |
| 79 base::FeatureList::IsEnabled(features::kRafAlignedMouseInputEvents)), | |
| 77 main_task_runner_(main_task_runner), | 80 main_task_runner_(main_task_runner), |
| 78 renderer_scheduler_(renderer_scheduler) {} | 81 renderer_scheduler_(renderer_scheduler) {} |
| 79 | 82 |
| 80 MainThreadEventQueue::~MainThreadEventQueue() {} | 83 MainThreadEventQueue::~MainThreadEventQueue() {} |
| 81 | 84 |
| 82 bool MainThreadEventQueue::HandleEvent( | 85 bool MainThreadEventQueue::HandleEvent( |
| 83 ui::ScopedWebInputEvent event, | 86 ui::ScopedWebInputEvent event, |
| 84 const ui::LatencyInfo& latency, | 87 const ui::LatencyInfo& latency, |
| 85 InputEventDispatchType original_dispatch_type, | 88 InputEventDispatchType original_dispatch_type, |
| 86 InputEventAckState ack_result) { | 89 InputEventAckState ack_result) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 | 139 |
| 137 // send an ack when we are non-blocking. | 140 // send an ack when we are non-blocking. |
| 138 return non_blocking; | 141 return non_blocking; |
| 139 } | 142 } |
| 140 | 143 |
| 141 void MainThreadEventQueue::DispatchInFlightEvent() { | 144 void MainThreadEventQueue::DispatchInFlightEvent() { |
| 142 if (in_flight_event_) { | 145 if (in_flight_event_) { |
| 143 // Report the coalesced count only for continuous events; otherwise | 146 // Report the coalesced count only for continuous events; otherwise |
| 144 // the zero value would be dominated by non-continuous events. | 147 // the zero value would be dominated by non-continuous events. |
| 145 base::TimeTicks now = base::TimeTicks::Now(); | 148 base::TimeTicks now = base::TimeTicks::Now(); |
| 146 if (isContinuousEvent(in_flight_event_)) { | 149 if (isPossiblyContinuousEvent(in_flight_event_)) { |
| 147 UMA_HISTOGRAM_CUSTOM_COUNTS( | 150 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 148 "Event.MainThreadEventQueue.Continuous.QueueingTime", | 151 "Event.MainThreadEventQueue.Continuous.QueueingTime", |
| 149 (now - in_flight_event_->creationTimestamp()).InMicroseconds(), 1, | 152 (now - in_flight_event_->creationTimestamp()).InMicroseconds(), 1, |
| 150 kTenSeconds, 50); | 153 kTenSeconds, 50); |
| 151 | 154 |
| 152 UMA_HISTOGRAM_CUSTOM_COUNTS( | 155 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 153 "Event.MainThreadEventQueue.Continuous.FreshnessTime", | 156 "Event.MainThreadEventQueue.Continuous.FreshnessTime", |
| 154 (now - in_flight_event_->lastCoalescedTimestamp()).InMicroseconds(), | 157 (now - in_flight_event_->lastCoalescedTimestamp()).InMicroseconds(), |
| 155 1, kTenSeconds, 50); | 158 1, kTenSeconds, 50); |
| 156 | 159 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 171 | 174 |
| 172 client_->HandleEventOnMainThread(routing_id_, &in_flight_event_->event(), | 175 client_->HandleEventOnMainThread(routing_id_, &in_flight_event_->event(), |
| 173 in_flight_event_->latencyInfo(), | 176 in_flight_event_->latencyInfo(), |
| 174 dispatch_type); | 177 dispatch_type); |
| 175 } | 178 } |
| 176 | 179 |
| 177 in_flight_event_.reset(); | 180 in_flight_event_.reset(); |
| 178 } | 181 } |
| 179 | 182 |
| 180 void MainThreadEventQueue::PossiblyScheduleMainFrame() { | 183 void MainThreadEventQueue::PossiblyScheduleMainFrame() { |
| 181 if (!handle_raf_aligned_input_) | 184 if (RafAlignedInputDisabled()) |
| 182 return; | 185 return; |
| 183 bool needs_main_frame = false; | 186 bool needs_main_frame = false; |
| 184 { | 187 { |
| 185 base::AutoLock lock(shared_state_lock_); | 188 base::AutoLock lock(shared_state_lock_); |
| 186 if (!shared_state_.sent_main_frame_request_ && | 189 if (!shared_state_.sent_main_frame_request_ && |
| 187 !shared_state_.events_.empty() && | 190 !shared_state_.events_.empty() && |
| 188 isContinuousEvent(shared_state_.events_.front())) { | 191 IsContinuousEvent(shared_state_.events_.front())) { |
| 189 needs_main_frame = !shared_state_.sent_main_frame_request_; | 192 needs_main_frame = !shared_state_.sent_main_frame_request_; |
| 190 shared_state_.sent_main_frame_request_ = false; | 193 shared_state_.sent_main_frame_request_ = false; |
| 191 } | 194 } |
| 192 } | 195 } |
| 193 if (needs_main_frame) | 196 if (needs_main_frame) |
| 194 client_->NeedsMainFrame(routing_id_); | 197 client_->NeedsMainFrame(routing_id_); |
| 195 } | 198 } |
| 196 | 199 |
| 197 void MainThreadEventQueue::DispatchSingleEvent() { | 200 void MainThreadEventQueue::DispatchSingleEvent() { |
| 198 { | 201 { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 214 client_->SendInputEventAck(routing_id_, type, ack_result, id); | 217 client_->SendInputEventAck(routing_id_, type, ack_result, id); |
| 215 if (renderer_scheduler_) { | 218 if (renderer_scheduler_) { |
| 216 renderer_scheduler_->DidHandleInputEventOnMainThread( | 219 renderer_scheduler_->DidHandleInputEventOnMainThread( |
| 217 in_flight_event_->event()); | 220 in_flight_event_->event()); |
| 218 } | 221 } |
| 219 } | 222 } |
| 220 } | 223 } |
| 221 } | 224 } |
| 222 | 225 |
| 223 void MainThreadEventQueue::DispatchRafAlignedInput() { | 226 void MainThreadEventQueue::DispatchRafAlignedInput() { |
| 224 if (!handle_raf_aligned_input_) | 227 if (RafAlignedInputDisabled()) |
| 225 return; | 228 return; |
| 226 | 229 |
| 227 std::deque<std::unique_ptr<EventWithDispatchType>> events_to_process; | 230 std::deque<std::unique_ptr<EventWithDispatchType>> events_to_process; |
| 228 { | 231 { |
| 229 base::AutoLock lock(shared_state_lock_); | 232 base::AutoLock lock(shared_state_lock_); |
| 230 shared_state_.sent_main_frame_request_ = false; | 233 shared_state_.sent_main_frame_request_ = false; |
| 231 | 234 |
| 232 while(!shared_state_.events_.empty()) { | 235 while(!shared_state_.events_.empty()) { |
| 233 if (!isContinuousEvent(shared_state_.events_.front())) | 236 if (!IsContinuousEvent(shared_state_.events_.front())) |
| 234 break; | 237 break; |
| 235 events_to_process.emplace_back(shared_state_.events_.Pop()); | 238 events_to_process.emplace_back(shared_state_.events_.Pop()); |
| 236 } | 239 } |
| 237 } | 240 } |
| 238 | 241 |
| 239 while(!events_to_process.empty()) { | 242 while(!events_to_process.empty()) { |
| 240 in_flight_event_ = std::move(events_to_process.front()); | 243 in_flight_event_ = std::move(events_to_process.front()); |
| 241 events_to_process.pop_front(); | 244 events_to_process.pop_front(); |
| 242 DispatchInFlightEvent(); | 245 DispatchInFlightEvent(); |
| 243 } | 246 } |
| 244 PossiblyScheduleMainFrame(); | 247 PossiblyScheduleMainFrame(); |
| 245 } | 248 } |
| 246 | 249 |
| 247 void MainThreadEventQueue::SendEventNotificationToMainThread() { | 250 void MainThreadEventQueue::SendEventNotificationToMainThread() { |
| 248 main_task_runner_->PostTask( | 251 main_task_runner_->PostTask( |
| 249 FROM_HERE, base::Bind(&MainThreadEventQueue::DispatchSingleEvent, this)); | 252 FROM_HERE, base::Bind(&MainThreadEventQueue::DispatchSingleEvent, this)); |
| 250 } | 253 } |
| 251 | 254 |
| 252 void MainThreadEventQueue::QueueEvent( | 255 void MainThreadEventQueue::QueueEvent( |
| 253 std::unique_ptr<EventWithDispatchType> event) { | 256 std::unique_ptr<EventWithDispatchType> event) { |
| 254 bool is_continuous = isContinuousEvent(event); | 257 bool is_continuous = IsContinuousEvent(event); |
| 255 size_t send_notification_count = 0; | 258 size_t send_notification_count = 0; |
| 256 bool needs_main_frame = false; | 259 bool needs_main_frame = false; |
| 257 { | 260 { |
| 258 base::AutoLock lock(shared_state_lock_); | 261 base::AutoLock lock(shared_state_lock_); |
| 259 size_t size_before = shared_state_.events_.size(); | 262 size_t size_before = shared_state_.events_.size(); |
| 260 shared_state_.events_.Queue(std::move(event)); | 263 shared_state_.events_.Queue(std::move(event)); |
| 261 size_t size_after = shared_state_.events_.size(); | 264 size_t size_after = shared_state_.events_.size(); |
| 265 | |
| 262 if (size_before != size_after) { | 266 if (size_before != size_after) { |
| 263 if (!handle_raf_aligned_input_) { | 267 if (RafAlignedInputDisabled()) { |
| 264 send_notification_count = 1; | 268 send_notification_count = 1; |
| 265 } else if (!is_continuous) { | 269 } else if (!is_continuous) { |
| 266 send_notification_count = 1; | 270 send_notification_count = 1; |
| 267 // If we had just enqueued a non-rAF input event we will send a series | 271 // If we had just enqueued a non-rAF input event we will send a series |
| 268 // of normal post messages to ensure they are all handled right away. | 272 // of normal post messages to ensure they are all handled right away. |
| 269 for (size_t pos = size_after - 1; pos >= 1; --pos) { | 273 for (size_t pos = size_after - 1; pos >= 1; --pos) { |
| 270 if (isContinuousEvent(shared_state_.events_.at(pos - 1))) | 274 if (IsContinuousEvent(shared_state_.events_.at(pos - 1))) |
| 271 send_notification_count++; | 275 send_notification_count++; |
| 272 else | 276 else |
| 273 break; | 277 break; |
| 274 } | 278 } |
| 275 } else { | 279 } else { |
| 276 needs_main_frame = !shared_state_.sent_main_frame_request_; | 280 needs_main_frame = !shared_state_.sent_main_frame_request_; |
| 277 shared_state_.sent_main_frame_request_ = true; | 281 shared_state_.sent_main_frame_request_ = true; |
| 278 } | 282 } |
| 279 } | 283 } |
| 280 } | 284 } |
| 281 for (size_t i = 0; i < send_notification_count; ++i) | 285 for (size_t i = 0; i < send_notification_count; ++i) |
| 282 SendEventNotificationToMainThread(); | 286 SendEventNotificationToMainThread(); |
| 283 if (needs_main_frame) | 287 if (needs_main_frame) |
| 284 client_->NeedsMainFrame(routing_id_); | 288 client_->NeedsMainFrame(routing_id_); |
| 285 } | 289 } |
| 286 | 290 |
| 291 bool MainThreadEventQueue::RafAlignedInputDisabled() { | |
| 292 return !handle_raf_aligned_mouse_input_ && !handle_raf_aligned_touch_input_; | |
| 293 } | |
| 294 | |
| 295 bool MainThreadEventQueue::IsContinuousEvent( | |
|
tdresser
2016/10/25 17:37:44
Can we name this more clearly? Whether or not rAF
dtapuska
2016/10/26 02:34:52
Done.
| |
| 296 const std::unique_ptr<EventWithDispatchType>& event) { | |
| 297 switch (event->event().type) { | |
| 298 case blink::WebInputEvent::MouseMove: | |
| 299 case blink::WebInputEvent::MouseWheel: | |
| 300 return handle_raf_aligned_mouse_input_; | |
| 301 case blink::WebInputEvent::TouchMove: | |
| 302 // TouchMoves that are blocking end up blocking scroll. Do not treat | |
| 303 // them as continuous events otherwise we will end up waiting up to an | |
| 304 // additional frame. | |
| 305 return static_cast<const blink::WebTouchEvent&>(event->event()) | |
| 306 .dispatchType != blink::WebInputEvent::Blocking && | |
| 307 handle_raf_aligned_touch_input_; | |
| 308 default: | |
| 309 return false; | |
| 310 } | |
| 311 } | |
| 312 | |
| 287 } // namespace content | 313 } // namespace content |
| OLD | NEW |