| 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..7447c7f42f987bf356858ea6f4fd603de51e60d0 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);
|
| }
|
|
|
| @@ -153,6 +162,7 @@ void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
|
| }
|
|
|
| void TouchEventQueue::TryForwardNextEventToRenderer() {
|
| + DCHECK(!dispatching_touch_ack_);
|
| // If there are queued touch events, then try to forward them to the renderer
|
| // immediately, or ACK the events back to the client if appropriate.
|
| while (!touch_queue_.empty()) {
|
| @@ -167,6 +177,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_| 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(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 +235,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 +257,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.
|
|
|