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