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

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

Issue 132083006: Delegate touch handler registration logic to the TouchEventQueue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleanup Created 6 years, 11 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"
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 } 96 }
97 97
98 bool HasTimeoutEvent() const { 98 bool HasTimeoutEvent() const {
99 return pending_ack_state_ != PENDING_ACK_NONE; 99 return pending_ack_state_ != PENDING_ACK_NONE;
100 } 100 }
101 101
102 bool IsTimeoutTimerRunning() const { 102 bool IsTimeoutTimerRunning() const {
103 return timeout_monitor_.IsRunning(); 103 return timeout_monitor_.IsRunning();
104 } 104 }
105 105
106 void Reset() {
107 pending_ack_state_ = PENDING_ACK_NONE;
108 timeout_monitor_.Stop();
109 }
110
106 private: 111 private:
107 enum PendingAckState { 112 enum PendingAckState {
108 PENDING_ACK_NONE, 113 PENDING_ACK_NONE,
109 PENDING_ACK_ORIGINAL_EVENT, 114 PENDING_ACK_ORIGINAL_EVENT,
110 PENDING_ACK_CANCEL_EVENT, 115 PENDING_ACK_CANCEL_EVENT,
111 }; 116 };
112 117
113 void OnTimeOut() { 118 void OnTimeOut() {
114 SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT); 119 SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT);
115 touch_queue_->FlushQueue(); 120 touch_queue_->FlushQueue();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 // when the event is acked. 234 // when the event is acked.
230 bool ignore_ack_; 235 bool ignore_ack_;
231 236
232 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); 237 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
233 }; 238 };
234 239
235 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) 240 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
236 : client_(client), 241 : client_(client),
237 dispatching_touch_ack_(NULL), 242 dispatching_touch_ack_(NULL),
238 dispatching_touch_(false), 243 dispatching_touch_(false),
239 no_touch_to_renderer_(false), 244 has_handlers_(false),
245 scroll_in_progress_(false),
240 renderer_is_consuming_touch_gesture_(false), 246 renderer_is_consuming_touch_gesture_(false),
241 ack_timeout_enabled_(false) { 247 ack_timeout_enabled_(false) {
242 DCHECK(client); 248 DCHECK(client);
243 } 249 }
244 250
245 TouchEventQueue::~TouchEventQueue() { 251 TouchEventQueue::~TouchEventQueue() {
246 if (!touch_queue_.empty()) 252 if (!touch_queue_.empty())
247 STLDeleteElements(&touch_queue_); 253 STLDeleteElements(&touch_queue_);
248 } 254 }
249 255
250 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 256 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
257 // Optimization of the case without touch handlers. Removing this path
258 // yields identical results, but this avoids unnecessary allocations.
259 if (!has_handlers_) {
260 DCHECK(touch_queue_.empty());
261 client_->OnTouchEventAck(event, kDefaultNotForwardedAck);
262 return;
263 }
264
251 // If the queueing of |event| was triggered by an ack dispatch, defer 265 // If the queueing of |event| was triggered by an ack dispatch, defer
252 // processing the event until the dispatch has finished. 266 // processing the event until the dispatch has finished.
253 if (touch_queue_.empty() && !dispatching_touch_ack_) { 267 if (touch_queue_.empty() && !dispatching_touch_ack_) {
254 // There is no touch event in the queue. Forward it to the renderer 268 // There is no touch event in the queue. Forward it to the renderer
255 // immediately. 269 // immediately.
256 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false)); 270 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
257 TryForwardNextEventToRenderer(); 271 TryForwardNextEventToRenderer();
258 return; 272 return;
259 } 273 }
260 274
(...skipping 28 matching lines...) Expand all
289 TryForwardNextEventToRenderer(); 303 TryForwardNextEventToRenderer();
290 } 304 }
291 305
292 void TouchEventQueue::TryForwardNextEventToRenderer() { 306 void TouchEventQueue::TryForwardNextEventToRenderer() {
293 DCHECK(!dispatching_touch_ack_); 307 DCHECK(!dispatching_touch_ack_);
294 // If there are queued touch events, then try to forward them to the renderer 308 // If there are queued touch events, then try to forward them to the renderer
295 // immediately, or ACK the events back to the client if appropriate. 309 // immediately, or ACK the events back to the client if appropriate.
296 while (!touch_queue_.empty()) { 310 while (!touch_queue_.empty()) {
297 const TouchEventWithLatencyInfo& touch = 311 const TouchEventWithLatencyInfo& touch =
298 touch_queue_.front()->coalesced_event(); 312 touch_queue_.front()->coalesced_event();
299 if (IsNewTouchGesture(touch.event)) 313 if (IsNewTouchGesture(touch.event)) {
314 touch_ack_states_.clear();
tdresser 2014/01/09 21:14:32 Shouldn't these be cleared per finger, not per ges
jdduke (slow) 2014/01/09 22:05:04 I thought about adding a DCHECK(touch_ack_states_.
300 renderer_is_consuming_touch_gesture_ = false; 315 renderer_is_consuming_touch_gesture_ = false;
316 }
301 if (ShouldForwardToRenderer(touch.event)) { 317 if (ShouldForwardToRenderer(touch.event)) {
302 ForwardToRenderer(touch); 318 ForwardToRenderer(touch);
303 break; 319 break;
304 } 320 }
305 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); 321 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
306 } 322 }
307 } 323 }
308 324
309 void TouchEventQueue::ForwardToRenderer( 325 void TouchEventQueue::ForwardToRenderer(
310 const TouchEventWithLatencyInfo& touch) { 326 const TouchEventWithLatencyInfo& touch) {
(...skipping 12 matching lines...) Expand all
323 } 339 }
324 340
325 void TouchEventQueue::OnGestureScrollEvent( 341 void TouchEventQueue::OnGestureScrollEvent(
326 const GestureEventWithLatencyInfo& gesture_event) { 342 const GestureEventWithLatencyInfo& gesture_event) {
327 blink::WebInputEvent::Type type = gesture_event.event.type; 343 blink::WebInputEvent::Type type = gesture_event.event.type;
328 if (type == blink::WebInputEvent::GestureScrollBegin) { 344 if (type == blink::WebInputEvent::GestureScrollBegin) {
329 // We assume the scroll event are generated synchronously from 345 // We assume the scroll event are generated synchronously from
330 // dispatching a touch event ack, so that we can fake a cancel 346 // dispatching a touch event ack, so that we can fake a cancel
331 // event that has the correct touch ids as the touch event that 347 // event that has the correct touch ids as the touch event that
332 // is being acked. If not, we don't do the touch-cancel optimization. 348 // is being acked. If not, we don't do the touch-cancel optimization.
333 if (no_touch_to_renderer_ || !dispatching_touch_ack_) 349 if (scroll_in_progress_ || !dispatching_touch_ack_)
334 return; 350 return;
335 no_touch_to_renderer_ = true; 351 scroll_in_progress_ = true;
336 352
337 // If we have a timeout event, a cancel has already been dispatched 353 // If we have a timeout event, a cancel has already been dispatched
338 // for the current touch stream. 354 // for the current touch stream.
339 if (HasTimeoutEvent()) 355 if (HasTimeoutEvent())
340 return; 356 return;
341 357
342 // Fake a TouchCancel to cancel the touch points of the touch event 358 // Fake a TouchCancel to cancel the touch points of the touch event
343 // that is currently being acked. 359 // that is currently being acked.
344 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we 360 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
345 // are in the scope of PopTouchEventToClient() and that no touch event 361 // are in the scope of PopTouchEventToClient() and that no touch event
346 // in the queue is waiting for ack from renderer. So we can just insert 362 // in the queue is waiting for ack from renderer. So we can just insert
347 // the touch cancel at the beginning of the queue. 363 // the touch cancel at the beginning of the queue.
348 touch_queue_.push_front(new CoalescedWebTouchEvent( 364 touch_queue_.push_front(new CoalescedWebTouchEvent(
349 ObtainCancelEventForTouchEvent( 365 ObtainCancelEventForTouchEvent(
350 dispatching_touch_ack_->coalesced_event()), true)); 366 dispatching_touch_ack_->coalesced_event()), true));
351 } else if (type == blink::WebInputEvent::GestureScrollEnd || 367 } else if (type == blink::WebInputEvent::GestureScrollEnd ||
352 type == blink::WebInputEvent::GestureFlingStart) { 368 type == blink::WebInputEvent::GestureFlingStart) {
353 no_touch_to_renderer_ = false; 369 scroll_in_progress_ = false;
354 } 370 }
355 } 371 }
356 372
357 void TouchEventQueue::FlushQueue() { 373 void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) {
358 DCHECK(!dispatching_touch_ack_); 374 DCHECK(!dispatching_touch_ack_);
359 DCHECK(!dispatching_touch_); 375 DCHECK(!dispatching_touch_);
360 while (!touch_queue_.empty()) 376 if (has_handlers_ == has_handlers)
361 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); 377 return;
tdresser 2014/01/09 21:14:32 This should be a DCHECK, shouldn't it? (Given the
378
379 has_handlers_ = has_handlers;
380
381 if (!has_handlers_) {
382 // TODO(jdduke): Synthesize a TouchCancel if necessary? This would only work
383 // if we cache the last WebTouchEvent sent to the renderer.
tdresser 2014/01/09 21:14:32 Can you give me an example of when we'd want a Tou
jdduke (slow) 2014/01/09 22:05:04 I was talking with rbyers@ about this. He seemed t
tdresser 2014/01/09 22:20:41 Perhaps "Synthesize a TouchCancel if necessary to
384 if (timeout_handler_)
385 timeout_handler_->Reset();
386 if (!touch_queue_.empty())
387 ProcessTouchAck(kDefaultNotForwardedAck, ui::LatencyInfo());
388 // As there is no touch handler, ack'ing the event should flush the queue.
389 DCHECK(touch_queue_.empty());
390 } else {
391 DCHECK(touch_queue_.empty());
392 // Prevent a partial sequence from being sent to the renderer.
393 TouchPointAckStates::iterator ack_it = touch_ack_states_.begin();
394 for (; ack_it != touch_ack_states_.end(); ++ack_it)
395 ack_it->second = kDefaultNotForwardedAck;
396 }
362 } 397 }
363 398
364 bool TouchEventQueue::IsPendingAckTouchStart() const { 399 bool TouchEventQueue::IsPendingAckTouchStart() const {
365 DCHECK(!dispatching_touch_ack_); 400 DCHECK(!dispatching_touch_ack_);
366 if (touch_queue_.empty()) 401 if (touch_queue_.empty())
367 return false; 402 return false;
368 403
369 const blink::WebTouchEvent& event = 404 const blink::WebTouchEvent& event =
370 touch_queue_.front()->coalesced_event().event; 405 touch_queue_.front()->coalesced_event().event;
371 return (event.type == WebInputEvent::TouchStart); 406 return (event.type == WebInputEvent::TouchStart);
(...skipping 19 matching lines...) Expand all
391 426
392 bool TouchEventQueue::IsTimeoutRunningForTesting() const { 427 bool TouchEventQueue::IsTimeoutRunningForTesting() const {
393 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning(); 428 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
394 } 429 }
395 430
396 const TouchEventWithLatencyInfo& 431 const TouchEventWithLatencyInfo&
397 TouchEventQueue::GetLatestEventForTesting() const { 432 TouchEventQueue::GetLatestEventForTesting() const {
398 return touch_queue_.back()->coalesced_event(); 433 return touch_queue_.back()->coalesced_event();
399 } 434 }
400 435
436 void TouchEventQueue::FlushQueue() {
437 DCHECK(!dispatching_touch_ack_);
438 DCHECK(!dispatching_touch_);
439 while (!touch_queue_.empty())
440 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
441 }
442
401 void TouchEventQueue::PopTouchEventToClient( 443 void TouchEventQueue::PopTouchEventToClient(
402 InputEventAckState ack_result, 444 InputEventAckState ack_result,
403 const ui::LatencyInfo& renderer_latency_info) { 445 const ui::LatencyInfo& renderer_latency_info) {
404 DCHECK(!dispatching_touch_ack_); 446 DCHECK(!dispatching_touch_ack_);
405 if (touch_queue_.empty()) 447 if (touch_queue_.empty())
406 return; 448 return;
407 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); 449 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
408 touch_queue_.pop_front(); 450 touch_queue_.pop_front();
409 451
410 if (acked_event->ignore_ack()) 452 if (acked_event->ignore_ack())
(...skipping 10 matching lines...) Expand all
421 iter->latency.AddNewLatencyFrom(renderer_latency_info); 463 iter->latency.AddNewLatencyFrom(renderer_latency_info);
422 client_->OnTouchEventAck((*iter), ack_result); 464 client_->OnTouchEventAck((*iter), ack_result);
423 } 465 }
424 } 466 }
425 467
426 bool TouchEventQueue::ShouldForwardToRenderer( 468 bool TouchEventQueue::ShouldForwardToRenderer(
427 const WebTouchEvent& event) const { 469 const WebTouchEvent& event) const {
428 if (HasTimeoutEvent()) 470 if (HasTimeoutEvent())
429 return false; 471 return false;
430 472
431 if (no_touch_to_renderer_ && 473 if (!has_handlers_)
474 return false;
475
476 if (scroll_in_progress_ &&
432 event.type != blink::WebInputEvent::TouchCancel) 477 event.type != blink::WebInputEvent::TouchCancel)
433 return false; 478 return false;
434 479
435 // Touch press events should always be forwarded to the renderer. 480 // Touch press events should always be forwarded to the renderer.
436 if (event.type == WebInputEvent::TouchStart) 481 if (event.type == WebInputEvent::TouchStart)
437 return true; 482 return true;
438 483
439 for (unsigned int i = 0; i < event.touchesLength; ++i) { 484 for (unsigned int i = 0; i < event.touchesLength; ++i) {
440 const WebTouchPoint& point = event.touches[i]; 485 const WebTouchPoint& point = event.touches[i];
441 // If a point has been stationary, then don't take it into account. 486 // If a point has been stationary, then don't take it into account.
(...skipping 29 matching lines...) Expand all
471 } else if (event.type == WebInputEvent::TouchStart) { 516 } else if (event.type == WebInputEvent::TouchStart) {
472 for (unsigned i = 0; i < event.touchesLength; ++i) { 517 for (unsigned i = 0; i < event.touchesLength; ++i) {
473 const WebTouchPoint& point = event.touches[i]; 518 const WebTouchPoint& point = event.touches[i];
474 if (point.state == WebTouchPoint::StatePressed) 519 if (point.state == WebTouchPoint::StatePressed)
475 touch_ack_states_[point.id] = ack_result; 520 touch_ack_states_[point.id] = ack_result;
476 } 521 }
477 } 522 }
478 } 523 }
479 524
480 } // namespace content 525 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698