Chromium Code Reviews| Index: content/browser/renderer_host/input/touch_event_queue.cc |
| diff --git a/content/browser/renderer_host/input/touch_event_queue.cc b/content/browser/renderer_host/input/touch_event_queue.cc |
| index 5921521e8ce0b2115106fad05b9561420f0aba6f..edf029975aa0e02c6904dbb1e1ce99ce85d05024 100644 |
| --- a/content/browser/renderer_host/input/touch_event_queue.cc |
| +++ b/content/browser/renderer_host/input/touch_event_queue.cc |
| @@ -80,8 +80,6 @@ class TouchEventQueue::TouchTimeoutHandler { |
| SetPendingAckState(PENDING_ACK_CANCEL_EVENT); |
| TouchEventWithLatencyInfo cancel_event = |
| ObtainCancelEventForTouchEvent(timeout_event_); |
| - touch_queue_->UpdateTouchAckStates( |
| - cancel_event.event, kDefaultNotForwardedAck); |
| touch_queue_->client_->SendTouchEventImmediately(cancel_event); |
| } else { |
| SetPendingAckState(PENDING_ACK_NONE); |
| @@ -241,9 +239,7 @@ TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) |
| : client_(client), |
| dispatching_touch_ack_(NULL), |
| dispatching_touch_(false), |
| - has_handlers_(false), |
| - scroll_in_progress_(false), |
| - renderer_is_consuming_touch_gesture_(false), |
| + touch_handling_state_(TOUCH_HANDLING_STATE_DEFAULT), |
| ack_timeout_enabled_(false) { |
| DCHECK(client); |
| } |
| @@ -256,7 +252,7 @@ TouchEventQueue::~TouchEventQueue() { |
| void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { |
| // Optimization of the case without touch handlers. Removing this path |
| // yields identical results, but this avoids unnecessary allocations. |
| - if (!has_handlers_) { |
| + if (touch_handling_state_ == NO_TOUCH_HANDLER) { |
|
Rick Byers
2014/01/21 22:00:25
Shouldn't we be able to handle the NO_TOUCH_HANDLE
jdduke (slow)
2014/01/22 02:47:00
Hmm, we'd have to check if it's a new touch sequen
|
| DCHECK(touch_queue_.empty()); |
| client_->OnTouchEventAck(event, kDefaultNotForwardedAck); |
| return; |
| @@ -294,7 +290,7 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, |
| return; |
| if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED) |
| - renderer_is_consuming_touch_gesture_ = true; |
| + touch_handling_state_ = RENDERER_CONSUMING_GESTURE; |
|
Rick Byers
2014/01/21 22:00:25
can we DCHECK that we're in the HAS_TOUCH_HANDLER
jdduke (slow)
2014/01/22 02:47:00
I'm trying to think if we could ever get an ack if
|
| const WebTouchEvent& acked_event = |
| touch_queue_.front()->coalesced_event().event; |
| @@ -310,10 +306,6 @@ void TouchEventQueue::TryForwardNextEventToRenderer() { |
| while (!touch_queue_.empty()) { |
| const TouchEventWithLatencyInfo& touch = |
| touch_queue_.front()->coalesced_event(); |
| - if (IsNewTouchGesture(touch.event)) { |
| - touch_ack_states_.clear(); |
| - renderer_is_consuming_touch_gesture_ = false; |
| - } |
| if (ShouldForwardToRenderer(touch.event)) { |
| ForwardToRenderer(touch); |
| break; |
| @@ -325,13 +317,20 @@ void TouchEventQueue::TryForwardNextEventToRenderer() { |
| void TouchEventQueue::ForwardToRenderer( |
| const TouchEventWithLatencyInfo& touch) { |
| DCHECK(!dispatching_touch_); |
| + DCHECK_NE(touch_handling_state_, NO_TOUCH_HANDLER); |
| + |
| + if (IsNewTouchGesture(touch.event)) { |
| + touch_handling_state_ = HAS_TOUCH_HANDLER; |
| + touch_ack_states_.clear(); |
| + } |
| + |
| // A synchronous ack will reset |dispatching_touch_|, in which case |
| // the touch timeout should not be started. |
| base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true); |
| client_->SendTouchEventImmediately(touch); |
| if (ack_timeout_enabled_ && |
| dispatching_touch_ && |
| - !renderer_is_consuming_touch_gesture_ && |
| + touch_handling_state_ != RENDERER_CONSUMING_GESTURE && |
| ShouldTouchTypeTriggerTimeout(touch.event.type)) { |
| DCHECK(timeout_handler_); |
| timeout_handler_->Start(touch); |
| @@ -340,59 +339,56 @@ void TouchEventQueue::ForwardToRenderer( |
| void TouchEventQueue::OnGestureScrollEvent( |
| const GestureEventWithLatencyInfo& gesture_event) { |
| - blink::WebInputEvent::Type type = gesture_event.event.type; |
| - if (type == blink::WebInputEvent::GestureScrollBegin) { |
| - // We assume the scroll event are generated synchronously from |
| - // dispatching a touch event ack, so that we can fake a cancel |
| - // event that has the correct touch ids as the touch event that |
| - // is being acked. If not, we don't do the touch-cancel optimization. |
| - if (scroll_in_progress_ || !dispatching_touch_ack_) |
| - return; |
| - scroll_in_progress_ = true; |
| + if (gesture_event.event.type != blink::WebInputEvent::GestureScrollBegin) |
| + return; |
| - // If we have a timeout event, a cancel has already been dispatched |
| - // for the current touch stream. |
| - if (HasTimeoutEvent()) |
| - return; |
| + // We assume that scroll events are generated synchronously from |
| + // dispatching a touch event ack. This allows us to generate a synthetic |
| + // cancel event that has the same touch ids as the touch event that |
| + // is being acked. Otherwise, we don't perform the touch-cancel optimization. |
| + if (!dispatching_touch_ack_) |
| + return; |
| - // Fake a TouchCancel to cancel the touch points of the touch event |
| - // that is currently being acked. |
| - // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we |
| - // are in the scope of PopTouchEventToClient() and that no touch event |
| - // in the queue is waiting for ack from renderer. So we can just insert |
| - // the touch cancel at the beginning of the queue. |
| - touch_queue_.push_front(new CoalescedWebTouchEvent( |
| - ObtainCancelEventForTouchEvent( |
| - dispatching_touch_ack_->coalesced_event()), true)); |
| - } else if (type == blink::WebInputEvent::GestureScrollEnd || |
| - type == blink::WebInputEvent::GestureFlingStart) { |
| - scroll_in_progress_ = false; |
| - } |
| + if (touch_handling_state_ == NO_TOUCH_HANDLER_FOR_GESTURE) |
| + return; |
| + |
| + touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE; |
| + |
| + // If we have a timeout event, a cancel has already been dispatched |
| + // for the current touch stream. |
| + if (HasTimeoutEvent()) |
| + return; |
| + |
| + // Fake a TouchCancel to cancel the touch points of the touch event |
| + // that is currently being acked. |
| + // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we |
| + // are in the scope of PopTouchEventToClient() and that no touch event |
| + // in the queue is waiting for ack from renderer. So we can just insert |
| + // the touch cancel at the beginning of the queue. |
| + touch_queue_.push_front(new CoalescedWebTouchEvent( |
| + ObtainCancelEventForTouchEvent( |
| + dispatching_touch_ack_->coalesced_event()), true)); |
| } |
| void TouchEventQueue::OnHasTouchEventHandlers(bool has_handlers) { |
| DCHECK(!dispatching_touch_ack_); |
| DCHECK(!dispatching_touch_); |
| - if (has_handlers_ == has_handlers) |
| - return; |
| - |
| - has_handlers_ = has_handlers; |
| - if (!has_handlers_) { |
| - // TODO(jdduke): Synthesize a TouchCancel if necessary to update Blink touch |
| - // state tracking. |
| + if (has_handlers) { |
| + if (touch_handling_state_ == NO_TOUCH_HANDLER) { |
| + // If no touch handler was previously registered, ensure that we don't |
| + // send a partial gesture to the renderer. |
| + DCHECK(touch_queue_.empty()); |
| + touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE; |
|
Rick Byers
2014/01/21 22:00:25
Your comment for this state says that no events ar
jdduke (slow)
2014/01/22 02:47:00
Sorry, by "partial gesture" I really mean "partial
|
| + } |
| + } else { |
| + touch_handling_state_ = NO_TOUCH_HANDLER; |
| if (timeout_handler_) |
| timeout_handler_->Reset(); |
| if (!touch_queue_.empty()) |
| ProcessTouchAck(kDefaultNotForwardedAck, ui::LatencyInfo()); |
| // As there is no touch handler, ack'ing the event should flush the queue. |
| DCHECK(touch_queue_.empty()); |
| - } else { |
| - DCHECK(touch_queue_.empty()); |
| - // Prevent a partial sequence from being sent to the renderer. |
| - TouchPointAckStates::iterator ack_it = touch_ack_states_.begin(); |
| - for (; ack_it != touch_ack_states_.end(); ++ack_it) |
| - ack_it->second = kDefaultNotForwardedAck; |
| } |
| } |
| @@ -436,6 +432,9 @@ TouchEventQueue::GetLatestEventForTesting() const { |
| void TouchEventQueue::FlushQueue() { |
| DCHECK(!dispatching_touch_ack_); |
| DCHECK(!dispatching_touch_); |
| + DCHECK_NE(RENDERER_CONSUMING_GESTURE, touch_handling_state_); |
| + if (touch_handling_state_ != NO_TOUCH_HANDLER) |
| + touch_handling_state_ = NO_TOUCH_HANDLER_FOR_GESTURE; |
| while (!touch_queue_.empty()) |
| PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo()); |
| } |
| @@ -470,12 +469,16 @@ bool TouchEventQueue::ShouldForwardToRenderer( |
| if (HasTimeoutEvent()) |
| return false; |
| - if (!has_handlers_) |
| + if (touch_handling_state_ == NO_TOUCH_HANDLER) |
| return false; |
| - if (scroll_in_progress_ && |
| - event.type != blink::WebInputEvent::TouchCancel) |
| + if (touch_handling_state_ == NO_TOUCH_HANDLER_FOR_GESTURE) { |
| + if (IsNewTouchGesture(event)) |
| + return true; |
| + if (event.type == WebInputEvent::TouchCancel) |
| + return true; |
| return false; |
| + } |
| // Touch press events should always be forwarded to the renderer. |
| if (event.type == WebInputEvent::TouchStart) |