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 9d0394ef162d034a0f43ebe90cb34969011867de..ffc4c5bb62212952e1f948e0ae9fd61d7b70aa49 100644 |
| --- a/content/browser/renderer_host/input/touch_event_queue.cc |
| +++ b/content/browser/renderer_host/input/touch_event_queue.cc |
| @@ -20,7 +20,8 @@ typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; |
| class CoalescedWebTouchEvent { |
| public: |
| explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event) |
| - : coalesced_event_(event) { |
| + : coalesced_event_(event), |
| + ignore_ack_(false) { |
| events_.push_back(event); |
| TRACE_EVENT_ASYNC_BEGIN0( |
| "input", "TouchEventQueue::QueueEvent", this); |
| @@ -40,7 +41,8 @@ class CoalescedWebTouchEvent { |
| coalesced_event_.event.modifiers == |
| event_with_latency.event.modifiers && |
| coalesced_event_.event.touchesLength == |
| - event_with_latency.event.touchesLength) { |
| + event_with_latency.event.touchesLength && |
| + !ignore_ack_) { |
| TRACE_EVENT_INSTANT0( |
| "input", "TouchEventQueue::MoveCoalesced", TRACE_EVENT_SCOPE_THREAD); |
| events_.push_back(event_with_latency); |
| @@ -79,6 +81,9 @@ class CoalescedWebTouchEvent { |
| size_t size() const { return events_.size(); } |
| + bool ignore_ack() const { return ignore_ack_; } |
| + void set_ignore_ack(bool value) { ignore_ack_ = value; } |
| + |
| private: |
| // This is the event that is forwarded to the renderer. |
| TouchEventWithLatencyInfo coalesced_event_; |
| @@ -86,13 +91,17 @@ class CoalescedWebTouchEvent { |
| // This is the list of the original events that were coalesced. |
| WebTouchEventWithLatencyList events_; |
| + // If |ignore_ack_| is true, don't send this touch event to client |
| + // when the event is acked. |
| + bool ignore_ack_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); |
| }; |
| TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) |
| : client_(client), |
| - dispatching_touch_ack_(false), |
| - no_touch_move_to_renderer_(false) { |
| + dispatching_touch_ack_(NULL), |
| + no_touch_to_renderer_(false) { |
| DCHECK(client); |
| } |
| @@ -167,6 +176,41 @@ void TouchEventQueue::TryForwardNextEventToRenderer() { |
| } |
| } |
| +void TouchEventQueue::OnGestureScrollEvent( |
| + const GestureEventWithLatencyInfo& gesture_event) { |
| + WebKit::WebInputEvent::Type type = gesture_event.event.type; |
| + if (type == WebKit::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 (no_touch_to_renderer_ || !dispatching_touch_ack_) |
| + return; |
| + no_touch_to_renderer_ = true; |
| + // Fake a TouchCancel to cancel the touch points of the touch event |
| + // that is currently being acked. |
| + TouchEventWithLatencyInfo cancel_event = |
| + dispatching_touch_ack_->coalesced_event(); |
| + cancel_event.event.type = WebKit::WebInputEvent::TouchCancel; |
| + for (size_t i = 0; i < cancel_event.event.touchesLength; i++) |
| + cancel_event.event.touches[i].state = |
| + WebKit::WebTouchPoint::StateCancelled; |
| + CoalescedWebTouchEvent* coalesced_cancel_event = |
| + new CoalescedWebTouchEvent(cancel_event); |
| + // Ignore the ack of the touch cancel so when it is acked, it won't get |
| + // sent to gesture recognizer. |
| + coalesced_cancel_event->set_ignore_ack(true); |
| + // |dispatching_touch_ack_| must be true when we reach here, meaning we |
|
sadrul
2013/10/01 11:32:45
s/must be true/is non-null/
Yufeng Shen (Slow to review)
2013/10/01 20:38:50
Done.
|
| + // 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(coalesced_cancel_event); |
| + } else if (type == WebKit::WebInputEvent::GestureScrollEnd || |
| + type == WebKit::WebInputEvent::GestureFlingStart) { |
| + no_touch_to_renderer_ = false; |
| + } |
| +} |
| + |
| void TouchEventQueue::FlushQueue() { |
| DCHECK(!dispatching_touch_ack_); |
| while (!touch_queue_.empty()) |
| @@ -190,9 +234,13 @@ void TouchEventQueue::PopTouchEventToClient( |
| scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); |
| touch_queue_.pop_front(); |
| + if (acked_event->ignore_ack()) |
| + return; |
| + |
| // Note that acking the touch-event may result in multiple gestures being sent |
| // to the renderer, or touch-events being queued. |
| - base::AutoReset<bool> dispatching_touch_ack(&dispatching_touch_ack_, true); |
| + base::AutoReset<CoalescedWebTouchEvent*> |
| + dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get()); |
| base::TimeTicks now = base::TimeTicks::HighResNow(); |
| for (WebTouchEventWithLatencyList::const_iterator iter = acked_event->begin(), |
| @@ -208,14 +256,14 @@ void TouchEventQueue::PopTouchEventToClient( |
| bool TouchEventQueue::ShouldForwardToRenderer( |
| const WebKit::WebTouchEvent& event) const { |
| + if (no_touch_to_renderer_ && |
| + event.type != WebKit::WebInputEvent::TouchCancel) |
| + return false; |
| + |
| // Touch press events should always be forwarded to the renderer. |
| if (event.type == WebKit::WebInputEvent::TouchStart) |
| return true; |
| - if (event.type == WebKit::WebInputEvent::TouchMove && |
| - no_touch_move_to_renderer_) |
| - return false; |
| - |
| for (unsigned int i = 0; i < event.touchesLength; ++i) { |
| const WebKit::WebTouchPoint& point = event.touches[i]; |
| // If a point has been stationary, then don't take it into account. |