| 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/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 // Time interval at which touchmove events will be skipped during rAF signal. |
| 18 const base::TimeDelta kAsyncTouchMoveInterval = |
| 19 base::TimeDelta::FromMilliseconds(200); |
| 20 |
| 17 const size_t kTenSeconds = 10 * 1000 * 1000; | 21 const size_t kTenSeconds = 10 * 1000 * 1000; |
| 18 | 22 |
| 19 bool IsContinuousEvent(const std::unique_ptr<EventWithDispatchType>& event) { | 23 bool IsContinuousEvent(const std::unique_ptr<EventWithDispatchType>& event) { |
| 20 switch (event->event().type()) { | 24 switch (event->event().type()) { |
| 21 case blink::WebInputEvent::MouseMove: | 25 case blink::WebInputEvent::MouseMove: |
| 22 case blink::WebInputEvent::MouseWheel: | 26 case blink::WebInputEvent::MouseWheel: |
| 23 case blink::WebInputEvent::TouchMove: | 27 case blink::WebInputEvent::TouchMove: |
| 24 return true; | 28 return true; |
| 25 default: | 29 default: |
| 26 return false; | 30 return false; |
| 27 } | 31 } |
| 28 } | 32 } |
| 29 | 33 |
| 34 bool IsAsyncTouchMove(const std::unique_ptr<EventWithDispatchType>& event) { |
| 35 if (event->event().type() != blink::WebInputEvent::TouchMove) |
| 36 return false; |
| 37 const blink::WebTouchEvent& touch_event = |
| 38 static_cast<const blink::WebTouchEvent&>(event->event()); |
| 39 return touch_event.movedBeyondSlopRegion && !event->originallyCancelable(); |
| 40 } |
| 41 |
| 30 } // namespace | 42 } // namespace |
| 31 | 43 |
| 32 EventWithDispatchType::EventWithDispatchType( | 44 EventWithDispatchType::EventWithDispatchType( |
| 33 ui::WebScopedInputEvent event, | 45 ui::WebScopedInputEvent event, |
| 34 const ui::LatencyInfo& latency, | 46 const ui::LatencyInfo& latency, |
| 35 InputEventDispatchType dispatch_type) | 47 InputEventDispatchType dispatch_type, |
| 48 bool originally_cancelable) |
| 36 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency), | 49 : ScopedWebInputEventWithLatencyInfo(std::move(event), latency), |
| 37 dispatch_type_(dispatch_type), | 50 dispatch_type_(dispatch_type), |
| 38 non_blocking_coalesced_count_(0), | 51 non_blocking_coalesced_count_(0), |
| 39 creation_timestamp_(base::TimeTicks::Now()), | 52 creation_timestamp_(base::TimeTicks::Now()), |
| 40 last_coalesced_timestamp_(creation_timestamp_) {} | 53 last_coalesced_timestamp_(creation_timestamp_), |
| 54 originally_cancelable_(originally_cancelable) {} |
| 41 | 55 |
| 42 EventWithDispatchType::~EventWithDispatchType() {} | 56 EventWithDispatchType::~EventWithDispatchType() {} |
| 43 | 57 |
| 44 void EventWithDispatchType::CoalesceWith(const EventWithDispatchType& other) { | 58 void EventWithDispatchType::CoalesceWith(const EventWithDispatchType& other) { |
| 45 // If this event was blocking push the event id to the blocking | 59 // If this event was blocking push the event id to the blocking |
| 46 // list before updating the dispatch_type of this event. | 60 // list before updating the dispatch_type of this event. |
| 47 if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) { | 61 if (dispatch_type_ == DISPATCH_TYPE_BLOCKING) { |
| 48 blocking_coalesced_event_ids_.push_back( | 62 blocking_coalesced_event_ids_.push_back( |
| 49 ui::WebInputEventTraits::GetUniqueTouchEventId(event())); | 63 ui::WebInputEventTraits::GetUniqueTouchEventId(event())); |
| 50 } else { | 64 } else { |
| 51 non_blocking_coalesced_count_++; | 65 non_blocking_coalesced_count_++; |
| 52 } | 66 } |
| 53 ScopedWebInputEventWithLatencyInfo::CoalesceWith(other); | 67 ScopedWebInputEventWithLatencyInfo::CoalesceWith(other); |
| 54 dispatch_type_ = other.dispatch_type_; | 68 dispatch_type_ = other.dispatch_type_; |
| 55 last_coalesced_timestamp_ = base::TimeTicks::Now(); | 69 last_coalesced_timestamp_ = base::TimeTicks::Now(); |
| 70 originally_cancelable_ = other.originally_cancelable_; |
| 56 } | 71 } |
| 57 | 72 |
| 58 MainThreadEventQueue::SharedState::SharedState() | 73 MainThreadEventQueue::SharedState::SharedState() |
| 59 : sent_main_frame_request_(false) {} | 74 : sent_main_frame_request_(false) {} |
| 60 | 75 |
| 61 MainThreadEventQueue::SharedState::~SharedState() {} | 76 MainThreadEventQueue::SharedState::~SharedState() {} |
| 62 | 77 |
| 63 MainThreadEventQueue::MainThreadEventQueue( | 78 MainThreadEventQueue::MainThreadEventQueue( |
| 64 int routing_id, | 79 int routing_id, |
| 65 MainThreadEventQueueClient* client, | 80 MainThreadEventQueueClient* client, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 DCHECK(original_dispatch_type == DISPATCH_TYPE_BLOCKING || | 124 DCHECK(original_dispatch_type == DISPATCH_TYPE_BLOCKING || |
| 110 original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING); | 125 original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING); |
| 111 DCHECK(ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING || | 126 DCHECK(ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING || |
| 112 ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING || | 127 ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING || |
| 113 ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED); | 128 ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| 114 | 129 |
| 115 bool non_blocking = original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING || | 130 bool non_blocking = original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING || |
| 116 ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING; | 131 ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING; |
| 117 bool is_wheel = event->type() == blink::WebInputEvent::MouseWheel; | 132 bool is_wheel = event->type() == blink::WebInputEvent::MouseWheel; |
| 118 bool is_touch = blink::WebInputEvent::isTouchEventType(event->type()); | 133 bool is_touch = blink::WebInputEvent::isTouchEventType(event->type()); |
| 134 bool originally_cancelable = false; |
| 119 | 135 |
| 120 if (is_touch) { | 136 if (is_touch) { |
| 121 blink::WebTouchEvent* touch_event = | 137 blink::WebTouchEvent* touch_event = |
| 122 static_cast<blink::WebTouchEvent*>(event.get()); | 138 static_cast<blink::WebTouchEvent*>(event.get()); |
| 123 | 139 |
| 140 originally_cancelable = |
| 141 touch_event->dispatchType == blink::WebInputEvent::Blocking; |
| 142 |
| 124 // Adjust the |dispatchType| on the event since the compositor | 143 // Adjust the |dispatchType| on the event since the compositor |
| 125 // determined all event listeners are passive. | 144 // determined all event listeners are passive. |
| 126 if (non_blocking) { | 145 if (non_blocking) { |
| 127 touch_event->dispatchType = | 146 touch_event->dispatchType = |
| 128 blink::WebInputEvent::ListenersNonBlockingPassive; | 147 blink::WebInputEvent::ListenersNonBlockingPassive; |
| 129 } | 148 } |
| 130 if (touch_event->type() == blink::WebInputEvent::TouchStart) | 149 if (touch_event->type() == blink::WebInputEvent::TouchStart) |
| 131 last_touch_start_forced_nonblocking_due_to_fling_ = false; | 150 last_touch_start_forced_nonblocking_due_to_fling_ = false; |
| 132 | 151 |
| 133 if (enable_fling_passive_listener_flag_ && | 152 if (enable_fling_passive_listener_flag_ && |
| (...skipping 20 matching lines...) Expand all Loading... |
| 154 ListenersForcedNonBlockingDueToMainThreadResponsiveness; | 173 ListenersForcedNonBlockingDueToMainThreadResponsiveness; |
| 155 non_blocking = true; | 174 non_blocking = true; |
| 156 } | 175 } |
| 157 } | 176 } |
| 158 // If the event is non-cancelable ACK it right away. | 177 // If the event is non-cancelable ACK it right away. |
| 159 if (!non_blocking && | 178 if (!non_blocking && |
| 160 touch_event->dispatchType != blink::WebInputEvent::Blocking) | 179 touch_event->dispatchType != blink::WebInputEvent::Blocking) |
| 161 non_blocking = true; | 180 non_blocking = true; |
| 162 } | 181 } |
| 163 | 182 |
| 164 if (is_wheel && non_blocking) { | 183 if (is_wheel) { |
| 165 // Adjust the |dispatchType| on the event since the compositor | 184 blink::WebMouseWheelEvent* wheel_event = |
| 166 // determined all event listeners are passive. | 185 static_cast<blink::WebMouseWheelEvent*>(event.get()); |
| 167 static_cast<blink::WebMouseWheelEvent*>(event.get()) | 186 originally_cancelable = |
| 168 ->dispatchType = blink::WebInputEvent::ListenersNonBlockingPassive; | 187 wheel_event->dispatchType == blink::WebInputEvent::Blocking; |
| 188 if (non_blocking) { |
| 189 // Adjust the |dispatchType| on the event since the compositor |
| 190 // determined all event listeners are passive. |
| 191 wheel_event->dispatchType = |
| 192 blink::WebInputEvent::ListenersNonBlockingPassive; |
| 193 } |
| 169 } | 194 } |
| 170 | 195 |
| 171 InputEventDispatchType dispatch_type = | 196 InputEventDispatchType dispatch_type = |
| 172 non_blocking ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING; | 197 non_blocking ? DISPATCH_TYPE_NON_BLOCKING : DISPATCH_TYPE_BLOCKING; |
| 173 | 198 |
| 174 std::unique_ptr<EventWithDispatchType> event_with_dispatch_type( | 199 std::unique_ptr<EventWithDispatchType> event_with_dispatch_type( |
| 175 new EventWithDispatchType(std::move(event), latency, dispatch_type)); | 200 new EventWithDispatchType(std::move(event), latency, dispatch_type, |
| 201 originally_cancelable)); |
| 176 | 202 |
| 177 QueueEvent(std::move(event_with_dispatch_type)); | 203 QueueEvent(std::move(event_with_dispatch_type)); |
| 178 | 204 |
| 179 // send an ack when we are non-blocking. | 205 // send an ack when we are non-blocking. |
| 180 return non_blocking; | 206 return non_blocking; |
| 181 } | 207 } |
| 182 | 208 |
| 183 void MainThreadEventQueue::DispatchInFlightEvent() { | 209 void MainThreadEventQueue::DispatchInFlightEvent() { |
| 184 if (in_flight_event_) { | 210 if (in_flight_event_) { |
| 185 // Report the coalesced count only for continuous events; otherwise | 211 // Report the coalesced count only for continuous events; otherwise |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 for (const auto id : in_flight_event_->blockingCoalescedEventIds()) { | 288 for (const auto id : in_flight_event_->blockingCoalescedEventIds()) { |
| 263 client_->SendInputEventAck(routing_id_, type, ack_result, id); | 289 client_->SendInputEventAck(routing_id_, type, ack_result, id); |
| 264 if (renderer_scheduler_) { | 290 if (renderer_scheduler_) { |
| 265 renderer_scheduler_->DidHandleInputEventOnMainThread( | 291 renderer_scheduler_->DidHandleInputEventOnMainThread( |
| 266 in_flight_event_->event(), result); | 292 in_flight_event_->event(), result); |
| 267 } | 293 } |
| 268 } | 294 } |
| 269 } | 295 } |
| 270 } | 296 } |
| 271 | 297 |
| 272 void MainThreadEventQueue::DispatchRafAlignedInput() { | 298 void MainThreadEventQueue::DispatchRafAlignedInput(base::TimeTicks frame_time) { |
| 273 if (IsRafAlignedInputDisabled()) | 299 if (IsRafAlignedInputDisabled()) |
| 274 return; | 300 return; |
| 275 | 301 |
| 276 std::deque<std::unique_ptr<EventWithDispatchType>> events_to_process; | 302 std::deque<std::unique_ptr<EventWithDispatchType>> events_to_process; |
| 277 { | 303 { |
| 278 base::AutoLock lock(shared_state_lock_); | 304 base::AutoLock lock(shared_state_lock_); |
| 279 shared_state_.sent_main_frame_request_ = false; | 305 shared_state_.sent_main_frame_request_ = false; |
| 280 | 306 |
| 281 while(!shared_state_.events_.empty()) { | 307 while (!shared_state_.events_.empty()) { |
| 282 if (!IsRafAlignedEvent(shared_state_.events_.front()->event())) | 308 if (!IsRafAlignedEvent(shared_state_.events_.front()->event())) |
| 283 break; | 309 break; |
| 310 |
| 311 // Throttle touchmoves that are async. |
| 312 if (handle_raf_aligned_touch_input_ && |
| 313 IsAsyncTouchMove(shared_state_.events_.front())) { |
| 314 if (shared_state_.events_.size() == 1 && |
| 315 frame_time < shared_state_.last_async_touch_move_timestamp_ + |
| 316 kAsyncTouchMoveInterval) { |
| 317 break; |
| 318 } |
| 319 shared_state_.last_async_touch_move_timestamp_ = frame_time; |
| 320 } |
| 284 events_to_process.emplace_back(shared_state_.events_.Pop()); | 321 events_to_process.emplace_back(shared_state_.events_.Pop()); |
| 285 } | 322 } |
| 286 } | 323 } |
| 287 | 324 |
| 288 while(!events_to_process.empty()) { | 325 while(!events_to_process.empty()) { |
| 289 in_flight_event_ = std::move(events_to_process.front()); | 326 in_flight_event_ = std::move(events_to_process.front()); |
| 290 events_to_process.pop_front(); | 327 events_to_process.pop_front(); |
| 291 DispatchInFlightEvent(); | 328 DispatchInFlightEvent(); |
| 292 } | 329 } |
| 293 PossiblyScheduleMainFrame(); | 330 PossiblyScheduleMainFrame(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 case blink::WebInputEvent::MouseWheel: | 398 case blink::WebInputEvent::MouseWheel: |
| 362 return handle_raf_aligned_mouse_input_; | 399 return handle_raf_aligned_mouse_input_; |
| 363 case blink::WebInputEvent::TouchMove: | 400 case blink::WebInputEvent::TouchMove: |
| 364 return handle_raf_aligned_touch_input_; | 401 return handle_raf_aligned_touch_input_; |
| 365 default: | 402 default: |
| 366 return false; | 403 return false; |
| 367 } | 404 } |
| 368 } | 405 } |
| 369 | 406 |
| 370 } // namespace content | 407 } // namespace content |
| OLD | NEW |