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

Side by Side Diff: content/browser/renderer_host/input/touch_event_queue.cc

Issue 245833002: Implement async touchmove dispatch during scroll (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup Created 6 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/browser/renderer_host/input/touch_event_queue.h" 5 #include "content/browser/renderer_host/input/touch_event_queue.h"
6 6
7 #include "base/auto_reset.h" 7 #include "base/auto_reset.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "content/browser/renderer_host/input/timeout_monitor.h" 11 #include "content/browser/renderer_host/input/timeout_monitor.h"
12 #include "content/browser/renderer_host/input/web_touch_event_traits.h" 12 #include "content/browser/renderer_host/input/web_touch_event_traits.h"
13 #include "content/public/common/content_switches.h" 13 #include "content/public/common/content_switches.h"
14 #include "ui/gfx/geometry/point_f.h" 14 #include "ui/gfx/geometry/point_f.h"
15 15
16 using blink::WebInputEvent; 16 using blink::WebInputEvent;
17 using blink::WebTouchEvent; 17 using blink::WebTouchEvent;
18 using blink::WebTouchPoint; 18 using blink::WebTouchPoint;
19 using ui::LatencyInfo; 19 using ui::LatencyInfo;
20 20
21 namespace content { 21 namespace content {
22 namespace { 22 namespace {
23 23
24 const double kAsyncTouchMoveIntervalS = .2;
25
24 // Using a small epsilon when comparing slop distances allows pixel perfect 26 // Using a small epsilon when comparing slop distances allows pixel perfect
25 // slop determination when using fractional DIP coordinates (assuming the slop 27 // slop determination when using fractional DIP coordinates (assuming the slop
26 // region and DPI scale are reasonably proportioned). 28 // region and DPI scale are reasonably proportioned).
27 const float kSlopEpsilon = .05f; 29 const float kSlopEpsilon = .05f;
28 30
29 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; 31 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
30 32
31 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( 33 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
32 const TouchEventWithLatencyInfo& event_to_cancel) { 34 const TouchEventWithLatencyInfo& event_to_cancel) {
33 TouchEventWithLatencyInfo event = event_to_cancel; 35 TouchEventWithLatencyInfo event = event_to_cancel;
34 event.event.type = WebInputEvent::TouchCancel; 36 event.event.type = WebInputEvent::TouchCancel;
35 for (size_t i = 0; i < event.event.touchesLength; i++) 37 for (size_t i = 0; i < event.event.touchesLength; i++)
36 event.event.touches[i].state = WebTouchPoint::StateCancelled; 38 event.event.touches[i].state = WebTouchPoint::StateCancelled;
37 return event; 39 return event;
38 } 40 }
39 41
40 bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) { 42 bool ShouldTouchTriggerTimeout(const WebInputEvent& event) {
41 return type == WebInputEvent::TouchStart || 43 return (event.type == WebInputEvent::TouchStart ||
42 type == WebInputEvent::TouchMove; 44 event.type == WebInputEvent::TouchMove) &&
45 !WebInputEventTraits::IgnoresAckDisposition(event);
43 } 46 }
44 47
45 } // namespace 48 } // namespace
46 49
47 50
48 // Cancels a touch sequence if a touchstart or touchmove ack response is 51 // Cancels a touch sequence if a touchstart or touchmove ack response is
49 // sufficiently delayed. 52 // sufficiently delayed.
50 class TouchEventQueue::TouchTimeoutHandler { 53 class TouchEventQueue::TouchTimeoutHandler {
51 public: 54 public:
52 TouchTimeoutHandler(TouchEventQueue* touch_queue, 55 TouchTimeoutHandler(TouchEventQueue* touch_queue,
53 base::TimeDelta timeout_delay) 56 base::TimeDelta timeout_delay)
54 : touch_queue_(touch_queue), 57 : touch_queue_(touch_queue),
55 timeout_delay_(timeout_delay), 58 timeout_delay_(timeout_delay),
56 pending_ack_state_(PENDING_ACK_NONE), 59 pending_ack_state_(PENDING_ACK_NONE),
57 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut, 60 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
58 base::Unretained(this))) {} 61 base::Unretained(this))) {}
59 62
60 ~TouchTimeoutHandler() {} 63 ~TouchTimeoutHandler() {}
61 64
62 void Start(const TouchEventWithLatencyInfo& event) { 65 void Start(const TouchEventWithLatencyInfo& event) {
63 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); 66 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
64 DCHECK(ShouldTouchTypeTriggerTimeout(event.event.type)); 67 DCHECK(ShouldTouchTriggerTimeout(event.event));
65 timeout_event_ = event; 68 timeout_event_ = event;
66 timeout_monitor_.Restart(timeout_delay_); 69 timeout_monitor_.Restart(timeout_delay_);
67 } 70 }
68 71
69 bool ConfirmTouchEvent(InputEventAckState ack_result) { 72 bool ConfirmTouchEvent(InputEventAckState ack_result) {
70 switch (pending_ack_state_) { 73 switch (pending_ack_state_) {
71 case PENDING_ACK_NONE: 74 case PENDING_ACK_NONE:
72 timeout_monitor_.Stop(); 75 timeout_monitor_.Stop();
73 return false; 76 return false;
74 case PENDING_ACK_ORIGINAL_EVENT: 77 case PENDING_ACK_ORIGINAL_EVENT:
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 // track of all the original touch-events that were coalesced into a single 226 // track of all the original touch-events that were coalesced into a single
224 // event. The coalesced event is forwarded to the renderer, while the original 227 // event. The coalesced event is forwarded to the renderer, while the original
225 // touch-events are sent to the Client (on ACK for the coalesced event) so that 228 // touch-events are sent to the Client (on ACK for the coalesced event) so that
226 // the Client receives the event with their original timestamp. 229 // the Client receives the event with their original timestamp.
227 class CoalescedWebTouchEvent { 230 class CoalescedWebTouchEvent {
228 public: 231 public:
229 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event, 232 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
230 bool ignore_ack) 233 bool ignore_ack)
231 : coalesced_event_(event), 234 : coalesced_event_(event),
232 ignore_ack_(ignore_ack) { 235 ignore_ack_(ignore_ack) {
233 events_.push_back(event); 236 if (!ignore_ack_)
234 TRACE_EVENT_ASYNC_BEGIN0( 237 events_.push_back(event);
235 "input", "TouchEventQueue::QueueEvent", this); 238 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventQueue::QueueEvent", this);
236 } 239 }
237 240
238 ~CoalescedWebTouchEvent() { 241 ~CoalescedWebTouchEvent() {
239 TRACE_EVENT_ASYNC_END0( 242 TRACE_EVENT_ASYNC_END0("input", "TouchEventQueue::QueueEvent", this);
240 "input", "TouchEventQueue::QueueEvent", this);
241 } 243 }
242 244
243 // Coalesces the event with the existing event if possible. Returns whether 245 // Coalesces the event with the existing event if possible. Returns whether
244 // the event was coalesced. 246 // the event was coalesced.
245 bool CoalesceEventIfPossible( 247 bool CoalesceEventIfPossible(
246 const TouchEventWithLatencyInfo& event_with_latency) { 248 const TouchEventWithLatencyInfo& event_with_latency) {
247 if (ignore_ack_) 249 if (ignore_ack_)
248 return false; 250 return false;
249 251
250 if (!coalesced_event_.CanCoalesceWith(event_with_latency)) 252 if (!coalesced_event_.CanCoalesceWith(event_with_latency))
251 return false; 253 return false;
252 254
253 TRACE_EVENT_INSTANT0( 255 TRACE_EVENT_INSTANT0(
254 "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD); 256 "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD);
255 coalesced_event_.CoalesceWith(event_with_latency); 257 coalesced_event_.CoalesceWith(event_with_latency);
256 events_.push_back(event_with_latency);
257 return true; 258 return true;
258 } 259 }
259 260
260 const TouchEventWithLatencyInfo& coalesced_event() const { 261 const TouchEventWithLatencyInfo& coalesced_event() const {
261 return coalesced_event_; 262 return coalesced_event_;
262 } 263 }
263 264
264 WebTouchEventWithLatencyList::iterator begin() { 265 WebTouchEventWithLatencyList::iterator begin() {
266 DCHECK(!ignore_ack_);
aelias_OOO_until_Jul13 2014/04/22 01:56:39 This is a bit ugly. Instead of returning these it
jdduke (slow) 2014/04/23 19:57:41 Done.
267 return events_.begin();
268 }
269
270 WebTouchEventWithLatencyList::const_iterator begin() const {
271 DCHECK(!ignore_ack_);
265 return events_.begin(); 272 return events_.begin();
266 } 273 }
267 274
268 WebTouchEventWithLatencyList::iterator end() { 275 WebTouchEventWithLatencyList::iterator end() {
276 DCHECK(!ignore_ack_);
269 return events_.end(); 277 return events_.end();
270 } 278 }
271 279
272 size_t size() const { return events_.size(); } 280 WebTouchEventWithLatencyList::const_iterator end() const {
281 DCHECK(!ignore_ack_);
282 return events_.end();
283 }
273 284
274 bool ignore_ack() const { return ignore_ack_; } 285 bool ignore_ack() const { return ignore_ack_; }
275 286
276 private: 287 private:
277 // This is the event that is forwarded to the renderer. 288 // This is the event that is forwarded to the renderer.
278 TouchEventWithLatencyInfo coalesced_event_; 289 TouchEventWithLatencyInfo coalesced_event_;
279 290
280 // This is the list of the original events that were coalesced. 291 // This is the list of the original events that were coalesced.
281 WebTouchEventWithLatencyList events_; 292 WebTouchEventWithLatencyList events_;
282 293
283 // If |ignore_ack_| is true, don't send this touch event to client 294 // If |ignore_ack_| is true, don't send this touch event to client
284 // when the event is acked. 295 // when the event is acked.
285 bool ignore_ack_; 296 bool ignore_ack_;
aelias_OOO_until_Jul13 2014/04/22 01:56:39 Would async_ be a better name?
jdduke (slow) 2014/04/23 19:57:41 Probably, yes.
286 297
287 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); 298 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
288 }; 299 };
289 300
290 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, 301 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
291 TouchScrollingMode mode, 302 TouchScrollingMode mode,
292 double touchmove_suppression_length_dips) 303 double touchmove_suppression_length_dips)
293 : client_(client), 304 : client_(client),
294 dispatching_touch_ack_(NULL), 305 dispatching_touch_ack_(NULL),
295 dispatching_touch_(false), 306 dispatching_touch_(false),
296 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT), 307 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
297 ack_timeout_enabled_(false), 308 ack_timeout_enabled_(false),
298 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor( 309 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor(
299 touchmove_suppression_length_dips + kSlopEpsilon)), 310 touchmove_suppression_length_dips + kSlopEpsilon)),
300 absorbing_touch_moves_(false), 311 absorbing_touch_moves_(false),
312 async_touch_moves_(false),
313 last_sent_touch_timestamp_(0),
301 touch_scrolling_mode_(mode) { 314 touch_scrolling_mode_(mode) {
302 DCHECK(client); 315 DCHECK(client);
303 } 316 }
304 317
305 TouchEventQueue::~TouchEventQueue() { 318 TouchEventQueue::~TouchEventQueue() {
306 if (!touch_queue_.empty()) 319 if (!touch_queue_.empty())
307 STLDeleteElements(&touch_queue_); 320 STLDeleteElements(&touch_queue_);
308 } 321 }
309 322
310 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 323 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
311 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); 324 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent");
312 325
326 DCHECK(!dispatching_touch_ack_);
327
313 // If the queueing of |event| was triggered by an ack dispatch, defer 328 // If the queueing of |event| was triggered by an ack dispatch, defer
314 // processing the event until the dispatch has finished. 329 // processing the event until the dispatch has finished.
315 if (touch_queue_.empty() && !dispatching_touch_ack_) { 330 if (touch_queue_.empty()) {
316 // Optimization of the case without touch handlers. Removing this path 331 // Optimization of the case without touch handlers. Removing this path
317 // yields identical results, but this avoids unnecessary allocations. 332 // yields identical results, but this avoids unnecessary allocations.
318 if (touch_filtering_state_ == DROP_ALL_TOUCHES || 333 if (touch_filtering_state_ == DROP_ALL_TOUCHES ||
319 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && 334 (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE &&
320 !WebTouchEventTraits::IsTouchSequenceStart(event.event))) { 335 !WebTouchEventTraits::IsTouchSequenceStart(event.event))) {
321 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); 336 client_->OnTouchEventAck(event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
322 return; 337 return;
323 } 338 }
324 339
325 // There is no touch event in the queue. Forward it to the renderer 340 // There is no touch event in the queue. Forward it to the renderer
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 UpdateTouchAckStates(acked_event, ack_result); 386 UpdateTouchAckStates(acked_event, ack_result);
372 PopTouchEventToClient(ack_result, latency_info); 387 PopTouchEventToClient(ack_result, latency_info);
373 TryForwardNextEventToRenderer(); 388 TryForwardNextEventToRenderer();
374 } 389 }
375 390
376 void TouchEventQueue::TryForwardNextEventToRenderer() { 391 void TouchEventQueue::TryForwardNextEventToRenderer() {
377 DCHECK(!dispatching_touch_ack_); 392 DCHECK(!dispatching_touch_ack_);
378 // If there are queued touch events, then try to forward them to the renderer 393 // If there are queued touch events, then try to forward them to the renderer
379 // immediately, or ACK the events back to the client if appropriate. 394 // immediately, or ACK the events back to the client if appropriate.
380 while (!touch_queue_.empty()) { 395 while (!touch_queue_.empty()) {
381 const TouchEventWithLatencyInfo& touch = 396 PreFilterResult result =
382 touch_queue_.front()->coalesced_event(); 397 FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event);
Rick Byers 2014/04/22 14:52:59 Thanks for the cleanup here - new names/signatures
383 PreFilterResult result = FilterBeforeForwarding(touch.event);
384 switch (result) { 398 switch (result) {
385 case ACK_WITH_NO_CONSUMER_EXISTS: 399 case ACK_WITH_NO_CONSUMER_EXISTS:
386 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, 400 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
387 LatencyInfo());
388 break; 401 break;
389 case ACK_WITH_NOT_CONSUMED: 402 case ACK_WITH_NOT_CONSUMED:
390 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, 403 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
391 LatencyInfo());
392 break; 404 break;
393 case FORWARD_TO_RENDERER: 405 case FORWARD_TO_RENDERER:
394 ForwardToRenderer(touch); 406 ForwardNextEventToRenderer();
395 return; 407 return;
396 } 408 }
397 } 409 }
398 } 410 }
399 411
400 void TouchEventQueue::ForwardToRenderer( 412 void TouchEventQueue::ForwardNextEventToRenderer() {
401 const TouchEventWithLatencyInfo& touch) {
402 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); 413 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer");
403 414
415 DCHECK(!empty());
404 DCHECK(!dispatching_touch_); 416 DCHECK(!dispatching_touch_);
405 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); 417 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES);
418 TouchEventWithLatencyInfo touch = touch_queue_.front()->coalesced_event();
406 419
407 if (WebTouchEventTraits::IsTouchSequenceStart(touch.event)) { 420 if (WebTouchEventTraits::IsTouchSequenceStart(touch.event)) {
408 touch_filtering_state_ = 421 touch_filtering_state_ =
409 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT 422 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT
410 : FORWARD_ALL_TOUCHES; 423 : FORWARD_ALL_TOUCHES;
411 touch_ack_states_.clear(); 424 touch_ack_states_.clear();
412 absorbing_touch_moves_ = false; 425 absorbing_touch_moves_ = false;
426 async_touch_moves_ = false;
413 } 427 }
414 428
429 if (async_touch_moves_ && touch.event.type == WebInputEvent::TouchEnd)
430 touch.event.cancelable = false;
431
432 if (async_touch_moves_ && touch.event.type == WebInputEvent::TouchMove) {
433 // If there are any events following this TouchMove, or sufficient time has
434 // past since sending the last touch event, flush any pending touch moves.
aelias_OOO_until_Jul13 2014/04/22 01:56:39 nit: "past" -> "passed"
jdduke (slow) 2014/04/23 19:57:41 Done.
435 // TODO(jdduke): Should the touchmove be dropped if there are other pending
aelias_OOO_until_Jul13 2014/04/22 01:56:39 I don't think it should be dropped. I think it's
Rick Byers 2014/04/22 14:52:59 Agreed. Coalescing according to our rules is the
436 // events?
437 const bool send_touch_move_now =
438 size() > 1 ||
439 touch.event.timeStampSeconds >
440 last_sent_touch_timestamp_ + kAsyncTouchMoveIntervalS;
441
442 // If there's a pending touchmove, coalescewith the new event. Otherwise
aelias_OOO_until_Jul13 2014/04/22 01:56:39 nit: missing space after "coalesce"
jdduke (slow) 2014/04/23 19:57:41 Done.
443 // create it if necessary for deferral.
444 if (pending_async_touch_move_) {
445 DCHECK(pending_async_touch_move_->CanCoalesceWith(touch));
Rick Byers 2014/04/22 14:52:59 Is this really guaranteed to be true? Eg. what if
jdduke (slow) 2014/04/23 19:57:41 Do our touch events use any modifiers? Android doe
446 pending_async_touch_move_->CoalesceWith(touch);
447 } else {
448 if (!send_touch_move_now)
449 pending_async_touch_move_.reset(new TouchEventWithLatencyInfo(touch));
450 }
451
452 // Ack the event immediately, allowing associated gestures to be dispatched
453 // immediately.
454 if (!send_touch_move_now) {
455 DCHECK(pending_async_touch_move_);
456 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
457 return;
458 }
459
460 if (pending_async_touch_move_)
461 touch = *pending_async_touch_move_.Pass();
462
463 touch.event.cancelable = false;
464 }
465
466 // Sending an event should clear any pending async touchmoves.
467 pending_async_touch_move_.reset();
468 last_sent_touch_timestamp_ = touch.event.timeStampSeconds;
469
415 // A synchronous ack will reset |dispatching_touch_|, in which case 470 // A synchronous ack will reset |dispatching_touch_|, in which case
416 // the touch timeout should not be started. 471 // the touch timeout should not be started.
417 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); 472 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
418 client_->SendTouchEventImmediately(touch); 473 client_->SendTouchEventImmediately(touch);
419 if (dispatching_touch_ && 474 if (dispatching_touch_ &&
420 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT && 475 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT &&
421 ShouldTouchTypeTriggerTimeout(touch.event.type)) { 476 ShouldTouchTriggerTimeout(touch.event)) {
422 DCHECK(timeout_handler_); 477 DCHECK(timeout_handler_);
423 timeout_handler_->Start(touch); 478 timeout_handler_->Start(touch);
424 } 479 }
425 } 480 }
426 481
427 void TouchEventQueue::OnGestureScrollEvent( 482 void TouchEventQueue::OnGestureScrollEvent(
428 const GestureEventWithLatencyInfo& gesture_event) { 483 const GestureEventWithLatencyInfo& gesture_event) {
429 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin) 484 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin)
430 return; 485 return;
431 486
487 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) {
488 pending_async_touch_move_.reset();
489 async_touch_moves_ = true;
490 }
491
432 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE) 492 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE)
433 absorbing_touch_moves_ = true; 493 absorbing_touch_moves_ = true;
434 494
435 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) 495 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL)
436 return; 496 return;
437 497
438 // We assume that scroll events are generated synchronously from 498 // We assume that scroll events are generated synchronously from
439 // dispatching a touch event ack. This allows us to generate a synthetic 499 // dispatching a touch event ack. This allows us to generate a synthetic
440 // cancel event that has the same touch ids as the touch event that 500 // cancel event that has the same touch ids as the touch event that
441 // is being acked. Otherwise, we don't perform the touch-cancel optimization. 501 // is being acked. Otherwise, we don't perform the touch-cancel optimization.
(...skipping 12 matching lines...) Expand all
454 // in the queue is waiting for ack from renderer. So we can just insert 514 // in the queue is waiting for ack from renderer. So we can just insert
455 // the touch cancel at the beginning of the queue. 515 // the touch cancel at the beginning of the queue.
456 touch_queue_.push_front(new CoalescedWebTouchEvent( 516 touch_queue_.push_front(new CoalescedWebTouchEvent(
457 ObtainCancelEventForTouchEvent( 517 ObtainCancelEventForTouchEvent(
458 dispatching_touch_ack_->coalesced_event()), true)); 518 dispatching_touch_ack_->coalesced_event()), true));
459 } 519 }
460 520
461 void TouchEventQueue::OnGestureEventAck( 521 void TouchEventQueue::OnGestureEventAck(
462 const GestureEventWithLatencyInfo& event, 522 const GestureEventWithLatencyInfo& event,
463 InputEventAckState ack_result) { 523 InputEventAckState ack_result) {
464 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE) 524 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate)
465 return; 525 return;
466 526
467 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate) 527 bool event_consumed = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
468 return; 528
529 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) {
530 async_touch_moves_ = event_consumed;
531 if (!async_touch_moves_) {
532 // TODO(jdduke): Should this be flushed?
aelias_OOO_until_Jul13 2014/04/22 01:56:39 I think it should.
533 pending_async_touch_move_.reset();
534 }
535 }
469 536
470 // Suspend sending touchmove events as long as the scroll events are handled. 537 // Suspend sending touchmove events as long as the scroll events are handled.
471 // Note that there's no guarantee that this ACK is for the most recent 538 // Note that there's no guarantee that this ACK is for the most recent
472 // gesture event (or even part of the current sequence). Worst case, the 539 // gesture event (or even part of the current sequence). Worst case, the
473 // delay in updating the absorption state should only result in minor UI 540 // delay in updating the absorption state should only result in minor UI
474 // glitches. 541 // glitches.
475 absorbing_touch_moves_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); 542 if (touch_scrolling_mode_ == TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE)
543 absorbing_touch_moves_ = event_consumed;
476 } 544 }
477 545
478 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { 546 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
479 DCHECK(!dispatching_touch_ack_); 547 DCHECK(!dispatching_touch_ack_);
480 DCHECK(!dispatching_touch_); 548 DCHECK(!dispatching_touch_);
481 549
482 if (has_handlers) { 550 if (has_handlers) {
483 if (touch_filtering_state_ == DROP_ALL_TOUCHES) { 551 if (touch_filtering_state_ == DROP_ALL_TOUCHES) {
484 // If no touch handler was previously registered, ensure that we don't 552 // If no touch handler was previously registered, ensure that we don't
485 // send a partial touch sequence to the renderer. 553 // send a partial touch sequence to the renderer.
486 DCHECK(touch_queue_.empty()); 554 DCHECK(touch_queue_.empty());
487 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 555 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
488 } 556 }
489 } else { 557 } else {
490 // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch 558 // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
491 // state tracking (e.g., if the touch handler was removed mid-sequence). 559 // state tracking (e.g., if the touch handler was removed mid-sequence).
492 touch_filtering_state_ = DROP_ALL_TOUCHES; 560 touch_filtering_state_ = DROP_ALL_TOUCHES;
561 pending_async_touch_move_.reset();
493 if (timeout_handler_) 562 if (timeout_handler_)
494 timeout_handler_->Reset(); 563 timeout_handler_->Reset();
495 if (!touch_queue_.empty()) 564 if (!touch_queue_.empty())
496 ProcessTouchAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, LatencyInfo()); 565 ProcessTouchAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, LatencyInfo());
497 // As there is no touch handler, ack'ing the event should flush the queue. 566 // As there is no touch handler, ack'ing the event should flush the queue.
498 DCHECK(touch_queue_.empty()); 567 DCHECK(touch_queue_.empty());
499 } 568 }
500 } 569 }
501 570
502 bool TouchEventQueue::IsPendingAckTouchStart() const { 571 bool TouchEventQueue::IsPendingAckTouchStart() const {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 } 604 }
536 605
537 const TouchEventWithLatencyInfo& 606 const TouchEventWithLatencyInfo&
538 TouchEventQueue::GetLatestEventForTesting() const { 607 TouchEventQueue::GetLatestEventForTesting() const {
539 return touch_queue_.back()->coalesced_event(); 608 return touch_queue_.back()->coalesced_event();
540 } 609 }
541 610
542 void TouchEventQueue::FlushQueue() { 611 void TouchEventQueue::FlushQueue() {
543 DCHECK(!dispatching_touch_ack_); 612 DCHECK(!dispatching_touch_ack_);
544 DCHECK(!dispatching_touch_); 613 DCHECK(!dispatching_touch_);
614 pending_async_touch_move_.reset();
545 if (touch_filtering_state_ != DROP_ALL_TOUCHES) 615 if (touch_filtering_state_ != DROP_ALL_TOUCHES)
546 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 616 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
547 while (!touch_queue_.empty()) { 617 while (!touch_queue_.empty())
548 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, 618 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
549 LatencyInfo()); 619 }
550 } 620
621 void TouchEventQueue::PopTouchEventToClient(
622 InputEventAckState ack_result) {
623 AckTouchEventToClient(ack_result, *PopTouchEvent());
551 } 624 }
552 625
553 void TouchEventQueue::PopTouchEventToClient( 626 void TouchEventQueue::PopTouchEventToClient(
554 InputEventAckState ack_result, 627 InputEventAckState ack_result,
555 const LatencyInfo& renderer_latency_info) { 628 const LatencyInfo& renderer_latency_info) {
629 scoped_ptr<CoalescedWebTouchEvent> acked_event = PopTouchEvent();
630 if (acked_event->ignore_ack())
631 return;
632 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(),
633 end = acked_event->end();
634 iter != end; ++iter) {
635 iter->latency.AddNewLatencyFrom(renderer_latency_info);
636 }
637 AckTouchEventToClient(ack_result, *acked_event);
638 }
639
640 void TouchEventQueue::AckTouchEventToClient(
641 InputEventAckState ack_result,
642 const CoalescedWebTouchEvent& acked_event) {
556 DCHECK(!dispatching_touch_ack_); 643 DCHECK(!dispatching_touch_ack_);
557 if (touch_queue_.empty()) 644 if (acked_event.ignore_ack())
558 return;
559 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
560 touch_queue_.pop_front();
561
562 if (acked_event->ignore_ack())
563 return; 645 return;
564 646
565 // Note that acking the touch-event may result in multiple gestures being sent 647 // Note that acking the touch-event may result in multiple gestures being sent
566 // to the renderer, or touch-events being queued. 648 // to the renderer, or touch-events being queued.
567 base::AutoReset<CoalescedWebTouchEvent*> 649 base::AutoReset<const CoalescedWebTouchEvent*>
568 dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get()); 650 dispatching_touch_ack(&dispatching_touch_ack_, &acked_event);
569 651
570 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(), 652 for (WebTouchEventWithLatencyList::const_iterator iter = acked_event.begin(),
571 end = acked_event->end(); 653 end = acked_event.end();
572 iter != end; ++iter) { 654 iter != end; ++iter) {
573 iter->latency.AddNewLatencyFrom(renderer_latency_info);
574 client_->OnTouchEventAck((*iter), ack_result); 655 client_->OnTouchEventAck((*iter), ack_result);
575 } 656 }
576 } 657 }
577 658
659 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() {
660 DCHECK(!touch_queue_.empty());
661 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front());
662 touch_queue_.pop_front();
663 return event.Pass();
664 }
665
578 TouchEventQueue::PreFilterResult 666 TouchEventQueue::PreFilterResult
579 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { 667 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
580 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) 668 if (timeout_handler_ && timeout_handler_->FilterEvent(event))
581 return ACK_WITH_NO_CONSUMER_EXISTS; 669 return ACK_WITH_NO_CONSUMER_EXISTS;
582 670
583 if (touchmove_slop_suppressor_->FilterEvent(event)) 671 if (touchmove_slop_suppressor_->FilterEvent(event))
584 return ACK_WITH_NOT_CONSUMED; 672 return ACK_WITH_NOT_CONSUMED;
585 673
586 if (touch_filtering_state_ == DROP_ALL_TOUCHES) 674 if (touch_filtering_state_ == DROP_ALL_TOUCHES)
587 return ACK_WITH_NO_CONSUMER_EXISTS; 675 return ACK_WITH_NO_CONSUMER_EXISTS;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 } else if (event.type == WebInputEvent::TouchStart) { 723 } else if (event.type == WebInputEvent::TouchStart) {
636 for (unsigned i = 0; i < event.touchesLength; ++i) { 724 for (unsigned i = 0; i < event.touchesLength; ++i) {
637 const WebTouchPoint& point = event.touches[i]; 725 const WebTouchPoint& point = event.touches[i];
638 if (point.state == WebTouchPoint::StatePressed) 726 if (point.state == WebTouchPoint::StatePressed)
639 touch_ack_states_[point.id] = ack_result; 727 touch_ack_states_[point.id] = ack_result;
640 } 728 }
641 } 729 }
642 } 730 }
643 731
644 } // namespace content 732 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698