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 |