OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/mouse_wheel_event_queue.h" | 5 #include "content/browser/renderer_host/input/mouse_wheel_event_queue.h" |
6 | 6 |
7 #include "base/memory/ptr_util.h" | 7 #include "base/memory/ptr_util.h" |
8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
9 #include "base/trace_event/trace_event.h" | 9 #include "base/trace_event/trace_event.h" |
10 #include "ui/events/base_event_utils.h" | 10 #include "ui/events/base_event_utils.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 }; | 35 }; |
36 | 36 |
37 MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client, | 37 MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client, |
38 bool enable_scroll_latching) | 38 bool enable_scroll_latching) |
39 : client_(client), | 39 : client_(client), |
40 needs_scroll_begin_(true), | 40 needs_scroll_begin_(true), |
41 needs_scroll_end_(false), | 41 needs_scroll_end_(false), |
42 enable_scroll_latching_(enable_scroll_latching), | 42 enable_scroll_latching_(enable_scroll_latching), |
43 scrolling_device_(blink::kWebGestureDeviceUninitialized) { | 43 scrolling_device_(blink::kWebGestureDeviceUninitialized) { |
44 DCHECK(client); | 44 DCHECK(client); |
45 scroll_transaction_ms_ = | |
46 enable_scroll_latching_ ? kDefaultWheelScrollLatchingTransactionMs : 0; | |
47 } | 45 } |
48 | 46 |
49 MouseWheelEventQueue::~MouseWheelEventQueue() { | 47 MouseWheelEventQueue::~MouseWheelEventQueue() { |
50 } | 48 } |
51 | 49 |
52 void MouseWheelEventQueue::QueueEvent( | 50 void MouseWheelEventQueue::QueueEvent( |
53 const MouseWheelEventWithLatencyInfo& event) { | 51 const MouseWheelEventWithLatencyInfo& event) { |
54 TRACE_EVENT0("input", "MouseWheelEventQueue::QueueEvent"); | 52 TRACE_EVENT0("input", "MouseWheelEventQueue::QueueEvent"); |
55 | 53 |
56 if (event_sent_for_gesture_ack_ && !wheel_queue_.empty()) { | 54 if (event_sent_for_gesture_ack_ && !wheel_queue_.empty()) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
168 event_sent_for_gesture_ack_->event.momentum_phase == | 166 event_sent_for_gesture_ack_->event.momentum_phase == |
169 blink::WebMouseWheelEvent::kPhaseEnded || | 167 blink::WebMouseWheelEvent::kPhaseEnded || |
170 event_sent_for_gesture_ack_->event.momentum_phase == | 168 event_sent_for_gesture_ack_->event.momentum_phase == |
171 blink::WebMouseWheelEvent::kPhaseCancelled; | 169 blink::WebMouseWheelEvent::kPhaseCancelled; |
172 current_phase_ended = scroll_phase_ended || momentum_phase_ended; | 170 current_phase_ended = scroll_phase_ended || momentum_phase_ended; |
173 } | 171 } |
174 | 172 |
175 bool needs_update = scroll_update.data.scroll_update.delta_x != 0 || | 173 bool needs_update = scroll_update.data.scroll_update.delta_x != 0 || |
176 scroll_update.data.scroll_update.delta_y != 0; | 174 scroll_update.data.scroll_update.delta_y != 0; |
177 | 175 |
178 // If there is no update to send and the current phase is ended yet a GSB | |
179 // needs to be sent, this event sequence doesn't need to be generated | |
180 // because the events generated will be a GSB (non-synthetic) and GSE | |
181 // (non-synthetic). This situation arises when OSX generates double | |
182 // phase end information. | |
183 bool empty_sequence = | |
184 !needs_update && needs_scroll_begin_ && current_phase_ended; | |
185 | |
186 if (enable_scroll_latching_) { | 176 if (enable_scroll_latching_) { |
187 if (event_sent_for_gesture_ack_->event.momentum_phase == | 177 if (event_sent_for_gesture_ack_->event.phase == |
188 blink::WebMouseWheelEvent::kPhaseBegan) { | 178 blink::WebMouseWheelEvent::kPhaseBegan) { |
189 // Don't send the pending scrollEnd if a fling starts. | 179 SendScrollBegin(scroll_update, false); |
190 if (scroll_end_timer_.IsRunning()) | |
191 scroll_end_timer_.Stop(); | |
192 } | 180 } |
193 | 181 |
194 if (needs_update || !empty_sequence) { | 182 if (needs_update) { |
195 if (needs_scroll_begin_) { | 183 ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL); |
196 SendScrollBegin(scroll_update, false); | 184 latency.AddLatencyNumber( |
197 } | 185 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0, |
198 | 186 0); |
199 if (needs_update) { | 187 client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency); |
200 ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL); | |
201 latency.AddLatencyNumber( | |
202 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, | |
203 0, 0); | |
204 client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency); | |
205 } | |
206 | |
207 if (momentum_phase_ended) { | |
208 // Send GSE with if scroll latching is enabled and no fling is going | |
209 // to happen next. | |
210 SendScrollEnd(scroll_update, false); | |
211 } else if (scroll_phase_ended || !has_phase_info) { | |
212 // If scroll latching is enabled and a fling might happen next, or | |
213 // no phase info exists, start the scroll_end_timer_. | |
214 scroll_end_timer_.Start( | |
215 FROM_HERE, | |
216 base::TimeDelta::FromMilliseconds(scroll_transaction_ms_), | |
217 base::Bind(&MouseWheelEventQueue::SendScrollEnd, | |
218 base::Unretained(this), scroll_update, false)); | |
219 } | |
220 } | 188 } |
221 | 189 |
| 190 if (current_phase_ended) { |
| 191 // Send GSE with if scroll latching is enabled and no fling is going |
| 192 // to happen next. |
| 193 SendScrollEnd(scroll_update, false); |
| 194 } |
222 } else { // !enable_scroll_latching_ | 195 } else { // !enable_scroll_latching_ |
| 196 |
| 197 // If there is no update to send and the current phase is ended yet a GSB |
| 198 // needs to be sent, this event sequence doesn't need to be generated |
| 199 // because the events generated will be a GSB (non-synthetic) and GSE |
| 200 // (non-synthetic). This situation arises when OSX generates double |
| 201 // phase end information. |
| 202 bool empty_sequence = |
| 203 !needs_update && needs_scroll_begin_ && current_phase_ended; |
223 if (needs_update || !empty_sequence) { | 204 if (needs_update || !empty_sequence) { |
224 if (needs_scroll_begin_) { | 205 if (needs_scroll_begin_) { |
225 // If no GSB has been sent, it will be a non-synthetic GSB. | 206 // If no GSB has been sent, it will be a non-synthetic GSB. |
226 SendScrollBegin(scroll_update, false); | 207 SendScrollBegin(scroll_update, false); |
227 } else if (has_phase_info) { | 208 } else if (has_phase_info) { |
228 // If a GSB has been sent, generate a synthetic GSB if we have phase | 209 // If a GSB has been sent, generate a synthetic GSB if we have phase |
229 // information. This should be removed once crbug.com/526463 is | 210 // information. This should be removed once crbug.com/526463 is |
230 // fully implemented. | 211 // fully implemented. |
231 SendScrollBegin(scroll_update, true); | 212 SendScrollBegin(scroll_update, true); |
232 } | 213 } |
233 | 214 |
234 if (needs_update) { | 215 if (needs_update) { |
235 ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL); | 216 ui::LatencyInfo latency = ui::LatencyInfo(ui::SourceEventType::WHEEL); |
236 latency.AddLatencyNumber( | 217 latency.AddLatencyNumber( |
237 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, | 218 ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, |
238 0, 0); | 219 0, 0); |
239 client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency); | 220 client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency); |
240 } | 221 } |
241 | 222 |
242 if (current_phase_ended) { | 223 if (current_phase_ended) { |
243 // Non-synthetic GSEs are sent when the current phase is canceled or | 224 // Non-synthetic GSEs are sent when the current phase is canceled or |
244 // ended. | 225 // ended. |
245 SendScrollEnd(scroll_update, false); | 226 SendScrollEnd(scroll_update, false); |
246 } else if (has_phase_info) { | 227 } else if (has_phase_info) { |
247 // Generate a synthetic GSE for every update to force hit testing so | 228 // Generate a synthetic GSE for every update to force hit testing so |
248 // that the non-latching behavior is preserved. Remove once | 229 // that the non-latching behavior is preserved. Remove once |
249 // crbug.com/526463 is fully implemented. | 230 // crbug.com/526463 is fully implemented. |
250 SendScrollEnd(scroll_update, true); | 231 SendScrollEnd(scroll_update, true); |
251 } else if (!has_phase_info) { | 232 } else if (!has_phase_info) { |
252 DCHECK_EQ(0, scroll_transaction_ms_); | |
253 SendScrollEnd(scroll_update, false); | 233 SendScrollEnd(scroll_update, false); |
254 } | 234 } |
255 } | 235 } |
256 } | 236 } |
257 } | 237 } |
258 | 238 |
259 event_sent_for_gesture_ack_.reset(); | 239 event_sent_for_gesture_ack_.reset(); |
260 TryForwardNextEventToRenderer(); | 240 TryForwardNextEventToRenderer(); |
261 } | 241 } |
262 | 242 |
263 void MouseWheelEventQueue::OnGestureScrollEvent( | 243 void MouseWheelEventQueue::OnGestureScrollEvent( |
264 const GestureEventWithLatencyInfo& gesture_event) { | 244 const GestureEventWithLatencyInfo& gesture_event) { |
265 if (gesture_event.event.GetType() == | 245 if (gesture_event.event.GetType() == |
266 blink::WebInputEvent::kGestureScrollBegin) { | 246 blink::WebInputEvent::kGestureScrollBegin) { |
267 // If there is a current scroll going on and a new scroll that isn't | |
268 // wheel based cancel current one by sending a ScrollEnd. | |
269 if (scroll_end_timer_.IsRunning() && | |
270 gesture_event.event.source_device != blink::kWebGestureDeviceTouchpad) { | |
271 base::Closure task = scroll_end_timer_.user_task(); | |
272 scroll_end_timer_.Reset(); | |
273 task.Run(); | |
274 } | |
275 scrolling_device_ = gesture_event.event.source_device; | 247 scrolling_device_ = gesture_event.event.source_device; |
276 } else if (scrolling_device_ == gesture_event.event.source_device && | 248 } else if (scrolling_device_ == gesture_event.event.source_device && |
277 (gesture_event.event.GetType() == | 249 (gesture_event.event.GetType() == |
278 blink::WebInputEvent::kGestureScrollEnd || | 250 blink::WebInputEvent::kGestureScrollEnd || |
279 gesture_event.event.GetType() == | 251 gesture_event.event.GetType() == |
280 blink::WebInputEvent::kGestureFlingStart)) { | 252 blink::WebInputEvent::kGestureFlingStart)) { |
281 scrolling_device_ = blink::kWebGestureDeviceUninitialized; | 253 scrolling_device_ = blink::kWebGestureDeviceUninitialized; |
282 if (scroll_end_timer_.IsRunning()) { | 254 if (enable_scroll_latching_) { |
283 if (enable_scroll_latching_) { | 255 needs_scroll_begin_ = true; |
284 // Don't send the pending ScrollEnd if a fling is happening. | 256 needs_scroll_end_ = false; |
285 // The next wheel event will still need a ScrollBegin. | |
286 scroll_end_timer_.Stop(); | |
287 needs_scroll_begin_ = true; | |
288 needs_scroll_end_ = false; | |
289 } else { | |
290 scroll_end_timer_.Reset(); | |
291 } | |
292 } | 257 } |
293 } | 258 } |
294 } | 259 } |
295 | 260 |
296 void MouseWheelEventQueue::TryForwardNextEventToRenderer() { | 261 void MouseWheelEventQueue::TryForwardNextEventToRenderer() { |
297 TRACE_EVENT0("input", "MouseWheelEventQueue::TryForwardNextEventToRenderer"); | 262 TRACE_EVENT0("input", "MouseWheelEventQueue::TryForwardNextEventToRenderer"); |
298 | 263 |
299 if (wheel_queue_.empty() || event_sent_for_gesture_ack_) | 264 if (wheel_queue_.empty() || event_sent_for_gesture_ack_) |
300 return; | 265 return; |
301 | 266 |
(...skipping 14 matching lines...) Expand all Loading... |
316 scroll_end.resending_plugin_id = -1; | 281 scroll_end.resending_plugin_id = -1; |
317 scroll_end.data.scroll_end.synthetic = synthetic; | 282 scroll_end.data.scroll_end.synthetic = synthetic; |
318 scroll_end.data.scroll_end.inertial_phase = | 283 scroll_end.data.scroll_end.inertial_phase = |
319 update_event.data.scroll_update.inertial_phase; | 284 update_event.data.scroll_update.inertial_phase; |
320 scroll_end.data.scroll_end.delta_units = | 285 scroll_end.data.scroll_end.delta_units = |
321 update_event.data.scroll_update.delta_units; | 286 update_event.data.scroll_update.delta_units; |
322 | 287 |
323 if (!synthetic) { | 288 if (!synthetic) { |
324 needs_scroll_begin_ = true; | 289 needs_scroll_begin_ = true; |
325 needs_scroll_end_ = false; | 290 needs_scroll_end_ = false; |
326 | |
327 if (scroll_end_timer_.IsRunning()) | |
328 scroll_end_timer_.Reset(); | |
329 } | 291 } |
330 client_->ForwardGestureEventWithLatencyInfo( | 292 client_->ForwardGestureEventWithLatencyInfo( |
331 scroll_end, ui::LatencyInfo(ui::SourceEventType::WHEEL)); | 293 scroll_end, ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
332 } | 294 } |
333 | 295 |
334 void MouseWheelEventQueue::SendScrollBegin( | 296 void MouseWheelEventQueue::SendScrollBegin( |
335 const WebGestureEvent& gesture_update, | 297 const WebGestureEvent& gesture_update, |
336 bool synthetic) { | 298 bool synthetic) { |
337 DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_); | 299 DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_); |
338 | 300 |
(...skipping 10 matching lines...) Expand all Loading... |
349 scroll_begin.data.scroll_begin.delta_hint_units = | 311 scroll_begin.data.scroll_begin.delta_hint_units = |
350 gesture_update.data.scroll_update.delta_units; | 312 gesture_update.data.scroll_update.delta_units; |
351 | 313 |
352 needs_scroll_begin_ = false; | 314 needs_scroll_begin_ = false; |
353 needs_scroll_end_ = true; | 315 needs_scroll_end_ = true; |
354 client_->ForwardGestureEventWithLatencyInfo( | 316 client_->ForwardGestureEventWithLatencyInfo( |
355 scroll_begin, ui::LatencyInfo(ui::SourceEventType::WHEEL)); | 317 scroll_begin, ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
356 } | 318 } |
357 | 319 |
358 } // namespace content | 320 } // namespace content |
OLD | NEW |