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

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

Issue 156783006: Consuming a touch move prevents only the next scroll update. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Clean up error handling and tests. Created 6 years, 10 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 | Annotate | Revision Log
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"
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 // This is the list of the original events that were coalesced. 285 // This is the list of the original events that were coalesced.
286 WebTouchEventWithLatencyList events_; 286 WebTouchEventWithLatencyList events_;
287 287
288 // If |ignore_ack_| is true, don't send this touch event to client 288 // If |ignore_ack_| is true, don't send this touch event to client
289 // when the event is acked. 289 // when the event is acked.
290 bool ignore_ack_; 290 bool ignore_ack_;
291 291
292 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); 292 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
293 }; 293 };
294 294
295 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) 295 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
296 TouchScrollingMode mode)
296 : client_(client), 297 : client_(client),
297 dispatching_touch_ack_(NULL), 298 dispatching_touch_ack_(NULL),
298 dispatching_touch_(false), 299 dispatching_touch_(false),
299 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT), 300 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
300 ack_timeout_enabled_(false) { 301 ack_timeout_enabled_(false),
302 touch_scrolling_mode_(mode),
303 absorbing_touch_moves_(false) {
301 DCHECK(client); 304 DCHECK(client);
302 } 305 }
303 306
304 TouchEventQueue::~TouchEventQueue() { 307 TouchEventQueue::~TouchEventQueue() {
305 if (!touch_queue_.empty()) 308 if (!touch_queue_.empty())
306 STLDeleteElements(&touch_queue_); 309 STLDeleteElements(&touch_queue_);
307 } 310 }
308 311
309 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 312 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
310 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); 313 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent");
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer"); 397 TRACE_EVENT0("input", "TouchEventQueue::ForwardToRenderer");
395 398
396 DCHECK(!dispatching_touch_); 399 DCHECK(!dispatching_touch_);
397 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES); 400 DCHECK_NE(touch_filtering_state_, DROP_ALL_TOUCHES);
398 401
399 if (IsNewTouchSequence(touch.event)) { 402 if (IsNewTouchSequence(touch.event)) {
400 touch_filtering_state_ = 403 touch_filtering_state_ =
401 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT 404 ack_timeout_enabled_ ? FORWARD_TOUCHES_UNTIL_TIMEOUT
402 : FORWARD_ALL_TOUCHES; 405 : FORWARD_ALL_TOUCHES;
403 touch_ack_states_.clear(); 406 touch_ack_states_.clear();
407 absorbing_touch_moves_ = false;
404 } 408 }
405 409
406 // A synchronous ack will reset |dispatching_touch_|, in which case 410 // A synchronous ack will reset |dispatching_touch_|, in which case
407 // the touch timeout should not be started. 411 // the touch timeout should not be started.
408 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); 412 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
409 client_->SendTouchEventImmediately(touch); 413 client_->SendTouchEventImmediately(touch);
410 if (dispatching_touch_ && 414 if (dispatching_touch_ &&
411 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT && 415 touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT &&
412 ShouldTouchTypeTriggerTimeout(touch.event.type)) { 416 ShouldTouchTypeTriggerTimeout(touch.event.type)) {
413 DCHECK(timeout_handler_); 417 DCHECK(timeout_handler_);
414 timeout_handler_->Start(touch); 418 timeout_handler_->Start(touch);
415 } 419 }
416 } 420 }
417 421
418 void TouchEventQueue::OnGestureScrollEvent( 422 void TouchEventQueue::OnGestureScrollEvent(
419 const GestureEventWithLatencyInfo& gesture_event) { 423 const GestureEventWithLatencyInfo& gesture_event) {
420 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin) 424 if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin)
421 return; 425 return;
422 426
427 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL)
428 return;
429
423 // We assume that scroll events are generated synchronously from 430 // We assume that scroll events are generated synchronously from
424 // dispatching a touch event ack. This allows us to generate a synthetic 431 // dispatching a touch event ack. This allows us to generate a synthetic
425 // cancel event that has the same touch ids as the touch event that 432 // cancel event that has the same touch ids as the touch event that
426 // is being acked. Otherwise, we don't perform the touch-cancel optimization. 433 // is being acked. Otherwise, we don't perform the touch-cancel optimization.
427 if (!dispatching_touch_ack_) 434 if (!dispatching_touch_ack_)
428 return; 435 return;
429 436
430 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE) 437 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE)
431 return; 438 return;
432 439
433 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 440 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
434 441
435 // Fake a TouchCancel to cancel the touch points of the touch event 442 // Fake a TouchCancel to cancel the touch points of the touch event
436 // that is currently being acked. 443 // that is currently being acked.
437 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we 444 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
438 // are in the scope of PopTouchEventToClient() and that no touch event 445 // are in the scope of PopTouchEventToClient() and that no touch event
439 // in the queue is waiting for ack from renderer. So we can just insert 446 // in the queue is waiting for ack from renderer. So we can just insert
440 // the touch cancel at the beginning of the queue. 447 // the touch cancel at the beginning of the queue.
441 touch_queue_.push_front(new CoalescedWebTouchEvent( 448 touch_queue_.push_front(new CoalescedWebTouchEvent(
442 ObtainCancelEventForTouchEvent( 449 ObtainCancelEventForTouchEvent(
443 dispatching_touch_ack_->coalesced_event()), true)); 450 dispatching_touch_ack_->coalesced_event()), true));
444 } 451 }
445 452
453 void TouchEventQueue::OnGestureEventAck(
454 const GestureEventWithLatencyInfo& event,
455 InputEventAckState ack_result) {
456 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE)
457 return;
458
459 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate)
460 return;
461
462 // Suspend sending touchmove events as long as the scroll events are handled.
463 // Note that there's no guarantee that this ACK is for the most recent
464 // gesture event (or even part of the current sequence). Worse case, the
465 // delay in updating the absorption state should onl result in minor UI
466 // glitches.
467 // TODO(rbyers): Define precise timing requirements and potentially implement
468 // mitigations for races.
469 absorbing_touch_moves_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
470 }
471
446 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { 472 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
447 DCHECK(!dispatching_touch_ack_); 473 DCHECK(!dispatching_touch_ack_);
448 DCHECK(!dispatching_touch_); 474 DCHECK(!dispatching_touch_);
449 475
450 if (has_handlers) { 476 if (has_handlers) {
451 if (touch_filtering_state_ == DROP_ALL_TOUCHES) { 477 if (touch_filtering_state_ == DROP_ALL_TOUCHES) {
452 // If no touch handler was previously registered, ensure that we don't 478 // If no touch handler was previously registered, ensure that we don't
453 // send a partial touch sequence to the renderer. 479 // send a partial touch sequence to the renderer.
454 DCHECK(touch_queue_.empty()); 480 DCHECK(touch_queue_.empty());
455 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 481 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 if (touch_filtering_state_ == DROP_ALL_TOUCHES) 587 if (touch_filtering_state_ == DROP_ALL_TOUCHES)
562 return ACK_WITH_NO_CONSUMER_EXISTS; 588 return ACK_WITH_NO_CONSUMER_EXISTS;
563 589
564 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE && 590 if (touch_filtering_state_ == DROP_TOUCHES_IN_SEQUENCE &&
565 event.type != WebInputEvent::TouchCancel) { 591 event.type != WebInputEvent::TouchCancel) {
566 if (IsNewTouchSequence(event)) 592 if (IsNewTouchSequence(event))
567 return FORWARD_TO_RENDERER; 593 return FORWARD_TO_RENDERER;
568 return ACK_WITH_NOT_CONSUMED; 594 return ACK_WITH_NOT_CONSUMED;
569 } 595 }
570 596
597 if (absorbing_touch_moves_ && event.type == WebInputEvent::TouchMove)
598 return ACK_WITH_NOT_CONSUMED;
599
571 // Touch press events should always be forwarded to the renderer. 600 // Touch press events should always be forwarded to the renderer.
572 if (event.type == WebInputEvent::TouchStart) 601 if (event.type == WebInputEvent::TouchStart)
573 return FORWARD_TO_RENDERER; 602 return FORWARD_TO_RENDERER;
574 603
575 for (unsigned int i = 0; i < event.touchesLength; ++i) { 604 for (unsigned int i = 0; i < event.touchesLength; ++i) {
576 const WebTouchPoint& point = event.touches[i]; 605 const WebTouchPoint& point = event.touches[i];
577 // If a point has been stationary, then don't take it into account. 606 // If a point has been stationary, then don't take it into account.
578 if (point.state == WebTouchPoint::StateStationary) 607 if (point.state == WebTouchPoint::StateStationary)
579 continue; 608 continue;
580 609
(...skipping 26 matching lines...) Expand all
607 } else if (event.type == WebInputEvent::TouchStart) { 636 } else if (event.type == WebInputEvent::TouchStart) {
608 for (unsigned i = 0; i < event.touchesLength; ++i) { 637 for (unsigned i = 0; i < event.touchesLength; ++i) {
609 const WebTouchPoint& point = event.touches[i]; 638 const WebTouchPoint& point = event.touches[i];
610 if (point.state == WebTouchPoint::StatePressed) 639 if (point.state == WebTouchPoint::StatePressed)
611 touch_ack_states_[point.id] = ack_result; 640 touch_ack_states_[point.id] = ack_result;
612 } 641 }
613 } 642 }
614 } 643 }
615 644
616 } // namespace content 645 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698