| 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/common/input/event_with_latency_info.h" | 5 #include "content/common/input/event_with_latency_info.h" | 
| 6 | 6 | 
| 7 #include <bitset> |  | 
| 8 #include <limits> |  | 
| 9 |  | 
| 10 using blink::WebGestureEvent; |  | 
| 11 using blink::WebInputEvent; | 7 using blink::WebInputEvent; | 
| 12 using blink::WebKeyboardEvent; |  | 
| 13 using blink::WebMouseEvent; |  | 
| 14 using blink::WebMouseWheelEvent; |  | 
| 15 using blink::WebTouchEvent; |  | 
| 16 using std::numeric_limits; |  | 
| 17 | 8 | 
| 18 namespace content { | 9 namespace content { | 
| 19 namespace { |  | 
| 20 |  | 
| 21 const int kInvalidTouchIndex = -1; |  | 
| 22 |  | 
| 23 float GetUnacceleratedDelta(float accelerated_delta, float acceleration_ratio) { |  | 
| 24   return accelerated_delta * acceleration_ratio; |  | 
| 25 } |  | 
| 26 |  | 
| 27 float GetAccelerationRatio(float accelerated_delta, float unaccelerated_delta) { |  | 
| 28   if (unaccelerated_delta == 0.f || accelerated_delta == 0.f) |  | 
| 29     return 1.f; |  | 
| 30   return unaccelerated_delta / accelerated_delta; |  | 
| 31 } |  | 
| 32 |  | 
| 33 // Returns |kInvalidTouchIndex| iff |event| lacks a touch with an ID of |id|. |  | 
| 34 int GetIndexOfTouchID(const WebTouchEvent& event, int id) { |  | 
| 35   for (unsigned i = 0; i < event.touchesLength; ++i) { |  | 
| 36     if (event.touches[i].id == id) |  | 
| 37       return i; |  | 
| 38   } |  | 
| 39   return kInvalidTouchIndex; |  | 
| 40 } |  | 
| 41 |  | 
| 42 WebInputEvent::DispatchType MergeDispatchTypes( |  | 
| 43     WebInputEvent::DispatchType type_1, |  | 
| 44     WebInputEvent::DispatchType type_2) { |  | 
| 45   static_assert(WebInputEvent::DispatchType::Blocking < |  | 
| 46                     WebInputEvent::DispatchType::EventNonBlocking, |  | 
| 47                 "Enum not ordered correctly"); |  | 
| 48   static_assert(WebInputEvent::DispatchType::EventNonBlocking < |  | 
| 49                     WebInputEvent::DispatchType::ListenersNonBlockingPassive, |  | 
| 50                 "Enum not ordered correctly"); |  | 
| 51   static_assert( |  | 
| 52       WebInputEvent::DispatchType::ListenersNonBlockingPassive < |  | 
| 53           WebInputEvent::DispatchType::ListenersForcedNonBlockingDueToFling, |  | 
| 54       "Enum not ordered correctly"); |  | 
| 55   return static_cast<WebInputEvent::DispatchType>( |  | 
| 56       std::min(static_cast<int>(type_1), static_cast<int>(type_2))); |  | 
| 57 } |  | 
| 58 |  | 
| 59 }  // namespace |  | 
| 60 |  | 
| 61 namespace internal { |  | 
| 62 |  | 
| 63 bool CanCoalesce(const WebMouseEvent& event_to_coalesce, |  | 
| 64                  const WebMouseEvent& event) { |  | 
| 65   return event.type == event_to_coalesce.type && |  | 
| 66          event.type == WebInputEvent::MouseMove; |  | 
| 67 } |  | 
| 68 |  | 
| 69 void Coalesce(const WebMouseEvent& event_to_coalesce, WebMouseEvent* event) { |  | 
| 70   DCHECK(CanCoalesce(event_to_coalesce, *event)); |  | 
| 71   // Accumulate movement deltas. |  | 
| 72   int x = event->movementX; |  | 
| 73   int y = event->movementY; |  | 
| 74   *event = event_to_coalesce; |  | 
| 75   event->movementX += x; |  | 
| 76   event->movementY += y; |  | 
| 77 } |  | 
| 78 |  | 
| 79 bool CanCoalesce(const WebMouseWheelEvent& event_to_coalesce, |  | 
| 80                  const WebMouseWheelEvent& event) { |  | 
| 81   return event.modifiers == event_to_coalesce.modifiers && |  | 
| 82          event.scrollByPage == event_to_coalesce.scrollByPage && |  | 
| 83          event.phase == event_to_coalesce.phase && |  | 
| 84          event.momentumPhase == event_to_coalesce.momentumPhase && |  | 
| 85          event.hasPreciseScrollingDeltas == |  | 
| 86              event_to_coalesce.hasPreciseScrollingDeltas; |  | 
| 87 } |  | 
| 88 |  | 
| 89 void Coalesce(const WebMouseWheelEvent& event_to_coalesce, |  | 
| 90               WebMouseWheelEvent* event) { |  | 
| 91   DCHECK(CanCoalesce(event_to_coalesce, *event)); |  | 
| 92   float unaccelerated_x = |  | 
| 93       GetUnacceleratedDelta(event->deltaX, event->accelerationRatioX) + |  | 
| 94       GetUnacceleratedDelta(event_to_coalesce.deltaX, |  | 
| 95                             event_to_coalesce.accelerationRatioX); |  | 
| 96   float unaccelerated_y = |  | 
| 97       GetUnacceleratedDelta(event->deltaY, event->accelerationRatioY) + |  | 
| 98       GetUnacceleratedDelta(event_to_coalesce.deltaY, |  | 
| 99                             event_to_coalesce.accelerationRatioY); |  | 
| 100   float old_deltaX = event->deltaX; |  | 
| 101   float old_deltaY = event->deltaY; |  | 
| 102   float old_wheelTicksX = event->wheelTicksX; |  | 
| 103   float old_wheelTicksY = event->wheelTicksY; |  | 
| 104   float old_movementX = event->movementX; |  | 
| 105   float old_movementY = event->movementY; |  | 
| 106   *event = event_to_coalesce; |  | 
| 107   event->deltaX += old_deltaX; |  | 
| 108   event->deltaY += old_deltaY; |  | 
| 109   event->wheelTicksX += old_wheelTicksX; |  | 
| 110   event->wheelTicksY += old_wheelTicksY; |  | 
| 111   event->movementX += old_movementX; |  | 
| 112   event->movementY += old_movementY; |  | 
| 113   event->accelerationRatioX = |  | 
| 114       GetAccelerationRatio(event->deltaX, unaccelerated_x); |  | 
| 115   event->accelerationRatioY = |  | 
| 116       GetAccelerationRatio(event->deltaY, unaccelerated_y); |  | 
| 117 } |  | 
| 118 |  | 
| 119 bool CanCoalesce(const WebTouchEvent& event_to_coalesce, |  | 
| 120                  const WebTouchEvent& event) { |  | 
| 121   if (event.type != event_to_coalesce.type || |  | 
| 122       event.type != WebInputEvent::TouchMove || |  | 
| 123       event.modifiers != event_to_coalesce.modifiers || |  | 
| 124       event.touchesLength != event_to_coalesce.touchesLength || |  | 
| 125       event.touchesLength > WebTouchEvent::kTouchesLengthCap) |  | 
| 126     return false; |  | 
| 127 |  | 
| 128   static_assert(WebTouchEvent::kTouchesLengthCap <= sizeof(int32_t) * 8U, |  | 
| 129                 "suboptimal kTouchesLengthCap size"); |  | 
| 130   // Ensure that we have a 1-to-1 mapping of pointer ids between touches. |  | 
| 131   std::bitset<WebTouchEvent::kTouchesLengthCap> unmatched_event_touches( |  | 
| 132       (1 << event.touchesLength) - 1); |  | 
| 133   for (unsigned i = 0; i < event_to_coalesce.touchesLength; ++i) { |  | 
| 134     int event_touch_index = |  | 
| 135         GetIndexOfTouchID(event, event_to_coalesce.touches[i].id); |  | 
| 136     if (event_touch_index == kInvalidTouchIndex) |  | 
| 137       return false; |  | 
| 138     if (!unmatched_event_touches[event_touch_index]) |  | 
| 139       return false; |  | 
| 140     unmatched_event_touches[event_touch_index] = false; |  | 
| 141   } |  | 
| 142   return unmatched_event_touches.none(); |  | 
| 143 } |  | 
| 144 |  | 
| 145 void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) { |  | 
| 146   DCHECK(CanCoalesce(event_to_coalesce, *event)); |  | 
| 147   // The WebTouchPoints include absolute position information. So it is |  | 
| 148   // sufficient to simply replace the previous event with the new event-> |  | 
| 149   // However, it is necessary to make sure that all the points have the |  | 
| 150   // correct state, i.e. the touch-points that moved in the last event, but |  | 
| 151   // didn't change in the current event, will have Stationary state. It is |  | 
| 152   // necessary to change them back to Moved state. |  | 
| 153   WebTouchEvent old_event = *event; |  | 
| 154   *event = event_to_coalesce; |  | 
| 155   for (unsigned i = 0; i < event->touchesLength; ++i) { |  | 
| 156     int i_old = GetIndexOfTouchID(old_event, event->touches[i].id); |  | 
| 157     if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved) |  | 
| 158       event->touches[i].state = blink::WebTouchPoint::StateMoved; |  | 
| 159   } |  | 
| 160   event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion; |  | 
| 161   event->dispatchType = MergeDispatchTypes(old_event.dispatchType, |  | 
| 162                                            event_to_coalesce.dispatchType); |  | 
| 163 } |  | 
| 164 |  | 
| 165 bool CanCoalesce(const WebGestureEvent& event_to_coalesce, |  | 
| 166                  const WebGestureEvent& event) { |  | 
| 167   if (event.type != event_to_coalesce.type || |  | 
| 168       event.sourceDevice != event_to_coalesce.sourceDevice || |  | 
| 169       event.modifiers != event_to_coalesce.modifiers) |  | 
| 170     return false; |  | 
| 171 |  | 
| 172   if (event.type == WebInputEvent::GestureScrollUpdate) |  | 
| 173     return true; |  | 
| 174 |  | 
| 175   // GesturePinchUpdate scales can be combined only if they share a focal point, |  | 
| 176   // e.g., with double-tap drag zoom. |  | 
| 177   if (event.type == WebInputEvent::GesturePinchUpdate && |  | 
| 178       event.x == event_to_coalesce.x && event.y == event_to_coalesce.y) |  | 
| 179     return true; |  | 
| 180 |  | 
| 181   return false; |  | 
| 182 } |  | 
| 183 |  | 
| 184 void Coalesce(const WebGestureEvent& event_to_coalesce, |  | 
| 185               WebGestureEvent* event) { |  | 
| 186   DCHECK(CanCoalesce(event_to_coalesce, *event)); |  | 
| 187   if (event->type == WebInputEvent::GestureScrollUpdate) { |  | 
| 188     event->data.scrollUpdate.deltaX += |  | 
| 189         event_to_coalesce.data.scrollUpdate.deltaX; |  | 
| 190     event->data.scrollUpdate.deltaY += |  | 
| 191         event_to_coalesce.data.scrollUpdate.deltaY; |  | 
| 192     DCHECK_EQ( |  | 
| 193         event->data.scrollUpdate.previousUpdateInSequencePrevented, |  | 
| 194         event_to_coalesce.data.scrollUpdate.previousUpdateInSequencePrevented); |  | 
| 195   } else if (event->type == WebInputEvent::GesturePinchUpdate) { |  | 
| 196     event->data.pinchUpdate.scale *= event_to_coalesce.data.pinchUpdate.scale; |  | 
| 197     // Ensure the scale remains bounded above 0 and below Infinity so that |  | 
| 198     // we can reliably perform operations like log on the values. |  | 
| 199     if (event->data.pinchUpdate.scale < numeric_limits<float>::min()) |  | 
| 200       event->data.pinchUpdate.scale = numeric_limits<float>::min(); |  | 
| 201     else if (event->data.pinchUpdate.scale > numeric_limits<float>::max()) |  | 
| 202       event->data.pinchUpdate.scale = numeric_limits<float>::max(); |  | 
| 203   } |  | 
| 204 } |  | 
| 205 |  | 
| 206 bool CanCoalesce(const blink::WebInputEvent& event_to_coalesce, |  | 
| 207                  const blink::WebInputEvent& event) { |  | 
| 208   if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |  | 
| 209       blink::WebInputEvent::isGestureEventType(event.type)) { |  | 
| 210     return CanCoalesce( |  | 
| 211         static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |  | 
| 212         static_cast<const blink::WebGestureEvent&>(event)); |  | 
| 213   } |  | 
| 214   if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |  | 
| 215       blink::WebInputEvent::isMouseEventType(event.type)) { |  | 
| 216     return CanCoalesce( |  | 
| 217         static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |  | 
| 218         static_cast<const blink::WebMouseEvent&>(event)); |  | 
| 219   } |  | 
| 220   if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |  | 
| 221       blink::WebInputEvent::isTouchEventType(event.type)) { |  | 
| 222     return CanCoalesce( |  | 
| 223         static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |  | 
| 224         static_cast<const blink::WebTouchEvent&>(event)); |  | 
| 225   } |  | 
| 226   if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |  | 
| 227       event.type == blink::WebInputEvent::MouseWheel) { |  | 
| 228     return CanCoalesce( |  | 
| 229         static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |  | 
| 230         static_cast<const blink::WebMouseWheelEvent&>(event)); |  | 
| 231   } |  | 
| 232   return false; |  | 
| 233 } |  | 
| 234 |  | 
| 235 void Coalesce(const blink::WebInputEvent& event_to_coalesce, |  | 
| 236               blink::WebInputEvent* event) { |  | 
| 237   if (blink::WebInputEvent::isGestureEventType(event_to_coalesce.type) && |  | 
| 238       blink::WebInputEvent::isGestureEventType(event->type)) { |  | 
| 239     Coalesce(static_cast<const blink::WebGestureEvent&>(event_to_coalesce), |  | 
| 240              static_cast<blink::WebGestureEvent*>(event)); |  | 
| 241     return; |  | 
| 242   } |  | 
| 243   if (blink::WebInputEvent::isMouseEventType(event_to_coalesce.type) && |  | 
| 244       blink::WebInputEvent::isMouseEventType(event->type)) { |  | 
| 245     Coalesce(static_cast<const blink::WebMouseEvent&>(event_to_coalesce), |  | 
| 246              static_cast<blink::WebMouseEvent*>(event)); |  | 
| 247     return; |  | 
| 248   } |  | 
| 249   if (blink::WebInputEvent::isTouchEventType(event_to_coalesce.type) && |  | 
| 250       blink::WebInputEvent::isTouchEventType(event->type)) { |  | 
| 251     Coalesce(static_cast<const blink::WebTouchEvent&>(event_to_coalesce), |  | 
| 252              static_cast<blink::WebTouchEvent*>(event)); |  | 
| 253     return; |  | 
| 254   } |  | 
| 255   if (event_to_coalesce.type == blink::WebInputEvent::MouseWheel && |  | 
| 256       event->type == blink::WebInputEvent::MouseWheel) { |  | 
| 257     Coalesce(static_cast<const blink::WebMouseWheelEvent&>(event_to_coalesce), |  | 
| 258              static_cast<blink::WebMouseWheelEvent*>(event)); |  | 
| 259   } |  | 
| 260 } |  | 
| 261 |  | 
| 262 }  // namespace internal |  | 
| 263 | 10 | 
| 264 ScopedWebInputEventWithLatencyInfo::ScopedWebInputEventWithLatencyInfo( | 11 ScopedWebInputEventWithLatencyInfo::ScopedWebInputEventWithLatencyInfo( | 
| 265     ui::ScopedWebInputEvent event, | 12     ui::ScopedWebInputEvent event, | 
| 266     const ui::LatencyInfo& latency_info) | 13     const ui::LatencyInfo& latency_info) | 
| 267     : event_(std::move(event)), latency_(latency_info) { | 14     : event_(std::move(event)), latency_(latency_info) { | 
| 268 } | 15 } | 
| 269 | 16 | 
| 270 ScopedWebInputEventWithLatencyInfo::~ScopedWebInputEventWithLatencyInfo() {} | 17 ScopedWebInputEventWithLatencyInfo::~ScopedWebInputEventWithLatencyInfo() {} | 
| 271 | 18 | 
| 272 bool ScopedWebInputEventWithLatencyInfo::CanCoalesceWith( | 19 bool ScopedWebInputEventWithLatencyInfo::CanCoalesceWith( | 
| 273     const ScopedWebInputEventWithLatencyInfo& other) const { | 20     const ScopedWebInputEventWithLatencyInfo& other) const { | 
| 274   return internal::CanCoalesce(other.event(), event()); | 21   return ui::CanCoalesce(other.event(), event()); | 
| 275 } | 22 } | 
| 276 | 23 | 
| 277 void ScopedWebInputEventWithLatencyInfo::CoalesceWith( | 24 void ScopedWebInputEventWithLatencyInfo::CoalesceWith( | 
| 278     const ScopedWebInputEventWithLatencyInfo& other) { | 25     const ScopedWebInputEventWithLatencyInfo& other) { | 
| 279   // |other| should be a newer event than |this|. | 26   // |other| should be a newer event than |this|. | 
| 280   if (other.latency_.trace_id() >= 0 && latency_.trace_id() >= 0) | 27   if (other.latency_.trace_id() >= 0 && latency_.trace_id() >= 0) | 
| 281     DCHECK_GT(other.latency_.trace_id(), latency_.trace_id()); | 28     DCHECK_GT(other.latency_.trace_id(), latency_.trace_id()); | 
| 282 | 29 | 
| 283   // New events get coalesced into older events, and the newer timestamp | 30   // New events get coalesced into older events, and the newer timestamp | 
| 284   // should always be preserved. | 31   // should always be preserved. | 
| 285   const double time_stamp_seconds = other.event().timeStampSeconds; | 32   const double time_stamp_seconds = other.event().timeStampSeconds; | 
| 286   internal::Coalesce(other.event(), event_.get()); | 33   ui::Coalesce(other.event(), event_.get()); | 
| 287   event_->timeStampSeconds = time_stamp_seconds; | 34   event_->timeStampSeconds = time_stamp_seconds; | 
| 288 | 35 | 
| 289   // When coalescing two input events, we keep the oldest LatencyInfo | 36   // When coalescing two input events, we keep the oldest LatencyInfo | 
| 290   // since it will represent the longest latency. | 37   // since it will represent the longest latency. | 
| 291   other.latency_ = latency_; | 38   other.latency_ = latency_; | 
| 292   other.latency_.set_coalesced(); | 39   other.latency_.set_coalesced(); | 
| 293 } | 40 } | 
| 294 | 41 | 
| 295 const blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() const { | 42 const blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() const { | 
| 296   return *event_; | 43   return *event_; | 
| 297 } | 44 } | 
| 298 | 45 | 
| 299 blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() { | 46 blink::WebInputEvent& ScopedWebInputEventWithLatencyInfo::event() { | 
| 300   return *event_; | 47   return *event_; | 
| 301 } | 48 } | 
| 302 | 49 | 
| 303 }  // namespace content | 50 }  // namespace content | 
| OLD | NEW | 
|---|