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

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

Issue 48973005: Move TouchEvent timeout code to the TouchEventQueue (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 7 years 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/debug/trace_event.h" 9 #include "base/debug/trace_event.h"
9 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "content/browser/renderer_host/input/timeout_monitor.h"
12 #include "content/common/input/web_input_event_traits.h"
13 #include "content/public/common/content_switches.h"
14
15 using blink::WebInputEvent;
16 using blink::WebTouchEvent;
17 using blink::WebTouchPoint;
10 18
11 namespace content { 19 namespace content {
20 namespace {
21
22 const InputEventAckState kDefaultNotForwardedAck =
23 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
12 24
13 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList; 25 typedef std::vector<TouchEventWithLatencyInfo> WebTouchEventWithLatencyList;
14 26
27 TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
28 const TouchEventWithLatencyInfo& event_to_cancel) {
29 TouchEventWithLatencyInfo event = event_to_cancel;
30 event.event.type = WebInputEvent::TouchCancel;
31 for (size_t i = 0; i < event.event.touchesLength; i++)
32 event.event.touches[i].state = WebTouchPoint::StateCancelled;
33 return event;
34 }
35
36 bool IsNewTouchGesture(const WebTouchEvent& event) {
37 if (event.type != WebInputEvent::TouchStart)
38 return false;
39 if (!event.touchesLength)
40 return false;
41 for (size_t i = 0; i < event.touchesLength; i++) {
42 if (event.touches[i].state != WebTouchPoint::StatePressed)
43 return false;
44 }
45 return true;
46 }
47
48 bool ShouldTouchTypeTriggerTimeout(WebInputEvent::Type type) {
49 return type == WebInputEvent::TouchStart ||
50 type == WebInputEvent::TouchMove;
51 }
52
53 } // namespace
54
55 class TouchEventQueue::TouchTimeoutHandler {
56 public:
57 TouchTimeoutHandler(TouchEventQueue* touch_queue, size_t timeout_delay_ms)
58 : touch_queue_(touch_queue),
59 timeout_delay_(base::TimeDelta::FromMilliseconds(timeout_delay_ms)),
60 pending_ack_state_(PENDING_ACK_NONE),
61 timeout_monitor_(base::Bind(&TouchTimeoutHandler::OnTimeOut,
62 base::Unretained(this))) {}
63
64 ~TouchTimeoutHandler() {}
65
66 void Start(const TouchEventWithLatencyInfo& event) {
67 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
68 DCHECK(ShouldTouchTypeTriggerTimeout(event.event.type));
69 timeout_event_ = event;
70 timeout_monitor_.Restart(timeout_delay_);
71 }
72
73 bool ConfirmTouchEvent(InputEventAckState ack_result) {
74 switch (pending_ack_state_) {
75 case PENDING_ACK_NONE:
76 timeout_monitor_.Stop();
77 return false;
78 case PENDING_ACK_ORIGINAL_EVENT:
79 if (AckedTimeoutEventRequiresCancel(ack_result)) {
80 SetPendingAckState(PENDING_ACK_CANCEL_EVENT);
81 TouchEventWithLatencyInfo cancel_event =
82 ObtainCancelEventForTouchEvent(timeout_event_);
83 touch_queue_->UpdateTouchAckStates(
84 cancel_event.event, kDefaultNotForwardedAck);
85 touch_queue_->client_->SendTouchEventImmediately(cancel_event);
86 } else {
87 SetPendingAckState(PENDING_ACK_NONE);
88 touch_queue_->UpdateTouchAckStates(timeout_event_.event, ack_result);
89 }
90 return true;
91 case PENDING_ACK_CANCEL_EVENT:
92 SetPendingAckState(PENDING_ACK_NONE);
93 return true;
94 }
95 return false;
96 }
97
98 bool HasTimeoutEvent() const {
99 return pending_ack_state_ != PENDING_ACK_NONE;
100 }
101
102 bool IsTimeoutTimerRunning() const {
103 return timeout_monitor_.IsRunning();
104 }
105
106 private:
107 enum PendingAckState {
108 PENDING_ACK_NONE,
109 PENDING_ACK_ORIGINAL_EVENT,
110 PENDING_ACK_CANCEL_EVENT,
111 };
112
113 void OnTimeOut() {
114 SetPendingAckState(PENDING_ACK_ORIGINAL_EVENT);
115 touch_queue_->FlushQueue();
116 }
117
118 // Skip a cancel event if the timed-out event had no consumer and was the
119 // initial event in the gesture.
120 bool AckedTimeoutEventRequiresCancel(InputEventAckState ack_result) const {
121 DCHECK(HasTimeoutEvent());
122 if (ack_result != INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
123 return true;
124 return !IsNewTouchGesture(timeout_event_.event);
125 }
126
127 void SetPendingAckState(PendingAckState new_pending_ack_state) {
128 DCHECK_NE(pending_ack_state_, new_pending_ack_state);
129 switch (new_pending_ack_state) {
130 case PENDING_ACK_ORIGINAL_EVENT:
131 DCHECK_EQ(pending_ack_state_, PENDING_ACK_NONE);
132 TRACE_EVENT_ASYNC_BEGIN0("input", "TouchEventTimeout", this);
133 break;
134 case PENDING_ACK_CANCEL_EVENT:
135 DCHECK_EQ(pending_ack_state_, PENDING_ACK_ORIGINAL_EVENT);
136 DCHECK(!timeout_monitor_.IsRunning());
137 DCHECK(touch_queue_->empty());
138 TRACE_EVENT_ASYNC_STEP_INTO0(
139 "input", "TouchEventTimeout", this, "CancelEvent");
140 break;
141 case PENDING_ACK_NONE:
142 DCHECK(!timeout_monitor_.IsRunning());
143 DCHECK(touch_queue_->empty());
144 TRACE_EVENT_ASYNC_END0("input", "TouchEventTimeout", this);
145 break;
146 }
147 pending_ack_state_ = new_pending_ack_state;
148 }
149
150
151 TouchEventQueue* touch_queue_;
152
153 // How long to wait on a touch ack before cancelling the touch sequence.
154 base::TimeDelta timeout_delay_;
155
156 // The touch event source for which we expect the next ack.
157 PendingAckState pending_ack_state_;
158
159 // The event for which the ack timeout is triggered.
160 TouchEventWithLatencyInfo timeout_event_;
161
162 // Provides timeout-based callback behavior.
163 TimeoutMonitor timeout_monitor_;
164 };
165
166
15 // This class represents a single coalesced touch event. However, it also keeps 167 // This class represents a single coalesced touch event. However, it also keeps
16 // track of all the original touch-events that were coalesced into a single 168 // track of all the original touch-events that were coalesced into a single
17 // event. The coalesced event is forwarded to the renderer, while the original 169 // event. The coalesced event is forwarded to the renderer, while the original
18 // touch-events are sent to the Client (on ACK for the coalesced event) so that 170 // touch-events are sent to the Client (on ACK for the coalesced event) so that
19 // the Client receives the event with their original timestamp. 171 // the Client receives the event with their original timestamp.
20 class CoalescedWebTouchEvent { 172 class CoalescedWebTouchEvent {
21 public: 173 public:
22 explicit CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event) 174 CoalescedWebTouchEvent(const TouchEventWithLatencyInfo& event,
175 bool ignore_ack)
23 : coalesced_event_(event), 176 : coalesced_event_(event),
24 ignore_ack_(false) { 177 ignore_ack_(ignore_ack) {
25 events_.push_back(event); 178 events_.push_back(event);
26 TRACE_EVENT_ASYNC_BEGIN0( 179 TRACE_EVENT_ASYNC_BEGIN0(
27 "input", "TouchEventQueue::QueueEvent", this); 180 "input", "TouchEventQueue::QueueEvent", this);
28 } 181 }
29 182
30 ~CoalescedWebTouchEvent() { 183 ~CoalescedWebTouchEvent() {
31 TRACE_EVENT_ASYNC_END0( 184 TRACE_EVENT_ASYNC_END0(
32 "input", "TouchEventQueue::QueueEvent", this); 185 "input", "TouchEventQueue::QueueEvent", this);
33 } 186 }
34 187
(...skipping 22 matching lines...) Expand all
57 return events_.begin(); 210 return events_.begin();
58 } 211 }
59 212
60 WebTouchEventWithLatencyList::iterator end() { 213 WebTouchEventWithLatencyList::iterator end() {
61 return events_.end(); 214 return events_.end();
62 } 215 }
63 216
64 size_t size() const { return events_.size(); } 217 size_t size() const { return events_.size(); }
65 218
66 bool ignore_ack() const { return ignore_ack_; } 219 bool ignore_ack() const { return ignore_ack_; }
67 void set_ignore_ack(bool value) { ignore_ack_ = value; }
68 220
69 private: 221 private:
70 // This is the event that is forwarded to the renderer. 222 // This is the event that is forwarded to the renderer.
71 TouchEventWithLatencyInfo coalesced_event_; 223 TouchEventWithLatencyInfo coalesced_event_;
72 224
73 // This is the list of the original events that were coalesced. 225 // This is the list of the original events that were coalesced.
74 WebTouchEventWithLatencyList events_; 226 WebTouchEventWithLatencyList events_;
75 227
76 // If |ignore_ack_| is true, don't send this touch event to client 228 // If |ignore_ack_| is true, don't send this touch event to client
77 // when the event is acked. 229 // when the event is acked.
78 bool ignore_ack_; 230 bool ignore_ack_;
79 231
80 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent); 232 DISALLOW_COPY_AND_ASSIGN(CoalescedWebTouchEvent);
81 }; 233 };
82 234
83 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client) 235 TouchEventQueue::TouchEventQueue(TouchEventQueueClient* client)
84 : client_(client), 236 : client_(client),
85 dispatching_touch_ack_(NULL), 237 dispatching_touch_ack_(NULL),
86 no_touch_to_renderer_(false) { 238 dispatching_touch_(false),
239 no_touch_to_renderer_(false),
240 renderer_is_consuming_touch_gesture_(false),
241 ack_timeout_enabled_(false) {
87 DCHECK(client); 242 DCHECK(client);
88 } 243 }
89 244
90 TouchEventQueue::~TouchEventQueue() { 245 TouchEventQueue::~TouchEventQueue() {
91 if (!touch_queue_.empty()) 246 if (!touch_queue_.empty())
92 STLDeleteElements(&touch_queue_); 247 STLDeleteElements(&touch_queue_);
93 } 248 }
94 249
95 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) { 250 void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
96 // If the queueing of |event| was triggered by an ack dispatch, defer 251 // If the queueing of |event| was triggered by an ack dispatch, defer
97 // processing the event until the dispatch has finished. 252 // processing the event until the dispatch has finished.
98 if (touch_queue_.empty() && !dispatching_touch_ack_) { 253 if (touch_queue_.empty() && !dispatching_touch_ack_) {
99 // There is no touch event in the queue. Forward it to the renderer 254 // There is no touch event in the queue. Forward it to the renderer
100 // immediately. 255 // immediately.
101 touch_queue_.push_back(new CoalescedWebTouchEvent(event)); 256 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
102 TryForwardNextEventToRenderer(); 257 TryForwardNextEventToRenderer();
103 return; 258 return;
104 } 259 }
105 260
106 // If the last queued touch-event was a touch-move, and the current event is 261 // If the last queued touch-event was a touch-move, and the current event is
107 // also a touch-move, then the events can be coalesced into a single event. 262 // also a touch-move, then the events can be coalesced into a single event.
108 if (touch_queue_.size() > 1) { 263 if (touch_queue_.size() > 1) {
109 CoalescedWebTouchEvent* last_event = touch_queue_.back(); 264 CoalescedWebTouchEvent* last_event = touch_queue_.back();
110 if (last_event->CoalesceEventIfPossible(event)) 265 if (last_event->CoalesceEventIfPossible(event))
111 return; 266 return;
112 } 267 }
113 touch_queue_.push_back(new CoalescedWebTouchEvent(event)); 268 touch_queue_.push_back(new CoalescedWebTouchEvent(event, false));
114 } 269 }
115 270
116 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result, 271 void TouchEventQueue::ProcessTouchAck(InputEventAckState ack_result,
117 const ui::LatencyInfo& latency_info) { 272 const ui::LatencyInfo& latency_info) {
118 DCHECK(!dispatching_touch_ack_); 273 DCHECK(!dispatching_touch_ack_);
274 dispatching_touch_ = false;
275
276 if (timeout_handler_ && timeout_handler_->ConfirmTouchEvent(ack_result))
277 return;
278
119 if (touch_queue_.empty()) 279 if (touch_queue_.empty())
120 return; 280 return;
121 281
122 // Update the ACK status for each touch point in the ACKed event. 282 if (ack_result == INPUT_EVENT_ACK_STATE_CONSUMED)
123 const blink::WebTouchEvent& event = 283 renderer_is_consuming_touch_gesture_ = true;
284
285 const WebTouchEvent& acked_event =
124 touch_queue_.front()->coalesced_event().event; 286 touch_queue_.front()->coalesced_event().event;
125 if (event.type == blink::WebInputEvent::TouchEnd || 287 UpdateTouchAckStates(acked_event, ack_result);
126 event.type == blink::WebInputEvent::TouchCancel) {
127 // The points have been released. Erase the ACK states.
128 for (unsigned i = 0; i < event.touchesLength; ++i) {
129 const blink::WebTouchPoint& point = event.touches[i];
130 if (point.state == blink::WebTouchPoint::StateReleased ||
131 point.state == blink::WebTouchPoint::StateCancelled)
132 touch_ack_states_.erase(point.id);
133 }
134 } else if (event.type == blink::WebInputEvent::TouchStart) {
135 for (unsigned i = 0; i < event.touchesLength; ++i) {
136 const blink::WebTouchPoint& point = event.touches[i];
137 if (point.state == blink::WebTouchPoint::StatePressed)
138 touch_ack_states_[point.id] = ack_result;
139 }
140 }
141
142 PopTouchEventToClient(ack_result, latency_info); 288 PopTouchEventToClient(ack_result, latency_info);
143 TryForwardNextEventToRenderer(); 289 TryForwardNextEventToRenderer();
144 } 290 }
145 291
146 void TouchEventQueue::TryForwardNextEventToRenderer() { 292 void TouchEventQueue::TryForwardNextEventToRenderer() {
147 DCHECK(!dispatching_touch_ack_); 293 DCHECK(!dispatching_touch_ack_);
148 // If there are queued touch events, then try to forward them to the renderer 294 // If there are queued touch events, then try to forward them to the renderer
149 // immediately, or ACK the events back to the client if appropriate. 295 // immediately, or ACK the events back to the client if appropriate.
150 while (!touch_queue_.empty()) { 296 while (!touch_queue_.empty()) {
151 const TouchEventWithLatencyInfo& touch = 297 const TouchEventWithLatencyInfo& touch =
152 touch_queue_.front()->coalesced_event(); 298 touch_queue_.front()->coalesced_event();
299 if (IsNewTouchGesture(touch.event))
300 renderer_is_consuming_touch_gesture_ = false;
153 if (ShouldForwardToRenderer(touch.event)) { 301 if (ShouldForwardToRenderer(touch.event)) {
154 client_->SendTouchEventImmediately(touch); 302 ForwardToRenderer(touch);
155 break; 303 break;
156 } 304 }
157 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, 305 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
158 ui::LatencyInfo());
159 } 306 }
160 } 307 }
161 308
309 void TouchEventQueue::ForwardToRenderer(
310 const TouchEventWithLatencyInfo& touch) {
311 DCHECK(!dispatching_touch_);
312 // A synchronous ack will reset |dispatching_touch_|, in which case
313 // the touch timeout should not be started.
314 base::AutoReset<bool> dispatching_touch(&dispatching_touch_, true);
315 client_->SendTouchEventImmediately(touch);
316 if (ack_timeout_enabled_ &&
317 dispatching_touch_ &&
318 !renderer_is_consuming_touch_gesture_ &&
319 ShouldTouchTypeTriggerTimeout(touch.event.type)) {
320 DCHECK(timeout_handler_);
321 timeout_handler_->Start(touch);
322 }
323 }
324
162 void TouchEventQueue::OnGestureScrollEvent( 325 void TouchEventQueue::OnGestureScrollEvent(
163 const GestureEventWithLatencyInfo& gesture_event) { 326 const GestureEventWithLatencyInfo& gesture_event) {
164 blink::WebInputEvent::Type type = gesture_event.event.type; 327 blink::WebInputEvent::Type type = gesture_event.event.type;
165 if (type == blink::WebInputEvent::GestureScrollBegin) { 328 if (type == blink::WebInputEvent::GestureScrollBegin) {
166 // We assume the scroll event are generated synchronously from 329 // We assume the scroll event are generated synchronously from
167 // dispatching a touch event ack, so that we can fake a cancel 330 // dispatching a touch event ack, so that we can fake a cancel
168 // event that has the correct touch ids as the touch event that 331 // event that has the correct touch ids as the touch event that
169 // is being acked. If not, we don't do the touch-cancel optimization. 332 // is being acked. If not, we don't do the touch-cancel optimization.
170 if (no_touch_to_renderer_ || !dispatching_touch_ack_) 333 if (no_touch_to_renderer_ || !dispatching_touch_ack_)
171 return; 334 return;
172 no_touch_to_renderer_ = true; 335 no_touch_to_renderer_ = true;
336
337 // If we have a timeout event, a cancel has already been dispatched
338 // for the current touch stream.
339 if (HasTimeoutEvent())
340 return;
341
173 // Fake a TouchCancel to cancel the touch points of the touch event 342 // Fake a TouchCancel to cancel the touch points of the touch event
174 // that is currently being acked. 343 // that is currently being acked.
175 TouchEventWithLatencyInfo cancel_event = 344 // Note: |dispatching_touch_ack_| is non-null when we reach here, meaning we
176 dispatching_touch_ack_->coalesced_event();
177 cancel_event.event.type = blink::WebInputEvent::TouchCancel;
178 for (size_t i = 0; i < cancel_event.event.touchesLength; i++)
179 cancel_event.event.touches[i].state =
180 blink::WebTouchPoint::StateCancelled;
181 CoalescedWebTouchEvent* coalesced_cancel_event =
182 new CoalescedWebTouchEvent(cancel_event);
183 // Ignore the ack of the touch cancel so when it is acked, it won't get
184 // sent to gesture recognizer.
185 coalesced_cancel_event->set_ignore_ack(true);
186 // |dispatching_touch_ack_| is non-null when we reach here, meaning we
187 // are in the scope of PopTouchEventToClient() and that no touch event 345 // are in the scope of PopTouchEventToClient() and that no touch event
188 // in the queue is waiting for ack from renderer. So we can just insert 346 // in the queue is waiting for ack from renderer. So we can just insert
189 // the touch cancel at the beginning of the queue. 347 // the touch cancel at the beginning of the queue.
190 touch_queue_.push_front(coalesced_cancel_event); 348 touch_queue_.push_front(new CoalescedWebTouchEvent(
349 ObtainCancelEventForTouchEvent(
350 dispatching_touch_ack_->coalesced_event()), true));
191 } else if (type == blink::WebInputEvent::GestureScrollEnd || 351 } else if (type == blink::WebInputEvent::GestureScrollEnd ||
192 type == blink::WebInputEvent::GestureFlingStart) { 352 type == blink::WebInputEvent::GestureFlingStart) {
193 no_touch_to_renderer_ = false; 353 no_touch_to_renderer_ = false;
194 } 354 }
195 } 355 }
196 356
197 void TouchEventQueue::FlushQueue() { 357 void TouchEventQueue::FlushQueue() {
198 DCHECK(!dispatching_touch_ack_); 358 DCHECK(!dispatching_touch_ack_);
359 DCHECK(!dispatching_touch_);
199 while (!touch_queue_.empty()) 360 while (!touch_queue_.empty())
200 PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, 361 PopTouchEventToClient(kDefaultNotForwardedAck, ui::LatencyInfo());
201 ui::LatencyInfo());
202 } 362 }
203 363
204 bool TouchEventQueue::IsPendingAckTouchStart() const { 364 bool TouchEventQueue::IsPendingAckTouchStart() const {
205 DCHECK(!dispatching_touch_ack_); 365 DCHECK(!dispatching_touch_ack_);
206 if (touch_queue_.empty()) 366 if (touch_queue_.empty())
207 return false; 367 return false;
208 368
209 const blink::WebTouchEvent& event = 369 const blink::WebTouchEvent& event =
210 touch_queue_.front()->coalesced_event().event; 370 touch_queue_.front()->coalesced_event().event;
211 return (event.type == blink::WebInputEvent::TouchStart); 371 return (event.type == WebInputEvent::TouchStart);
212 } 372 }
213 373
214 size_t TouchEventQueue::GetQueueSize() const { 374 void TouchEventQueue::SetAckTimeoutEnabled(bool enabled,
215 return touch_queue_.size(); 375 size_t ack_timeout_delay_ms) {
376 if (!enabled) {
377 // Avoid resetting |timeout_handler_|, as an outstanding timeout may
378 // be active and must be completed for ack handling consistency.
379 ack_timeout_enabled_ = false;
380 return;
381 }
382
383 ack_timeout_enabled_ = true;
384 if (!timeout_handler_)
385 timeout_handler_.reset(new TouchTimeoutHandler(this, ack_timeout_delay_ms));
216 } 386 }
217 387
218 const TouchEventWithLatencyInfo& TouchEventQueue::GetLatestEvent() const { 388 bool TouchEventQueue::HasTimeoutEvent() const {
389 return timeout_handler_ && timeout_handler_->HasTimeoutEvent();
390 }
391
392 bool TouchEventQueue::IsTimeoutRunningForTesting() const {
393 return timeout_handler_ && timeout_handler_->IsTimeoutTimerRunning();
394 }
395
396 const TouchEventWithLatencyInfo&
397 TouchEventQueue::GetLatestEventForTesting() const {
219 return touch_queue_.back()->coalesced_event(); 398 return touch_queue_.back()->coalesced_event();
220 } 399 }
221 400
222 void TouchEventQueue::PopTouchEventToClient( 401 void TouchEventQueue::PopTouchEventToClient(
223 InputEventAckState ack_result, 402 InputEventAckState ack_result,
224 const ui::LatencyInfo& renderer_latency_info) { 403 const ui::LatencyInfo& renderer_latency_info) {
404 DCHECK(!dispatching_touch_ack_);
225 if (touch_queue_.empty()) 405 if (touch_queue_.empty())
226 return; 406 return;
227 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front()); 407 scoped_ptr<CoalescedWebTouchEvent> acked_event(touch_queue_.front());
228 touch_queue_.pop_front(); 408 touch_queue_.pop_front();
229 409
230 if (acked_event->ignore_ack()) 410 if (acked_event->ignore_ack())
231 return; 411 return;
232 412
233 // Note that acking the touch-event may result in multiple gestures being sent 413 // Note that acking the touch-event may result in multiple gestures being sent
234 // to the renderer, or touch-events being queued. 414 // to the renderer, or touch-events being queued.
235 base::AutoReset<CoalescedWebTouchEvent*> 415 base::AutoReset<CoalescedWebTouchEvent*>
236 dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get()); 416 dispatching_touch_ack(&dispatching_touch_ack_, acked_event.get());
237 417
238 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(), 418 for (WebTouchEventWithLatencyList::iterator iter = acked_event->begin(),
239 end = acked_event->end(); 419 end = acked_event->end();
240 iter != end; ++iter) { 420 iter != end; ++iter) {
241 iter->latency.AddNewLatencyFrom(renderer_latency_info); 421 iter->latency.AddNewLatencyFrom(renderer_latency_info);
242 client_->OnTouchEventAck((*iter), ack_result); 422 client_->OnTouchEventAck((*iter), ack_result);
243 } 423 }
244 } 424 }
245 425
246 bool TouchEventQueue::ShouldForwardToRenderer( 426 bool TouchEventQueue::ShouldForwardToRenderer(
247 const blink::WebTouchEvent& event) const { 427 const WebTouchEvent& event) const {
428 if (HasTimeoutEvent())
429 return false;
430
248 if (no_touch_to_renderer_ && 431 if (no_touch_to_renderer_ &&
249 event.type != blink::WebInputEvent::TouchCancel) 432 event.type != blink::WebInputEvent::TouchCancel)
250 return false; 433 return false;
251 434
252 // Touch press events should always be forwarded to the renderer. 435 // Touch press events should always be forwarded to the renderer.
253 if (event.type == blink::WebInputEvent::TouchStart) 436 if (event.type == WebInputEvent::TouchStart)
254 return true; 437 return true;
255 438
256 for (unsigned int i = 0; i < event.touchesLength; ++i) { 439 for (unsigned int i = 0; i < event.touchesLength; ++i) {
257 const blink::WebTouchPoint& point = event.touches[i]; 440 const WebTouchPoint& point = event.touches[i];
258 // If a point has been stationary, then don't take it into account. 441 // If a point has been stationary, then don't take it into account.
259 if (point.state == blink::WebTouchPoint::StateStationary) 442 if (point.state == WebTouchPoint::StateStationary)
260 continue; 443 continue;
261 444
262 if (touch_ack_states_.count(point.id) > 0) { 445 if (touch_ack_states_.count(point.id) > 0) {
263 if (touch_ack_states_.find(point.id)->second != 446 if (touch_ack_states_.find(point.id)->second !=
264 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS) 447 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS)
265 return true; 448 return true;
266 } else { 449 } else {
267 // If the ACK status of a point is unknown, then the event should be 450 // If the ACK status of a point is unknown, then the event should be
268 // forwarded to the renderer. 451 // forwarded to the renderer.
269 return true; 452 return true;
270 } 453 }
271 } 454 }
272 455
273 return false; 456 return false;
274 } 457 }
275 458
459 void TouchEventQueue::UpdateTouchAckStates(const WebTouchEvent& event,
460 InputEventAckState ack_result) {
461 // Update the ACK status for each touch point in the ACKed event.
462 if (event.type == WebInputEvent::TouchEnd ||
463 event.type == WebInputEvent::TouchCancel) {
464 // The points have been released. Erase the ACK states.
465 for (unsigned i = 0; i < event.touchesLength; ++i) {
466 const WebTouchPoint& point = event.touches[i];
467 if (point.state == WebTouchPoint::StateReleased ||
468 point.state == WebTouchPoint::StateCancelled)
469 touch_ack_states_.erase(point.id);
470 }
471 } else if (event.type == WebInputEvent::TouchStart) {
472 for (unsigned i = 0; i < event.touchesLength; ++i) {
473 const WebTouchPoint& point = event.touches[i];
474 if (point.state == WebTouchPoint::StatePressed)
475 touch_ack_states_[point.id] = ack_result;
476 }
477 }
478 }
479
276 } // namespace content 480 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698