| 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 |
| 314 GestureEventWithLatencyInfo* second_last_event = nullptr; |
| 315 if (unsent_events_count > 1 && |
| 316 ui::IsCompatibleScrollorPinch( |
| 317 gesture_event.event, |
| 318 coalesced_gesture_events_[coalesced_gesture_events_.size() - 2] |
| 319 .event)) { |
| 320 second_last_event = |
| 321 &coalesced_gesture_events_[coalesced_gesture_events_.size() - 2]; |
| 322 } |
| 323 |
| 324 std::pair<blink::WebGestureEvent, blink::WebGestureEvent> coalesced_events = |
| 325 ui::CoalesceScrollAndPinch( |
| 326 second_last_event ? &second_last_event->event : nullptr, |
| 327 last_event->event, gesture_event.event); |
| 328 |
| 329 DCHECK_LE(last_event->latency.trace_id(), gesture_event.latency.trace_id()); |
| 330 if (second_last_event) { |
| 331 DCHECK_LE(second_last_event->latency.trace_id(), |
| 332 last_event->latency.trace_id()); |
| 333 } |
| 334 ui::LatencyInfo oldest_latency = |
| 335 second_last_event ? second_last_event->latency : last_event->latency; |
| 336 oldest_latency.set_coalesced(); |
| 337 |
| 354 GestureEventWithLatencyInfo scroll_event; | 338 GestureEventWithLatencyInfo scroll_event; |
| 339 scroll_event.event = coalesced_events.first; |
| 340 scroll_event.latency = oldest_latency; |
| 341 |
| 355 GestureEventWithLatencyInfo pinch_event; | 342 GestureEventWithLatencyInfo pinch_event; |
| 356 scroll_event.event.modifiers |= gesture_event.event.modifiers; | 343 pinch_event.event = coalesced_events.second; |
| 357 scroll_event.event.sourceDevice = gesture_event.event.sourceDevice; | 344 pinch_event.latency = oldest_latency; |
| 358 scroll_event.event.timeStampSeconds = gesture_event.event.timeStampSeconds; | |
| 359 // Keep the oldest LatencyInfo. | |
| 360 DCHECK_LE(last_event->latency.trace_id(), gesture_event.latency.trace_id()); | |
| 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 | 345 |
| 372 gfx::Transform combined_scroll_pinch = GetTransformForEvent(*last_event); | 346 // Pop |last_event| and |second_last_event| first. |
| 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(); | 347 coalesced_gesture_events_.pop_back(); |
| 391 | 348 if (second_last_event) |
| 392 float combined_scale = | 349 coalesced_gesture_events_.pop_back(); |
| 393 SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 0)); | |
| 394 float combined_scroll_pinch_x = | |
| 395 SkMScalarToFloat(combined_scroll_pinch.matrix().get(0, 3)); | |
| 396 float combined_scroll_pinch_y = | |
| 397 SkMScalarToFloat(combined_scroll_pinch.matrix().get(1, 3)); | |
| 398 scroll_event.event.data.scrollUpdate.deltaX = | |
| 399 (combined_scroll_pinch_x + pinch_event.event.x) / combined_scale - | |
| 400 pinch_event.event.x; | |
| 401 scroll_event.event.data.scrollUpdate.deltaY = | |
| 402 (combined_scroll_pinch_y + pinch_event.event.y) / combined_scale - | |
| 403 pinch_event.event.y; | |
| 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 |