OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/gesture_event_queue.h" | 5 #include "content/browser/renderer_host/input/gesture_event_queue.h" |
6 | 6 |
7 #include "base/trace_event/trace_event.h" | 7 #include "base/trace_event/trace_event.h" |
8 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle r.h" | 8 #include "content/browser/renderer_host/input/touchpad_tap_suppression_controlle r.h" |
9 #include "content/browser/renderer_host/input/touchscreen_tap_suppression_contro ller.h" | 9 #include "content/browser/renderer_host/input/touchscreen_tap_suppression_contro ller.h" |
10 #include "ui/events/blink/web_input_event_traits.h" | 10 #include "ui/events/blink/web_input_event_traits.h" |
11 | 11 |
12 using blink::WebGestureEvent; | 12 using blink::WebGestureEvent; |
13 using blink::WebInputEvent; | 13 using blink::WebInputEvent; |
14 | 14 |
15 namespace content { | 15 namespace content { |
16 namespace { | |
17 | |
18 // Whether |event_in_queue| is GesturePinchUpdate or GestureScrollUpdate and | |
19 // has the same modifiers/source as the new scroll/pinch event. Compatible | |
20 // scroll and pinch event pairs can be logically coalesced. | |
21 bool IsCompatibleScrollorPinch( | |
22 const GestureEventWithLatencyInfo& new_event, | |
23 const GestureEventWithLatencyInfo& event_in_queue) { | |
24 DCHECK(new_event.event.type == WebInputEvent::GestureScrollUpdate || | |
25 new_event.event.type == WebInputEvent::GesturePinchUpdate) | |
26 << "Invalid event type for pinch/scroll coalescing: " | |
27 << WebInputEvent::GetName(new_event.event.type); | |
28 DLOG_IF(WARNING, new_event.event.timeStampSeconds < | |
29 event_in_queue.event.timeStampSeconds) | |
30 << "Event time not monotonic?\n"; | |
31 return (event_in_queue.event.type == WebInputEvent::GestureScrollUpdate || | |
32 event_in_queue.event.type == WebInputEvent::GesturePinchUpdate) && | |
33 event_in_queue.event.modifiers == new_event.event.modifiers && | |
34 event_in_queue.event.sourceDevice == new_event.event.sourceDevice; | |
35 } | |
36 | |
37 // Returns the transform matrix corresponding to the gesture event. | |
38 gfx::Transform GetTransformForEvent( | |
39 const GestureEventWithLatencyInfo& gesture_event) { | |
40 gfx::Transform gesture_transform; | |
41 if (gesture_event.event.type == WebInputEvent::GestureScrollUpdate) { | |
42 gesture_transform.Translate(gesture_event.event.data.scrollUpdate.deltaX, | |
43 gesture_event.event.data.scrollUpdate.deltaY); | |
44 } else if (gesture_event.event.type == WebInputEvent::GesturePinchUpdate) { | |
45 float scale = gesture_event.event.data.pinchUpdate.scale; | |
46 gesture_transform.Translate(-gesture_event.event.x, -gesture_event.event.y); | |
47 gesture_transform.Scale(scale, scale); | |
48 gesture_transform.Translate(gesture_event.event.x, gesture_event.event.y); | |
49 } else { | |
50 NOTREACHED() << "Invalid event type for transform retrieval: " | |
51 << WebInputEvent::GetName(gesture_event.event.type); | |
52 } | |
53 return gesture_transform; | |
54 } | |
55 | |
56 } // namespace | |
57 | 16 |
58 GestureEventQueue::Config::Config() { | 17 GestureEventQueue::Config::Config() { |
59 } | 18 } |
60 | 19 |
61 GestureEventQueue::GestureEventQueue( | 20 GestureEventQueue::GestureEventQueue( |
62 GestureEventQueueClient* client, | 21 GestureEventQueueClient* client, |
63 TouchpadTapSuppressionControllerClient* touchpad_client, | 22 TouchpadTapSuppressionControllerClient* touchpad_client, |
64 const Config& config) | 23 const Config& config) |
65 : client_(client), | 24 : client_(client), |
66 fling_in_progress_(false), | 25 fling_in_progress_(false), |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 if (coalesced_gesture_events_.size() == 1) { | 284 if (coalesced_gesture_events_.size() == 1) { |
326 client_->SendGestureEventImmediately(gesture_event); | 285 client_->SendGestureEventImmediately(gesture_event); |
327 } else if (coalesced_gesture_events_.size() == 2) { | 286 } else if (coalesced_gesture_events_.size() == 2) { |
328 DCHECK(!ignore_next_ack_); | 287 DCHECK(!ignore_next_ack_); |
329 // If there is an in-flight scroll, the new pinch can be forwarded | 288 // If there is an in-flight scroll, the new pinch can be forwarded |
330 // immediately, avoiding a potential frame delay between the two | 289 // immediately, avoiding a potential frame delay between the two |
331 // (similarly for an in-flight pinch with a new scroll). | 290 // (similarly for an in-flight pinch with a new scroll). |
332 const GestureEventWithLatencyInfo& first_event = | 291 const GestureEventWithLatencyInfo& first_event = |
333 coalesced_gesture_events_.front(); | 292 coalesced_gesture_events_.front(); |
334 if (gesture_event.event.type != first_event.event.type && | 293 if (gesture_event.event.type != first_event.event.type && |
335 IsCompatibleScrollorPinch(gesture_event, first_event)) { | 294 ui::IsCompatibleScrollorPinch(gesture_event.event, |
295 first_event.event)) { | |
336 ignore_next_ack_ = true; | 296 ignore_next_ack_ = true; |
337 client_->SendGestureEventImmediately(gesture_event); | 297 client_->SendGestureEventImmediately(gesture_event); |
338 } | 298 } |
339 } | 299 } |
340 return; | 300 return; |
341 } | 301 } |
342 | 302 |
343 GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back(); | 303 GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back(); |
344 if (last_event->CanCoalesceWith(gesture_event)) { | 304 if (last_event->CanCoalesceWith(gesture_event)) { |
345 last_event->CoalesceWith(gesture_event); | 305 last_event->CoalesceWith(gesture_event); |
346 return; | 306 return; |
347 } | 307 } |
348 | 308 |
349 if (!IsCompatibleScrollorPinch(gesture_event, *last_event)) { | 309 if (!ui::IsCompatibleScrollorPinch(gesture_event.event, last_event->event)) { |
350 coalesced_gesture_events_.push_back(gesture_event); | 310 coalesced_gesture_events_.push_back(gesture_event); |
351 return; | 311 return; |
352 } | 312 } |
353 | 313 |
354 GestureEventWithLatencyInfo scroll_event; | 314 // Extract the last event in queue. |
355 GestureEventWithLatencyInfo pinch_event; | 315 ui::ScopedWebInputEvent last_gesture_event = |
356 scroll_event.event.modifiers |= gesture_event.event.modifiers; | 316 ui::WebInputEventTraits::Clone(coalesced_gesture_events_.back().event); |
dtapuska
2016/12/13 15:57:22
Does last_gesture_event really need to be heap all
chongz
2016/12/13 16:30:44
Done.
| |
357 scroll_event.event.sourceDevice = gesture_event.event.sourceDevice; | 317 DCHECK_LE(coalesced_gesture_events_.back().latency.trace_id(), |
358 scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds; | 318 gesture_event.latency.trace_id()); |
359 // Keep the oldest LatencyInfo. | 319 ui::LatencyInfo oldest_latency = coalesced_gesture_events_.back().latency; |
360 DCHECK_LE(last_event->latency.trace_id(), gesture_event.latency.trace_id()); | 320 oldest_latency.set_coalesced(); |
361 scroll_event.latency = last_event->latency; | |
362 pinch_event = scroll_event; | |
363 scroll_event.event.type = WebInputEvent::GestureScrollUpdate; | |
364 pinch_event.event.type = WebInputEvent::GesturePinchUpdate; | |
365 pinch_event.event.x = gesture_event.event.type == | |
366 WebInputEvent::GesturePinchUpdate ? | |
367 gesture_event.event.x : last_event->event.x; | |
368 pinch_event.event.y = gesture_event.event.type == | |
369 WebInputEvent::GesturePinchUpdate ? | |
370 gesture_event.event.y : last_event->event.y; | |
371 | |
372 gfx::Transform combined_scroll_pinch = GetTransformForEvent(*last_event); | |
373 // Only include the second-to-last event in the coalesced pair if it exists | |
374 // and can be combined with the new event. | |
375 if (unsent_events_count > 1) { | |
376 const GestureEventWithLatencyInfo& second_last_event = | |
377 coalesced_gesture_events_[coalesced_gesture_events_.size() - 2]; | |
378 if (IsCompatibleScrollorPinch(gesture_event, second_last_event)) { | |
379 // Keep the oldest LatencyInfo. | |
380 DCHECK_LE(second_last_event.latency.trace_id(), | |
381 scroll_event.latency.trace_id()); | |
382 scroll_event.latency = second_last_event.latency; | |
383 pinch_event.latency = second_last_event.latency; | |
384 combined_scroll_pinch.PreconcatTransform( | |
385 GetTransformForEvent(second_last_event)); | |
386 coalesced_gesture_events_.pop_back(); | |
387 } | |
388 } | |
389 combined_scroll_pinch.ConcatTransform(GetTransformForEvent(gesture_event)); | |
390 coalesced_gesture_events_.pop_back(); | 321 coalesced_gesture_events_.pop_back(); |
391 | 322 |
392 float combined_scale = | 323 // Extract the second last event in queue. |
393 SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 0)); | 324 ui::ScopedWebInputEvent second_last_gesture_event = nullptr; |
394 float combined_scroll_pinch_x = | 325 if (unsent_events_count > 1 && |
395 SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 3)); | 326 ui::IsCompatibleScrollorPinch(gesture_event.event, |
396 float combined_scroll_pinch_y = | 327 coalesced_gesture_events_.back().event)) { |
397 SkMScalarToFloat(combined_scroll_pinch.matrix().get(1, 3)); | 328 second_last_gesture_event = |
398 scroll_event.event.data.scrollUpdate.deltaX = | 329 ui::WebInputEventTraits::Clone(coalesced_gesture_events_.back().event); |
399 (combined_scroll_pinch_x + pinch_event.event.x) / combined_scale - | 330 DCHECK_LE(coalesced_gesture_events_.back().latency.trace_id(), |
400 pinch_event.event.x; | 331 oldest_latency.trace_id()); |
401 scroll_event.event.data.scrollUpdate.deltaY = | 332 oldest_latency = coalesced_gesture_events_.back().latency; |
402 (combined_scroll_pinch_y + pinch_event.event.y) / combined_scale - | 333 oldest_latency.set_coalesced(); |
403 pinch_event.event.y; | 334 coalesced_gesture_events_.pop_back(); |
335 } | |
336 | |
337 std::pair<blink::WebGestureEvent, blink::WebGestureEvent> coalesced_events = | |
338 ui::CoalesceScrollAndPinch( | |
339 ui::ToWebGestureEvent(second_last_gesture_event.get()), | |
340 ui::ToWebGestureEvent(*last_gesture_event), gesture_event.event); | |
341 | |
342 GestureEventWithLatencyInfo scroll_event; | |
343 scroll_event.event = coalesced_events.first; | |
344 scroll_event.latency = oldest_latency; | |
345 | |
346 GestureEventWithLatencyInfo pinch_event; | |
347 pinch_event.event = coalesced_events.second; | |
348 pinch_event.latency = oldest_latency; | |
349 | |
404 coalesced_gesture_events_.push_back(scroll_event); | 350 coalesced_gesture_events_.push_back(scroll_event); |
405 pinch_event.event.data.pinchUpdate.scale = combined_scale; | |
406 coalesced_gesture_events_.push_back(pinch_event); | 351 coalesced_gesture_events_.push_back(pinch_event); |
407 } | 352 } |
408 | 353 |
409 size_t GestureEventQueue::EventsInFlightCount() const { | 354 size_t GestureEventQueue::EventsInFlightCount() const { |
410 if (coalesced_gesture_events_.empty()) | 355 if (coalesced_gesture_events_.empty()) |
411 return 0; | 356 return 0; |
412 | 357 |
413 if (!ignore_next_ack_) | 358 if (!ignore_next_ack_) |
414 return 1; | 359 return 1; |
415 | 360 |
416 DCHECK_GT(coalesced_gesture_events_.size(), 1U); | 361 DCHECK_GT(coalesced_gesture_events_.size(), 1U); |
417 return 2; | 362 return 2; |
418 } | 363 } |
419 | 364 |
420 } // namespace content | 365 } // namespace content |
OLD | NEW |