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