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

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

Issue 235003005: Consolidate all touch/gesture related constants in content (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Compilation fixes Created 6 years, 7 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"
9 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
10 #include "base/stl_util.h" 9 #include "base/stl_util.h"
11 #include "content/browser/renderer_host/input/timeout_monitor.h" 10 #include "content/browser/renderer_host/input/timeout_monitor.h"
12 #include "content/common/input/web_touch_event_traits.h" 11 #include "content/common/input/web_touch_event_traits.h"
13 #include "content/public/common/content_switches.h"
14 #include "ui/gfx/geometry/point_f.h" 12 #include "ui/gfx/geometry/point_f.h"
15 13
16 using blink::WebInputEvent; 14 using blink::WebInputEvent;
17 using blink::WebTouchEvent; 15 using blink::WebTouchEvent;
18 using blink::WebTouchPoint; 16 using blink::WebTouchPoint;
19 using ui::LatencyInfo; 17 using ui::LatencyInfo;
20 18
21 namespace content { 19 namespace content {
22 namespace { 20 namespace {
23 21
24 // Time interval at which touchmove events will be forwarded to the client while 22 // Time interval at which touchmove events will be forwarded to the client while
25 // scrolling is active and possible. 23 // scrolling is active and possible.
26 const double kAsyncTouchMoveIntervalSec = .2; 24 const double kAsyncTouchMoveIntervalSec = .2;
27 25
28 // A slop region just larger than that used by many web applications. When 26 // A slop region just larger than that used by many web applications. When
29 // touchmove's are being sent asynchronously, movement outside this region will 27 // touchmove's are being sent asynchronously, movement outside this region will
30 // trigger an immediate async touchmove to cancel potential tap-related logic. 28 // trigger an immediate async touchmove to cancel potential tap-related logic.
31 const double kApplicationSlopRegionLengthDipsSqared = 15. * 15.; 29 const double kApplicationSlopRegionLengthDipsSqared = 15. * 15.;
32 30
33 // Using a small epsilon when comparing slop distances allows pixel perfect 31 // Using a small epsilon when comparing slop distances allows pixel perfect
34 // slop determination when using fractional DIP coordinates (assuming the slop 32 // slop determination when using fractional DIP coordinates (assuming the slop
35 // region and DPI scale are reasonably proportioned). 33 // region and DPI scale are reasonably proportioned).
36 const float kSlopEpsilon = .05f; 34 const float kSlopEpsilon = .05f;
37 35
38 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
39
40 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent( 36 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
41 const TouchEventWithLatencyInfo& event_to_cancel) { 37 const TouchEventWithLatencyInfo& event_to_cancel) {
42 TouchEventWithLatencyInfo event = event_to_cancel; 38 TouchEventWithLatencyInfo event = event_to_cancel;
43 WebTouchEventTraits::ResetTypeAndTouchStates( 39 WebTouchEventTraits::ResetTypeAndTouchStates(
44 WebInputEvent::TouchCancel, 40 WebInputEvent::TouchCancel,
45 // TODO(rbyers): Shouldn't we use a fresh timestamp? 41 // TODO(rbyers): Shouldn't we use a fresh timestamp?
46 event.event.timeStampSeconds, 42 event.event.timeStampSeconds,
47 &event.event); 43 &event.event);
48 return event; 44 return event;
49 } 45 }
(...skipping 16 matching lines...) Expand all
66 // Cancels a touch sequence if a touchstart or touchmove ack response is 62 // Cancels a touch sequence if a touchstart or touchmove ack response is
67 // sufficiently delayed. 63 // sufficiently delayed.
68 class TouchEventQueue::TouchTimeoutHandler { 64 class TouchEventQueue::TouchTimeoutHandler {
69 public: 65 public:
70 TouchTimeoutHandler(TouchEventQueue* touch_queue, 66 TouchTimeoutHandler(TouchEventQueue* touch_queue,
71 base::TimeDelta timeout_delay) 67 base::TimeDelta timeout_delay)
72 : touch_queue_(touch_queue), 68 : touch_queue_(touch_queue),
73 timeout_delay_(timeout_delay), 69 timeout_delay_(timeout_delay),
74 pending_ack_state_(PENDING_ACK_NONE), 70 pending_ack_state_(PENDING_ACK_NONE),
75 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut, 71 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
76 base::Unretained(this))) {} 72 base::Unretained(this))) {
73 DCHECK(timeout_delay != base::TimeDelta());
74 }
77 75
78 ~TouchTimeoutHandler() {} 76 ~TouchTimeoutHandler() {}
79 77
80 void Start(const TouchEventWithLatencyInfo& event) { 78 void Start(const TouchEventWithLatencyInfo& event) {
81 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE); 79 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
82 DCHECK(ShouldTouchTriggerTimeout(event.event)); 80 DCHECK(ShouldTouchTriggerTimeout(event.event));
83 timeout_event_ = event; 81 timeout_event_ = event;
84 timeout_monitor_.Restart(timeout_delay_); 82 timeout_monitor_.Restart(timeout_delay_);
85 } 83 }
86 84
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 188
191 // Provides touchmove slop suppression for a single touch that remains within 189 // Provides touchmove slop suppression for a single touch that remains within
192 // a given slop region, unless the touchstart is preventDefault'ed. 190 // a given slop region, unless the touchstart is preventDefault'ed.
193 // TODO(jdduke): Use a flag bundled with each TouchEvent declaring whether it 191 // TODO(jdduke): Use a flag bundled with each TouchEvent declaring whether it
194 // has exceeded the slop region, removing duplicated slop determination logic. 192 // has exceeded the slop region, removing duplicated slop determination logic.
195 class TouchEventQueue::TouchMoveSlopSuppressor { 193 class TouchEventQueue::TouchMoveSlopSuppressor {
196 public: 194 public:
197 TouchMoveSlopSuppressor(double slop_suppression_length_dips) 195 TouchMoveSlopSuppressor(double slop_suppression_length_dips)
198 : slop_suppression_length_dips_squared_(slop_suppression_length_dips * 196 : slop_suppression_length_dips_squared_(slop_suppression_length_dips *
199 slop_suppression_length_dips), 197 slop_suppression_length_dips),
200 suppressing_touch_moves_(false) {} 198 suppressing_touchmoves_(false) {}
201 199
202 bool FilterEvent(const WebTouchEvent& event) { 200 bool FilterEvent(const WebTouchEvent& event) {
203 if (WebTouchEventTraits::IsTouchSequenceStart(event)) { 201 if (WebTouchEventTraits::IsTouchSequenceStart(event)) {
204 touch_sequence_start_position_ = 202 touch_sequence_start_position_ =
205 gfx::PointF(event.touches[0].position); 203 gfx::PointF(event.touches[0].position);
206 suppressing_touch_moves_ = slop_suppression_length_dips_squared_ != 0; 204 suppressing_touchmoves_ = slop_suppression_length_dips_squared_ != 0;
207 } 205 }
208 206
209 if (event.type != WebInputEvent::TouchMove) 207 if (event.type != WebInputEvent::TouchMove)
210 return false; 208 return false;
211 209
212 if (suppressing_touch_moves_) { 210 if (suppressing_touchmoves_) {
213 // Movement with a secondary pointer should terminate suppression. 211 // Movement with a secondary pointer should terminate suppression.
214 if (event.touchesLength > 1) { 212 if (event.touchesLength > 1) {
215 suppressing_touch_moves_ = false; 213 suppressing_touchmoves_ = false;
216 } else if (event.touchesLength == 1) { 214 } else if (event.touchesLength == 1) {
217 // Movement outside of the slop region should terminate suppression. 215 // Movement outside of the slop region should terminate suppression.
218 gfx::PointF position(event.touches[0].position); 216 gfx::PointF position(event.touches[0].position);
219 if ((position - touch_sequence_start_position_).LengthSquared() > 217 if ((position - touch_sequence_start_position_).LengthSquared() >
220 slop_suppression_length_dips_squared_) 218 slop_suppression_length_dips_squared_)
221 suppressing_touch_moves_ = false; 219 suppressing_touchmoves_ = false;
222 } 220 }
223 } 221 }
224 return suppressing_touch_moves_; 222 return suppressing_touchmoves_;
225 } 223 }
226 224
227 void ConfirmTouchEvent(InputEventAckState ack_result) { 225 void ConfirmTouchEvent(InputEventAckState ack_result) {
228 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) 226 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
229 suppressing_touch_moves_ = false; 227 suppressing_touchmoves_ = false;
230 } 228 }
231 229
232 private: 230 private:
233 double slop_suppression_length_dips_squared_; 231 double slop_suppression_length_dips_squared_;
234 gfx::PointF touch_sequence_start_position_; 232 gfx::PointF touch_sequence_start_position_;
235 bool suppressing_touch_moves_; 233 bool suppressing_touchmoves_;
236 234
237 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor); 235 DISALLOW_COPY_AND_ASSIGN(TouchMoveSlopSuppressor);
238 }; 236 };
239 237
240 // This class represents a single coalesced touch event. However, it also keeps 238 // This class represents a single coalesced touch event. However, it also keeps
241 // track of all the original touch-events that were coalesced into a single 239 // track of all the original touch-events that were coalesced into a single
242 // event. The coalesced event is forwarded to the renderer, while the original 240 // event. The coalesced event is forwarded to the renderer, while the original
243 // touch-events are sent to the Client (on ACK for the coalesced event) so that 241 // touch-events are sent to the Client (on ACK for the coalesced event) so that
244 // the Client receives the event with their original timestamp. 242 // the Client receives the event with their original timestamp.
245 class CoalescedWebTouchEvent { 243 class CoalescedWebTouchEvent {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 } 307 }
310 308
311 private: 309 private:
312 bool WillDispatchAckToClient() const { return !events_to_ack_.empty(); } 310 bool WillDispatchAckToClient() const { return !events_to_ack_.empty(); }
313 311
314 // This is the event that is forwarded to the renderer. 312 // This is the event that is forwarded to the renderer.
315 TouchEventWithLatencyInfo coalesced_event_; 313 TouchEventWithLatencyInfo coalesced_event_;
316 314
317 // This is the list of the original events that were coalesced, each requiring 315 // This is the list of the original events that were coalesced, each requiring
318 // future ack dispatch to the client. 316 // future ack dispatch to the client.
317 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
319 WebTouchEventWithLatencyList events_to_ack_; 318 WebTouchEventWithLatencyList events_to_ack_;
320 319
321 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); 320 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
322 }; 321 };
323 322
323 TouchEventQueue::Config::Config()
324 : touchmove_slop_suppression_length_dips(0),
325 touch_scrolling_mode(TOUCH_SCROLLING_MODE_DEFAULT),
326 touch_ack_timeout_delay(base::TimeDelta::FromMilliseconds(200)),
327 touch_ack_timeout_supported(false) {
328 }
329
324 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client, 330 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client,
325 TouchScrollingMode mode, 331 const Config& config)
326 double touchmove_suppression_length_dips)
327 : client_(client), 332 : client_(client),
328 dispatching_touch_ack_(NULL), 333 dispatching_touch_ack_(NULL),
329 dispatching_touch_(false), 334 dispatching_touch_(false),
330 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT), 335 touch_filtering_state_(TOUCH_FILTERING_STATE_DEFAULT),
331 ack_timeout_enabled_(false), 336 ack_timeout_enabled_(config.touch_ack_timeout_supported),
332 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor( 337 touchmove_slop_suppressor_(new TouchMoveSlopSuppressor(
333 touchmove_suppression_length_dips + kSlopEpsilon)), 338 config.touchmove_slop_suppression_length_dips + kSlopEpsilon)),
334 send_touch_events_async_(false), 339 send_touch_events_async_(false),
335 needs_async_touch_move_for_outer_slop_region_(false), 340 needs_async_touchmove_for_outer_slop_region_(false),
336 last_sent_touch_timestamp_sec_(0), 341 last_sent_touch_timestamp_sec_(0),
337 touch_scrolling_mode_(mode) { 342 touch_scrolling_mode_(config.touch_scrolling_mode) {
338 DCHECK(client); 343 DCHECK(client);
344 if (ack_timeout_enabled_) {
345 timeout_handler_.reset(
346 new TouchTimeoutHandler(this, config.touch_ack_timeout_delay));
347 }
339 } 348 }
340 349
341 TouchEventQueue::~TouchEventQueue() { 350 TouchEventQueue::~TouchEventQueue() {
342 if (!touch_queue_.empty()) 351 if (!touch_queue_.empty())
343 STLDeleteElements(&touch_queue_); 352 STLDeleteElements(&touch_queue_);
344 } 353 }
345 354
346 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 355 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
347 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent"); 356 TRACE_EVENT0("input", "TouchEventQueue::QueueEvent");
348 357
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 gfx::PointF(touch.event.touches[0].position); 449 gfx::PointF(touch.event.touches[0].position);
441 } 450 }
442 451
443 if (send_touch_events_async_ && 452 if (send_touch_events_async_ &&
444 touch.event.type == WebInputEvent::TouchMove) { 453 touch.event.type == WebInputEvent::TouchMove) {
445 // Throttling touchmove's in a continuous touchmove stream while scrolling 454 // Throttling touchmove's in a continuous touchmove stream while scrolling
446 // reduces the risk of jank. However, it's still important that the web 455 // reduces the risk of jank. However, it's still important that the web
447 // application be sent touches at key points in the gesture stream, 456 // application be sent touches at key points in the gesture stream,
448 // e.g., when the application slop region is exceeded or touchmove 457 // e.g., when the application slop region is exceeded or touchmove
449 // coalescing fails because of different modifiers. 458 // coalescing fails because of different modifiers.
450 const bool send_touch_move_now = 459 const bool send_touchmove_now =
451 size() > 1 || 460 size() > 1 ||
452 (touch.event.timeStampSeconds >= 461 (touch.event.timeStampSeconds >=
453 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec) || 462 last_sent_touch_timestamp_sec_ + kAsyncTouchMoveIntervalSec) ||
454 (needs_async_touch_move_for_outer_slop_region_ && 463 (needs_async_touchmove_for_outer_slop_region_ &&
455 OutsideApplicationSlopRegion(touch.event, 464 OutsideApplicationSlopRegion(touch.event,
456 touch_sequence_start_position_)) || 465 touch_sequence_start_position_)) ||
457 (pending_async_touch_move_ && 466 (pending_async_touchmove_ &&
458 !pending_async_touch_move_->CanCoalesceWith(touch)); 467 !pending_async_touchmove_->CanCoalesceWith(touch));
459 468
460 if (!send_touch_move_now) { 469 if (!send_touchmove_now) {
461 if (!pending_async_touch_move_) { 470 if (!pending_async_touchmove_) {
462 pending_async_touch_move_.reset(new TouchEventWithLatencyInfo(touch)); 471 pending_async_touchmove_.reset(new TouchEventWithLatencyInfo(touch));
463 } else { 472 } else {
464 DCHECK(pending_async_touch_move_->CanCoalesceWith(touch)); 473 DCHECK(pending_async_touchmove_->CanCoalesceWith(touch));
465 pending_async_touch_move_->CoalesceWith(touch); 474 pending_async_touchmove_->CoalesceWith(touch);
466 } 475 }
467 DCHECK_EQ(1U, size()); 476 DCHECK_EQ(1U, size());
468 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); 477 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
469 // It's possible (though unlikely) that ack'ing the current touch will 478 // It's possible (though unlikely) that ack'ing the current touch will
470 // trigger the queueing of another touch event (e.g., a touchcancel). As 479 // trigger the queueing of another touch event (e.g., a touchcancel). As
471 // forwarding of the queued event will be deferred while the ack is being 480 // forwarding of the queued event will be deferred while the ack is being
472 // dispatched (see |OnTouchEvent()|), try forwarding it now. 481 // dispatched (see |OnTouchEvent()|), try forwarding it now.
473 TryForwardNextEventToRenderer(); 482 TryForwardNextEventToRenderer();
474 return; 483 return;
475 } 484 }
476 } 485 }
477 486
478 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds; 487 last_sent_touch_timestamp_sec_ = touch.event.timeStampSeconds;
479 488
480 // Flush any pending async touch move. If it can be combined with the current 489 // Flush any pending async touch move. If it can be combined with the current
481 // (touchmove) event, great, otherwise send it immediately but separately. Its 490 // (touchmove) event, great, otherwise send it immediately but separately. Its
482 // ack will trigger forwarding of the original |touch| event. 491 // ack will trigger forwarding of the original |touch| event.
483 if (pending_async_touch_move_) { 492 if (pending_async_touchmove_) {
484 if (pending_async_touch_move_->CanCoalesceWith(touch)) { 493 if (pending_async_touchmove_->CanCoalesceWith(touch)) {
485 pending_async_touch_move_->CoalesceWith(touch); 494 pending_async_touchmove_->CoalesceWith(touch);
486 pending_async_touch_move_->event.cancelable = !send_touch_events_async_; 495 pending_async_touchmove_->event.cancelable = !send_touch_events_async_;
487 touch = *pending_async_touch_move_.Pass(); 496 touch = *pending_async_touchmove_.Pass();
488 } else { 497 } else {
489 scoped_ptr<TouchEventWithLatencyInfo> async_move = 498 scoped_ptr<TouchEventWithLatencyInfo> async_move =
490 pending_async_touch_move_.Pass(); 499 pending_async_touchmove_.Pass();
491 async_move->event.cancelable = false; 500 async_move->event.cancelable = false;
492 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true)); 501 touch_queue_.push_front(new CoalescedWebTouchEvent(*async_move, true));
493 SendTouchEventImmediately(*async_move); 502 SendTouchEventImmediately(*async_move);
494 return; 503 return;
495 } 504 }
496 } 505 }
497 506
498 // Note: Marking touchstart events as not-cancelable prevents them from 507 // Note: Marking touchstart events as not-cancelable prevents them from
499 // blocking subsequent gestures, but it may not be the best long term solution 508 // blocking subsequent gestures, but it may not be the best long term solution
500 // for tracking touch point dispatch. 509 // for tracking touch point dispatch.
(...skipping 26 matching lines...) Expand all
527 // always be preventDefault'ed (cancelable == true). 536 // always be preventDefault'ed (cancelable == true).
528 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable. 537 // TODO(jdduke): Revisit if touchstarts during scroll are made cancelable.
529 if (touch_ack_states_.empty() || 538 if (touch_ack_states_.empty() ||
530 AllTouchAckStatesHaveState( 539 AllTouchAckStatesHaveState(
531 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) { 540 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)) {
532 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 541 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
533 return; 542 return;
534 } 543 }
535 } 544 }
536 545
537 pending_async_touch_move_.reset(); 546 pending_async_touchmove_.reset();
538 send_touch_events_async_ = true; 547 send_touch_events_async_ = true;
539 needs_async_touch_move_for_outer_slop_region_ = true; 548 needs_async_touchmove_for_outer_slop_region_ = true;
540 return; 549 return;
541 } 550 }
542 551
543 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL) 552 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_TOUCHCANCEL)
544 return; 553 return;
545 554
546 // We assume that scroll events are generated synchronously from 555 // We assume that scroll events are generated synchronously from
547 // dispatching a touch event ack. This allows us to generate a synthetic 556 // dispatching a touch event ack. This allows us to generate a synthetic
548 // cancel event that has the same touch ids as the touch event that 557 // cancel event that has the same touch ids as the touch event that
549 // is being acked. Otherwise, we don't perform the touch-cancel optimization. 558 // is being acked. Otherwise, we don't perform the touch-cancel optimization.
(...skipping 22 matching lines...) Expand all
572 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE) 581 if (touch_scrolling_mode_ != TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE)
573 return; 582 return;
574 583
575 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate) 584 if (event.event.type != blink::WebInputEvent::GestureScrollUpdate)
576 return; 585 return;
577 586
578 // Throttle sending touchmove events as long as the scroll events are handled. 587 // Throttle sending touchmove events as long as the scroll events are handled.
579 // Note that there's no guarantee that this ACK is for the most recent 588 // Note that there's no guarantee that this ACK is for the most recent
580 // gesture event (or even part of the current sequence). Worst case, the 589 // gesture event (or even part of the current sequence). Worst case, the
581 // delay in updating the absorption state will result in minor UI glitches. 590 // delay in updating the absorption state will result in minor UI glitches.
582 // A valid |pending_async_touch_move_| will be flushed when the next event is 591 // A valid |pending_async_touchmove_| will be flushed when the next event is
583 // forwarded. 592 // forwarded.
584 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED); 593 send_touch_events_async_ = (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED);
585 if (!send_touch_events_async_) 594 if (!send_touch_events_async_)
586 needs_async_touch_move_for_outer_slop_region_ = false; 595 needs_async_touchmove_for_outer_slop_region_ = false;
587 } 596 }
588 597
589 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { 598 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
590 DCHECK(!dispatching_touch_ack_); 599 DCHECK(!dispatching_touch_ack_);
591 DCHECK(!dispatching_touch_); 600 DCHECK(!dispatching_touch_);
592 601
593 if (has_handlers) { 602 if (has_handlers) {
594 if (touch_filtering_state_ == DROP_ALL_TOUCHES) { 603 if (touch_filtering_state_ == DROP_ALL_TOUCHES) {
595 // If no touch handler was previously registered, ensure that we don't 604 // If no touch handler was previously registered, ensure that we don't
596 // send a partial touch sequence to the renderer. 605 // send a partial touch sequence to the renderer.
597 DCHECK(touch_queue_.empty()); 606 DCHECK(touch_queue_.empty());
598 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 607 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
599 } 608 }
600 } else { 609 } else {
601 // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch 610 // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch
602 // state tracking (e.g., if the touch handler was removed mid-sequence). 611 // state tracking (e.g., if the touch handler was removed mid-sequence).
603 touch_filtering_state_ = DROP_ALL_TOUCHES; 612 touch_filtering_state_ = DROP_ALL_TOUCHES;
604 pending_async_touch_move_.reset(); 613 pending_async_touchmove_.reset();
605 if (timeout_handler_) 614 if (timeout_handler_)
606 timeout_handler_->Reset(); 615 timeout_handler_->Reset();
607 if (!touch_queue_.empty()) 616 if (!touch_queue_.empty())
608 ProcessTouchAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, LatencyInfo()); 617 ProcessTouchAck(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, LatencyInfo());
609 // As there is no touch handler, ack'ing the event should flush the queue. 618 // As there is no touch handler, ack'ing the event should flush the queue.
610 DCHECK(touch_queue_.empty()); 619 DCHECK(touch_queue_.empty());
611 } 620 }
612 } 621 }
613 622
614 bool TouchEventQueue::IsPendingAckTouchStart() const { 623 bool TouchEventQueue::IsPendingAckTouchStart() const {
615 DCHECK(!dispatching_touch_ack_); 624 DCHECK(!dispatching_touch_ack_);
616 if (touch_queue_.empty()) 625 if (touch_queue_.empty())
617 return false; 626 return false;
618 627
619 const blink::WebTouchEvent& event = 628 const blink::WebTouchEvent& event =
620 touch_queue_.front()->coalesced_event().event; 629 touch_queue_.front()->coalesced_event().event;
621 return (event.type == WebInputEvent::TouchStart); 630 return (event.type == WebInputEvent::TouchStart);
622 } 631 }
623 632
624 void TouchEventQueue::SetAckTimeoutEnabled(bool enabled, 633 void TouchEventQueue::SetAckTimeoutEnabled(bool enabled) {
625 base::TimeDelta ack_timeout_delay) { 634 // The timeout handler is valid only if explicitly supported in the config.
626 if (!enabled) { 635 if (!timeout_handler_)
627 ack_timeout_enabled_ = false;
628 if (touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT)
629 touch_filtering_state_ = FORWARD_ALL_TOUCHES;
630 // Only reset the |timeout_handler_| if the timer is running and has not yet
631 // timed out. This ensures that an already timed out sequence is properly
632 // flushed by the handler.
633 if (timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning())
634 timeout_handler_->Reset();
635 return; 636 return;
636 }
637 637
638 ack_timeout_enabled_ = true; 638 if (ack_timeout_enabled_ == enabled)
639 if (!timeout_handler_) 639 return;
640 timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay)); 640
641 else 641 ack_timeout_enabled_ = enabled;
642 timeout_handler_->set_timeout_delay(ack_timeout_delay); 642
643 if (enabled)
644 return;
645
646 if (touch_filtering_state_ == FORWARD_TOUCHES_UNTIL_TIMEOUT)
647 touch_filtering_state_ = FORWARD_ALL_TOUCHES;
648 // Only reset the |timeout_handler_| if the timer is running and has not yet
649 // timed out. This ensures that an already timed out sequence is properly
650 // flushed by the handler.
651 if (timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning())
652 timeout_handler_->Reset();
643 } 653 }
644 654
645 bool TouchEventQueue::HasPendingAsyncTouchMoveForTesting() const { 655 bool TouchEventQueue::HasPendingAsyncTouchMoveForTesting() const {
646 return pending_async_touch_move_; 656 return pending_async_touchmove_;
647 } 657 }
648 658
649 bool TouchEventQueue::IsTimeoutRunningForTesting() const { 659 bool TouchEventQueue::IsTimeoutRunningForTesting() const {
650 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); 660 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
651 } 661 }
652 662
653 const TouchEventWithLatencyInfo& 663 const TouchEventWithLatencyInfo&
654 TouchEventQueue::GetLatestEventForTesting() const { 664 TouchEventQueue::GetLatestEventForTesting() const {
655 return touch_queue_.back()->coalesced_event(); 665 return touch_queue_.back()->coalesced_event();
656 } 666 }
657 667
658 void TouchEventQueue::FlushQueue() { 668 void TouchEventQueue::FlushQueue() {
659 DCHECK(!dispatching_touch_ack_); 669 DCHECK(!dispatching_touch_ack_);
660 DCHECK(!dispatching_touch_); 670 DCHECK(!dispatching_touch_);
661 pending_async_touch_move_.reset(); 671 pending_async_touchmove_.reset();
662 if (touch_filtering_state_ != DROP_ALL_TOUCHES) 672 if (touch_filtering_state_ != DROP_ALL_TOUCHES)
663 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE; 673 touch_filtering_state_ = DROP_TOUCHES_IN_SEQUENCE;
664 while (!touch_queue_.empty()) 674 while (!touch_queue_.empty())
665 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS); 675 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
666 } 676 }
667 677
668 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) { 678 void TouchEventQueue::PopTouchEventToClient(InputEventAckState ack_result) {
669 AckTouchEventToClient(ack_result, PopTouchEvent()); 679 AckTouchEventToClient(ack_result, PopTouchEvent());
670 } 680 }
671 681
(...skipping 21 matching lines...) Expand all
693 703
694 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() { 704 scoped_ptr<CoalescedWebTouchEvent> TouchEventQueue::PopTouchEvent() {
695 DCHECK(!touch_queue_.empty()); 705 DCHECK(!touch_queue_.empty());
696 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front()); 706 scoped_ptr<CoalescedWebTouchEvent> event(touch_queue_.front());
697 touch_queue_.pop_front(); 707 touch_queue_.pop_front();
698 return event.Pass(); 708 return event.Pass();
699 } 709 }
700 710
701 void TouchEventQueue::SendTouchEventImmediately( 711 void TouchEventQueue::SendTouchEventImmediately(
702 const TouchEventWithLatencyInfo& touch) { 712 const TouchEventWithLatencyInfo& touch) {
703 if (needs_async_touch_move_for_outer_slop_region_) { 713 if (needs_async_touchmove_for_outer_slop_region_) {
704 // Any event other than a touchmove (e.g., touchcancel or secondary 714 // Any event other than a touchmove (e.g., touchcancel or secondary
705 // touchstart) after a scroll has started will interrupt the need to send a 715 // touchstart) after a scroll has started will interrupt the need to send a
706 // an outer slop-region exceeding touchmove. 716 // an outer slop-region exceeding touchmove.
707 if (touch.event.type != WebInputEvent::TouchMove || 717 if (touch.event.type != WebInputEvent::TouchMove ||
708 OutsideApplicationSlopRegion(touch.event, 718 OutsideApplicationSlopRegion(touch.event,
709 touch_sequence_start_position_)) 719 touch_sequence_start_position_))
710 needs_async_touch_move_for_outer_slop_region_ = false; 720 needs_async_touchmove_for_outer_slop_region_ = false;
711 } 721 }
712 722
713 client_->SendTouchEventImmediately(touch); 723 client_->SendTouchEventImmediately(touch);
714 } 724 }
715 725
716 TouchEventQueue::PreFilterResult 726 TouchEventQueue::PreFilterResult
717 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) { 727 TouchEventQueue::FilterBeforeForwarding(const WebTouchEvent& event) {
718 if (timeout_handler_ && timeout_handler_->FilterEvent(event)) 728 if (timeout_handler_ && timeout_handler_->FilterEvent(event))
719 return ACK_WITH_NO_CONSUMER_EXISTS; 729 return ACK_WITH_NO_CONSUMER_EXISTS;
720 730
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 iter != end; 796 iter != end;
787 ++iter) { 797 ++iter) {
788 if (iter->second != ack_state) 798 if (iter->second != ack_state)
789 return false; 799 return false;
790 } 800 }
791 801
792 return true; 802 return true;
793 } 803 }
794 804
795 } // namespace content 805 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698