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

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

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

Powered by Google App Engine
This is Rietveld 408576698